private void replacePoly()

in src/main/java/com/amazon/checkerframework/checker/data_classification/DataClassificationVisitor.java [125:185]


    private void replacePoly(final AnnotatedTypeMirror atm, final Tree localTree) {
        List<TypeMirror> underlyingTypes = new ArrayList<>();

        // Collect the types associated with the parameters and receiver of the enclosing method;
        // mirrors polymorphic resolution. Ignore @poly("use") by using isPolyWithNoArgs(), which
        // only looks for @PolyClassification with no arguments.
        MethodTree enclosingMethod = TreeUtils.enclosingMethod(atypeFactory.getPath(localTree));
        if (enclosingMethod != null) {
            ExecutableElement execElem = TreeUtils.elementFromDeclaration(enclosingMethod);
            AnnotatedTypeMirror.AnnotatedExecutableType methodSignature =
                    atypeFactory.fromElement(execElem);
            for (AnnotatedTypeMirror param : methodSignature.getParameterTypes()) {
                if (isPolyWithNoArgs(param)) {
                    underlyingTypes.add(param.getUnderlyingType());
                }
            }
            if (methodSignature.getReceiverType() != null) {
                if (isPolyWithNoArgs(methodSignature.getReceiverType())) {
                    underlyingTypes.add(methodSignature.getReceiverType().getUnderlyingType());
                }
            }
        }

        // Always include the underlying type of the input ATM. For fields and other non-method code
        // (or
        // code in methods with no polymorphic arguments), this will be the only type used for
        // resolution.
        underlyingTypes.add(atm.getUnderlyingType());

        // The annotation that will replace the polymorphic annotation in the computation.
        AnnotationMirror finalClassAnnotation = atypeFactory.getCanonicalPublicAnnotation();

        for (TypeMirror underlyingType : underlyingTypes) {
            // For each type, first get the underlying class as an element.
            Element underlyingClassElem = TypesUtils.getTypeElement(underlyingType);
            if (underlyingClassElem != null) {
                // And then use the ATF to produce the type the user wrote on the class - and those
                // inferred by DataClassificationTypeFactory#fromElement.
                AnnotatedTypeMirror classDefaultType =
                        atypeFactory.fromElement(underlyingClassElem);
                if (classDefaultType != null) {
                    // If the class does have a default type (all should...), try to read an DCC
                    // annotation from it.
                    AnnotationMirror classDefaultAnnotation =
                            classDefaultType.getAnnotationInHierarchy(
                                    atypeFactory.getCanonicalPublicAnnotation());
                    if (classDefaultAnnotation != null) {
                        // If there was an DCC annotation, LUB it with whatever else has been found
                        // so far.
                        finalClassAnnotation =
                                atypeFactory
                                        .getQualifierHierarchy()
                                        .leastUpperBound(
                                                finalClassAnnotation, classDefaultAnnotation);
                    }
                }
            }
        }
        // Take the final LUB and then replace the original polymorphic annotation with it.
        atm.replaceAnnotation(finalClassAnnotation);
    }