use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType in project checker-framework by typetools.
the class TypeVarUseApplier method extractAndApply.
/**
* Applies the bound annotations from the declaration of the type parameter and then applies the
* explicit annotations written on the type variable
*/
public void extractAndApply() {
ElementAnnotationUtil.addAnnotationsFromElement(typeVariable, useElem.getAnnotationMirrors());
// apply declaration annotations
ElementAnnotationApplier.apply(typeVariable, declarationElem, typeFactory);
final List<Attribute.TypeCompound> annotations = getAnnotations(useElem, declarationElem);
final List<Attribute.TypeCompound> typeVarAnnotations;
if (arrayType != null) {
// if the outer-most type is an array type then we want to ensure the outer annotations
// are not applied as the type variables primary annotation
typeVarAnnotations = removeComponentAnnotations(arrayType, annotations);
ElementAnnotationUtil.annotateViaTypeAnnoPosition(arrayType, annotations);
} else {
typeVarAnnotations = annotations;
}
for (final Attribute.TypeCompound annotation : typeVarAnnotations) {
typeVariable.removeAnnotationInHierarchy(annotation);
typeVariable.addAnnotation(annotation);
final List<? extends AnnotatedTypeMirror> upperBounds;
if (typeVariable.getUpperBound() instanceof AnnotatedIntersectionType) {
upperBounds = typeVariable.getUpperBound().directSuperTypes();
} else {
upperBounds = Arrays.asList(typeVariable.getUpperBound());
}
// TODO: to all of them? Que dealio? What should we do?
for (final AnnotatedTypeMirror bound : upperBounds) {
bound.removeAnnotationInHierarchy(annotation);
bound.addAnnotation(annotation);
}
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType in project checker-framework by typetools.
the class AsSuperVisitor method ensurePrimaryIsCorrectForUnionsAndIntersections.
/**
* The code in this class is assuming that the primary annotation of an {@link
* AnnotatedIntersectionType} is the greatest lower bound of the annotations on its direct super
* types and that the primary annotation of an {@link AnnotatedUnionType} is the least upper
* bound of its alternatives. This method makes this assumption true.
*/
private void ensurePrimaryIsCorrectForUnionsAndIntersections(AnnotatedTypeMirror type) {
if (type.getKind() == TypeKind.INTERSECTION) {
AnnotatedIntersectionType intersectionType = (AnnotatedIntersectionType) type;
Set<AnnotationMirror> glbs = null;
for (AnnotatedDeclaredType directST : intersectionType.directSuperTypes()) {
if (glbs == null) {
glbs = directST.getAnnotations();
} else {
Set<AnnotationMirror> newGlbs = AnnotationUtils.createAnnotationSet();
for (AnnotationMirror glb : glbs) {
AnnotationMirror anno = directST.getAnnotationInHierarchy(glb);
newGlbs.add(annotatedTypeFactory.getQualifierHierarchy().greatestLowerBound(anno, glb));
}
glbs = newGlbs;
}
}
type.replaceAnnotations(glbs);
} else if (type.getKind() == TypeKind.UNION) {
AnnotatedUnionType annotatedUnionType = (AnnotatedUnionType) type;
Set<AnnotationMirror> lubs = null;
for (AnnotatedDeclaredType altern : annotatedUnionType.getAlternatives()) {
if (lubs == null) {
lubs = altern.getAnnotations();
} else {
Set<AnnotationMirror> newLubs = AnnotationUtils.createAnnotationSet();
for (AnnotationMirror lub : lubs) {
AnnotationMirror anno = altern.getAnnotationInHierarchy(lub);
newLubs.add(annotatedTypeFactory.getQualifierHierarchy().leastUpperBound(anno, lub));
}
lubs = newLubs;
}
}
type.replaceAnnotations(lubs);
}
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType in project checker-framework by typetools.
the class AnnotatedTypeCopier method visitIntersection.
@Override
public AnnotatedTypeMirror visitIntersection(AnnotatedIntersectionType original, IdentityHashMap<AnnotatedTypeMirror, AnnotatedTypeMirror> originalToCopy) {
if (originalToCopy.containsKey(original)) {
return originalToCopy.get(original);
}
final AnnotatedIntersectionType copy = (AnnotatedIntersectionType) AnnotatedTypeMirror.createType(original.getUnderlyingType(), original.atypeFactory, original.isDeclaration());
maybeCopyPrimaryAnnotations(original, copy);
originalToCopy.put(original, copy);
if (original.supertypes != null) {
final List<AnnotatedDeclaredType> copySupertypes = new ArrayList<>();
for (final AnnotatedDeclaredType supertype : original.supertypes) {
copySupertypes.add((AnnotatedDeclaredType) visit(supertype, originalToCopy));
}
copy.supertypes = Collections.unmodifiableList(copySupertypes);
}
return copy;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType 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.AnnotatedIntersectionType in project checker-framework by typetools.
the class TypeFromTypeTreeVisitor method visitTypeParameter.
@Override
public AnnotatedTypeMirror visitTypeParameter(TypeParameterTree node, AnnotatedTypeFactory f) {
List<AnnotatedTypeMirror> bounds = new ArrayList<>(node.getBounds().size());
for (Tree t : node.getBounds()) {
AnnotatedTypeMirror bound;
if (visitedBounds.containsKey(t) && f == visitedBounds.get(t).atypeFactory) {
bound = visitedBounds.get(t);
} else {
visitedBounds.put(t, f.type(t));
bound = visit(t, f);
visitedBounds.remove(t);
}
bounds.add(bound);
}
AnnotatedTypeVariable result = (AnnotatedTypeVariable) f.type(node);
List<? extends AnnotationMirror> annotations = TreeUtils.annotationsFromTree(node);
result.getLowerBound().addAnnotations(annotations);
switch(bounds.size()) {
case 0:
break;
case 1:
result.setUpperBound(bounds.get(0));
break;
default:
AnnotatedIntersectionType upperBound = (AnnotatedIntersectionType) result.getUpperBound();
List<AnnotatedDeclaredType> superBounds = new ArrayList<>(bounds.size());
for (AnnotatedTypeMirror b : bounds) {
superBounds.add((AnnotatedDeclaredType) b);
}
upperBound.setDirectSuperTypes(superBounds);
}
return result;
}
Aggregations