View Javadoc

    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  }