1
2
3
4 package net.sourceforge.pmd.lang.java.rule.design;
5
6 import net.sourceforge.pmd.lang.ast.Node;
7 import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
8 import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
9 import net.sourceforge.pmd.lang.java.ast.ASTInitializer;
10 import net.sourceforge.pmd.lang.java.ast.ASTName;
11 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
12 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
13 import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
14 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
15 import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
16
17 public class CompareObjectsWithEqualsRule extends AbstractJavaRule {
18
19 private boolean hasName(Node n) {
20 return n.jjtGetNumChildren() > 0 && n.jjtGetChild(0) instanceof ASTName;
21 }
22
23
24
25
26
27
28
29
30 private boolean isAllocation(Node n) {
31 return n.jjtGetNumChildren() > 0 && n.jjtGetChild(0) instanceof ASTAllocationExpression
32 && n.jjtGetParent().jjtGetNumChildren() == 1;
33 }
34
35 public Object visit(ASTEqualityExpression node, Object data) {
36 Node c0 = node.jjtGetChild(0).jjtGetChild(0);
37 Node c1 = node.jjtGetChild(1).jjtGetChild(0);
38
39
40
41 if (isAllocation(c0) || isAllocation(c1)) {
42 addViolation(data, node);
43 return data;
44 }
45
46
47 if (!hasName(c0) || !hasName(c1)) {
48 return data;
49 }
50
51
52 if (isQualifiedName(c0.jjtGetChild(0)) || isQualifiedName(c1.jjtGetChild(0))) {
53 return data;
54 }
55
56
57 if (isPartOfQualifiedName(node.jjtGetChild(0)) || isPartOfQualifiedName(node.jjtGetChild(1))) {
58 return data;
59 }
60
61
62 if (!node.getParentsOfType(ASTInitializer.class).isEmpty()) {
63 return data;
64 }
65
66 ASTName n0 = (ASTName) c0.jjtGetChild(0);
67 ASTName n1 = (ASTName) c1.jjtGetChild(0);
68
69 if (n0.getNameDeclaration() instanceof VariableNameDeclaration
70 && n1.getNameDeclaration() instanceof VariableNameDeclaration) {
71 VariableNameDeclaration nd0 = (VariableNameDeclaration) n0.getNameDeclaration();
72 VariableNameDeclaration nd1 = (VariableNameDeclaration) n1.getNameDeclaration();
73
74
75
76 if (nd0.isArray() || nd1.isArray()) {
77 return data;
78 }
79
80 if (nd0.isReferenceType() && nd1.isReferenceType()) {
81 ASTReferenceType type0 = ((Node) nd0.getAccessNodeParent()).getFirstDescendantOfType(ASTReferenceType.class);
82 ASTReferenceType type1 = ((Node) nd1.getAccessNodeParent()).getFirstDescendantOfType(ASTReferenceType.class);
83
84 if (type0.getType() != null && type0.getType().equals(type1.getType()) && type0.getType().isEnum()) {
85 return data;
86 }
87
88 addViolation(data, node);
89 }
90 }
91
92 return data;
93 }
94
95
96
97
98
99
100
101
102
103 private boolean isPartOfQualifiedName(Node node) {
104 return node.jjtGetChild(0) instanceof ASTPrimaryPrefix
105 && !node.findChildrenOfType(ASTPrimarySuffix.class).isEmpty();
106 }
107 }