use of net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition in project pmd by pmd.
the class MethodTypeResolution method getTypeDefOfMethod.
public static MethodType getTypeDefOfMethod(JavaTypeDefinition context, Method method, List<JavaTypeDefinition> typeArguments) {
if (typeArguments.isEmpty() && isGeneric(method)) {
return MethodType.build(method);
}
JavaTypeDefinition returnType = context.resolveTypeDefinition(method.getGenericReturnType(), method, typeArguments);
List<JavaTypeDefinition> argTypes = new ArrayList<>();
for (Type argType : method.getGenericParameterTypes()) {
argTypes.add(context.resolveTypeDefinition(argType, method, typeArguments));
}
return MethodType.build(returnType, argTypes, method);
}
use of net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition in project pmd by pmd.
the class TypeInferenceResolver method lub.
public static JavaTypeDefinition lub(List<JavaTypeDefinition> types) {
for (JavaTypeDefinition type : types) {
if (type.isArrayType()) {
// TODO: add support for array types
return JavaTypeDefinition.forClass(Object.class);
}
}
// step 1 - EC
Set<Class<?>> erasedCandidateSet = getErasedCandidateSet(types);
// step 2 - MEC
Set<Class<?>> minimalSet = getMinimalErasedCandidateSet(erasedCandidateSet);
List<JavaTypeDefinition> candidates = new ArrayList<>();
// for each element G n MEC
for (Class<?> erasedSupertype : minimalSet) {
JavaTypeDefinition lci = types.get(0).getAsSuper(erasedSupertype);
for (JavaTypeDefinition type : types) {
if (lci == null) {
throw new ResolutionFailedException();
}
lci = intersect(lci, type.getAsSuper(erasedSupertype));
}
candidates.add(lci);
}
if (candidates.isEmpty()) {
throw new ResolutionFailedException();
}
JavaTypeDefinition result = candidates.get(0);
for (JavaTypeDefinition candidate : candidates) {
if (MethodTypeResolution.isSubtypeable(candidate, result)) {
result = candidate;
} else if (!MethodTypeResolution.isSubtypeable(result, candidate)) {
// TODO: add support for compound types
throw new ResolutionFailedException();
}
// else: result contains candidate, nothing else to do
}
return result;
}
use of net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition in project pmd by pmd.
the class ClassTypeResolver method visit.
@Override
public Object visit(ASTName node, Object data) {
Class<?> accessingClass = getEnclosingTypeDeclarationClass(node);
String[] dotSplitImage = node.getImage().split("\\.");
int startIndex = searchNodeNameForClass(node);
ASTArguments astArguments = getSuffixMethodArgs(node);
ASTArgumentList astArgumentList = getArgumentList(astArguments);
int methodArgsArity = getArgumentListArity(astArgumentList);
JavaTypeDefinition previousType;
if (node.getType() != null) {
// static field or method
// node.getType() has been set by the call to searchNodeNameForClass above
// node.getType() will have the value equal to the Class found by that method
previousType = node.getTypeDefinition();
} else {
// non-static field or method
if (dotSplitImage.length == 1 && astArguments != null) {
// method
List<MethodType> methods = getLocalApplicableMethods(node, dotSplitImage[0], Collections.<JavaTypeDefinition>emptyList(), methodArgsArity, accessingClass);
TypeNode enclosingType = getEnclosingTypeDeclaration(node);
if (enclosingType == null) {
// we can't proceed, probably uncompiled sources
return data;
}
previousType = getBestMethodReturnType(enclosingType.getTypeDefinition(), methods, astArgumentList);
} else {
// field
previousType = getTypeDefinitionOfVariableFromScope(node.getScope(), dotSplitImage[0], accessingClass);
}
// first element's type in dotSplitImage has already been resolved
startIndex = 1;
}
// as the code is not compiled there and symbol table works on uncompiled code
if (node.getNameDeclaration() != null && // if it's not null, then let other code handle things
previousType == null && node.getNameDeclaration().getNode() instanceof TypeNode) {
// Carry over the type from the declaration
Class<?> nodeType = ((TypeNode) node.getNameDeclaration().getNode()).getType();
// FIXME : generic classes and class with generic super types could have the wrong type assigned here
if (nodeType != null) {
node.setType(nodeType);
return super.visit(node, data);
}
}
for (int i = startIndex; i < dotSplitImage.length; ++i) {
if (previousType == null) {
break;
}
if (i == dotSplitImage.length - 1 && astArguments != null) {
// method
List<MethodType> methods = getApplicableMethods(previousType, dotSplitImage[i], Collections.<JavaTypeDefinition>emptyList(), methodArgsArity, accessingClass);
previousType = getBestMethodReturnType(previousType, methods, astArgumentList);
} else {
// field
previousType = getFieldType(previousType, dotSplitImage[i], accessingClass);
}
}
if (previousType != null) {
node.setTypeDefinition(previousType);
}
return super.visit(node, data);
}
use of net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition in project pmd by pmd.
the class ClassTypeResolver method visit.
@Override
public Object visit(ASTPrimaryExpression primaryNode, Object data) {
// visit method arguments in reverse
for (int i = primaryNode.jjtGetNumChildren() - 1; i >= 0; --i) {
((JavaNode) primaryNode.jjtGetChild(i)).jjtAccept(this, data);
}
JavaTypeDefinition primaryNodeType = null;
AbstractJavaTypeNode previousChild = null;
AbstractJavaTypeNode nextChild;
Class<?> accessingClass = getEnclosingTypeDeclarationClass(primaryNode);
for (int childIndex = 0; childIndex < primaryNode.jjtGetNumChildren(); ++childIndex) {
AbstractJavaTypeNode currentChild = (AbstractJavaTypeNode) primaryNode.jjtGetChild(childIndex);
nextChild = childIndex + 1 < primaryNode.jjtGetNumChildren() ? (AbstractJavaTypeNode) primaryNode.jjtGetChild(childIndex + 1) : null;
// skip children which already have their type assigned
if (currentChild.getType() == null) {
// Last token, because if 'this' is a Suffix, it'll have tokens '.' and 'this'
if (currentChild.jjtGetLastToken().toString().equals("this")) {
if (previousChild != null) {
// Qualified 'this' expression
currentChild.setTypeDefinition(previousChild.getTypeDefinition());
} else {
// simple 'this' expression
ASTClassOrInterfaceDeclaration typeDeclaration = currentChild.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
if (typeDeclaration != null) {
currentChild.setTypeDefinition(typeDeclaration.getTypeDefinition());
}
}
// Last token, because if 'super' is a Suffix, it'll have tokens '.' and 'super'
} else if (currentChild.jjtGetLastToken().toString().equals("super")) {
if (previousChild != null) {
// Qualified 'super' expression
// anonymous classes can't have qualified super expression, thus
// getSuperClassTypeDefinition's second argumet isn't null, but we are not
// looking for enclosing super types
currentChild.setTypeDefinition(getSuperClassTypeDefinition(currentChild, previousChild.getType()));
} else {
// simple 'super' expression
currentChild.setTypeDefinition(getSuperClassTypeDefinition(currentChild, null));
}
} else if (currentChild.getFirstChildOfType(ASTArguments.class) != null) {
currentChild.setTypeDefinition(previousChild.getTypeDefinition());
} else if (previousChild != null && previousChild.getType() != null) {
String currentChildImage = currentChild.getImage();
if (currentChildImage == null) {
// this.<Something>foo(); <Something>foo would be in a Suffix and would have a null image
currentChildImage = currentChild.jjtGetLastToken().toString();
}
ASTArguments astArguments = nextChild != null ? nextChild.getFirstChildOfType(ASTArguments.class) : null;
if (astArguments != null) {
// method
ASTArgumentList astArgumentList = getArgumentList(astArguments);
int methodArgsArity = getArgumentListArity(astArgumentList);
List<JavaTypeDefinition> typeArguments = getMethodExplicitTypeArugments(currentChild);
List<MethodType> methods = getApplicableMethods(previousChild.getTypeDefinition(), currentChildImage, typeArguments, methodArgsArity, accessingClass);
currentChild.setTypeDefinition(getBestMethodReturnType(previousChild.getTypeDefinition(), methods, astArgumentList));
} else {
// field
currentChild.setTypeDefinition(getFieldType(previousChild.getTypeDefinition(), currentChildImage, accessingClass));
}
}
}
if (currentChild.getType() != null) {
primaryNodeType = currentChild.getTypeDefinition();
} else {
// avoid falsely passing tests
primaryNodeType = null;
break;
}
previousChild = currentChild;
}
primaryNode.setTypeDefinition(primaryNodeType);
return data;
}
use of net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition in project pmd by pmd.
the class ClassTypeResolver method searchImportedStaticMethods.
private List<MethodType> searchImportedStaticMethods(String methodName, List<JavaTypeDefinition> typeArguments, int argArity, Class<?> accessingClass) {
List<MethodType> foundMethods = new ArrayList<>();
// TODO: member methods must not be looked at in the code below
// TODO: add support for properly dealing with shadowing
List<JavaTypeDefinition> explicitImports = staticNamesToClasses.get(methodName);
if (explicitImports != null) {
for (JavaTypeDefinition anImport : explicitImports) {
foundMethods.addAll(getApplicableMethods(anImport, methodName, typeArguments, argArity, accessingClass));
}
}
if (!foundMethods.isEmpty()) {
// explicit imports shadow them by name, regardless of method parameters
return foundMethods;
}
for (JavaTypeDefinition anOnDemandImport : importOnDemandStaticClasses) {
foundMethods.addAll(getApplicableMethods(anOnDemandImport, methodName, typeArguments, argArity, accessingClass));
}
return foundMethods;
}
Aggregations