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);
}