forked from phoedos/pmd
refactored type lookup functionality with a new TypeMap
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4703 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
@ -3,8 +3,6 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.rules.design;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.AbstractRule;
|
||||
import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.ast.ASTFieldDeclaration;
|
||||
@ -16,12 +14,12 @@ import net.sourceforge.pmd.util.CollectionUtil;
|
||||
public class LooseCoupling extends AbstractRule {
|
||||
|
||||
// TODO - these should be brought in via external properties
|
||||
private static final Set implClassNames = CollectionUtil.asSet( new Object[] {
|
||||
"ArrayList", "HashSet", "HashMap", "LinkedHashMap", "LinkedHashSet", "TreeSet", "TreeMap", "Vector",
|
||||
"java.util.ArrayList", "java.util.HashSet", "java.util.HashMap",
|
||||
"java.util.LinkedHashMap", "java.util.LinkedHashSet", "java.util.TreeSet",
|
||||
"java.util.TreeMap", "java.util.Vector"
|
||||
});
|
||||
// private static final Set implClassNames = CollectionUtil.asSet( new Object[] {
|
||||
// "ArrayList", "HashSet", "HashMap", "LinkedHashMap", "LinkedHashSet", "TreeSet", "TreeMap", "Vector",
|
||||
// "java.util.ArrayList", "java.util.HashSet", "java.util.HashMap",
|
||||
// "java.util.LinkedHashMap", "java.util.LinkedHashSet", "java.util.TreeSet",
|
||||
// "java.util.TreeMap", "java.util.Vector"
|
||||
// });
|
||||
|
||||
public LooseCoupling() {
|
||||
super();
|
||||
@ -29,8 +27,9 @@ public class LooseCoupling extends AbstractRule {
|
||||
|
||||
public Object visit(ASTClassOrInterfaceType node, Object data) {
|
||||
Node parent = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
||||
if (implClassNames.contains(node.getImage()) && (parent instanceof ASTFieldDeclaration || parent instanceof ASTFormalParameter || parent instanceof ASTResultType)) {
|
||||
addViolation(data, node, node.getImage());
|
||||
String typeName = node.getImage();
|
||||
if (CollectionUtil.isCollectionType(typeName, false) && (parent instanceof ASTFieldDeclaration || parent instanceof ASTFormalParameter || parent instanceof ASTResultType)) {
|
||||
addViolation(data, node, typeName);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.sourceforge.pmd.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
@ -13,39 +12,40 @@ public class ClassUtil {
|
||||
|
||||
private ClassUtil() {};
|
||||
|
||||
private static final Map primitiveTypesByName = CollectionUtil.mapFrom( new Object[][] {
|
||||
{"int", int.class },
|
||||
{"byte", byte.class },
|
||||
{"long", long.class },
|
||||
{"short", short.class },
|
||||
{"float", float.class },
|
||||
{"double", double.class },
|
||||
{"char", char.class },
|
||||
{"boolean", boolean.class },
|
||||
private static final TypeMap primitiveTypesByName = new TypeMap( new Class[] {
|
||||
int.class,
|
||||
byte.class,
|
||||
long.class,
|
||||
short.class,
|
||||
float.class,
|
||||
double.class,
|
||||
char.class,
|
||||
boolean.class,
|
||||
});
|
||||
|
||||
private static final Map typesByShortName = CollectionUtil.mapFrom( new Object[][] {
|
||||
{"Integer", Integer.class },
|
||||
{"Byte", Byte.class },
|
||||
{"Long", Long.class },
|
||||
{"Short", Short.class },
|
||||
{"Float", Float.class },
|
||||
{"Double", Double.class },
|
||||
{"Character", Character.class },
|
||||
{"Boolean", Boolean.class },
|
||||
{"BigDecimal", BigDecimal.class },
|
||||
{"String", String.class },
|
||||
{"Object", Object.class },
|
||||
{"Object[]", Object[].class }
|
||||
private static final TypeMap typesByNames = new TypeMap( new Class[] {
|
||||
Integer.class,
|
||||
Byte.class,
|
||||
Long.class,
|
||||
Short.class,
|
||||
Float.class,
|
||||
Double.class,
|
||||
Character.class,
|
||||
Boolean.class,
|
||||
BigDecimal.class,
|
||||
String.class,
|
||||
Object.class,
|
||||
});
|
||||
|
||||
/**
|
||||
* Method getPrimitiveTypeFor.
|
||||
* Returns the type(class) for the name specified
|
||||
* or null if not found.
|
||||
*
|
||||
* @param name String
|
||||
* @return Class
|
||||
*/
|
||||
public static Class getPrimitiveTypeFor(String name) {
|
||||
return (Class)primitiveTypesByName.get(name);
|
||||
return primitiveTypesByName.typeFor(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,13 +56,28 @@ public class ClassUtil {
|
||||
*/
|
||||
public static Class getTypeFor(String shortName) {
|
||||
|
||||
Class cls = (Class)typesByShortName.get(shortName);
|
||||
if (cls != null) return cls;
|
||||
Class type = typesByNames.typeFor(shortName);
|
||||
if (type != null) return type;
|
||||
|
||||
cls = (Class)primitiveTypesByName.get(shortName);
|
||||
if (cls != null) return cls;
|
||||
type = primitiveTypesByName.typeFor(shortName);
|
||||
if (type != null) return type;
|
||||
|
||||
return CollectionUtil.getCollectionTypeFor(shortName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the abbreviated name of the type,
|
||||
* without the package name
|
||||
*
|
||||
* @param fullTypeName
|
||||
* @return String
|
||||
*/
|
||||
|
||||
public static String withoutPackageName(String fullTypeName) {
|
||||
|
||||
int dotPos = fullTypeName.lastIndexOf('.');
|
||||
|
||||
return dotPos > 0 ?
|
||||
fullTypeName.substring(dotPos+1) :
|
||||
fullTypeName;
|
||||
}
|
||||
}
|
||||
|
@ -15,31 +15,56 @@ import java.util.Map.Entry;
|
||||
*/
|
||||
public class CollectionUtil {
|
||||
|
||||
public static final Map collectionTypesByShortName = mapFrom( new Object[][] {
|
||||
{"List", java.util.List.class },
|
||||
{"Collection", java.util.Collection.class },
|
||||
{"Map", java.util.Map.class },
|
||||
{"ArrayList", java.util.ArrayList.class },
|
||||
{"LinkedList", java.util.LinkedList.class },
|
||||
{"Vector", java.util.Vector.class },
|
||||
{"HashMap", java.util.HashMap.class },
|
||||
{"TreeMap", java.util.TreeMap.class },
|
||||
{"Set", java.util.Set.class },
|
||||
{"HashSet", java.util.HashSet.class }
|
||||
});
|
||||
public static final TypeMap collectionInterfacesByNames = new TypeMap( new Class[] {
|
||||
java.util.List.class,
|
||||
java.util.Collection.class,
|
||||
java.util.Map.class,
|
||||
java.util.Set.class,
|
||||
});
|
||||
|
||||
public static final TypeMap collectionClassesByNames = new TypeMap( new Class[] {
|
||||
java.util.ArrayList.class,
|
||||
java.util.LinkedList.class,
|
||||
java.util.Vector.class,
|
||||
java.util.HashMap.class,
|
||||
java.util.LinkedHashMap.class,
|
||||
java.util.TreeMap.class,
|
||||
java.util.TreeSet.class,
|
||||
java.util.HashSet.class,
|
||||
java.util.LinkedHashSet.class
|
||||
});
|
||||
|
||||
private CollectionUtil() {};
|
||||
|
||||
/**
|
||||
* Returns the collection type if we know it by its short name.
|
||||
* Returns the collection type if we recognize it by its short name.
|
||||
*
|
||||
* @param name String
|
||||
* @param shortName String
|
||||
* @return Class
|
||||
*/
|
||||
public static Class getCollectionTypeFor(String name) {
|
||||
return (Class)collectionTypesByShortName.get(name);
|
||||
public static Class getCollectionTypeFor(String shortName) {
|
||||
Class cls = collectionClassesByNames.typeFor(shortName);
|
||||
if (cls != null) return cls;
|
||||
|
||||
return collectionInterfacesByNames.typeFor(shortName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether we can identify the typeName as a java.util collection class
|
||||
* or interface as specified.
|
||||
*
|
||||
* @param typeName String
|
||||
* @param includeInterfaces boolean
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isCollectionType(String typeName, boolean includeInterfaces) {
|
||||
|
||||
if (collectionClassesByNames.contains(typeName)) return true;
|
||||
|
||||
return includeInterfaces && collectionInterfacesByNames.contains(typeName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the items as a populated set.
|
||||
*
|
||||
|
84
pmd/src/net/sourceforge/pmd/util/TypeMap.java
Normal file
84
pmd/src/net/sourceforge/pmd/util/TypeMap.java
Normal file
@ -0,0 +1,84 @@
|
||||
package net.sourceforge.pmd.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A specialized map that stores classes by both their full and short names.
|
||||
*
|
||||
* @author Brian Remedios
|
||||
*/
|
||||
public class TypeMap {
|
||||
|
||||
private Map typesByName;
|
||||
|
||||
/**
|
||||
* Constructor for TypeMap.
|
||||
* @param initialSize int
|
||||
*/
|
||||
public TypeMap(int initialSize) {
|
||||
typesByName = new HashMap(initialSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for TypeMap that takes in an initial set of types.
|
||||
*
|
||||
* @param types Class[]
|
||||
*/
|
||||
public TypeMap(Class[] types) {
|
||||
this(types.length);
|
||||
add(types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a type to the receiver and stores it keyed by both its full
|
||||
* and short names.
|
||||
*
|
||||
* @param type Class
|
||||
*/
|
||||
public void add(Class type) {
|
||||
typesByName.put(type.getName(), type);
|
||||
typesByName.put(ClassUtil.withoutPackageName(type.getName()), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the type is known to the receiver.
|
||||
*
|
||||
* @param type Class
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean contains(Class type) {
|
||||
return typesByName.containsValue(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the typeName is known to the receiver.
|
||||
*
|
||||
* @param typeName String
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean contains(String typeName) {
|
||||
return typesByName.containsKey(typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type for the typeName specified.
|
||||
*
|
||||
* @param typeName String
|
||||
* @return Class
|
||||
*/
|
||||
public Class typeFor(String typeName) {
|
||||
return (Class)typesByName.get(typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an array of types to the receiver at once.
|
||||
*
|
||||
* @param types Class[]
|
||||
*/
|
||||
public void add(Class[] types) {
|
||||
for (int i=0; i<types.length; i++) {
|
||||
add(types[i]);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user