View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule.migrating;
5   
6   import java.util.HashSet;
7   import java.util.List;
8   import java.util.Set;
9   
10  import net.sourceforge.pmd.lang.ast.Node;
11  import net.sourceforge.pmd.lang.java.ast.ASTCastExpression;
12  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
13  import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
14  import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
15  import net.sourceforge.pmd.lang.java.ast.ASTName;
16  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
17  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
18  import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
19  
20  /**
21   * This is a rule, that detects unnecessary casts when using Java 1.5 generics and
22   * collections.
23   *
24   * <p>Example:
25   * <pre>
26   * List<Double> list = new ArrayList<Double>();
27   * ...
28   * Double d = (Double) list.get(0); //The cast is unnecessary on this typed array.
29   * </pre>
30   *
31   * @see <a href="http://sourceforge.net/p/pmd/discussion/188192/thread/276fd6f0">Java 5 rules: Unnecessary casts/Iterators</a>
32   */
33  //TODO This is not referenced by any RuleSet?
34  public class UnnecessaryCastRule extends AbstractJavaRule {
35  
36      private static Set<String> implClassNames = new HashSet<String>();
37  
38      static {
39          implClassNames.add("List");
40          implClassNames.add("Set");
41          implClassNames.add("Map");
42          implClassNames.add("java.util.List");
43          implClassNames.add("java.util.Set");
44          implClassNames.add("java.util.Map");
45          implClassNames.add("ArrayList");
46          implClassNames.add("HashSet");
47          implClassNames.add("HashMap");
48          implClassNames.add("LinkedHashMap");
49          implClassNames.add("LinkedHashSet");
50          implClassNames.add("TreeSet");
51          implClassNames.add("TreeMap");
52          implClassNames.add("Vector");
53          implClassNames.add("java.util.ArrayList");
54          implClassNames.add("java.util.HashSet");
55          implClassNames.add("java.util.HashMap");
56          implClassNames.add("java.util.LinkedHashMap");
57          implClassNames.add("java.util.LinkedHashSet");
58          implClassNames.add("java.util.TreeSet");
59          implClassNames.add("java.util.TreeMap");
60          implClassNames.add("java.util.Vector");
61      }
62  
63      @Override
64      public Object visit(ASTLocalVariableDeclaration node, Object data) {
65          return process(node, data);
66      }
67  
68      @Override
69      public Object visit(ASTFieldDeclaration node, Object data) {
70          return process(node, data);
71      }
72  
73      private Object process(Node node, Object data) {
74          ASTClassOrInterfaceType cit = node.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
75          if (cit == null || !implClassNames.contains(cit.getImage())) {
76              return data;
77          }
78          cit = cit.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
79          if (cit == null) {
80              return data;
81          }
82          ASTVariableDeclaratorId decl = node.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
83          List<NameOccurrence> usages = decl.getUsages();
84          for (NameOccurrence no: usages) {
85              ASTName name = (ASTName) no.getLocation();
86              Node n = name.jjtGetParent().jjtGetParent().jjtGetParent();
87              if (n instanceof ASTCastExpression) {
88                  addViolation(data, n);
89              }
90          }
91          return null;
92      }
93  }