NullAssignmentRule.java
01 /**
02  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03  */
04 package net.sourceforge.pmd.lang.java.rule.controversial;
05 
06 import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
07 import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
08 import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
09 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(5instanceof ASTStatementExpression) {
25             ASTStatementExpression n = (ASTStatementExpressionnode.getNthParent(5);
26 
27             if (isAssignmentToFinalField(n)) {
28                 return data;
29             }
30 
31             if (n.jjtGetNumChildren() && n.jjtGetChild(1instanceof ASTAssignmentOperator) {
32                 addViolation(data, node);
33             }
34         else if (node.getNthParent(4instanceof ASTConditionalExpression) {
35             // "false" expression of ternary
36             if (isBadTernary((ASTConditionalExpression)node.getNthParent(4))) {
37                 addViolation(data, node);
38             }
39         else if (node.getNthParent(5instanceof ASTConditionalExpression && node.getNthParent(4instanceof 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                 && ((VariableNameDeclarationname.getNameDeclaration()).getAccessNodeParent().isFinal();
54     }
55 
56     private boolean isBadTernary(ASTConditionalExpression n) {
57         return n.isTernary() && !(n.jjtGetChild(0instanceof ASTEqualityExpression);
58     }
59 }