package org.checkerframework.checker.units; import java.lang.annotation.Annotation; import javax.lang.model.element.AnnotationMirror; import org.checkerframework.checker.units.qual.UnitsMultiple; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotationClassLoader; import org.checkerframework.framework.util.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationUtils; public class UnitsAnnotationClassLoader extends AnnotationClassLoader { public UnitsAnnotationClassLoader(BaseTypeChecker checker) { super(checker); } /** * Custom filter for units annotations: * * <p>This filter will ignore (by returning false) any units annotation which is an alias of * another base unit annotation (identified via {@link UnitsMultiple} meta-annotation). Alias * annotations can still be used in source code; they are converted into a base annotation by * {@link UnitsAnnotatedTypeFactory#aliasedAnnotation(AnnotationMirror)}. This filter simply * makes sure that the alias annotations themselves don't become part of the type hierarchy as * their base annotations already are in the hierarchy. */ @Override protected boolean isSupportedAnnotationClass(Class<? extends Annotation> annoClass) { // build the initial annotation mirror (missing prefix) AnnotationBuilder builder = new AnnotationBuilder(processingEnv, annoClass); AnnotationMirror initialResult = builder.build(); // further refine to see if the annotation is an alias of some other SI Unit annotation for (AnnotationMirror metaAnno : initialResult.getAnnotationType().asElement().getAnnotationMirrors()) { // TODO : special treatment of invisible qualifiers? // if the annotation is a SI prefix multiple of some base unit, then return false // classic Units checker does not need to load the annotations of SI prefix multiples of base units if (AnnotationUtils.areSameByClass(metaAnno, UnitsMultiple.class)) { return false; } } // Not an alias unit return true; } }