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