Class BasicAnnotationProcessor

  • All Implemented Interfaces:
    javax.annotation.processing.Processor
    Direct Known Subclasses:
    MemoizedValidator

    public abstract class BasicAnnotationProcessor
    extends javax.annotation.processing.AbstractProcessor
    An abstract Processor implementation that defers processing of Elements to later rounds if they cannot be processed.

    Subclasses put their processing logic in BasicAnnotationProcessor.ProcessingStep implementations. The steps are passed to the processor by returning them in the initSteps() method, and can access the ProcessingEnvironment using AbstractProcessor.processingEnv. Any logic that needs to happen once per round can be specified by overriding postRound(RoundEnvironment).

    Ill-formed elements are deferred

    Any annotated element whose nearest enclosing type is not well-formed is deferred, and not passed to any ProcessingStep. This helps processors to avoid many common pitfalls, such as ErrorType instances, ClassCastExceptions and badly coerced types.

    A non-package element is considered well-formed if its type, type parameters, parameters, default values, supertypes, annotations, and enclosed elements are. Package elements are treated similarly, except that their enclosed elements are not validated. See SuperficialValidation.validateElement(Element) for details.

    The primary disadvantage to this validation is that any element that forms a circular dependency with a type generated by another BasicAnnotationProcessor will never compile because the element will never be fully complete. All such compilations will fail with an error message on the offending type that describes the issue.

    Each ProcessingStep can defer elements

    Each ProcessingStep can defer elements by including them in the set returned by BasicAnnotationProcessor.ProcessingStep.process(SetMultimap); elements deferred by a step will be passed back to that step in a later round of processing.

    This feature is useful when one processor may depend on code generated by another, independent processor, in a way that isn't caught by the well-formedness check described above. For example, if an element A cannot be processed because processing it depends on the existence of some class B, then A should be deferred until a later round of processing, when B will have been generated by another processor.

    If A directly references B, then the well-formedness check will correctly defer processing of A until B has been generated.

    However, if A references B only indirectly (for example, from within a method body), then the well-formedness check will not defer processing A, but a processing step can reject A.

    • Method Summary

      All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods 
      Modifier and Type Method Description
      private com.google.common.collect.ImmutableMap<java.lang.String,​com.google.common.base.Optional<? extends javax.lang.model.element.Element>> deferredElements()
      Returns the previously deferred elements.
      private static void findAnnotatedElements​(javax.lang.model.element.Element element, com.google.common.collect.ImmutableSet<? extends java.lang.Class<? extends java.lang.annotation.Annotation>> annotationClasses, com.google.common.collect.ImmutableSetMultimap.Builder<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> annotatedElements)
      Adds element and its enclosed elements to annotatedElements if they are annotated with any annotations in annotationClasses.
      private static javax.lang.model.element.TypeElement getEnclosingType​(javax.lang.model.element.Element element)
      Returns the nearest enclosing TypeElement to the current element, throwing an IllegalArgumentException if the provided Element is a PackageElement or is otherwise not enclosed by a type.
      private com.google.common.collect.ImmutableSet<? extends java.lang.Class<? extends java.lang.annotation.Annotation>> getSupportedAnnotationClasses()  
      com.google.common.collect.ImmutableSet<java.lang.String> getSupportedAnnotationTypes()
      Returns the set of supported annotation types as a collected from registered processing steps.
      private com.google.common.collect.ImmutableSetMultimap<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> indexByAnnotation​(java.util.Set<BasicAnnotationProcessor.ElementName> annotatedElements)  
      void init​(javax.annotation.processing.ProcessingEnvironment processingEnv)  
      protected abstract java.lang.Iterable<? extends BasicAnnotationProcessor.ProcessingStep> initSteps()
      Creates processing steps for this processor.
      protected void postProcess()
      Deprecated.
      protected void postRound​(javax.annotation.processing.RoundEnvironment roundEnv)
      An optional hook for logic to be executed at the end of each round.
      private void process​(com.google.common.collect.ImmutableSetMultimap<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> validElements)
      Processes the valid elements, including those previously deferred by each step.
      boolean process​(java.util.Set<? extends javax.lang.model.element.TypeElement> annotations, javax.annotation.processing.RoundEnvironment roundEnv)  
      private java.lang.String processingErrorMessage​(java.lang.String target)  
      private void reportMissingElements​(java.util.Map<java.lang.String,​? extends com.google.common.base.Optional<? extends javax.lang.model.element.Element>> missingElements, java.util.Collection<BasicAnnotationProcessor.ElementName> missingElementNames)  
      private com.google.common.collect.ImmutableSetMultimap<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> validElements​(com.google.common.collect.ImmutableMap<java.lang.String,​com.google.common.base.Optional<? extends javax.lang.model.element.Element>> deferredElements, javax.annotation.processing.RoundEnvironment roundEnv)
      Returns the valid annotated elements contained in all of the deferred elements.
      • Methods inherited from class javax.annotation.processing.AbstractProcessor

        getCompletions, getSupportedOptions, getSupportedSourceVersion, isInitialized
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • BasicAnnotationProcessor

        public BasicAnnotationProcessor()
    • Method Detail

      • init

        public final void init​(javax.annotation.processing.ProcessingEnvironment processingEnv)
        Specified by:
        init in interface javax.annotation.processing.Processor
        Overrides:
        init in class javax.annotation.processing.AbstractProcessor
      • postProcess

        @Deprecated
        protected void postProcess()
        Deprecated.
        An optional hook for logic to be executed at the end of each round.
      • postRound

        protected void postRound​(javax.annotation.processing.RoundEnvironment roundEnv)
        An optional hook for logic to be executed at the end of each round.
      • getSupportedAnnotationClasses

        private com.google.common.collect.ImmutableSet<? extends java.lang.Class<? extends java.lang.annotation.Annotation>> getSupportedAnnotationClasses()
      • getSupportedAnnotationTypes

        public final com.google.common.collect.ImmutableSet<java.lang.String> getSupportedAnnotationTypes()
        Returns the set of supported annotation types as a collected from registered processing steps.
        Specified by:
        getSupportedAnnotationTypes in interface javax.annotation.processing.Processor
        Overrides:
        getSupportedAnnotationTypes in class javax.annotation.processing.AbstractProcessor
      • process

        public final boolean process​(java.util.Set<? extends javax.lang.model.element.TypeElement> annotations,
                                     javax.annotation.processing.RoundEnvironment roundEnv)
        Specified by:
        process in interface javax.annotation.processing.Processor
        Specified by:
        process in class javax.annotation.processing.AbstractProcessor
      • deferredElements

        private com.google.common.collect.ImmutableMap<java.lang.String,​com.google.common.base.Optional<? extends javax.lang.model.element.Element>> deferredElements()
        Returns the previously deferred elements.
      • reportMissingElements

        private void reportMissingElements​(java.util.Map<java.lang.String,​? extends com.google.common.base.Optional<? extends javax.lang.model.element.Element>> missingElements,
                                           java.util.Collection<BasicAnnotationProcessor.ElementName> missingElementNames)
      • processingErrorMessage

        private java.lang.String processingErrorMessage​(java.lang.String target)
      • validElements

        private com.google.common.collect.ImmutableSetMultimap<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> validElements​(com.google.common.collect.ImmutableMap<java.lang.String,​com.google.common.base.Optional<? extends javax.lang.model.element.Element>> deferredElements,
                                                                                                                                                                                javax.annotation.processing.RoundEnvironment roundEnv)
        Returns the valid annotated elements contained in all of the deferred elements. If none are found for a deferred element, defers it again.
      • process

        private void process​(com.google.common.collect.ImmutableSetMultimap<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> validElements)
        Processes the valid elements, including those previously deferred by each step.
      • indexByAnnotation

        private com.google.common.collect.ImmutableSetMultimap<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> indexByAnnotation​(java.util.Set<BasicAnnotationProcessor.ElementName> annotatedElements)
      • findAnnotatedElements

        private static void findAnnotatedElements​(javax.lang.model.element.Element element,
                                                  com.google.common.collect.ImmutableSet<? extends java.lang.Class<? extends java.lang.annotation.Annotation>> annotationClasses,
                                                  com.google.common.collect.ImmutableSetMultimap.Builder<java.lang.Class<? extends java.lang.annotation.Annotation>,​javax.lang.model.element.Element> annotatedElements)
        Adds element and its enclosed elements to annotatedElements if they are annotated with any annotations in annotationClasses. Does not traverse to member types of element, so that if Outer is passed in the example below, looking for @X, then Outer, Outer.foo, and Outer.foo() will be added to the multimap, but neither Inner nor its members will.
        
           @X class Outer {
             @X Object foo;
             @X void foo() {}
             @X static class Inner {
               @X Object bar;
               @X void bar() {}
             }
           }
         
      • getEnclosingType

        private static javax.lang.model.element.TypeElement getEnclosingType​(javax.lang.model.element.Element element)
        Returns the nearest enclosing TypeElement to the current element, throwing an IllegalArgumentException if the provided Element is a PackageElement or is otherwise not enclosed by a type.