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