use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class AnnotatedTypes method annotatedGLB.
/**
* Returns the "annotated greatest lower bound" of {@code type1} and {@code type2}.
*
* <p>Suppose that there is an expression e with annotated type T. The underlying type of T must
* be the same as javac's type for e. (This is a requirement of the Checker Framework.) As a
* corollary, when computing a glb of atype1 and atype2, it is required that
* underlyingType(cfGLB(atype1, atype2) == glb(javacGLB(underlyingType(atype1),
* underlyingType(atype2)). Because of this requirement, the return value of this method (the
* "annotated GLB") may not be a subtype of one of the types.
*
* <p>The "annotated greatest lower bound" is defined as follows:
*
* <ol>
* <li>If the underlying type of {@code type1} and {@code type2} are the same, then return a
* copy of {@code type1} whose primary annotations are the greatest lower bound of the
* primary annotations on {@code type1} and {@code type2}.
* <li>If the underlying type of {@code type1} is a subtype of the underlying type of {@code
* type2}, then return a copy of {@code type1} whose primary annotations are the greatest
* lower bound of the primary annotations on {@code type1} and {@code type2}.
* <li>If the underlying type of {@code type1} is a supertype of the underlying type of {@code
* type2}, then return a copy of {@code type2} whose primary annotations are the greatest
* lower bound of the primary annotations on {@code type1} and {@code type2}.
* <li>If the underlying type of {@code type1} and {@code type2} are not in a subtyping
* relationship, then return an annotated intersection type whose bounds are {@code type1}
* and {@code type2}.
* </ol>
*
* @param atypeFactory the AnnotatedTypeFactory
* @param type1 annotated type
* @param type2 annotated type
* @return the annotated glb of type1 and type2
*/
public static AnnotatedTypeMirror annotatedGLB(AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror type1, AnnotatedTypeMirror type2) {
TypeMirror glbJava = TypesUtils.greatestLowerBound(type1.getUnderlyingType(), type2.getUnderlyingType(), atypeFactory.getProcessingEnv());
Types types = atypeFactory.types;
if (types.isSubtype(type1.getUnderlyingType(), type2.getUnderlyingType())) {
return glbSubtype(atypeFactory.getQualifierHierarchy(), type1, type2);
} else if (types.isSubtype(type2.getUnderlyingType(), type1.getUnderlyingType())) {
return glbSubtype(atypeFactory.getQualifierHierarchy(), type2, type1);
}
if (types.isSameType(type1.getUnderlyingType(), glbJava)) {
return glbSubtype(atypeFactory.getQualifierHierarchy(), type1, type2);
} else if (types.isSameType(type2.getUnderlyingType(), glbJava)) {
return glbSubtype(atypeFactory.getQualifierHierarchy(), type2, type1);
}
if (glbJava.getKind() != TypeKind.INTERSECTION) {
// If one type isn't a subtype of the other, then GLB must be an intersection.
throw new BugInCF("AnnotatedTypes#annotatedGLB: expected intersection, got [%s] %s. " + "type1: %s, type2: %s", glbJava.getKind(), glbJava, type1, type2);
}
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
Set<AnnotationMirror> set1 = AnnotatedTypes.findEffectiveLowerBoundAnnotations(qualifierHierarchy, type1);
Set<AnnotationMirror> set2 = AnnotatedTypes.findEffectiveLowerBoundAnnotations(qualifierHierarchy, type2);
Set<? extends AnnotationMirror> glbAnno = qualifierHierarchy.greatestLowerBounds(set1, set2);
AnnotatedIntersectionType glb = (AnnotatedIntersectionType) AnnotatedTypeMirror.createType(glbJava, atypeFactory, false);
List<AnnotatedTypeMirror> newBounds = new ArrayList<>(2);
for (AnnotatedTypeMirror bound : glb.getBounds()) {
if (types.isSameType(bound.getUnderlyingType(), type1.getUnderlyingType())) {
newBounds.add(type1.deepCopy());
} else if (types.isSameType(bound.getUnderlyingType(), type2.getUnderlyingType())) {
newBounds.add(type2.deepCopy());
} else if (type1.getKind() == TypeKind.INTERSECTION) {
AnnotatedIntersectionType intertype1 = (AnnotatedIntersectionType) type1;
for (AnnotatedTypeMirror otherBound : intertype1.getBounds()) {
if (types.isSameType(bound.getUnderlyingType(), otherBound.getUnderlyingType())) {
newBounds.add(otherBound.deepCopy());
}
}
} else if (type2.getKind() == TypeKind.INTERSECTION) {
AnnotatedIntersectionType intertype2 = (AnnotatedIntersectionType) type2;
for (AnnotatedTypeMirror otherBound : intertype2.getBounds()) {
if (types.isSameType(bound.getUnderlyingType(), otherBound.getUnderlyingType())) {
newBounds.add(otherBound.deepCopy());
}
}
} else {
throw new BugInCF("Neither %s nor %s is one of the intersection bounds in %s. Bound: %s", type1, type2, bound, glb);
}
}
glb.setBounds(newBounds);
glb.addAnnotations(glbAnno);
return glb;
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class MethodApplier method applyThrowsAnnotations.
/**
* For each thrown type, collect all the annotations for that type and apply them.
*/
private void applyThrowsAnnotations(final List<Attribute.TypeCompound> annos) throws UnexpectedAnnotationLocationException {
final List<AnnotatedTypeMirror> thrown = methodType.getThrownTypes();
if (thrown.isEmpty()) {
return;
}
Map<AnnotatedTypeMirror, List<TypeCompound>> typeToAnnos = new LinkedHashMap<>();
for (final AnnotatedTypeMirror thrownType : thrown) {
typeToAnnos.put(thrownType, new ArrayList<>());
}
for (TypeCompound anno : annos) {
final TypeAnnotationPosition annoPos = anno.position;
if (annoPos.type_index >= 0 && annoPos.type_index < thrown.size()) {
final AnnotatedTypeMirror thrownType = thrown.get(annoPos.type_index);
typeToAnnos.get(thrownType).add(anno);
} else {
throw new BugInCF("MethodApplier.applyThrowsAnnotation: " + "invalid throws index " + annoPos.type_index + " for annotation: " + anno + " for element: " + ElementUtils.getQualifiedName(element));
}
}
for (final Map.Entry<AnnotatedTypeMirror, List<TypeCompound>> typeToAnno : typeToAnnos.entrySet()) {
ElementAnnotationUtil.annotateViaTypeAnnoPosition(typeToAnno.getKey(), typeToAnno.getValue());
}
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class TypeParamElementAnnotationApplier method applyUpperBounds.
/**
* Applies a list of annotations to the upperBound of the type parameter. If the type of the upper
* bound is an intersection we must first find the correct location for each annotation.
*/
private void applyUpperBounds(final List<TypeCompound> upperBounds) {
if (!upperBounds.isEmpty()) {
final AnnotatedTypeMirror upperBoundType = typeParam.getUpperBound();
if (upperBoundType.getKind() == TypeKind.INTERSECTION) {
final List<AnnotatedTypeMirror> bounds = ((AnnotatedIntersectionType) upperBoundType).getBounds();
final int boundIndexOffset = ElementAnnotationUtil.getBoundIndexOffset(bounds);
for (final TypeCompound anno : upperBounds) {
final int boundIndex = anno.position.bound_index + boundIndexOffset;
if (boundIndex < 0 || boundIndex > bounds.size()) {
throw new BugInCF("Invalid bound index on element annotation ( " + anno + " ) " + "for type ( " + typeParam + " ) with " + "upper bound ( " + typeParam.getUpperBound() + " ) " + "and boundIndex( " + boundIndex + " ) ");
}
// TODO: WHY NOT ADD?
bounds.get(boundIndex).replaceAnnotation(anno);
}
((AnnotatedIntersectionType) upperBoundType).copyIntersectionBoundAnnotations();
} else {
upperBoundType.addAnnotations(upperBounds);
}
}
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class AnnotatedTypes method asMemberOfImpl.
/**
* Helper for {@link AnnotatedTypes#asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror,
* Element)}.
*
* @param types the Types instance to use
* @param atypeFactory the type factory to use
* @param receiverType the receiver type
* @param member the element that should be viewed as member of receiverType
* @param memberType unsubstituted type of member
* @return the type of member as a member of receiverType; can be an alias to memberType
*/
private static AnnotatedTypeMirror asMemberOfImpl(final Types types, final AnnotatedTypeFactory atypeFactory, final AnnotatedTypeMirror receiverType, final Element member, final AnnotatedTypeMirror memberType) {
switch(receiverType.getKind()) {
case ARRAY:
// rather than Object.
if (SyntheticArrays.isArrayClone(receiverType, member)) {
return SyntheticArrays.replaceReturnType(member, (AnnotatedArrayType) receiverType);
}
return memberType;
case TYPEVAR:
return asMemberOf(types, atypeFactory, atypeFactory.applyCaptureConversion(((AnnotatedTypeVariable) receiverType).getUpperBound()), member, memberType);
case WILDCARD:
if (((AnnotatedWildcardType) receiverType).isUninferredTypeArgument()) {
return substituteUninferredTypeArgs(atypeFactory, member, memberType);
}
return asMemberOf(types, atypeFactory, ((AnnotatedWildcardType) receiverType).getExtendsBound().deepCopy(), member, memberType);
case INTERSECTION:
AnnotatedTypeMirror result = memberType;
TypeMirror enclosingElementType = member.getEnclosingElement().asType();
for (AnnotatedTypeMirror bound : ((AnnotatedIntersectionType) receiverType).getBounds()) {
if (TypesUtils.isErasedSubtype(bound.getUnderlyingType(), enclosingElementType, types)) {
result = substituteTypeVariables(types, atypeFactory, atypeFactory.applyCaptureConversion(bound), member, result);
}
}
return result;
case UNION:
case DECLARED:
return substituteTypeVariables(types, atypeFactory, receiverType, member, memberType);
default:
throw new BugInCF("asMemberOf called on unexpected type.%nt: %s", receiverType);
}
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class StringToJavaExpression method atFieldAccess.
/**
* uf found Parses a string as if it were written at the declaration of the field and then
* viewpoint-adapts the result to the use.
*
* @param expression a Java expression to parse
* @param fieldAccess the field access tree
* @param checker checker used to get the {@link
* javax.annotation.processing.ProcessingEnvironment} and current {@link
* com.sun.source.tree.CompilationUnitTree}
* @return a {@code JavaExpression} for {@code expression}
* @throws JavaExpressionParseException if {@code expression} cannot be parsed
*/
static JavaExpression atFieldAccess(String expression, MemberSelectTree fieldAccess, SourceChecker checker) throws JavaExpressionParseException {
Element ele = TreeUtils.elementFromUse(fieldAccess);
if (ele.getKind() != ElementKind.FIELD && ele.getKind() != ElementKind.ENUM_CONSTANT) {
throw new BugInCF("Expected a field, but found %s for %s", ele.getKind(), fieldAccess);
}
VariableElement fieldEle = (VariableElement) ele;
JavaExpression receiver = JavaExpression.fromTree(fieldAccess.getExpression());
JavaExpression javaExpr = StringToJavaExpression.atFieldDecl(expression, fieldEle, checker);
return javaExpr.atFieldAccess(receiver);
}
Aggregations