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.ASTName;
11 import net.sourceforge.pmd.ast.ASTNullLiteral;
12 import net.sourceforge.pmd.ast.ASTStatementExpression;
13 import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
14
15
16
17
18 public class NullAssignmentRule extends AbstractRule {
19
20 public Object visit(ASTNullLiteral node, Object data) {
21
22 if (node.getNthParent(5) instanceof ASTStatementExpression) {
23 ASTStatementExpression n = (ASTStatementExpression) node.getNthParent(5);
24
25 if (isAssignmentToFinalField(n)) {
26 return data;
27 }
28
29 if (n.jjtGetNumChildren() > 2 && n.jjtGetChild(1) instanceof ASTAssignmentOperator) {
30 addViolation(data, node);
31 }
32 } else if (node.getNthParent(4) instanceof ASTConditionalExpression) {
33 if (isBadTernary((ASTConditionalExpression)node.getNthParent(4))) {
34 addViolation(data, node);
35 }
36 } else if (node.getNthParent(5) instanceof ASTConditionalExpression) {
37 if (isBadTernary((ASTConditionalExpression)node.getNthParent(5))) {
38 addViolation(data, node);
39 }
40 }
41
42 return data;
43 }
44
45 private boolean isAssignmentToFinalField(ASTStatementExpression n) {
46 ASTName name = n.getFirstChildOfType(ASTName.class);
47 return name != null
48 && name.getNameDeclaration() instanceof VariableNameDeclaration
49 && ((VariableNameDeclaration) name.getNameDeclaration()).getAccessNodeParent().isFinal();
50 }
51
52 private boolean isBadTernary(ASTConditionalExpression n) {
53 return n.isTernary() && !(n.jjtGetChild(0) instanceof ASTEqualityExpression);
54 }
55 }