public abstract class AutoValueExtension
extends java.lang.Object
Extensions are discovered at compile time using the ServiceLoader
APIs,
allowing them to run without any additional annotations. To be found by ServiceLoader
, an
extension class must be public with a public no-arg constructor, and its fully-qualified name
must appear in a file called META-INF/services/com.google.auto.value.extension.AutoValueExtension
in a jar that is on the
compiler's -classpath
or -processorpath
.
When the AutoValue processor runs for a class Foo
, it will ask each Extension whether
it is applicable. Suppose two Extensions reply that they are. Then
the processor will generate the AutoValue logic in a direct subclass of Foo
, and it
will ask the first Extension to generate a subclass of that, and the second Extension to generate
a subclass of the subclass. So we might have this hierarchy:
@AutoValue abstract class Foo {...} // the hand-written class abstract class $$AutoValue_Foo extends Foo {...} // generated by AutoValue processor abstract class $AutoValue_Foo extends $$AutoValue_Foo {...} // generated by first Extension final class AutoValue_Foo extends $AutoValue_Foo {...} // generated by second Extension
(The exact naming scheme illustrated here is not fixed and should not be relied on.)
If an Extension needs its generated class to be the final class in the inheritance hierarchy,
its mustBeFinal(Context)
method returns true. Only one Extension can return true for a
given context. Only generated classes that will be the final class in the inheritance hierarchy
can be declared final. All others should be declared abstract.
The first generated class in the hierarchy will always be the one generated by the AutoValue
processor and the last one will always be the one generated by the Extension that mustBeFinal
, if any. Other than that, the order of the classes in the hierarchy is unspecified.
The last class in the hierarchy is AutoValue_Foo
and that is the one that the
Foo
class will reference, for example with new AutoValue_Foo(...)
.
Each Extension must also be sure to generate a constructor with arguments corresponding to all
properties in AutoValueExtension.Context.propertyTypes()
,
in order, and to call the superclass constructor with the same arguments. This constructor must
have at least package visibility.
Because the class generated by the AutoValue processor is at the top of the generated
hierarchy, Extensions can override its methods, for example hashCode()
,
toString()
, or the implementations of the various bar()
property methods.
Modifier and Type | Class and Description |
---|---|
static interface |
AutoValueExtension.BuilderContext
Represents a
Builder associated with an @AutoValue class. |
static interface |
AutoValueExtension.Context
The context of the generation cycle.
|
static class |
AutoValueExtension.IncrementalExtensionType
Indicates to an annotation processor environment supporting incremental annotation processing
(currently a feature specific to Gradle starting with version 4.8) the incremental type of an
Extension.
|
Constructor and Description |
---|
AutoValueExtension() |
Modifier and Type | Method and Description |
---|---|
boolean |
applicable(AutoValueExtension.Context context)
Determines whether this Extension applies to the given context.
|
java.util.Set<javax.lang.model.element.ExecutableElement> |
consumeMethods(AutoValueExtension.Context context)
Returns a possible empty set of abstract methods that this Extension intends to implement.
|
java.util.Set<java.lang.String> |
consumeProperties(AutoValueExtension.Context context)
Returns a possibly empty set of property names that this Extension intends to implement.
|
abstract java.lang.String |
generateClass(AutoValueExtension.Context context,
java.lang.String className,
java.lang.String classToExtend,
boolean isFinal)
Returns the generated source code of the class named
className to extend classToExtend , or null if this extension does not generate a class in the hierarchy. |
java.util.Set<java.lang.String> |
getSupportedOptions()
Analogous to
Processor.getSupportedOptions() , here to allow extensions to report their
own. |
AutoValueExtension.IncrementalExtensionType |
incrementalType(javax.annotation.processing.ProcessingEnvironment processingEnvironment)
Determines the incremental type of this Extension.
|
boolean |
mustBeFinal(AutoValueExtension.Context context)
Denotes that the class generated by this Extension must be the final class in the inheritance
hierarchy.
|
public AutoValueExtension.IncrementalExtensionType incrementalType(javax.annotation.processing.ProcessingEnvironment processingEnvironment)
The ProcessingEnvironment
can be used, among other things, to obtain the processor
options, using ProcessingEnvironment.getOptions()
.
The actual incremental type of the AutoValue processor as a whole will be the loosest
incremental types of the Extensions present in the annotation processor path. The default
returned value is AutoValueExtension.IncrementalExtensionType.UNKNOWN
, which will disable incremental
annotation processing entirely.
public java.util.Set<java.lang.String> getSupportedOptions()
Processor.getSupportedOptions()
, here to allow extensions to report their
own.
By default, if the extension class is annotated with SupportedOptions
, this will
return a set with the strings in the annotation. If the class is not so annotated, an empty set
is returned.
SupportedOptions
public boolean applicable(AutoValueExtension.Context context)
false
for a given class, it will not be called again during the processing of that class. An
Extension can return true
and still choose not to generate any code for the class, by
returning null
from generateClass(com.google.auto.value.extension.AutoValueExtension.Context, java.lang.String, java.lang.String, boolean)
. That is often a more flexible approach.context
- The Context of the code generation for this class.public boolean mustBeFinal(AutoValueExtension.Context context)
context
- the Context of the code generation for this class.public java.util.Set<java.lang.String> consumeProperties(AutoValueExtension.Context context)
toString
, equals
, and hashCode
. The
default set returned by this method is empty.
Each returned string must be one of the property names in AutoValueExtension.Context.properties()
.
Returning a property name from this method is equivalent to returning the property's getter
method from consumeMethods(com.google.auto.value.extension.AutoValueExtension.Context)
.
For example, Android's Parcelable
interface includes a method
int describeContents()
. Since this is an abstract method with no parameters, by default
AutoValue will consider that it defines an int
property called describeContents
. If an @AutoValue
class implements Parcelable
and does not
provide an implementation of this method, by default its implementation will include describeContents
in builders, constructors, and so on. But an AutoValueExtension
that
understands Parcelable
can instead provide a useful implementation and return a set
containing "describeContents"
. Then describeContents
will be omitted from
builders and the rest.
context
- the Context of the code generation for this class.public java.util.Set<javax.lang.model.element.ExecutableElement> consumeMethods(AutoValueExtension.Context context)
Each returned method must be one of the abstract methods in AutoValueExtension.Context.abstractMethods()
.
For example, Android's Parcelable
interface includes a method
void writeToParcel(Parcel, int)
. Normally AutoValue would not know what to do with that
abstract method. But an AutoValueExtension
that understands Parcelable
can
provide a useful implementation and return the writeToParcel
method here. That will
prevent a warning about the method from AutoValue.
context
- the Context of the code generation for this class.public abstract java.lang.String generateClass(AutoValueExtension.Context context, java.lang.String className, java.lang.String classToExtend, boolean isFinal)
className
to extend classToExtend
, or null
if this extension does not generate a class in the hierarchy.
If there is a generated class, it should be final if isFinal
is true; otherwise it
should be abstract. The returned string should be a complete Java class definition of the class
className
in the package context.packageName()
.
The returned string will typically look like this:
package <package>;
...
<finalOrAbstract> class <className> extends <classToExtend> {
// Constructor
<className>(<constructorParameters>) {
super(<constructorParameterNames>);
...
}
...
}
Here, <package>
is AutoValueExtension.Context.packageName()
; <finalOrAbstract>
is the
keyword final
if isFinal
is true or abstract
otherwise; and <className>
and <classToExtend>
are the values of this method's parameters of the same
name. The <constructorParameters>
and <constructorParameterNames>
are typically
derived from AutoValueExtension.Context.propertyTypes()
.
context
- The AutoValueExtension.Context
of the code generation for this class.className
- The simple name of the resulting class. The returned code will be written to a
file named accordingly.classToExtend
- The simple name of the direct parent of the generated class. This could be
the AutoValue generated class, or a class generated as the result of another Extension.isFinal
- True if this class is the last class in the chain, meaning it should be marked
as final. Otherwise it should be marked as abstract.null
if this extension does not
generate a class in the hierarchy.Copyright © 2021 Google LLC. All Rights Reserved.