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(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 }
|