use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class GlbUtil method glbAll.
/**
* Note: This method can be improved for wildcards and type variables.
*
* @return the greatest lower bound of typeMirrors. If any of the type mirrors are incomparable,
* use an AnnotatedNullType that will contain the greatest lower bounds of the primary
* annotations of typeMirrors.
*/
public static AnnotatedTypeMirror glbAll(final Map<AnnotatedTypeMirror, AnnotationMirrorSet> typeMirrors, final AnnotatedTypeFactory typeFactory) {
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
if (typeMirrors.isEmpty()) {
return null;
}
// dtermine the greatest lower bounds for the primary annotations
AnnotationMirrorMap<AnnotationMirror> glbPrimaries = new AnnotationMirrorMap<>();
for (Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> tmEntry : typeMirrors.entrySet()) {
final AnnotationMirrorSet typeAnnoHierarchies = tmEntry.getValue();
final AnnotatedTypeMirror type = tmEntry.getKey();
for (AnnotationMirror top : typeAnnoHierarchies) {
// TODO: When all of the typeMirrors are either wildcards or type variables than the
// greatest lower bound should involve handling the bounds individually rather than
// using the effective annotation. We are doing this for expediency.
final AnnotationMirror typeAnno = type.getEffectiveAnnotationInHierarchy(top);
final AnnotationMirror currentAnno = glbPrimaries.get(top);
if (typeAnno != null && currentAnno != null) {
glbPrimaries.put(top, qualifierHierarchy.greatestLowerBound(currentAnno, typeAnno));
} else if (typeAnno != null) {
glbPrimaries.put(top, typeAnno);
}
}
}
final List<AnnotatedTypeMirror> glbTypes = new ArrayList<>();
// create a copy of all of the types and apply the glb primary annotation
final AnnotationMirrorSet values = new AnnotationMirrorSet(glbPrimaries.values());
for (AnnotatedTypeMirror type : typeMirrors.keySet()) {
if (type.getKind() != TypeKind.TYPEVAR || !qualifierHierarchy.isSubtype(type.getEffectiveAnnotations(), values)) {
final AnnotatedTypeMirror copy = type.deepCopy();
copy.replaceAnnotations(values);
glbTypes.add(copy);
} else {
// if the annotations came from the upper bound of this typevar
// we do NOT want to place them as primary annotations (and destroy the
// type vars lower bound)
glbTypes.add(type);
}
}
final TypeHierarchy typeHierarchy = typeFactory.getTypeHierarchy();
// sort placing supertypes first
sortForGlb(glbTypes, typeFactory);
// find the lowest type in the list that is not an AnnotatedNullType
AnnotatedTypeMirror glbType = glbTypes.get(0);
int index = 1;
while (index < glbTypes.size()) {
// NULL types
if (glbType.getKind() != TypeKind.NULL) {
glbType = glbTypes.get(index);
}
index += 1;
}
// if the lowest type is a subtype of all glbTypes then it is the GLB, otherwise there are two
// types in glbTypes that are incomparable and we need to use bottom (AnnotatedNullType)
boolean incomparable = false;
for (final AnnotatedTypeMirror type : glbTypes) {
if (!incomparable && type.getKind() != TypeKind.NULL && (!TypesUtils.isErasedSubtype(glbType.getUnderlyingType(), type.getUnderlyingType(), typeFactory.getChecker().getTypeUtils()) || !typeHierarchy.isSubtype(glbType, type))) {
incomparable = true;
}
}
// we had two incomparable types in glbTypes
if (incomparable) {
return createBottom(typeFactory, glbType.getEffectiveAnnotations());
}
return glbType;
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class DefaultQualifierForUseTypeAnnotator method getDefaultAnnosForUses.
/**
* Returns the set of qualifiers that should be applied to unannotated uses of this element.
*/
protected Set<AnnotationMirror> getDefaultAnnosForUses(Element element) {
if (typeFactory.shouldCache && elementToDefaults.containsKey(element)) {
return elementToDefaults.get(element);
}
Set<AnnotationMirror> explictAnnos = getExplicitAnnos(element);
Set<AnnotationMirror> defaultAnnos = getDefaultQualifierForUses(element);
Set<AnnotationMirror> noDefaultAnnos = getHierarchiesNoDefault(element);
AnnotationMirrorSet annosToApply = new AnnotationMirrorSet();
for (AnnotationMirror top : typeFactory.getQualifierHierarchy().getTopAnnotations()) {
if (AnnotationUtils.containsSame(noDefaultAnnos, top)) {
continue;
}
AnnotationMirror defaultAnno = typeFactory.getQualifierHierarchy().findAnnotationInHierarchy(defaultAnnos, top);
if (defaultAnno != null) {
annosToApply.add(defaultAnno);
} else {
AnnotationMirror explict = typeFactory.getQualifierHierarchy().findAnnotationInHierarchy(explictAnnos, top);
if (explict != null) {
annosToApply.add(explict);
}
}
}
// If parsing stub files, then the annosToApply is incomplete, so don't cache them.
if (typeFactory.shouldCache && !typeFactory.stubTypes.isParsing() && !typeFactory.ajavaTypes.isParsing()) {
elementToDefaults.put(element, annosToApply);
}
return annosToApply;
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class AnnotatedTypeFactory method annotateCapturedTypeVar.
/**
* Set the annotated bounds for fresh type variable {@code capturedTypeVar}, so that it is the
* capture of {@code wildcard}. Also, sets {@code capturedTypeVar} primary annotation if the
* annotation on the bounds is identical.
*
* @param typeVarToAnnotatedTypeArg mapping from a (type mirror) type variable to its (annotated
* type mirror) type argument
* @param capturedTypeVarToAnnotatedTypeVar mapping from a captured type variable to its {@link
* AnnotatedTypeMirror}
* @param wildcard wildcard which is converted to {@code capturedTypeVar}
* @param typeVariable type variable for which {@code wildcard} is a type argument
* @param capturedTypeVar the fresh type variable which is side-effected by this method
*/
private void annotateCapturedTypeVar(Map<TypeVariable, AnnotatedTypeMirror> typeVarToAnnotatedTypeArg, Map<TypeVariable, AnnotatedTypeVariable> capturedTypeVarToAnnotatedTypeVar, AnnotatedWildcardType wildcard, AnnotatedTypeVariable typeVariable, AnnotatedTypeVariable capturedTypeVar) {
AnnotatedTypeMirror typeVarUpperBound = typeVarSubstitutor.substituteWithoutCopyingTypeArguments(typeVarToAnnotatedTypeArg, typeVariable.getUpperBound());
AnnotatedTypeMirror upperBound = AnnotatedTypes.annotatedGLB(this, typeVarUpperBound, wildcard.getExtendsBound());
// There is a bug in javac such that the upper bound of the captured type variable is not the
// greatest lower bound. So the captureTypeVar.getUnderlyingType().getUpperBound() may not
// be the same type as upperbound.getUnderlyingType(). See
// framework/tests/all-systems/Issue4890Interfaces.java,
// framework/tests/all-systems/Issue4890.java and framework/tests/all-systems/Issue4877.java.
capturedTypeVar.setUpperBound(upperBound);
// typeVariable's lower bound is a NullType, so there's nothing to substitute.
AnnotatedTypeMirror lowerBound = AnnotatedTypes.leastUpperBound(this, typeVariable.getLowerBound(), wildcard.getSuperBound());
capturedTypeVar.setLowerBound(lowerBound);
// Add as a primary annotation any qualifiers that are the same on the upper and lower bound.
AnnotationMirrorSet p = new AnnotationMirrorSet(capturedTypeVar.getUpperBound().getAnnotations());
p.retainAll(capturedTypeVar.getLowerBound().getAnnotations());
capturedTypeVar.replaceAnnotations(p);
capturedTypeVarSubstitutor.substitute(capturedTypeVar, capturedTypeVarToAnnotatedTypeVar);
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class QualifierUpperBounds method getBoundQualifiers.
/**
* Returns the set of qualifiers that are the upper bounds for a use of the type.
*
* @param type the TypeMirror
* @return the set of qualifiers that are the upper bounds for a use of the type
*/
public Set<AnnotationMirror> getBoundQualifiers(TypeMirror type) {
AnnotationMirrorSet bounds = new AnnotationMirrorSet();
String qname;
if (type.getKind() == TypeKind.DECLARED) {
DeclaredType declaredType = (DeclaredType) type;
bounds.addAll(getAnnotationFromElement(declaredType.asElement()));
qname = TypesUtils.getQualifiedName(declaredType);
} else if (type.getKind().isPrimitive()) {
qname = type.toString();
} else {
qname = null;
}
if (qname != null && types.containsKey(qname)) {
Set<AnnotationMirror> fnd = types.get(qname);
addMissingAnnotations(bounds, fnd);
}
if (typeKinds.containsKey(type.getKind())) {
Set<AnnotationMirror> fnd = typeKinds.get(type.getKind());
addMissingAnnotations(bounds, fnd);
}
addMissingAnnotations(bounds, atypeFactory.getDefaultTypeDeclarationBounds());
return bounds;
}
Aggregations