Class BasicAnnotationProcessor
- All Implemented Interfaces:
Processor
Processor
implementation that defers processing of Element
s 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 anyProcessingStep
. This helps processors to avoid many common pitfalls, such as
ErrorType
instances, ClassCastException
s 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
.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final class
A package or type name.static interface
The unit of processing logic that runs under the guarantee that all elements are complete and well-formed. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final Set<BasicAnnotationProcessor.ElementName>
private Elements
private final com.google.common.collect.SetMultimap<BasicAnnotationProcessor.ProcessingStep,
BasicAnnotationProcessor.ElementName> private Messager
private com.google.common.collect.ImmutableList<? extends BasicAnnotationProcessor.ProcessingStep>
Fields inherited from class javax.annotation.processing.AbstractProcessor
processingEnv
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate com.google.common.collect.ImmutableMap<String,
com.google.common.base.Optional<? extends Element>> Returns the previously deferred elements.private static void
findAnnotatedElements
(Element element, com.google.common.collect.ImmutableSet<? extends Class<? extends Annotation>> annotationClasses, com.google.common.collect.ImmutableSetMultimap.Builder<Class<? extends Annotation>, Element> annotatedElements) Addselement
and its enclosed elements toannotatedElements
if they are annotated with any annotations inannotationClasses
.private static TypeElement
getEnclosingType
(Element element) Returns the nearest enclosingTypeElement
to the current element, throwing anIllegalArgumentException
if the providedElement
is aPackageElement
or is otherwise not enclosed by a type.private com.google.common.collect.ImmutableSet<? extends Class<? extends Annotation>>
final com.google.common.collect.ImmutableSet<String>
Returns the set of supported annotation types as a collected from registered processing steps.private com.google.common.collect.ImmutableSetMultimap<Class<? extends Annotation>,
Element> indexByAnnotation
(Set<BasicAnnotationProcessor.ElementName> annotatedElements) final void
init
(ProcessingEnvironment processingEnv) protected abstract Iterable<? extends BasicAnnotationProcessor.ProcessingStep>
Creates processing steps for this processor.protected void
Deprecated.protected void
postRound
(RoundEnvironment roundEnv) An optional hook for logic to be executed at the end of each round.private void
process
(com.google.common.collect.ImmutableSetMultimap<Class<? extends Annotation>, Element> validElements) Processes the valid elements, including those previously deferred by each step.final boolean
process
(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) private String
processingErrorMessage
(String target) private void
reportMissingElements
(Map<String, ? extends com.google.common.base.Optional<? extends Element>> missingElements, Collection<BasicAnnotationProcessor.ElementName> missingElementNames) private com.google.common.collect.ImmutableSetMultimap<Class<? extends Annotation>,
Element> validElements
(com.google.common.collect.ImmutableMap<String, com.google.common.base.Optional<? extends Element>> deferredElements, 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
-
Field Details
-
deferredElementNames
-
elementsDeferredBySteps
private final com.google.common.collect.SetMultimap<BasicAnnotationProcessor.ProcessingStep,BasicAnnotationProcessor.ElementName> elementsDeferredBySteps -
elements
-
messager
-
steps
private com.google.common.collect.ImmutableList<? extends BasicAnnotationProcessor.ProcessingStep> steps
-
-
Constructor Details
-
BasicAnnotationProcessor
public BasicAnnotationProcessor()
-
-
Method Details
-
init
- Specified by:
init
in interfaceProcessor
- Overrides:
init
in classAbstractProcessor
-
initSteps
Creates processing steps for this processor.AbstractProcessor.processingEnv
is guaranteed to be set when this method is invoked. -
postProcess
Deprecated.usepostRound(RoundEnvironment)
insteadAn optional hook for logic to be executed at the end of each round. -
postRound
An optional hook for logic to be executed at the end of each round. -
getSupportedAnnotationClasses
private com.google.common.collect.ImmutableSet<? extends Class<? extends Annotation>> getSupportedAnnotationClasses() -
getSupportedAnnotationTypes
Returns the set of supported annotation types as a collected from registered processing steps.- Specified by:
getSupportedAnnotationTypes
in interfaceProcessor
- Overrides:
getSupportedAnnotationTypes
in classAbstractProcessor
-
process
- Specified by:
process
in interfaceProcessor
- Specified by:
process
in classAbstractProcessor
-
deferredElements
private com.google.common.collect.ImmutableMap<String,com.google.common.base.Optional<? extends Element>> deferredElements()Returns the previously deferred elements. -
reportMissingElements
private void reportMissingElements(Map<String, ? extends com.google.common.base.Optional<? extends Element>> missingElements, Collection<BasicAnnotationProcessor.ElementName> missingElementNames) -
processingErrorMessage
-
validElements
private com.google.common.collect.ImmutableSetMultimap<Class<? extends Annotation>,Element> validElements(com.google.common.collect.ImmutableMap<String, com.google.common.base.Optional<? extends Element>> deferredElements, 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<Class<? extends Annotation>, Element> validElements) Processes the valid elements, including those previously deferred by each step. -
indexByAnnotation
private com.google.common.collect.ImmutableSetMultimap<Class<? extends Annotation>,Element> indexByAnnotation(Set<BasicAnnotationProcessor.ElementName> annotatedElements) -
findAnnotatedElements
private static void findAnnotatedElements(Element element, com.google.common.collect.ImmutableSet<? extends Class<? extends Annotation>> annotationClasses, com.google.common.collect.ImmutableSetMultimap.Builder<Class<? extends Annotation>, Element> annotatedElements) Addselement
and its enclosed elements toannotatedElements
if they are annotated with any annotations inannotationClasses
. Does not traverse to member types ofelement
, so that ifOuter
is passed in the example below, looking for@X
, thenOuter
,Outer.foo
, andOuter.foo()
will be added to the multimap, but neitherInner
nor its members will.@X class Outer { @X Object foo; @X void foo() {} @X static class Inner { @X Object bar; @X void bar() {} } }
-
getEnclosingType
Returns the nearest enclosingTypeElement
to the current element, throwing anIllegalArgumentException
if the providedElement
is aPackageElement
or is otherwise not enclosed by a type.
-
postRound(RoundEnvironment)
instead