use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class BaseTypeVisitor method visitReturn.
/**
* Checks that the type of the return expression is a subtype of the enclosing method required
* return type. If not, it issues a "return.type.incompatible" error.
*/
@Override
public Void visitReturn(ReturnTree node, Void p) {
// Don't try to check return expressions for void methods.
if (node.getExpression() == null) {
return super.visitReturn(node, p);
}
Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
try {
Tree enclosing = TreeUtils.enclosingOfKind(getCurrentPath(), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)));
AnnotatedTypeMirror ret = null;
if (enclosing.getKind() == Tree.Kind.METHOD) {
MethodTree enclosingMethod = TreeUtils.enclosingMethod(getCurrentPath());
boolean valid = validateTypeOf(enclosing);
if (valid) {
ret = atypeFactory.getMethodReturnType(enclosingMethod, node);
}
} else {
Pair<AnnotatedDeclaredType, AnnotatedExecutableType> result = atypeFactory.getFnInterfaceFromTree((LambdaExpressionTree) enclosing);
ret = result.second.getReturnType();
}
if (ret != null) {
visitorState.setAssignmentContext(Pair.of((Tree) node, ret));
commonAssignmentCheck(ret, node.getExpression(), "return.type.incompatible");
}
return super.visitReturn(node, p);
} finally {
visitorState.setAssignmentContext(preAssCtxt);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class DefaultReflectionResolver method resolveMethodCall.
/**
* Resolves a call to {@link Method#invoke(Object, Object...)}.
*
* @param factory the {@link AnnotatedTypeFactory} of the underlying type system
* @param tree the method invocation tree that has to be resolved
* @param origResult the original result from {@code factory.methodFromUse}.
*/
private Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> resolveMethodCall(AnnotatedTypeFactory factory, MethodInvocationTree tree, Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> origResult) {
debugReflection("Try to resolve reflective method call: " + tree);
List<MethodInvocationTree> possibleMethods = resolveReflectiveMethod(tree, factory);
// Reflective method could not be resolved
if (possibleMethods.size() == 0) {
return origResult;
}
Set<? extends AnnotationMirror> returnLub = null;
Set<? extends AnnotationMirror> receiverGlb = null;
Set<? extends AnnotationMirror> paramsGlb = null;
// and parameter types
for (MethodInvocationTree resolvedTree : possibleMethods) {
debugReflection("Resolved method invocation: " + resolvedTree);
if (!checkMethodAgruments(resolvedTree)) {
debugReflection("Spoofed tree's arguments did not match declaration" + resolvedTree.toString());
// in QualifierPolymorphism.PolyCollector.visitArray(...)
continue;
}
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> resolvedResult = factory.methodFromUse(resolvedTree);
// Lub return types
returnLub = lub(returnLub, resolvedResult.first.getReturnType().getAnnotations(), factory);
// Check for static methods whose receiver is null
if (resolvedResult.first.getReceiverType() == null) {
// If the method is static the first argument to Method.invoke isn't used,
// so assume top.
receiverGlb = glb(receiverGlb, factory.getQualifierHierarchy().getTopAnnotations(), factory);
} else {
receiverGlb = glb(receiverGlb, resolvedResult.first.getReceiverType().getAnnotations(), factory);
}
// the types of different formal parameters.
for (AnnotatedTypeMirror mirror : resolvedResult.first.getParameterTypes()) {
paramsGlb = glb(paramsGlb, mirror.getAnnotations(), factory);
}
}
if (returnLub == null) {
// None of the spoofed tree's arguments matched the declared method
return origResult;
}
/*
* Clear all original (return, receiver, parameter type) annotations and
* set lub/glb annotations from resolved method(s)
*/
// return value
origResult.first.getReturnType().clearAnnotations();
origResult.first.getReturnType().addAnnotations(returnLub);
// receiver type
origResult.first.getParameterTypes().get(0).clearAnnotations();
origResult.first.getParameterTypes().get(0).addAnnotations(receiverGlb);
// parameter types
if (paramsGlb != null) {
AnnotatedArrayType origArrayType = (AnnotatedArrayType) origResult.first.getParameterTypes().get(1);
origArrayType.getComponentType().clearAnnotations();
origArrayType.getComponentType().addAnnotations(paramsGlb);
}
debugReflection("Resolved annotations: " + origResult.first);
return origResult;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class SyntheticArrays method replaceReturnType.
/**
* @param methodElem identifies a method that should have an AnnotatedArrayType as its return
* type
* @param newReturnType identifies a type that should replace methodElem's return type
* @return the annotated type of methodElem with its return type replaced by newReturnType
*/
public static AnnotatedExecutableType replaceReturnType(final Element methodElem, final AnnotatedArrayType newReturnType) {
final AnnotatedExecutableType method = (AnnotatedExecutableType) newReturnType.atypeFactory.getAnnotatedType(methodElem);
method.returnType = newReturnType;
return method;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class TypeFromExpressionVisitor method visitNewClass.
/**
* Creates an AnnotatedDeclaredType for the NewClassTree and adds, for each hierarchy, one of:
*
* <ul>
* <li>an explicit annotation on the new class expression ({@code new @HERE MyClass()}), or
* <li>an explicit annotation on the declaration of the class ({@code @HERE class MyClass
* {}}), or
* <li>an explicit annotation on the declaration of the constructor ({@code @HERE public
* MyClass() {}}), or
* <li>no annotation for this hierarchy.
* </ul>
*
* @param node NewClassTree
* @param f the type factory
* @return AnnotatedDeclaredType of {@code node}
*/
@Override
public AnnotatedTypeMirror visitNewClass(NewClassTree node, AnnotatedTypeFactory f) {
// constructorFromUse return type has implicits
// so use fromNewClass which does diamond inference and only
// contains explicit annotations and those inherited from the class declaration
AnnotatedDeclaredType type = f.fromNewClass(node);
// TODO: is there more to check? Can one annotate them?
if (isNewEnum(type)) {
return type;
}
// Add annotations that are on the constructor declaration.
// constructorFromUse gives us resolution of polymorphic qualifiers.
// However, it also applies defaulting, so we might apply too many qualifiers.
// Therefore, ensure to only add the qualifiers that are explicitly on
// the constructor, but then take the possibly substituted qualifier.
AnnotatedExecutableType ex = f.constructorFromUse(node).first;
AnnotatedTypes.copyOnlyExplicitConstructorAnnotations(f, type, ex);
return type;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType in project checker-framework by typetools.
the class AnnotatedTypeComparer method visitExecutable.
@Override
public final R visitExecutable(AnnotatedExecutableType type, AnnotatedTypeMirror p) {
assert p instanceof AnnotatedExecutableType : p;
AnnotatedExecutableType ex = (AnnotatedExecutableType) p;
R r = scan(type.getReturnType(), ex.getReturnType());
if (type.getReceiverType() != null) {
r = scanAndReduce(type.getReceiverType(), ex.getReceiverType(), r);
}
r = scanAndReduce(type.getParameterTypes(), ex.getParameterTypes(), r);
r = scanAndReduce(type.getThrownTypes(), ex.getThrownTypes(), r);
r = scanAndReduce(type.getTypeVariables(), ex.getTypeVariables(), r);
return r;
}
Aggregations