/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.migrating; import java.util.HashSet; import java.util.List; import java.util.Set; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; /** * This is a rule, that detects unnecessary casts when using Java 1.5 generics * and collections. * * <p>Example:</p> * * <pre> * List<Double> list = new ArrayList<Double>(); * ... * Double d = (Double) list.get(0); //The cast is unnecessary on this typed array. * </pre> * * @see <a href= * "http://sourceforge.net/p/pmd/discussion/188192/thread/276fd6f0">Java 5 * rules: Unnecessary casts/Iterators</a> */ // TODO This is not referenced by any RuleSet? public class UnnecessaryCastRule extends AbstractJavaRule { private static Set<String> implClassNames = new HashSet<>(); static { implClassNames.add("List"); implClassNames.add("Set"); implClassNames.add("Map"); implClassNames.add("java.util.List"); implClassNames.add("java.util.Set"); implClassNames.add("java.util.Map"); implClassNames.add("ArrayList"); implClassNames.add("HashSet"); implClassNames.add("HashMap"); implClassNames.add("LinkedHashMap"); implClassNames.add("LinkedHashSet"); implClassNames.add("TreeSet"); implClassNames.add("TreeMap"); implClassNames.add("Vector"); implClassNames.add("java.util.ArrayList"); implClassNames.add("java.util.HashSet"); implClassNames.add("java.util.HashMap"); implClassNames.add("java.util.LinkedHashMap"); implClassNames.add("java.util.LinkedHashSet"); implClassNames.add("java.util.TreeSet"); implClassNames.add("java.util.TreeMap"); implClassNames.add("java.util.Vector"); } @Override public Object visit(ASTLocalVariableDeclaration node, Object data) { return process(node, data); } @Override public Object visit(ASTFieldDeclaration node, Object data) { return process(node, data); } private Object process(Node node, Object data) { ASTClassOrInterfaceType cit = node.getFirstDescendantOfType(ASTClassOrInterfaceType.class); if (cit == null || !implClassNames.contains(cit.getImage())) { return data; } cit = cit.getFirstDescendantOfType(ASTClassOrInterfaceType.class); if (cit == null) { return data; } ASTVariableDeclaratorId decl = node.getFirstDescendantOfType(ASTVariableDeclaratorId.class); List<NameOccurrence> usages = decl.getUsages(); for (NameOccurrence no : usages) { ASTName name = (ASTName) no.getLocation(); Node n = name.jjtGetParent().jjtGetParent().jjtGetParent(); if (n instanceof ASTCastExpression) { addViolation(data, n); } } return null; } }