use of org.checkerframework.framework.util.AnnotationMirrorMap in project checker-framework by typetools.
the class EqualitiesSolver method mergeTypesAndPrimaries.
/**
* Returns a concrete type argument or null if there was not enough information to infer one.
*
* @param typesToHierarchies a mapping of (types → hierarchies) that indicate that the
* argument being inferred is equal to the types in each of the hierarchies
* @param primaries a map (hierarchy → annotation in hierarchy) where the annotation in
* hierarchy is equal to the primary annotation on the argument being inferred
* @param tops the set of top annotations in the qualifier hierarchy
* @return a concrete type argument or null if there was not enough information to infer one
*/
private InferredType mergeTypesAndPrimaries(Map<AnnotatedTypeMirror, AnnotationMirrorSet> typesToHierarchies, AnnotationMirrorMap<AnnotationMirror> primaries, final AnnotationMirrorSet tops, AnnotatedTypeFactory typeFactory) {
final AnnotationMirrorSet missingAnnos = new AnnotationMirrorSet(tops);
Iterator<Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet>> entryIterator = typesToHierarchies.entrySet().iterator();
if (!entryIterator.hasNext()) {
throw new BugInCF("Merging a list of empty types.");
}
final Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> head = entryIterator.next();
AnnotatedTypeMirror mergedType = head.getKey();
missingAnnos.removeAll(head.getValue());
// AnnotatedDeclaredTypes, AnnotatedTypeVariables, and AnnotatedArrayTypes
while (entryIterator.hasNext() && !missingAnnos.isEmpty()) {
final Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> current = entryIterator.next();
final AnnotatedTypeMirror currentType = current.getKey();
final AnnotationMirrorSet currentHierarchies = current.getValue();
AnnotationMirrorSet found = new AnnotationMirrorSet();
for (AnnotationMirror top : missingAnnos) {
if (currentHierarchies.contains(top)) {
final AnnotationMirror newAnno = currentType.getAnnotationInHierarchy(top);
if (newAnno != null) {
mergedType.replaceAnnotation(newAnno);
found.add(top);
} else if (mergedType.getKind() == TypeKind.TYPEVAR && typeFactory.types.isSameType(currentType.getUnderlyingType(), mergedType.getUnderlyingType())) {
// the options here are we are merging with the same typevar, in which case
// we can just remove the annotation from the missing list
found.add(top);
} else {
// otherwise the other type is missing an annotation
throw new BugInCF("Missing annotation.%nmergedType=%s%ncurrentType=%s", mergedType, currentType);
}
}
}
missingAnnos.removeAll(found);
}
// add all the annotations from the primaries
for (final AnnotationMirror top : missingAnnos) {
final AnnotationMirror anno = primaries.get(top);
if (anno != null) {
mergedType.replaceAnnotation(anno);
}
}
typesToHierarchies.clear();
if (missingAnnos.isEmpty()) {
return new InferredType(mergedType);
}
// TODO: we probably can do more with this information than just putting it back into the
// TODO: ConstraintMap (which is what's happening here)
final AnnotationMirrorSet hierarchies = new AnnotationMirrorSet(tops);
hierarchies.removeAll(missingAnnos);
typesToHierarchies.put(mergedType, hierarchies);
return null;
}
use of org.checkerframework.framework.util.AnnotationMirrorMap in project checker-framework by typetools.
the class SubtypesSolver method glbSubtypes.
public InferenceResult glbSubtypes(final Set<TypeVariable> remainingTargets, final ConstraintMap constraints, final AnnotatedTypeFactory typeFactory) {
final InferenceResult inferenceResult = new InferenceResult();
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
final Types types = typeFactory.getProcessingEnv().getTypeUtils();
List<TypeVariable> targetsSubtypesLast = new ArrayList<>(remainingTargets);
// If we have two type variables <A, A extends B> order them A then B
// this is required because we will use the fact that B must be below A
// when determining the glb of B
Collections.sort(targetsSubtypesLast, new Comparator<TypeVariable>() {
@Override
public int compare(TypeVariable o1, TypeVariable o2) {
if (types.isSubtype(o1, o2)) {
return 1;
} else if (types.isSubtype(o2, o1)) {
return -1;
}
return 0;
}
});
for (final TypeVariable target : targetsSubtypesLast) {
Subtypes subtypes = constraints.getConstraints(target).subtypes;
if (subtypes.types.isEmpty()) {
continue;
}
propagatePreviousGlbs(subtypes, inferenceResult, subtypes.types);
// if the subtypes size is only 1 then we need not do any GLBing on the underlying types
// but we may have primary annotations that need to be GLBed
AnnotationMirrorMap<AnnotationMirrorSet> primaries = subtypes.primaries;
if (subtypes.types.size() == 1) {
final Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> entry = subtypes.types.entrySet().iterator().next();
AnnotatedTypeMirror supertype = entry.getKey().deepCopy();
for (AnnotationMirror top : entry.getValue()) {
final AnnotationMirrorSet superAnnos = primaries.get(top);
// if it is null we're just going to use the anno already on supertype
if (superAnnos != null) {
final AnnotationMirror supertypeAnno = supertype.getAnnotationInHierarchy(top);
superAnnos.add(supertypeAnno);
}
}
if (!primaries.isEmpty()) {
for (AnnotationMirror top : qualifierHierarchy.getTopAnnotations()) {
final AnnotationMirror glb = greatestLowerBound(subtypes.primaries.get(top), qualifierHierarchy);
supertype.replaceAnnotation(glb);
}
}
inferenceResult.put(target, new InferredType(supertype));
} else {
// GLB all of the types than combine this with the GLB of primary annotation constraints
final AnnotatedTypeMirror glbType = GlbUtil.glbAll(subtypes.types, typeFactory);
if (glbType != null) {
if (!primaries.isEmpty()) {
for (AnnotationMirror top : qualifierHierarchy.getTopAnnotations()) {
final AnnotationMirror glb = greatestLowerBound(subtypes.primaries.get(top), qualifierHierarchy);
final AnnotationMirror currentAnno = glbType.getAnnotationInHierarchy(top);
if (currentAnno == null) {
glbType.addAnnotation(glb);
} else if (glb != null) {
glbType.replaceAnnotation(qualifierHierarchy.greatestLowerBound(glb, currentAnno));
}
}
}
inferenceResult.put(target, new InferredType(glbType));
}
}
}
return inferenceResult;
}
use of org.checkerframework.framework.util.AnnotationMirrorMap in project checker-framework by typetools.
the class AbstractQualifierPolymorphism method mapQualifierToPoly.
/**
* If the primary annotation of {@code polyType} is a polymorphic qualifier, then it is mapped to
* the primary annotation of {@code type} and the map is returned. Otherwise, an empty map is
* returned.
*
* @param type type with qualifier to us in the map
* @param polyType type that may have polymorphic qualifiers
* @return a mapping from the polymorphic qualifiers in {@code polyType} to the qualifiers in
* {@code type}
*/
private AnnotationMirrorMap<AnnotationMirror> mapQualifierToPoly(AnnotatedTypeMirror type, AnnotatedTypeMirror polyType) {
AnnotationMirrorMap<AnnotationMirror> result = new AnnotationMirrorMap<>();
for (Map.Entry<AnnotationMirror, AnnotationMirror> kv : polyQuals.entrySet()) {
AnnotationMirror top = kv.getValue();
AnnotationMirror poly = kv.getKey();
if (polyType.hasAnnotation(poly)) {
AnnotationMirror typeQual = type.getAnnotationInHierarchy(top);
if (typeQual != null) {
if (atypeFactory.hasQualifierParameterInHierarchy(type, top)) {
polyInstantiationForQualifierParameter.put(poly, typeQual);
}
result.put(poly, typeQual);
}
}
}
return result;
}
use of org.checkerframework.framework.util.AnnotationMirrorMap in project checker-framework by typetools.
the class AbstractQualifierPolymorphism method resolve.
@Override
public void resolve(VariableElement field, AnnotatedTypeMirror owner, AnnotatedTypeMirror type) {
if (polyQuals.isEmpty() || !hasPolymorphicQualifiers(type)) {
return;
}
AnnotationMirrorMap<AnnotationMirror> matchingMapping = new AnnotationMirrorMap<>();
polyQuals.forEach((polyAnnotation, topAnno) -> {
AnnotationMirror annoOnOwner = owner.getAnnotationInHierarchy(topAnno);
if (annoOnOwner != null) {
matchingMapping.put(polyAnnotation, annoOnOwner);
}
});
if (!matchingMapping.isEmpty()) {
replacer.visit(type, matchingMapping);
} else {
completer.visit(type);
}
reset();
}
use of org.checkerframework.framework.util.AnnotationMirrorMap in project checker-framework by typetools.
the class DefaultQualifierPolymorphism method replace.
@Override
protected void replace(AnnotatedTypeMirror type, AnnotationMirrorMap<AnnotationMirror> replacements) {
for (Map.Entry<AnnotationMirror, AnnotationMirror> pqentry : replacements.entrySet()) {
AnnotationMirror poly = pqentry.getKey();
if (type.hasAnnotation(poly)) {
type.removeAnnotation(poly);
AnnotationMirror qual;
if (polyInstantiationForQualifierParameter.containsKey(poly)) {
qual = polyInstantiationForQualifierParameter.get(poly);
} else {
qual = pqentry.getValue();
}
type.replaceAnnotation(qual);
}
}
}
Aggregations