Class BasicAnnotationProcessor
- java.lang.Object
-
- javax.annotation.processing.AbstractProcessor
-
- com.google.auto.common.BasicAnnotationProcessor
-
- All Implemented Interfaces:
javax.annotation.processing.Processor
public abstract class BasicAnnotationProcessor extends javax.annotation.processing.AbstractProcessor
An abstractProcessor
implementation that defers processing ofElement
s 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 thesteps()
method, and can access theProcessingEnvironment
usingAbstractProcessor.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 asErrorType
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
Step
can defer elementsEach
Step
can defer elements by including them in the set returned byBasicAnnotationProcessor.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 classB
, thenA
should be deferred until a later round of processing, whenB
will have been generated by another processor.If
A
directly referencesB
, then the well-formedness check will correctly defer processing ofA
untilB
has been generated.However, if
A
referencesB
only indirectly (for example, from within a method body), then the well-formedness check will not defer processingA
, but a processing step can rejectA
.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
BasicAnnotationProcessor.ElementName
A package or type name.static interface
BasicAnnotationProcessor.ProcessingStep
Deprecated.ImplementBasicAnnotationProcessor.Step
instead.private static class
BasicAnnotationProcessor.ProcessingStepAsStep
static interface
BasicAnnotationProcessor.Step
The unit of processing logic that runs under the guarantee that all elements are complete and well-formed.
-
Field Summary
Fields Modifier and Type Field Description private java.util.Set<BasicAnnotationProcessor.ElementName>
deferredElementNames
private javax.lang.model.util.Elements
elements
private com.google.common.collect.SetMultimap<BasicAnnotationProcessor.Step,BasicAnnotationProcessor.ElementName>
elementsDeferredBySteps
private javax.annotation.processing.Messager
messager
private com.google.common.collect.ImmutableList<? extends BasicAnnotationProcessor.Step>
steps
-
Constructor Summary
Constructors Constructor Description BasicAnnotationProcessor()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description protected static BasicAnnotationProcessor.Step
asStep(BasicAnnotationProcessor.ProcessingStep processingStep)
Wraps the passedBasicAnnotationProcessor.ProcessingStep
in aBasicAnnotationProcessor.Step
.private static void
findAnnotatedElements(javax.lang.model.element.Element element, com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement> annotationTypes, com.google.common.collect.ImmutableSetMultimap.Builder<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> annotatedElements)
Addselement
and its enclosed elements toannotatedElements
if they are annotated with any annotations inannotationTypes
.private static javax.lang.model.element.TypeElement
getEnclosingType(javax.lang.model.element.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<javax.lang.model.element.TypeElement>
getSupportedAnnotationTypeElements()
private com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement>
getSupportedAnnotationTypeElements(BasicAnnotationProcessor.Step step)
com.google.common.collect.ImmutableSet<java.lang.String>
getSupportedAnnotationTypes()
Returns the set of supported annotation types as collected from registered processing steps.private com.google.common.collect.ImmutableSetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element>
indexByAnnotation(java.util.Set<BasicAnnotationProcessor.ElementName> annotatedElements, com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement> annotationTypes)
void
init(javax.annotation.processing.ProcessingEnvironment processingEnv)
protected java.lang.Iterable<? extends BasicAnnotationProcessor.ProcessingStep>
initSteps()
Deprecated.Implementsteps()
instead.private static boolean
isAnnotationPresent(javax.lang.model.element.Element element, javax.lang.model.element.TypeElement annotationType)
protected void
postProcess()
Deprecated.usepostRound(RoundEnvironment)
insteadprotected 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<javax.lang.model.element.TypeElement,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.Set<BasicAnnotationProcessor.ElementName> missingElementNames)
protected java.lang.Iterable<? extends BasicAnnotationProcessor.Step>
steps()
Creates processing steps for this processor.private static com.google.common.collect.ImmutableSetMultimap<java.lang.String,javax.lang.model.element.Element>
toClassNameKeyedMultimap(com.google.common.collect.SetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> elements)
private com.google.common.collect.ImmutableSetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element>
validElements(javax.annotation.processing.RoundEnvironment roundEnv)
Returns the valid annotated elements contained in all of the deferred elements.
-
-
-
Field Detail
-
deferredElementNames
private final java.util.Set<BasicAnnotationProcessor.ElementName> deferredElementNames
-
elementsDeferredBySteps
private final com.google.common.collect.SetMultimap<BasicAnnotationProcessor.Step,BasicAnnotationProcessor.ElementName> elementsDeferredBySteps
-
elements
private javax.lang.model.util.Elements elements
-
messager
private javax.annotation.processing.Messager messager
-
steps
private com.google.common.collect.ImmutableList<? extends BasicAnnotationProcessor.Step> steps
-
-
Method Detail
-
init
public final void init(javax.annotation.processing.ProcessingEnvironment processingEnv)
- Specified by:
init
in interfacejavax.annotation.processing.Processor
- Overrides:
init
in classjavax.annotation.processing.AbstractProcessor
-
initSteps
@Deprecated protected java.lang.Iterable<? extends BasicAnnotationProcessor.ProcessingStep> initSteps()
Deprecated.Implementsteps()
instead.Creates processing steps for this processor.AbstractProcessor.processingEnv
is guaranteed to be set when this method is invoked.
-
steps
protected java.lang.Iterable<? extends BasicAnnotationProcessor.Step> steps()
Creates processing steps for this processor.AbstractProcessor.processingEnv
is guaranteed to be set when this method is invoked.Note: If you are migrating some steps from
BasicAnnotationProcessor.ProcessingStep
toBasicAnnotationProcessor.Step
, then you can callasStep(ProcessingStep)
on any unmigrated steps.
-
postProcess
@Deprecated protected void postProcess()
Deprecated.usepostRound(RoundEnvironment)
insteadAn 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.
-
getSupportedAnnotationTypeElements
private com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement> getSupportedAnnotationTypeElements()
-
getSupportedAnnotationTypeElements
private com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement> getSupportedAnnotationTypeElements(BasicAnnotationProcessor.Step step)
-
getSupportedAnnotationTypes
public final com.google.common.collect.ImmutableSet<java.lang.String> getSupportedAnnotationTypes()
Returns the set of supported annotation types as collected from registered processing steps.- Specified by:
getSupportedAnnotationTypes
in interfacejavax.annotation.processing.Processor
- Overrides:
getSupportedAnnotationTypes
in classjavax.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 interfacejavax.annotation.processing.Processor
- Specified by:
process
in classjavax.annotation.processing.AbstractProcessor
-
process
private void process(com.google.common.collect.ImmutableSetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> validElements)
Processes the valid elements, including those previously deferred by each step.
-
reportMissingElements
private void reportMissingElements(java.util.Set<BasicAnnotationProcessor.ElementName> missingElementNames)
-
processingErrorMessage
private java.lang.String processingErrorMessage(java.lang.String target)
-
validElements
private com.google.common.collect.ImmutableSetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> validElements(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.
-
indexByAnnotation
private com.google.common.collect.ImmutableSetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> indexByAnnotation(java.util.Set<BasicAnnotationProcessor.ElementName> annotatedElements, com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement> annotationTypes)
-
findAnnotatedElements
private static void findAnnotatedElements(javax.lang.model.element.Element element, com.google.common.collect.ImmutableSet<javax.lang.model.element.TypeElement> annotationTypes, com.google.common.collect.ImmutableSetMultimap.Builder<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> annotatedElements)
Addselement
and its enclosed elements toannotatedElements
if they are annotated with any annotations inannotationTypes
. 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() {} } }
-
isAnnotationPresent
private static boolean isAnnotationPresent(javax.lang.model.element.Element element, javax.lang.model.element.TypeElement annotationType)
-
getEnclosingType
private static javax.lang.model.element.TypeElement getEnclosingType(javax.lang.model.element.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.
-
toClassNameKeyedMultimap
private static com.google.common.collect.ImmutableSetMultimap<java.lang.String,javax.lang.model.element.Element> toClassNameKeyedMultimap(com.google.common.collect.SetMultimap<javax.lang.model.element.TypeElement,javax.lang.model.element.Element> elements)
-
asStep
protected static BasicAnnotationProcessor.Step asStep(BasicAnnotationProcessor.ProcessingStep processingStep)
Wraps the passedBasicAnnotationProcessor.ProcessingStep
in 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.ProcessingStep
fromsteps()
.
-
-