View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule.controversial;
5   
6   import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
7   import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
8   import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
9   import net.sourceforge.pmd.lang.java.ast.ASTExpression;
10  import net.sourceforge.pmd.lang.java.ast.ASTName;
11  import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
12  import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
13  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
14  import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
15  
16  // TODO - should check that this is not the first assignment.  e.g., this is OK:
17  // Object x;
18  // x = null;
19  public class NullAssignmentRule extends AbstractJavaRule {
20  
21      @Override
22      public Object visit(ASTNullLiteral node, Object data) {
23  
24          if (node.getNthParent(5) instanceof ASTStatementExpression) {
25              ASTStatementExpression n = (ASTStatementExpression) node.getNthParent(5);
26  
27              if (isAssignmentToFinalField(n)) {
28                  return data;
29              }
30  
31              if (n.jjtGetNumChildren() > 2 && n.jjtGetChild(1) instanceof ASTAssignmentOperator) {
32                  addViolation(data, node);
33              }
34          } else if (node.getNthParent(4) instanceof ASTConditionalExpression) {
35              // "false" expression of ternary
36              if (isBadTernary((ASTConditionalExpression)node.getNthParent(4))) {
37                  addViolation(data, node);
38              }
39          } else if (node.getNthParent(5) instanceof ASTConditionalExpression && node.getNthParent(4) instanceof ASTExpression) {
40              // "true" expression of ternary
41              if (isBadTernary((ASTConditionalExpression)node.getNthParent(5))) {
42                  addViolation(data, node);
43              }
44          }
45  
46          return data;
47      }
48  
49      private boolean isAssignmentToFinalField(ASTStatementExpression n) {
50          ASTName name = n.getFirstDescendantOfType(ASTName.class);
51          return name != null
52                  && name.getNameDeclaration() instanceof VariableNameDeclaration
53                  && ((VariableNameDeclaration) name.getNameDeclaration()).getAccessNodeParent().isFinal();
54      }
55  
56      private boolean isBadTernary(ASTConditionalExpression n) {
57          return n.isTernary() && !(n.jjtGetChild(0) instanceof ASTEqualityExpression);
58      }
59  }