1 package net.sourceforge.pmd.rules; 2 3 import net.sourceforge.pmd.AbstractRule; 4 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration; 5 import net.sourceforge.pmd.ast.ASTClassOrInterfaceType; 6 import net.sourceforge.pmd.ast.ASTFormalParameter; 7 import net.sourceforge.pmd.ast.ASTFormalParameters; 8 import net.sourceforge.pmd.ast.ASTImplementsList; 9 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 implementsComparable = 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 (!implementsComparable && (containsEquals ^ containsHashCode)) { 30 if(nodeFound == null){ 31 nodeFound = node; 32 } 33 addViolation(data, nodeFound); 34 } 35 implementsComparable = containsEquals = containsHashCode = false; 36 nodeFound = null; 37 return data; 38 } 39 40 public Object visit(ASTImplementsList node, Object data) { 41 for (int ix = 0; ix < node.jjtGetNumChildren(); ix++) { 42 if (node.jjtGetChild(ix).getClass().equals(ASTClassOrInterfaceType.class)) { 43 ASTClassOrInterfaceType cit = (ASTClassOrInterfaceType)node.jjtGetChild(ix); 44 Class clazz = cit.getType(); 45 if (clazz != null || ((SimpleNode) node.jjtGetChild(ix)).hasImageEqualTo("Comparable")) { 46 implementsComparable = true; 47 return data; 48 } 49 } 50 } 51 return super.visit(node, data); 52 } 53 54 public Object visit(ASTMethodDeclarator node, Object data) { 55 if (implementsComparable) { 56 return data; 57 } 58 59 int iFormalParams = 0; 60 String paramName = null; 61 for (int ix = 0; ix < node.jjtGetNumChildren(); ix++) { 62 SimpleNode sn = (SimpleNode) node.jjtGetChild(ix); 63 if (sn.getClass().equals(ASTFormalParameters.class)) { 64 List<ASTFormalParameter> allParams = ((ASTFormalParameters) sn).findChildrenOfType(ASTFormalParameter.class); 65 for (ASTFormalParameter formalParam: allParams) { 66 iFormalParams++; 67 ASTClassOrInterfaceType param = formalParam.getFirstChildOfType(ASTClassOrInterfaceType.class); 68 if (param != null) { 69 paramName = param.getImage(); 70 } 71 } 72 } 73 } 74 75 if (iFormalParams == 0 && node.hasImageEqualTo("hashCode")) { 76 containsHashCode = true; 77 nodeFound = node; 78 } else if (iFormalParams == 1 && node.hasImageEqualTo("equals") && ("Object".equals(paramName) || "java.lang.Object".equals(paramName))) { 79 containsEquals = true; 80 nodeFound = node; 81 } 82 return super.visit(node, data); 83 } 84 85 }