use of net.sourceforge.pmd.lang.java.ast.ASTTypeParameter in project pmd by pmd.
the class ClassScope method resolveGenericType.
/**
* Tries to resolve a given typeImage as a generic Type. If the Generic Type
* is found, any defined ClassOrInterfaceType below this type declaration is
* used (this is typically a type bound, e.g. {@code <T extends List>}.
*
* @param argument
* the node, from where to start searching.
* @param typeImage
* the type as string
* @return the resolved class or <code>null</code> if nothing was found.
*/
private Class<?> resolveGenericType(Node argument, String typeImage) {
List<ASTTypeParameter> types = new ArrayList<>();
// first search only within the same method
ASTClassOrInterfaceBodyDeclaration firstParentOfType = argument.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class);
if (firstParentOfType != null) {
types.addAll(firstParentOfType.findDescendantsOfType(ASTTypeParameter.class));
}
// then search class level types, from inner-most to outer-most
List<ASTClassOrInterfaceDeclaration> enclosingClasses = argument.getParentsOfType(ASTClassOrInterfaceDeclaration.class);
for (ASTClassOrInterfaceDeclaration enclosing : enclosingClasses) {
ASTTypeParameters classLevelTypeParameters = enclosing.getFirstChildOfType(ASTTypeParameters.class);
if (classLevelTypeParameters != null) {
types.addAll(classLevelTypeParameters.findDescendantsOfType(ASTTypeParameter.class));
}
}
return resolveGenericType(typeImage, types);
}
use of net.sourceforge.pmd.lang.java.ast.ASTTypeParameter in project pmd by pmd.
the class ClassTypeResolver method populateType.
private void populateType(TypeNode node, String className, int arrayDimens) {
String qualifiedName = className;
Class<?> myType = PRIMITIVE_TYPES.get(className);
if (myType == null && importedClasses != null) {
if (importedClasses.containsKey(className)) {
qualifiedName = importedClasses.get(className);
} else if (importedClasses.containsValue(className)) {
qualifiedName = className;
}
if (qualifiedName != null) {
try {
/*
* TODO - the map right now contains just class names. if we
* use a map of classname/class then we don't have to hit
* the class loader for every type - much faster
*/
myType = pmdClassLoader.loadClass(qualifiedName);
} catch (ClassNotFoundException e) {
myType = processOnDemand(qualifiedName);
} catch (LinkageError e) {
myType = processOnDemand(qualifiedName);
}
}
}
if (myType == null && qualifiedName != null && qualifiedName.contains(".")) {
// try if the last part defines a inner class
String qualifiedNameInner = qualifiedName.substring(0, qualifiedName.lastIndexOf('.')) + "$" + qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
try {
myType = pmdClassLoader.loadClass(qualifiedNameInner);
} catch (Exception ignored) {
// ignored, we'll try again with a different package name/fqcn
}
}
if (myType == null && qualifiedName != null && !qualifiedName.contains(".")) {
// try again with java.lang....
try {
myType = pmdClassLoader.loadClass("java.lang." + qualifiedName);
} catch (Exception ignored) {
// ignored, we'll try again with generics
}
}
// TODO: generic declarations can shadow type declarations ... :(
if (myType == null) {
ASTTypeParameter parameter = getTypeParameterDeclaration(node, className);
if (parameter != null) {
node.setTypeDefinition(parameter.getTypeDefinition());
}
} else {
if (arrayDimens > 0) {
myType = Array.newInstance(myType, (int[]) Array.newInstance(int.class, arrayDimens)).getClass();
}
node.setType(myType);
}
}
Aggregations