blob: 6c199c35cf2857b740bcc2e4e9e6a0dd9546eb86 [file] [log] [blame]
package com.google.auto.value.extension;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
/**
* This API is not final and WILL CHANGE in a future release.
* An AutoValueExtension allows for extra functionality to be created during the generation
* of an AutoValue class.
*
* <p>Extensions are discovered at compile time using the {@link java.util.ServiceLoader} APIs,
* allowing them to run without any additional annotations.
*
* <p>Extensions can extend the AutoValue implementation by generating subclasses of the AutoValue
* generated class. It is not guaranteed that an Extension's generated class will be the final
* class in the inheritance hierarchy, unless its {@link #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.
*
* <p>Each Extension must also be sure to generate a constructor with arguments corresponding to
* all properties in
* {@link com.google.auto.value.extension.AutoValueExtension.Context#properties()}, in order. This
* constructor must have at least package visibility.
*/
public abstract class AutoValueExtension {
/**
* The context of the generation cycle.
*/
public interface Context {
/**
* The processing environment of this generation cycle.
*
* @return The ProcessingEnvironment of this generation cycle.
*/
ProcessingEnvironment processingEnvironment();
/**
* The package name of the classes to be generated.
*
* @return The package name of the classes to be generated.
*/
String packageName();
/**
* The annotated class that this generation cycle is based on.
*
* <p>Given {@code @AutoValue public class Foo {...}}, this will be {@code Foo}.
*
* @return The annotated class.
*/
TypeElement autoValueClass();
/**
* The ordered collection of properties to be generated by AutoValue.
*
* @return The ordered collection of properties.
*/
Map<String, ExecutableElement> properties();
}
/**
* Determines whether this extension applies to the given context.
*
* @param context The Context of the code generation for this class.
* @return True if this extension should be applied in the given context.
*/
public boolean applicable(Context context) {
return false;
}
/**
* Denotes that the class generated by this Extension must be the final class
* in the inheritance hierarchy. Only one extension may be the final class, so
* this should be used sparingly.
*
* @param context The Context of the code generation for this class.
* @return True if the resulting class must be the final class in the inheritance hierarchy.
*/
public boolean mustBeFinal(Context context) {
return false;
}
/**
* Returns a non-null set of property names from {@link Context#properties()} that this extension
* intends to implement. This will prevent AutoValue from generating an implementation, and remove
* the supplied properties from builders, constructors, {@code toString}, {@code equals},
* and {@code hashCode}. The default set returned by this method is empty.
*
* <p>For example, Android's {@code Parcelable} interface includes a
* <a href="http://developer.android.com/reference/android/os/Parcelable.html#describeContents()">method</a>
* {@code int describeContents()}. Since this is an abstract method with no parameters, by
* default AutoValue will consider that it defines an {@code int} property called
* {@code describeContents}. If an {@code @AutoValue} class implements {@code Parcelable} and does
* not provide an implementation of this method, by default its implementation will include
* {@code describeContents} in builders, constructors, and so on. But an
* {@code AutoValueExtension} that understands {@code Parcelable} can instead provide a useful
* implementation and return a set containing {@code "describeContents"}. Then
* {@code describeContents} will be omitted from builders and the rest.
*
* @param context The Context of the code generation for this class.
* @return A collection of property names that this extension intends to implement.
*/
public Set<String> consumeProperties(Context context) {
return Collections.emptySet();
}
/**
* Generates the source code of the class named {@code className} to extend
* {@code classToExtend}. The generated class should be final if {@code isFinal}
* is true; otherwise it should be abstract.
*
* @param context The {@link Context} of the code generation for this class.
* @param className The name of the resulting class. The returned code will be written to a
* file named accordingly.
* @param classToExtend The direct parent of the generated class. Could be the AutoValue
* generated class, or a class generated as the result of another
* extension.
* @param 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.
* @return The source code of the generated class
*/
public abstract String generateClass(
Context context, String className, String classToExtend, boolean isFinal);
}