Class BasicAnnotationProcessor
- All Implemented Interfaces:
Processor
Processor implementation that defers processing of Elements to later
rounds if they cannot be processed.
Subclasses put their processing logic in BasicAnnotationProcessor.Step implementations. The steps are passed to
the processor by returning them in the steps() 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 anyStep. 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 Step can defer elements
Each Step can defer elements by including them in the set returned by BasicAnnotationProcessor.Step.process(ImmutableSetMultimap); 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 classA package or type name.static interfaceDeprecated.private static classstatic interfaceThe 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 Elementsprivate final com.google.common.collect.SetMultimap<BasicAnnotationProcessor.Step, BasicAnnotationProcessor.ElementName> private Messagerprivate com.google.common.collect.ImmutableList<? extends BasicAnnotationProcessor.Step> Fields inherited from class AbstractProcessor
processingEnv -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected static BasicAnnotationProcessor.StepasStep(BasicAnnotationProcessor.ProcessingStep processingStep) Wraps the passedBasicAnnotationProcessor.ProcessingStepin aBasicAnnotationProcessor.Step.private static voidfindAnnotatedElements(Element element, com.google.common.collect.ImmutableSet<TypeElement> annotationTypes, com.google.common.collect.ImmutableSetMultimap.Builder<TypeElement, Element> annotatedElements) Addselementand its enclosed elements toannotatedElementsif they are annotated with any annotations inannotationTypes.private static TypeElementgetEnclosingType(Element element) Returns the nearest enclosingTypeElementto the current element, throwing anIllegalArgumentExceptionif the providedElementis aPackageElementor is otherwise not enclosed by a type.private com.google.common.collect.ImmutableSet<TypeElement> private com.google.common.collect.ImmutableSet<TypeElement> final com.google.common.collect.ImmutableSet<String> Returns the set of supported annotation types as collected from registered processing steps.private com.google.common.collect.ImmutableSetMultimap<TypeElement, Element> indexByAnnotation(Set<BasicAnnotationProcessor.ElementName> annotatedElements, com.google.common.collect.ImmutableSet<TypeElement> annotationTypes) final voidinit(ProcessingEnvironment processingEnv) protected Iterable<? extends BasicAnnotationProcessor.ProcessingStep> Deprecated.Implementsteps()instead.private static booleanisAnnotationPresent(Element element, TypeElement annotationType) protected voidDeprecated.usepostRound(RoundEnvironment)insteadprotected voidpostRound(RoundEnvironment roundEnv) An optional hook for logic to be executed at the end of each round.private voidprocess(com.google.common.collect.ImmutableSetMultimap<TypeElement, Element> validElements) Processes the valid elements, including those previously deferred by each step.final booleanprocess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) private StringprocessingErrorMessage(String target) private voidreportMissingElements(Set<BasicAnnotationProcessor.ElementName> missingElementNames) protected Iterable<? extends BasicAnnotationProcessor.Step> steps()Creates processing steps for this processor.toClassNameKeyedMultimap(com.google.common.collect.SetMultimap<TypeElement, Element> elements) private com.google.common.collect.ImmutableSetMultimap<TypeElement, Element> validElements(RoundEnvironment roundEnv) Returns the valid annotated elements contained in all of the deferred elements.Methods inherited from class AbstractProcessor
getCompletions, getSupportedOptions, getSupportedSourceVersion, isInitialized
-
Field Details
-
deferredElementNames
-
elementsDeferredBySteps
private final com.google.common.collect.SetMultimap<BasicAnnotationProcessor.Step, BasicAnnotationProcessor.ElementName> elementsDeferredBySteps -
elements
-
messager
-
steps
-
-
Constructor Details
-
BasicAnnotationProcessor
public BasicAnnotationProcessor()
-
-
Method Details
-
init
- Specified by:
initin interfaceProcessor- Overrides:
initin classAbstractProcessor
-
initSteps
Deprecated.Implementsteps()instead.Creates processing steps for this processor.AbstractProcessor.processingEnvis guaranteed to be set when this method is invoked. -
steps
Creates processing steps for this processor.AbstractProcessor.processingEnvis guaranteed to be set when this method is invoked.Note: If you are migrating some steps from
BasicAnnotationProcessor.ProcessingSteptoBasicAnnotationProcessor.Step, then you can callasStep(ProcessingStep)on any unmigrated steps. -
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. -
getSupportedAnnotationTypeElements
-
getSupportedAnnotationTypeElements
private com.google.common.collect.ImmutableSet<TypeElement> getSupportedAnnotationTypeElements(BasicAnnotationProcessor.Step step) -
getSupportedAnnotationTypes
Returns the set of supported annotation types as collected from registered processing steps.- Specified by:
getSupportedAnnotationTypesin interfaceProcessor- Overrides:
getSupportedAnnotationTypesin classAbstractProcessor
-
process
- Specified by:
processin interfaceProcessor- Specified by:
processin classAbstractProcessor
-
process
private void process(com.google.common.collect.ImmutableSetMultimap<TypeElement, Element> validElements) Processes the valid elements, including those previously deferred by each step. -
reportMissingElements
-
processingErrorMessage
-
validElements
private com.google.common.collect.ImmutableSetMultimap<TypeElement, Element> validElements(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. -
indexByAnnotation
private com.google.common.collect.ImmutableSetMultimap<TypeElement, Element> indexByAnnotation(Set<BasicAnnotationProcessor.ElementName> annotatedElements, com.google.common.collect.ImmutableSet<TypeElement> annotationTypes) -
findAnnotatedElements
private static void findAnnotatedElements(Element element, com.google.common.collect.ImmutableSet<TypeElement> annotationTypes, com.google.common.collect.ImmutableSetMultimap.Builder<TypeElement, Element> annotatedElements) Addselementand its enclosed elements toannotatedElementsif they are annotated with any annotations inannotationTypes. Does not traverse to member types ofelement, so that ifOuteris passed in the example below, looking for@X, thenOuter,Outer.foo, andOuter.foo()will be added to the multimap, but neitherInnernor its members will.@X class Outer { @X Object foo; @X void foo() {} @X static class Inner { @X Object bar; @X void bar() {} } } -
isAnnotationPresent
-
getEnclosingType
Returns the nearest enclosingTypeElementto the current element, throwing anIllegalArgumentExceptionif the providedElementis aPackageElementor is otherwise not enclosed by a type. -
toClassNameKeyedMultimap
private static com.google.common.collect.ImmutableSetMultimap<String,Element> toClassNameKeyedMultimap(com.google.common.collect.SetMultimap<TypeElement, Element> elements) -
asStep
protected static BasicAnnotationProcessor.Step asStep(BasicAnnotationProcessor.ProcessingStep processingStep) Wraps the passedBasicAnnotationProcessor.ProcessingStepin aBasicAnnotationProcessor.Step. This is a convenience method to allow incremental migration to a String-based API. This method can be used to return a not yet convertedBasicAnnotationProcessor.ProcessingStepfromsteps().
-
BasicAnnotationProcessor.Stepinstead.