| /* |
| * Copyright 2015 Google LLC |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.google.auto.value.extension; |
| |
| import com.google.common.collect.ImmutableSet; |
| import java.util.Map; |
| import java.util.Optional; |
| import java.util.Set; |
| import javax.annotation.processing.ProcessingEnvironment; |
| import javax.annotation.processing.Processor; |
| import javax.annotation.processing.SupportedOptions; |
| import javax.lang.model.element.ExecutableElement; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.type.TypeMirror; |
| |
| /** |
| * 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. To be found by {@code ServiceLoader}, an |
| * extension class must be public with a public no-arg constructor, and its fully-qualified name |
| * must appear in a file called {@code |
| * META-INF/services/com.google.auto.value.extension.AutoValueExtension} in a jar that is on the |
| * compiler's {@code -classpath} or {@code -processorpath}. |
| * |
| * <p>When the AutoValue processor runs for a class {@code Foo}, it will ask each Extension whether |
| * it is {@linkplain #applicable applicable}. Suppose two Extensions reply that they are. Then |
| * the processor will generate the AutoValue logic in a direct subclass of {@code 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: |
| * |
| * <pre> |
| * @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 |
| * </pre> |
| * |
| * <p>(The exact naming scheme illustrated here is not fixed and should not be relied on.) |
| * |
| * <p>If an Extension needs its generated class to be the final class in the inheritance hierarchy, |
| * 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>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 {@code |
| * mustBeFinal}, if any. Other than that, the order of the classes in the hierarchy is unspecified. |
| * The last class in the hierarchy is {@code AutoValue_Foo} and that is the one that the |
| * {@code Foo} class will reference, for example with {@code new AutoValue_Foo(...)}. |
| * |
| * <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#propertyTypes()}, |
| * in order, and to call the superclass constructor with the same arguments. This constructor must |
| * have at least package visibility. |
| * |
| * <p>Because the class generated by the AutoValue processor is at the top of the generated |
| * hierarchy, Extensions can override its methods, for example {@code hashCode()}, |
| * {@code toString()}, or the implementations of the various {@code bar()} property methods. |
| */ |
| public abstract class AutoValueExtension { |
| |
| /** The context of the generation cycle. */ |
| public interface Context { |
| |
| /** |
| * Returns the processing environment of this generation cycle. This can be used, among other |
| * things, to produce compilation warnings or errors, using {@link |
| * ProcessingEnvironment#getMessager()}. |
| */ |
| ProcessingEnvironment processingEnvironment(); |
| |
| /** Returns the package name of the classes to be generated. */ |
| String packageName(); |
| |
| /** |
| * Returns the annotated class that this generation cycle is based on. |
| * |
| * <p>Given {@code @AutoValue public class Foo {...}}, this will be {@code Foo}. |
| */ |
| TypeElement autoValueClass(); |
| |
| /** |
| * The fully-qualified name of the last class in the {@code AutoValue} hierarchy. For an |
| * {@code @AutoValue} class {@code foo.bar.Baz}, this will be {@code foo.bar.AutoValue_Baz}. |
| * The class may be generated by an extension, which will be the current extension if the |
| * {@code isFinal} parameter to {@link AutoValueExtension#generateClass} is true and the |
| * returned string is not {@code null}. |
| * |
| * <p>For compatibility reasons, this method has a default implementation that throws an |
| * exception. The AutoValue processor supplies an implementation that behaves as documented. |
| */ |
| default String finalAutoValueClassName() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * Returns the ordered collection of properties to be generated by AutoValue. Each key is a |
| * property name, and the corresponding value is the getter method for that property. For |
| * example, if property {@code bar} is defined by {@code abstract String getBar()} then this map |
| * will have an entry mapping {@code "bar"} to the {@code ExecutableElement} for {@code |
| * getBar()}. |
| * |
| * <p>To determine the type of a property, it is best to use {@link #propertyTypes()} rather |
| * than looking at the return type of the {@link ExecutableElement} in this map. The reason is |
| * that the final type of the property might be different because of type variables. For |
| * example, if you have... |
| * |
| * <pre> |
| * {@code interface Parent<T>} { |
| * T bar(); |
| * } |
| * {@code @AutoValue abstract class Foo implements Parent<String> {...}}</pre> |
| * |
| * ...then the type of the {@code bar} property in {@code Foo} is actually {@code String}, but |
| * the {@code ExecutableElement} will be the the method in {@code Parent}, whose return type is |
| * {@code T}. |
| */ |
| Map<String, ExecutableElement> properties(); |
| |
| /** |
| * Returns the properties to be generated by AutoValue, with their types. Each key is a property |
| * name, and the corresponding value is the type of that property. The order of the map entries |
| * is the same as the order of the {@code @AutoValue} properties. |
| * |
| * <p>For example, if property {@code bar} is defined by {@code abstract String getBar()} then |
| * this map will have an entry mapping {@code "bar"} to the {@code TypeMirror} for {@code |
| * String}. |
| * |
| * <p>For compatibility reasons, this method has a default implementation that throws an |
| * exception. The AutoValue processor supplies an implementation that behaves as documented. |
| */ |
| default Map<String, TypeMirror> propertyTypes() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * Returns the complete set of abstract methods defined in or inherited by the |
| * {@code @AutoValue} class. This includes all methods that define properties (like {@code |
| * abstract String getBar()}), any abstract {@code toBuilder()} method, and any other abstract |
| * method even if it has been consumed by this or another Extension. |
| */ |
| Set<ExecutableElement> abstractMethods(); |
| |
| /** |
| * Returns a representation of the {@code Builder} associated with the {@code @AutoValue} class, |
| * if there is one. |
| * |
| * <p>This method returns {@link Optional#empty()} if called from within the {@link #applicable} |
| * method. If an Extension needs {@code Builder} information to decide whether it is applicable, |
| * it should return {@code true} from the {@link #applicable} method and then return {@code |
| * null} from the {@link #generateClass} method if it does not need to generate a class after |
| * all. |
| * |
| * <p>The default implementation of this method returns {@link Optional#empty()} for |
| * compatibility with extensions which may have implemented this interface themselves. |
| */ |
| default Optional<BuilderContext> builder() { |
| return Optional.empty(); |
| } |
| } |
| |
| /** |
| * Represents a {@code Builder} associated with an {@code @AutoValue} class. |
| */ |
| public interface BuilderContext { |
| /** |
| * Returns the {@code @AutoValue.Builder} interface or abstract class that this object |
| * represents. |
| */ |
| TypeElement builderType(); |
| |
| /** |
| * Returns abstract no-argument methods in the {@code @AutoValue} class that return the builder |
| * type. |
| * |
| * <p>Consider a class like this: |
| * <pre> |
| * {@code @AutoValue} abstract class Foo { |
| * abstract String bar(); |
| * |
| * abstract Builder toBuilder(); |
| * |
| * ... |
| * {@code @AutoValue.Builder} |
| * abstract static class Builder {...} |
| * } |
| * </pre> |
| * |
| * <p>Here {@code toBuilderMethods()} will return a set containing the method |
| * {@code Foo.toBuilder()}. |
| */ |
| Set<ExecutableElement> toBuilderMethods(); |
| |
| /** |
| * Returns static no-argument methods in the {@code @AutoValue} class that return the builder |
| * type. |
| * |
| * <p>Consider a class like this: |
| * <pre> |
| * {@code @AutoValue} abstract class Foo { |
| * abstract String bar(); |
| * |
| * static Builder builder() { |
| * return new AutoValue_Foo.Builder() |
| * .setBar("default bar"); |
| * } |
| * |
| * {@code @AutoValue.Builder} |
| * abstract class Builder { |
| * abstract Builder setBar(String x); |
| * abstract Foo build(); |
| * } |
| * } |
| * </pre> |
| * |
| * <p>Here {@code builderMethods()} will return a set containing the method |
| * {@code Foo.builder()}. Generated code should usually call this method in preference to |
| * constructing {@code AutoValue_Foo.Builder()} directly, because this method can establish |
| * default values for properties, as it does here. |
| */ |
| Set<ExecutableElement> builderMethods(); |
| |
| /** |
| * Returns the method {@code build()} in the builder class, if it exists and returns the |
| * {@code @AutoValue} type. This is the method that generated code for |
| * {@code @AutoValue class Foo} should call in order to get an instance of {@code Foo} from its |
| * builder. The returned method is called {@code build()}; if the builder uses some other name |
| * then extensions have no good way to guess how they should build. |
| * |
| * <p>A common convention is for {@code build()} to be a concrete method in the |
| * {@code @AutoValue.Builder} class, which calls an abstract method {@code autoBuild()} that is |
| * implemented in the generated subclass. The {@code build()} method can then do validation, |
| * defaulting, and so on. |
| */ |
| Optional<ExecutableElement> buildMethod(); |
| |
| /** |
| * Returns the abstract build method. If the {@code @AutoValue} class is {@code Foo}, this is an |
| * abstract no-argument method in the builder class that returns {@code Foo}. This might be |
| * called {@code build()}, or, following a common convention, it might be called |
| * {@code autoBuild()} and used in the implementation of a {@code build()} method that is |
| * defined in the builder class. |
| * |
| * <p>Extensions should call the {@code build()} method in preference to this one. But they |
| * should override this one if they want to customize build-time behaviour. |
| */ |
| ExecutableElement autoBuildMethod(); |
| |
| /** |
| * Returns a map from property names to the corresponding setters. A property may have more than |
| * one setter. For example, an {@code ImmutableList<String>} might be set by |
| * {@code setFoo(ImmutableList<String>)} and {@code setFoo(String[])}. |
| */ |
| Map<String, Set<ExecutableElement>> setters(); |
| |
| /** |
| * Returns a map from property names to property builders. For example, if there is a property |
| * {@code foo} defined by {@code abstract ImmutableList<String> foo();} or |
| * {@code abstract ImmutableList<String> getFoo();} in the {@code @AutoValue} class, |
| * then there can potentially be a builder defined by |
| * {@code abstract ImmutableList.Builder<String> fooBuilder();} in the |
| * {@code @AutoValue.Builder} class. This map would then map {@code "foo"} to the |
| * {@link ExecutableElement} representing {@code fooBuilder()}. |
| */ |
| Map<String, ExecutableElement> propertyBuilders(); |
| } |
| |
| /** |
| * 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. |
| * |
| * <p>The constants for this enum are ordered by increasing performance (but also constraints). |
| * |
| * @see <a |
| * href="https://docs.gradle.org/current/userguide/java_plugin.html#sec:incremental_annotation_processing">Gradle |
| * documentation of its incremental annotation processing</a> |
| */ |
| public enum IncrementalExtensionType { |
| /** |
| * The incrementality of this extension is unknown, or it is neither aggregating nor isolating. |
| */ |
| UNKNOWN, |
| |
| /** |
| * This extension is <i>aggregating</i>, meaning that it may generate outputs based on several |
| * annotated input classes and it respects the constraints imposed on aggregating processors. |
| * It is unusual for AutoValue extensions to be aggregating. |
| * |
| * @see <a |
| * href="https://docs.gradle.org/current/userguide/java_plugin.html#aggregating_annotation_processors">Gradle |
| * definition of aggregating processors</a> |
| */ |
| AGGREGATING, |
| |
| /** |
| * This extension is <i>isolating</i>, meaning roughly that its output depends on the |
| * {@code @AutoValue} class and its dependencies, but not on other {@code @AutoValue} classes |
| * that might be compiled at the same time. The constraints that an isolating extension must |
| * respect are the same as those that Gradle imposes on an isolating annotation processor. |
| * |
| * @see <a |
| * href="https://docs.gradle.org/current/userguide/java_plugin.html#isolating_annotation_processors">Gradle |
| * definition of isolating processors</a> |
| */ |
| ISOLATING |
| } |
| |
| /** |
| * Determines the incremental type of this Extension. |
| * |
| * <p>The {@link ProcessingEnvironment} can be used, among other things, to obtain the processor |
| * options, using {@link ProcessingEnvironment#getOptions()}. |
| * |
| * <p>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 {@link IncrementalExtensionType#UNKNOWN}, which will disable incremental |
| * annotation processing entirely. |
| */ |
| public IncrementalExtensionType incrementalType(ProcessingEnvironment processingEnvironment) { |
| return IncrementalExtensionType.UNKNOWN; |
| } |
| |
| /** |
| * Analogous to {@link Processor#getSupportedOptions()}, here to allow extensions to report their |
| * own. |
| * |
| * <p>By default, if the extension class is annotated with {@link SupportedOptions}, this will |
| * return a set with the strings in the annotation. If the class is not so annotated, an empty set |
| * is returned. |
| * |
| * @return the set of options recognized by this extension or an empty set if none |
| * @see SupportedOptions |
| */ |
| public Set<String> getSupportedOptions() { |
| SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class); |
| if (so == null) { |
| return ImmutableSet.of(); |
| } else { |
| return ImmutableSet.copyOf(so.value()); |
| } |
| } |
| |
| /** |
| * Determines whether this Extension applies to the given context. If an Extension returns {@code |
| * false} for a given class, it will not be called again during the processing of that class. An |
| * Extension can return {@code true} and still choose not to generate any code for the class, by |
| * returning {@code null} from {@link #generateClass}. That is often a more flexible approach. |
| * |
| * @param context The Context of the code generation for this class. |
| */ |
| 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. |
| */ |
| public boolean mustBeFinal(Context context) { |
| return false; |
| } |
| |
| /** |
| * Returns a possibly empty set of property names 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>Each returned string must be one of the property names in {@link Context#properties()}. |
| * |
| * <p>Returning a property name from this method is equivalent to returning the property's getter |
| * method from {@link #consumeMethods}. |
| * |
| * <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. |
| */ |
| public Set<String> consumeProperties(Context context) { |
| return ImmutableSet.of(); |
| } |
| |
| /** |
| * Returns a possible empty set of abstract methods that this Extension intends to implement. This |
| * will prevent AutoValue from generating an implementation, in cases where it would have, and it |
| * will also avoid warnings about abstract methods that AutoValue doesn't expect. The default set |
| * returned by this method is empty. |
| * |
| * <p>Each returned method must be one of the abstract methods in {@link |
| * Context#abstractMethods()}. |
| * |
| * <p>For example, Android's {@code Parcelable} interface includes a <a |
| * href="http://developer.android.com/reference/android/os/Parcelable.html#writeToParcel(android.os.Parcel,int)">method</a> |
| * {@code void writeToParcel(Parcel, int)}. Normally AutoValue would not know what to do with that |
| * abstract method. But an {@code AutoValueExtension} that understands {@code Parcelable} can |
| * provide a useful implementation and return the {@code writeToParcel} method here. That will |
| * prevent a warning about the method from AutoValue. |
| * |
| * @param context the Context of the code generation for this class. |
| */ |
| public Set<ExecutableElement> consumeMethods(Context context) { |
| return ImmutableSet.of(); |
| } |
| |
| /** |
| * Returns the generated source code of the class named {@code className} to extend {@code |
| * classToExtend}, or {@code null} if this extension does not generate a class in the hierarchy. |
| * If there is a generated class, it should be final if {@code isFinal} is true; otherwise it |
| * should be abstract. The returned string should be a complete Java class definition of the class |
| * {@code className} in the package {@link Context#packageName() context.packageName()}. |
| * |
| * <p>The returned string will typically look like this: |
| * |
| * <pre>{@code |
| * package <package>; |
| * ... |
| * <finalOrAbstract> class <className> extends <classToExtend> { |
| * // Constructor |
| * <className>(<constructorParameters>) { |
| * super(<constructorParameterNames>); |
| * ... |
| * } |
| * ... |
| * }}</pre> |
| * |
| * <p>Here, {@code <package>} is {@link Context#packageName()}; {@code <finalOrAbstract>} is the |
| * keyword {@code final} if {@code isFinal} is true or {@code abstract} otherwise; and {@code |
| * <className>} and {@code <classToExtend>} are the values of this method's parameters of the same |
| * name. The {@code <constructorParameters>} and {@code <constructorParameterNames>} are typically |
| * derived from {@link Context#propertyTypes()}. |
| * |
| * @param context The {@link Context} of the code generation for this class. |
| * @param className The simple name of the resulting class. The returned code will be written to a |
| * file named accordingly. |
| * @param 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. |
| * @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, or {@code null} if this extension does not |
| * generate a class in the hierarchy. |
| */ |
| public abstract String generateClass( |
| Context context, String className, String classToExtend, boolean isFinal); |
| } |