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
17
18
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
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
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 }