/** * Returns the type qualifier hierarchy graph to be used by this processor. * * <p>The implementation builds the type qualifier hierarchy for the {@link * #getSupportedTypeQualifiers()} using the meta-annotations found in them. The current * implementation returns an instance of {@code GraphQualifierHierarchy}. * * <p>Subclasses may override this method to express any relationships that cannot be inferred * using meta-annotations (e.g. due to lack of meta-annotations). * * @return an annotation relation tree representing the supported qualifiers */ protected QualifierHierarchy createQualifierHierarchy() { MultiGraphQualifierHierarchy.MultiGraphFactory factory = this.createQualifierHierarchyFactory(); Elements elements = processingEnv.getElementUtils(); for (Class<? extends Annotation> typeQualifier : getSupportedTypeQualifiers()) { AnnotationMirror typeQualifierAnno = AnnotationUtils.fromClass(elements, typeQualifier); assert typeQualifierAnno != null : "Loading annotation \"" + typeQualifier + "\" failed!"; factory.addQualifier(typeQualifierAnno); // Polymorphic qualifiers can't declare their supertypes. // An error is raised if one is present. if (typeQualifier.getAnnotation(PolymorphicQualifier.class) != null) { if (typeQualifier.getAnnotation(SubtypeOf.class) != null) { // This is currently not supported. At some point we might add // polymorphic qualifiers with upper and lower bounds. errorAbort( "BaseTypeChecker: " + typeQualifier + " is polymorphic and specifies super qualifiers. " + "Remove the @checkers.quals.SubtypeOf or @checkers.quals.PolymorphicQualifier annotation from it."); } continue; } if (typeQualifier.getAnnotation(SubtypeOf.class) == null) { errorAbort( "BaseTypeChecker: " + typeQualifier + " does not specify its super qualifiers. " + "Add an @checkers.quals.SubtypeOf annotation to it."); } Class<? extends Annotation>[] superQualifiers = typeQualifier.getAnnotation(SubtypeOf.class).value(); for (Class<? extends Annotation> superQualifier : superQualifiers) { AnnotationMirror superAnno = null; superAnno = AnnotationUtils.fromClass(elements, superQualifier); factory.addSubtype(typeQualifierAnno, superAnno); } } QualifierHierarchy hierarchy = factory.build(); if (hierarchy.getTypeQualifiers().size() < 1) { errorAbort( "BaseTypeChecker: invalid qualifier hierarchy: hierarchy requires at least one annotation: " + hierarchy.getTypeQualifiers()); } return hierarchy; }
/** * If the checker class is annotated with {@link TypeQualifiers}, return an immutable set with the * same set of classes as the annotation. If the class is not so annotated, return an empty set. * * <p>Subclasses may override this method to return an immutable set of their supported type * qualifiers. * * @return the type qualifiers supported this processor, or an empty set if none * @see TypeQualifiers */ protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() { Class<?> classType = this.getClass(); TypeQualifiers typeQualifiersAnnotation = classType.getAnnotation(TypeQualifiers.class); if (typeQualifiersAnnotation == null) return Collections.emptySet(); Set<Class<? extends Annotation>> typeQualifiers = new HashSet<Class<? extends Annotation>>(); for (Class<? extends Annotation> qualifier : typeQualifiersAnnotation.value()) { typeQualifiers.add(qualifier); } return Collections.unmodifiableSet(typeQualifiers); }