Search in sources :

Example 1 with AnnotationMirrorMap

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;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) BugInCF(org.checkerframework.javacutil.BugInCF) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 2 with AnnotationMirrorMap

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;
}
Also used : Types(javax.lang.model.util.Types) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) ArrayList(java.util.ArrayList) Subtypes(org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Subtypes) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) TypeVariable(javax.lang.model.type.TypeVariable) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap) Map(java.util.Map)

Example 3 with AnnotationMirrorMap

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;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap)

Example 4 with AnnotationMirrorMap

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();
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap)

Example 5 with AnnotationMirrorMap

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);
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) Map(java.util.Map) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap)

Aggregations

AnnotationMirror (javax.lang.model.element.AnnotationMirror)9 AnnotationMirrorMap (org.checkerframework.framework.util.AnnotationMirrorMap)9 Map (java.util.Map)7 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)6 AnnotationMirrorSet (org.checkerframework.framework.util.AnnotationMirrorSet)6 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)4 ArrayList (java.util.ArrayList)3 LinkedHashMap (java.util.LinkedHashMap)3 InferredType (org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType)3 TypeVariable (javax.lang.model.type.TypeVariable)2 Types (javax.lang.model.util.Types)2 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)2 BugInCF (org.checkerframework.javacutil.BugInCF)2 IdentityHashMap (java.util.IdentityHashMap)1 AnnotatedPrimitiveType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType)1 TypeHierarchy (org.checkerframework.framework.type.TypeHierarchy)1 AnnotatedTypes (org.checkerframework.framework.util.AnnotatedTypes)1 Equalities (org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Equalities)1 Subtypes (org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Subtypes)1