View Javadoc

1   package net.sourceforge.pmd.rules.design;
2   
3   import net.sourceforge.pmd.AbstractRule;
4   import net.sourceforge.pmd.ast.ASTEqualityExpression;
5   import net.sourceforge.pmd.ast.ASTInitializer;
6   import net.sourceforge.pmd.ast.ASTName;
7   import net.sourceforge.pmd.ast.Node;
8   import net.sourceforge.pmd.ast.SimpleNode;
9   import net.sourceforge.pmd.symboltable.NameOccurrence;
10  import net.sourceforge.pmd.symboltable.Scope;
11  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
12  
13  import java.util.Iterator;
14  import java.util.List;
15  import java.util.Map;
16  
17  public class CompareObjectsWithEquals extends AbstractRule {
18  
19      private boolean hasName(Node n) {
20          return n.jjtGetNumChildren() > 0 && n.jjtGetChild(0) instanceof ASTName;
21      }
22  
23      public Object visit(ASTEqualityExpression node, Object data) {
24          // skip if either child is not a simple name
25          if (!hasName(((SimpleNode)node.jjtGetChild(0)).jjtGetChild(0)) || !hasName(((SimpleNode)node.jjtGetChild(1)).jjtGetChild(0))) {
26              return data;
27          }
28  
29          // skip if either is a qualified name
30          if (((SimpleNode)node.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0)).getImage().indexOf(".") != -1
31          || ((SimpleNode)node.jjtGetChild(1).jjtGetChild(0).jjtGetChild(0)).getImage().indexOf(".") != -1) {
32              return data;
33          }
34  
35          // skip static initializers... missing some cases here
36          if (!node.getParentsOfType(ASTInitializer.class).isEmpty()) {
37              return data;
38          }
39  
40          check((Scope)node.getScope(), node, data);
41          check(node.getScope().getEnclosingMethodScope(), node, data);
42          return data;
43      }
44  
45      private void check(Scope scope, SimpleNode node, Object ctx) {
46          Map vars = scope.getVariableDeclarations();
47          for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
48              VariableNameDeclaration key = (VariableNameDeclaration)i.next();
49              if (key.isPrimitiveType() || key.isArray()) {
50                  continue;
51              }
52              List usages = (List)vars.get(key);
53              if (usages.isEmpty()) {
54                  continue;
55              }
56              for (Iterator j = usages.iterator(); j.hasNext();) {
57                  if (((NameOccurrence)j.next()).getLocation().jjtGetParent().jjtGetParent().jjtGetParent() == node) {
58                      addViolation(ctx, node);
59                      return;
60                  }
61              }
62          }
63      }
64  }