View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.rules.design;
5   
6   import net.sourceforge.pmd.AbstractRule;
7   import net.sourceforge.pmd.ast.ASTAssignmentOperator;
8   import net.sourceforge.pmd.ast.ASTConditionalExpression;
9   import net.sourceforge.pmd.ast.ASTEqualityExpression;
10  import net.sourceforge.pmd.ast.ASTExpression;
11  import net.sourceforge.pmd.ast.ASTName;
12  import net.sourceforge.pmd.ast.ASTNullLiteral;
13  import net.sourceforge.pmd.ast.ASTStatementExpression;
14  import net.sourceforge.pmd.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 AbstractRule {
20  
21      public Object visit(ASTNullLiteral node, Object data) {
22          
23          if (node.getNthParent(5) instanceof ASTStatementExpression) {
24              ASTStatementExpression n = (ASTStatementExpression) node.getNthParent(5);
25  
26              if (isAssignmentToFinalField(n)) {
27                  return data;
28              }
29  
30              if (n.jjtGetNumChildren() > 2 && n.jjtGetChild(1) instanceof ASTAssignmentOperator) {
31                  addViolation(data, node);
32              }
33          } else if (node.getNthParent(4) instanceof ASTConditionalExpression) {
34              // "false" expression of ternary
35              if (isBadTernary((ASTConditionalExpression)node.getNthParent(4))) {
36                  addViolation(data, node);
37              }
38          } else if (node.getNthParent(5) instanceof ASTConditionalExpression && node.getNthParent(4) instanceof ASTExpression) {
39              // "true" expression of ternary
40              if (isBadTernary((ASTConditionalExpression)node.getNthParent(5))) {
41                  addViolation(data, node);
42              }
43          }
44  
45          return data;
46      }
47  
48      private boolean isAssignmentToFinalField(ASTStatementExpression n) {
49          ASTName name = n.getFirstChildOfType(ASTName.class);
50          return name != null
51                  && name.getNameDeclaration() instanceof VariableNameDeclaration
52                  && ((VariableNameDeclaration) name.getNameDeclaration()).getAccessNodeParent().isFinal();
53      }
54  
55      private boolean isBadTernary(ASTConditionalExpression n) {
56          return n.isTernary() && !(n.jjtGetChild(0) instanceof ASTEqualityExpression);
57      }
58  }