use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AnnotatedTypeFactory method getBoxedType.
/**
* Returns the annotated boxed type of the given primitive type. The returned type would only
* have the annotations on the given type.
*
* <p>Subclasses may override this method safely to override this behavior.
*
* @param type the primitive type
* @return the boxed declared type of the passed primitive type
*/
public AnnotatedDeclaredType getBoxedType(AnnotatedPrimitiveType type) {
TypeElement typeElt = types.boxedClass(type.getUnderlyingType());
AnnotatedDeclaredType dt = fromElement(typeElt);
dt.addAnnotations(type.getAnnotations());
return dt;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AnnotatedTypeFactory method fromNewClass.
/**
* Creates an AnnotatedDeclaredType for a NewClassTree. Adds explicit annotations and
* annotations inherited from class declarations {@link
* #annotateInheritedFromClass(AnnotatedTypeMirror)}.
*
* <p>If the NewClassTree has type arguments, then any explicit (or inherited from class)
* annotations on those type arguments are included. If the NewClassTree has a diamond operator,
* then the annotations on the type arguments are inferred using the assignment context.
*
* <p>(Subclass beside {@link GenericAnnotatedTypeFactory} should not override this method.)
*
* @param newClassTree NewClassTree
* @return AnnotatedDeclaredType
*/
public AnnotatedDeclaredType fromNewClass(NewClassTree newClassTree) {
if (TreeUtils.isDiamondTree(newClassTree)) {
AnnotatedDeclaredType type = (AnnotatedDeclaredType) toAnnotatedType(TreeUtils.typeOf(newClassTree), false);
if (((com.sun.tools.javac.code.Type) type.actualType).tsym.getTypeParameters().nonEmpty()) {
Pair<Tree, AnnotatedTypeMirror> ctx = this.visitorState.getAssignmentContext();
if (ctx != null) {
AnnotatedTypeMirror ctxtype = ctx.second;
fromNewClassContextHelper(type, ctxtype);
}
}
return type;
} else if (newClassTree.getClassBody() != null) {
AnnotatedDeclaredType type = (AnnotatedDeclaredType) toAnnotatedType(TreeUtils.typeOf(newClassTree), false);
// If newClassTree creates an anonymous class, then annotations in this location:
// new @HERE Class() {}
// are on not on the identifier newClassTree, but rather on the modifier newClassTree.
List<? extends AnnotationTree> annos = newClassTree.getClassBody().getModifiers().getAnnotations();
type.addAnnotations(TreeUtils.annotationsFromTypeAnnotationTrees(annos));
return type;
} else {
// new @HERE Class()
return (AnnotatedDeclaredType) fromTypeTree(newClassTree.getIdentifier());
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AnnotatedTypeFactory method getFunctionalInterfaceType.
/**
* Get the AnnotatedDeclaredType for the FunctionalInterface from assignment context of the
* method reference or lambda expression which may be a variable assignment, a method call, or a
* cast.
*
* <p>The assignment context is not always correct, so we must search up the AST. It will
* recursively search for lambdas nested in lambdas.
*
* @param tree the tree of the lambda or method reference
* @return the functional interface type
*/
private AnnotatedDeclaredType getFunctionalInterfaceType(Tree tree) {
Tree parentTree = getPath(tree).getParentPath().getLeaf();
switch(parentTree.getKind()) {
case PARENTHESIZED:
return getFunctionalInterfaceType(parentTree);
case TYPE_CAST:
TypeCastTree cast = (TypeCastTree) parentTree;
assert isFunctionalInterface(trees.getTypeMirror(getPath(cast.getType())), parentTree, tree);
AnnotatedTypeMirror castATM = getAnnotatedType(cast.getType());
if (castATM.getKind() == TypeKind.INTERSECTION) {
AnnotatedIntersectionType itype = (AnnotatedIntersectionType) castATM;
for (AnnotatedTypeMirror t : itype.directSuperTypes()) {
if (TypesUtils.isFunctionalInterface(t.getUnderlyingType(), getProcessingEnv())) {
return (AnnotatedDeclaredType) t;
}
}
// We should never reach here: isFunctionalInterface performs the same check
// and would have raised an error already.
ErrorReporter.errorAbort(String.format("Expected the type of a cast tree in an assignment context to contain a functional interface bound. " + "Found type: %s for tree: %s in lambda tree: %s", castATM, cast, tree));
}
return (AnnotatedDeclaredType) castATM;
case NEW_CLASS:
NewClassTree newClass = (NewClassTree) parentTree;
int indexOfLambda = newClass.getArguments().indexOf(tree);
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> con = this.constructorFromUse(newClass);
AnnotatedTypeMirror constructorParam = AnnotatedTypes.getAnnotatedTypeMirrorOfParameter(con.first, indexOfLambda);
assert isFunctionalInterface(constructorParam.getUnderlyingType(), parentTree, tree);
return (AnnotatedDeclaredType) constructorParam;
case NEW_ARRAY:
NewArrayTree newArray = (NewArrayTree) parentTree;
AnnotatedArrayType newArrayATM = getAnnotatedType(newArray);
AnnotatedTypeMirror elementATM = newArrayATM.getComponentType();
assert isFunctionalInterface(elementATM.getUnderlyingType(), parentTree, tree);
return (AnnotatedDeclaredType) elementATM;
case METHOD_INVOCATION:
MethodInvocationTree method = (MethodInvocationTree) parentTree;
int index = method.getArguments().indexOf(tree);
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> exe = this.methodFromUse(method);
AnnotatedTypeMirror param = AnnotatedTypes.getAnnotatedTypeMirrorOfParameter(exe.first, index);
if (param.getKind() == TypeKind.WILDCARD) {
// param is an uninferred wildcard.
TypeMirror typeMirror = TreeUtils.typeOf(tree);
param = AnnotatedTypeMirror.createType(typeMirror, this, false);
addDefaultAnnotations(param);
}
assert isFunctionalInterface(param.getUnderlyingType(), parentTree, tree);
return (AnnotatedDeclaredType) param;
case VARIABLE:
VariableTree varTree = (VariableTree) parentTree;
assert isFunctionalInterface(TreeUtils.typeOf(varTree), parentTree, tree);
return (AnnotatedDeclaredType) getAnnotatedType(varTree.getType());
case ASSIGNMENT:
AssignmentTree assignmentTree = (AssignmentTree) parentTree;
assert isFunctionalInterface(TreeUtils.typeOf(assignmentTree), parentTree, tree);
return (AnnotatedDeclaredType) getAnnotatedType(assignmentTree.getVariable());
case RETURN:
Tree enclosing = TreeUtils.enclosingOfKind(getPath(parentTree), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)));
if (enclosing.getKind() == Tree.Kind.METHOD) {
MethodTree enclosingMethod = (MethodTree) enclosing;
return (AnnotatedDeclaredType) getAnnotatedType(enclosingMethod.getReturnType());
} else {
LambdaExpressionTree enclosingLambda = (LambdaExpressionTree) enclosing;
Pair<AnnotatedDeclaredType, AnnotatedExecutableType> result = getFnInterfaceFromTree(enclosingLambda);
AnnotatedExecutableType methodExe = result.second;
return (AnnotatedDeclaredType) methodExe.getReturnType();
}
case LAMBDA_EXPRESSION:
LambdaExpressionTree enclosingLambda = (LambdaExpressionTree) parentTree;
Pair<AnnotatedDeclaredType, AnnotatedExecutableType> result = getFnInterfaceFromTree(enclosingLambda);
AnnotatedExecutableType methodExe = result.second;
return (AnnotatedDeclaredType) methodExe.getReturnType();
case CONDITIONAL_EXPRESSION:
ConditionalExpressionTree conditionalExpressionTree = (ConditionalExpressionTree) parentTree;
final AnnotatedTypeMirror falseType = getAnnotatedType(conditionalExpressionTree.getFalseExpression());
final AnnotatedTypeMirror trueType = getAnnotatedType(conditionalExpressionTree.getTrueExpression());
// Known cases where we must use LUB because falseType/trueType will not be equal:
// a) when one of the types is a type variable that extends a functional interface
// or extends a type variable that extends a functional interface
// b) When one of the two sides of the expression is a reference to a sub-interface.
// e.g. interface ConsumeStr {
// public void consume(String s)
// }
// interface SubConsumer extends ConsumeStr {
// default void someOtherMethod() { ... }
// }
// SubConsumer s = ...;
// ConsumeStr stringConsumer = (someCondition) ? s : System.out::println;
AnnotatedTypeMirror conditionalType = AnnotatedTypes.leastUpperBound(this, trueType, falseType);
assert isFunctionalInterface(conditionalType.getUnderlyingType(), parentTree, tree);
return (AnnotatedDeclaredType) conditionalType;
default:
ErrorReporter.errorAbort("Could not find functional interface from assignment context. " + "Unexpected tree type: " + parentTree.getKind() + " For lambda tree: " + tree);
return null;
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AnnotatedTypeFactory method getImplicitReceiverType.
// **********************************************************************
// Utilities method for getting specific types from trees or elements
// **********************************************************************
/**
* Return the implicit receiver type of an expression tree.
*
* <p>The result is null for expressions that don't have a receiver, e.g. for a local variable
* or method parameter access.
*
* @param tree the expression that might have an implicit receiver
* @return the type of the receiver
*/
/*
* TODO: receiver annotations on outer this.
* TODO: Better document the difference between getImplicitReceiverType and getSelfType?
* TODO: this method assumes that the tree is within the current
* Compilation Unit. This assumption fails in testcase Bug109_A/B, where
* a chain of dependencies leads into a different compilation unit.
* I didn't find a way how to handle this better and conservatively
* return null. See TODO comment below.
*
*/
protected AnnotatedDeclaredType getImplicitReceiverType(ExpressionTree tree) {
assert (tree.getKind() == Tree.Kind.IDENTIFIER || tree.getKind() == Tree.Kind.MEMBER_SELECT || tree.getKind() == Tree.Kind.METHOD_INVOCATION || tree.getKind() == Tree.Kind.NEW_CLASS) : "Unexpected tree kind: " + tree.getKind();
Element element = TreeUtils.elementFromTree(tree);
assert element != null : "Unexpected null element for tree: " + tree;
// Return null if the element kind has no receiver.
if (!ElementUtils.hasReceiver(element)) {
return null;
}
ExpressionTree receiver = TreeUtils.getReceiverTree(tree);
if (receiver == null) {
if (isMostEnclosingThisDeref(tree)) {
// TODO: is this fixed?
return getSelfType(tree);
} else {
TreePath path = getPath(tree);
if (path == null) {
// This only arises in the Nullness Checker when substituting rawness.
return null;
}
TypeElement typeElt = ElementUtils.enclosingClass(element);
if (typeElt == null) {
ErrorReporter.errorAbort("AnnotatedTypeFactory.getImplicitReceiver: enclosingClass()==null for element: " + element);
}
// TODO: method receiver annotations on outer this
return getEnclosingType(typeElt, tree);
}
}
Element rcvelem = TreeUtils.elementFromTree(receiver);
assert rcvelem != null : "Unexpected null element for receiver: " + receiver;
if (!ElementUtils.hasReceiver(rcvelem)) {
return null;
}
if (receiver.getKind() == Tree.Kind.IDENTIFIER && ((IdentifierTree) receiver).getName().contentEquals("this")) {
// TODO: also "super"?
return this.getSelfType(tree);
}
TypeElement typeElt = ElementUtils.enclosingClass(rcvelem);
if (typeElt == null) {
ErrorReporter.errorAbort("AnnotatedTypeFactory.getImplicitReceiver: enclosingClass()==null for element: " + rcvelem);
}
AnnotatedDeclaredType type = getAnnotatedType(typeElt);
// TODO: go through _all_ enclosing methods to see whether any of them has a
// receiver annotation of the correct type.
// TODO: Can we reuse getSelfType for outer this accesses?
AnnotatedDeclaredType methodReceiver = getCurrentMethodReceiver(tree);
if (shouldTakeFromReceiver(methodReceiver)) {
// TODO: this only takes the main annotations.
// What about other annotations (annotations on the type argument, outer types, ...)
type.clearAnnotations();
type.addAnnotations(methodReceiver.getAnnotations());
}
return type;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AsSuperVisitor method visitDeclared_Intersection.
@Override
public AnnotatedTypeMirror visitDeclared_Intersection(AnnotatedDeclaredType type, AnnotatedIntersectionType superType, Void p) {
List<AnnotatedDeclaredType> newDirectSupertypes = new ArrayList<>();
// in the intersection.
for (AnnotatedDeclaredType superDirect : superType.directSuperTypes()) {
AnnotatedDeclaredType found = (AnnotatedDeclaredType) visit(type, superDirect, p);
newDirectSupertypes.add(found);
}
// The ATM for each type in an intersection is stored in the direct super types field.
superType.setDirectSuperTypes(newDirectSupertypes);
return copyPrimaryAnnos(type, superType);
}
Aggregations