Beispiel #1
0
  /**
   * 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;
  }
Beispiel #2
0
  /**
   * 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);
  }