Description
Issues #87, #162, and #201 are examples of use cases that are a bit too specialized to put into the core of AutoValue, but which are still important when they apply. We should define an extensibility API so that users can build extensions that run at the same time as AutoValue. The general idea would be that there would be an interface, say AutoValueExtension, and that the AutoValue processor would use ServiceLoader to find implementations of this interface. So if you include on your -processorpath
a jar that contains such an implementation, AutoValue will invoke it when it runs.
A possible sketch of the interface is this:
public interface AutoValueExtension {
interface Context {
ProcessingEnvironment processingEnvironment();
String packageName();
TypeElement autoValueClass();
Map<String, ExecutableElement> properties();
}
boolean applicable(Context context);
String generateClass(Context context, String classToExtend, String classToImplement);
}
The idea is that every extension gets its applicable
method called, and those that return true get their generateClass
method called. That method can return a String that is an implementation of the class called classToImplement that extends the class called classToExtend; or it can return null (for example if it has generated some related code but doesn't need to intervene in the AutoValue hierarchy). So if you have two extensions, @AutoValue class Foo
might result in a hierarchy AutoValue_Foo extends $AutoValue_Foo extends $$AutoValue_Foo extends Foo
, where AutoValue_Foo
is generated by one of the extensions, $AutoValue_Foo
is generated by the other, and $$AutoValue_Foo
contains the logic generated by the AutoValue processor. This means that extensions can override the implementations of toString()
etc.