01: package net.sourceforge.pmd.rules;
02:
03: import net.sourceforge.pmd.AbstractRule;
04: import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
05: import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
06: import net.sourceforge.pmd.ast.ASTFormalParameter;
07: import net.sourceforge.pmd.ast.ASTFormalParameters;
08: import net.sourceforge.pmd.ast.ASTImplementsList;
09: import net.sourceforge.pmd.ast.ASTMethodDeclarator;
10: import net.sourceforge.pmd.ast.SimpleNode;
11:
12: import java.util.List;
13:
14: public class OverrideBothEqualsAndHashcode extends AbstractRule {
15:
16: private boolean implements Comparable = false;
17:
18: private boolean containsEquals = false;
19:
20: private boolean containsHashCode = false;
21:
22: private SimpleNode nodeFound = null;
23:
24: public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
25: if (node.isInterface()) {
26: return data;
27: }
28: super .visit(node, data);
29: if (!implements Comparable
30: && (containsEquals ^ containsHashCode)) {
31: if (nodeFound == null) {
32: nodeFound = node;
33: }
34: addViolation(data, nodeFound);
35: }
36: implements Comparable = containsEquals = containsHashCode = false;
37: nodeFound = null;
38: return data;
39: }
40:
41: public Object visit(ASTImplementsList node, Object data) {
42: for (int ix = 0; ix < node.jjtGetNumChildren(); ix++) {
43: if (node.jjtGetChild(ix).getClass().equals(
44: ASTClassOrInterfaceType.class)) {
45: ASTClassOrInterfaceType cit = (ASTClassOrInterfaceType) node
46: .jjtGetChild(ix);
47: Class clazz = cit.getType();
48: if (clazz != null
49: || ((SimpleNode) node.jjtGetChild(ix))
50: .hasImageEqualTo("Comparable")) {
51: implements Comparable = true;
52: return data;
53: }
54: }
55: }
56: return super .visit(node, data);
57: }
58:
59: public Object visit(ASTMethodDeclarator node, Object data) {
60: if (implements Comparable) {
61: return data;
62: }
63:
64: int iFormalParams = 0;
65: String paramName = null;
66: for (int ix = 0; ix < node.jjtGetNumChildren(); ix++) {
67: SimpleNode sn = (SimpleNode) node.jjtGetChild(ix);
68: if (sn.getClass().equals(ASTFormalParameters.class)) {
69: List<ASTFormalParameter> allParams = ((ASTFormalParameters) sn)
70: .findChildrenOfType(ASTFormalParameter.class);
71: for (ASTFormalParameter formalParam : allParams) {
72: iFormalParams++;
73: ASTClassOrInterfaceType param = formalParam
74: .getFirstChildOfType(ASTClassOrInterfaceType.class);
75: if (param != null) {
76: paramName = param.getImage();
77: }
78: }
79: }
80: }
81:
82: if (iFormalParams == 0 && node.hasImageEqualTo("hashCode")) {
83: containsHashCode = true;
84: nodeFound = node;
85: } else if (iFormalParams == 1
86: && node.hasImageEqualTo("equals")
87: && ("Object".equals(paramName) || "java.lang.Object"
88: .equals(paramName))) {
89: containsEquals = true;
90: nodeFound = node;
91: }
92: return super.visit(node, data);
93: }
94:
95: }
|