• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.auto.value.extension;
17 
18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.ImmutableSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Optional;
23 import java.util.Set;
24 import javax.annotation.processing.ProcessingEnvironment;
25 import javax.annotation.processing.Processor;
26 import javax.annotation.processing.SupportedOptions;
27 import javax.lang.model.element.AnnotationMirror;
28 import javax.lang.model.element.ExecutableElement;
29 import javax.lang.model.element.TypeElement;
30 import javax.lang.model.type.TypeMirror;
31 
32 /**
33  * An AutoValueExtension allows for extra functionality to be created during the generation of an
34  * AutoValue class.
35  *
36  * <p>Extensions are discovered at compile time using the {@link java.util.ServiceLoader} APIs,
37  * allowing them to run without any additional annotations. To be found by {@code ServiceLoader}, an
38  * extension class must be public with a public no-arg constructor, and its fully-qualified name
39  * must appear in a file called {@code
40  * META-INF/services/com.google.auto.value.extension.AutoValueExtension} in a jar that is on the
41  * compiler's {@code -classpath} or {@code -processorpath}.
42  *
43  * <p>When the AutoValue processor runs for a class {@code Foo}, it will ask each Extension whether
44  * it is {@linkplain #applicable applicable}. Suppose two Extensions reply that they are. Then
45  * the processor will generate the AutoValue logic in a direct subclass of {@code Foo}, and it
46  * will ask the first Extension to generate a subclass of that, and the second Extension to generate
47  * a subclass of the subclass. So we might have this hierarchy:
48  *
49  * <pre>
50  * &#64;AutoValue abstract class Foo {...}                          // the hand-written class
51  * abstract class $$AutoValue_Foo extends Foo {...}             // generated by AutoValue processor
52  * abstract class $AutoValue_Foo extends $$AutoValue_Foo {...}  // generated by first Extension
53  * final class AutoValue_Foo extends $AutoValue_Foo {...}       // generated by second Extension
54  * </pre>
55  *
56  * <p>(The exact naming scheme illustrated here is not fixed and should not be relied on.)
57  *
58  * <p>If an Extension needs its generated class to be the final class in the inheritance hierarchy,
59  * its {@link #mustBeFinal(Context)} method returns true. Only one Extension can return true for a
60  * given context. Only generated classes that will be the final class in the inheritance hierarchy
61  * can be declared final. All others should be declared abstract.
62  *
63  * <p>The first generated class in the hierarchy will always be the one generated by the AutoValue
64  * processor and the last one will always be the one generated by the Extension that {@code
65  * mustBeFinal}, if any. Other than that, the order of the classes in the hierarchy is unspecified.
66  * The last class in the hierarchy is {@code AutoValue_Foo} and that is the one that the
67  * {@code Foo} class will reference, for example with {@code new AutoValue_Foo(...)}.
68  *
69  * <p>Each Extension must also be sure to generate a constructor with arguments corresponding to all
70  * properties in {@link com.google.auto.value.extension.AutoValueExtension.Context#propertyTypes()},
71  * in order, and to call the superclass constructor with the same arguments. This constructor must
72  * have at least package visibility.
73  *
74  * <p>Because the class generated by the AutoValue processor is at the top of the generated
75  * hierarchy, Extensions can override its methods, for example {@code hashCode()},
76  * {@code toString()}, or the implementations of the various {@code bar()} property methods.
77  */
78 public abstract class AutoValueExtension {
79 
80   /** The context of the generation cycle. */
81   public interface Context {
82 
83     /**
84      * Returns the processing environment of this generation cycle. This can be used, among other
85      * things, to produce compilation warnings or errors, using {@link
86      * ProcessingEnvironment#getMessager()}.
87      */
processingEnvironment()88     ProcessingEnvironment processingEnvironment();
89 
90     /** Returns the package name of the classes to be generated. */
packageName()91     String packageName();
92 
93     /**
94      * Returns the annotated class that this generation cycle is based on.
95      *
96      * <p>Given {@code @AutoValue public class Foo {...}}, this will be {@code Foo}.
97      */
autoValueClass()98     TypeElement autoValueClass();
99 
100     /**
101      * The fully-qualified name of the last class in the {@code AutoValue} hierarchy. For an
102      * {@code @AutoValue} class {@code foo.bar.Baz}, this will be {@code foo.bar.AutoValue_Baz}.
103      * The class may be generated by an extension, which will be the current extension if the
104      * {@code isFinal} parameter to {@link AutoValueExtension#generateClass} is true and the
105      * returned string is not {@code null}.
106      *
107      * <p>For compatibility reasons, this method has a default implementation that throws an
108      * exception. The AutoValue processor supplies an implementation that behaves as documented.
109      */
finalAutoValueClassName()110     default String finalAutoValueClassName() {
111       throw new UnsupportedOperationException();
112     }
113 
114     /**
115      * Returns the ordered collection of properties to be generated by AutoValue. Each key is a
116      * property name, and the corresponding value is the getter method for that property. For
117      * example, if property {@code bar} is defined by {@code abstract String getBar()} then this map
118      * will have an entry mapping {@code "bar"} to the {@code ExecutableElement} for {@code
119      * getBar()}.
120      *
121      * <p>To determine the type of a property, it is best to use {@link #propertyTypes()} rather
122      * than looking at the return type of the {@link ExecutableElement} in this map. The reason is
123      * that the final type of the property might be different because of type variables. For
124      * example, if you have...
125      *
126      * <pre>
127      *   {@code interface Parent<T>} {
128      *     T bar();
129      *   }
130      *  {@code @AutoValue abstract class Foo implements Parent<String> {...}}</pre>
131      *
132      * ...then the type of the {@code bar} property in {@code Foo} is actually {@code String}, but
133      * the {@code ExecutableElement} will be the the method in {@code Parent}, whose return type is
134      * {@code T}.
135      */
properties()136     Map<String, ExecutableElement> properties();
137 
138     /**
139      * Returns the properties to be generated by AutoValue, with their types. Each key is a property
140      * name, and the corresponding value is the type of that property. The order of the map entries
141      * is the same as the order of the {@code @AutoValue} properties.
142      *
143      * <p>For example, if property {@code bar} is defined by {@code abstract String getBar()} then
144      * this map will have an entry mapping {@code "bar"} to the {@code TypeMirror} for {@code
145      * String}.
146      *
147      * <p>For compatibility reasons, this method has a default implementation that throws an
148      * exception. The AutoValue processor supplies an implementation that behaves as documented.
149      */
propertyTypes()150     default Map<String, TypeMirror> propertyTypes() {
151       throw new UnsupportedOperationException();
152     }
153 
154     /**
155      * Returns the complete set of abstract methods defined in or inherited by the
156      * {@code @AutoValue} class. This includes all methods that define properties (like {@code
157      * abstract String getBar()}), any abstract {@code toBuilder()} method, and any other abstract
158      * method even if it has been consumed by this or another Extension.
159      */
abstractMethods()160     Set<ExecutableElement> abstractMethods();
161 
162     /**
163      * Returns the complete list of annotations defined on the {@code classToCopyFrom} that should
164      * be added to any generated subclass. Only annotations visible to the {@code @AutoValue} will
165      * be present. See {@link com.google.auto.value.AutoValue.CopyAnnotations
166      * AutoValue.CopyAnnotations} for more information.
167      *
168      * <p>The default implementation of this method returns an empty list for compatibility with
169      * extensions which may have implemented this interface themselves.
170      */
classAnnotationsToCopy(TypeElement classToCopyFrom)171     default List<AnnotationMirror> classAnnotationsToCopy(TypeElement classToCopyFrom) {
172       return ImmutableList.of();
173     }
174 
175     /**
176      * Returns the complete list of annotations defined on the {@code method} that should be applied
177      * to any override of that method. Only annotations visible to the {@code @AutoValue} will be
178      * present. See {@link com.google.auto.value.AutoValue.CopyAnnotations
179      * AutoValue.CopyAnnotations} for more information.
180      *
181      * <p>The default implementation of this method returns an empty list for compatibility with
182      * extensions which may have implemented this interface themselves.
183      */
methodAnnotationsToCopy(ExecutableElement method)184     default List<AnnotationMirror> methodAnnotationsToCopy(ExecutableElement method) {
185       return ImmutableList.of();
186     }
187 
188     /**
189      * Returns a representation of the {@code Builder} associated with the {@code @AutoValue} class,
190      * if there is one.
191      *
192      * <p>This method returns {@link Optional#empty()} if called from within the {@link #applicable}
193      * method. If an Extension needs {@code Builder} information to decide whether it is applicable,
194      * it should return {@code true} from the {@link #applicable} method and then return {@code
195      * null} from the {@link #generateClass} method if it does not need to generate a class after
196      * all.
197      *
198      * <p>The default implementation of this method returns {@link Optional#empty()} for
199      * compatibility with extensions which may have implemented this interface themselves.
200      */
builder()201     default Optional<BuilderContext> builder() {
202       return Optional.empty();
203     }
204   }
205 
206   /**
207    * Represents a {@code Builder} associated with an {@code @AutoValue} class.
208    */
209   public interface BuilderContext {
210     /**
211      * Returns the {@code @AutoValue.Builder} interface or abstract class that this object
212      * represents.
213      */
builderType()214     TypeElement builderType();
215 
216     /**
217      * Returns abstract no-argument methods in the {@code @AutoValue} class that return the builder
218      * type.
219      *
220      * <p>Consider a class like this:
221      * <pre>
222      *   {@code @AutoValue} abstract class Foo {
223      *     abstract String bar();
224      *
225      *     abstract Builder toBuilder();
226      *
227      *     ...
228      *     {@code @AutoValue.Builder}
229      *     abstract static class Builder {...}
230      *   }
231      * </pre>
232      *
233      * <p>Here {@code toBuilderMethods()} will return a set containing the method
234      * {@code Foo.toBuilder()}.
235      */
toBuilderMethods()236     Set<ExecutableElement> toBuilderMethods();
237 
238     /**
239      * Returns static no-argument methods in the {@code @AutoValue} class that return the builder
240      * type.
241      *
242      * <p>Consider a class like this:
243      * <pre>
244      *   {@code @AutoValue} abstract class Foo {
245      *     abstract String bar();
246      *
247      *     static Builder builder() {
248      *       return new AutoValue_Foo.Builder()
249      *           .setBar("default bar");
250      *     }
251      *
252      *     {@code @AutoValue.Builder}
253      *     abstract class Builder {
254      *       abstract Builder setBar(String x);
255      *       abstract Foo build();
256      *     }
257      *   }
258      * </pre>
259      *
260      * <p>Here {@code builderMethods()} will return a set containing the method
261      * {@code Foo.builder()}. Generated code should usually call this method in preference to
262      * constructing {@code AutoValue_Foo.Builder()} directly, because this method can establish
263      * default values for properties, as it does here.
264      */
builderMethods()265     Set<ExecutableElement> builderMethods();
266 
267     /**
268      * Returns the method {@code build()} in the builder class, if it exists and returns the
269      * {@code @AutoValue} type. This is the method that generated code for
270      * {@code @AutoValue class Foo} should call in order to get an instance of {@code Foo} from its
271      * builder. The returned method is called {@code build()}; if the builder uses some other name
272      * then extensions have no good way to guess how they should build.
273      *
274      * <p>A common convention is for {@code build()} to be a concrete method in the
275      * {@code @AutoValue.Builder} class, which calls an abstract method {@code autoBuild()} that is
276      * implemented in the generated subclass. The {@code build()} method can then do validation,
277      * defaulting, and so on.
278      */
buildMethod()279     Optional<ExecutableElement> buildMethod();
280 
281     /**
282      * Returns the abstract build method. If the {@code @AutoValue} class is {@code Foo}, this is an
283      * abstract no-argument method in the builder class that returns {@code Foo}. This might be
284      * called {@code build()}, or, following a common convention, it might be called
285      * {@code autoBuild()} and used in the implementation of a {@code build()} method that is
286      * defined in the builder class.
287      *
288      * <p>Extensions should call the {@code build()} method in preference to this one. But they
289      * should override this one if they want to customize build-time behaviour.
290      */
autoBuildMethod()291     ExecutableElement autoBuildMethod();
292 
293     /**
294      * Returns a map from property names to the corresponding setters. A property may have more than
295      * one setter. For example, an {@code ImmutableList<String>} might be set by
296      * {@code setFoo(ImmutableList<String>)} and {@code setFoo(String[])}.
297      */
setters()298     Map<String, Set<ExecutableElement>> setters();
299 
300     /**
301      * Returns a map from property names to property builders. For example, if there is a property
302      * {@code foo} defined by {@code abstract ImmutableList<String> foo();} or
303      * {@code abstract ImmutableList<String> getFoo();} in the {@code @AutoValue} class,
304      * then there can potentially be a builder defined by
305      * {@code abstract ImmutableList.Builder<String> fooBuilder();} in the
306      * {@code @AutoValue.Builder} class. This map would then map {@code "foo"} to the
307      * {@link ExecutableElement} representing {@code fooBuilder()}.
308      */
propertyBuilders()309     Map<String, ExecutableElement> propertyBuilders();
310   }
311 
312   /**
313    * Indicates to an annotation processor environment supporting incremental annotation processing
314    * (currently a feature specific to Gradle starting with version 4.8) the incremental type of an
315    * Extension.
316    *
317    * <p>The constants for this enum are ordered by increasing performance (but also constraints).
318    *
319    * @see <a
320    *     href="https://docs.gradle.org/current/userguide/java_plugin.html#sec:incremental_annotation_processing">Gradle
321    *     documentation of its incremental annotation processing</a>
322    */
323   public enum IncrementalExtensionType {
324     /**
325      * The incrementality of this extension is unknown, or it is neither aggregating nor isolating.
326      */
327     UNKNOWN,
328 
329     /**
330      * This extension is <i>aggregating</i>, meaning that it may generate outputs based on several
331      * annotated input classes and it respects the constraints imposed on aggregating processors.
332      * It is unusual for AutoValue extensions to be aggregating.
333      *
334      * @see <a
335      *     href="https://docs.gradle.org/current/userguide/java_plugin.html#aggregating_annotation_processors">Gradle
336      *     definition of aggregating processors</a>
337      */
338     AGGREGATING,
339 
340     /**
341      * This extension is <i>isolating</i>, meaning roughly that its output depends on the
342      * {@code @AutoValue} class and its dependencies, but not on other {@code @AutoValue} classes
343      * that might be compiled at the same time. The constraints that an isolating extension must
344      * respect are the same as those that Gradle imposes on an isolating annotation processor.
345      *
346      * @see <a
347      *     href="https://docs.gradle.org/current/userguide/java_plugin.html#isolating_annotation_processors">Gradle
348      *     definition of isolating processors</a>
349      */
350     ISOLATING
351   }
352 
353   /**
354    * Determines the incremental type of this Extension.
355    *
356    * <p>The {@link ProcessingEnvironment} can be used, among other things, to obtain the processor
357    * options, using {@link ProcessingEnvironment#getOptions()}.
358    *
359    * <p>The actual incremental type of the AutoValue processor as a whole will be the loosest
360    * incremental types of the Extensions present in the annotation processor path. The default
361    * returned value is {@link IncrementalExtensionType#UNKNOWN}, which will disable incremental
362    * annotation processing entirely.
363    */
incrementalType(ProcessingEnvironment processingEnvironment)364   public IncrementalExtensionType incrementalType(ProcessingEnvironment processingEnvironment) {
365     return IncrementalExtensionType.UNKNOWN;
366   }
367 
368   /**
369    * Analogous to {@link Processor#getSupportedOptions()}, here to allow extensions to report their
370    * own.
371    *
372    * <p>By default, if the extension class is annotated with {@link SupportedOptions}, this will
373    * return a set with the strings in the annotation. If the class is not so annotated, an empty set
374    * is returned.
375    *
376    * @return the set of options recognized by this extension or an empty set if none
377    * @see SupportedOptions
378    */
getSupportedOptions()379   public Set<String> getSupportedOptions() {
380     SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class);
381     if (so == null) {
382       return ImmutableSet.of();
383     } else {
384       return ImmutableSet.copyOf(so.value());
385     }
386   }
387 
388   /**
389    * Determines whether this Extension applies to the given context. If an Extension returns {@code
390    * false} for a given class, it will not be called again during the processing of that class. An
391    * Extension can return {@code true} and still choose not to generate any code for the class, by
392    * returning {@code null} from {@link #generateClass}. That is often a more flexible approach.
393    *
394    * @param context The Context of the code generation for this class.
395    */
applicable(Context context)396   public boolean applicable(Context context) {
397     return false;
398   }
399 
400   /**
401    * Denotes that the class generated by this Extension must be the final class in the inheritance
402    * hierarchy. Only one Extension may be the final class, so this should be used sparingly.
403    *
404    * @param context the Context of the code generation for this class.
405    */
mustBeFinal(Context context)406   public boolean mustBeFinal(Context context) {
407     return false;
408   }
409 
410   /**
411    * Returns a possibly empty set of property names that this Extension intends to implement. This
412    * will prevent AutoValue from generating an implementation, and remove the supplied properties
413    * from builders, constructors, {@code toString}, {@code equals}, and {@code hashCode}. The
414    * default set returned by this method is empty.
415    *
416    * <p>Each returned string must be one of the property names in {@link Context#properties()}.
417    *
418    * <p>Returning a property name from this method is equivalent to returning the property's getter
419    * method from {@link #consumeMethods}.
420    *
421    * <p>For example, Android's {@code Parcelable} interface includes a <a
422    * href="http://developer.android.com/reference/android/os/Parcelable.html#describeContents()">method</a>
423    * {@code int describeContents()}. Since this is an abstract method with no parameters, by default
424    * AutoValue will consider that it defines an {@code int} property called {@code
425    * describeContents}. If an {@code @AutoValue} class implements {@code Parcelable} and does not
426    * provide an implementation of this method, by default its implementation will include {@code
427    * describeContents} in builders, constructors, and so on. But an {@code AutoValueExtension} that
428    * understands {@code Parcelable} can instead provide a useful implementation and return a set
429    * containing {@code "describeContents"}. Then {@code describeContents} will be omitted from
430    * builders and the rest.
431    *
432    * @param context the Context of the code generation for this class.
433    */
consumeProperties(Context context)434   public Set<String> consumeProperties(Context context) {
435     return ImmutableSet.of();
436   }
437 
438   /**
439    * Returns a possible empty set of abstract methods that this Extension intends to implement. This
440    * will prevent AutoValue from generating an implementation, in cases where it would have, and it
441    * will also avoid warnings about abstract methods that AutoValue doesn't expect. The default set
442    * returned by this method is empty.
443    *
444    * <p>Each returned method must be one of the abstract methods in {@link
445    * Context#abstractMethods()}.
446    *
447    * <p>For example, Android's {@code Parcelable} interface includes a <a
448    * href="http://developer.android.com/reference/android/os/Parcelable.html#writeToParcel(android.os.Parcel,int)">method</a>
449    * {@code void writeToParcel(Parcel, int)}. Normally AutoValue would not know what to do with that
450    * abstract method. But an {@code AutoValueExtension} that understands {@code Parcelable} can
451    * provide a useful implementation and return the {@code writeToParcel} method here. That will
452    * prevent a warning about the method from AutoValue.
453    *
454    * @param context the Context of the code generation for this class.
455    */
consumeMethods(Context context)456   public Set<ExecutableElement> consumeMethods(Context context) {
457     return ImmutableSet.of();
458   }
459 
460   /**
461    * Returns the generated source code of the class named {@code className} to extend {@code
462    * classToExtend}, or {@code null} if this extension does not generate a class in the hierarchy.
463    * If there is a generated class, it should be final if {@code isFinal} is true; otherwise it
464    * should be abstract. The returned string should be a complete Java class definition of the class
465    * {@code className} in the package {@link Context#packageName() context.packageName()}.
466    *
467    * <p>The returned string will typically look like this:
468    *
469    * <pre>{@code
470    * package <package>;
471    * ...
472    * <finalOrAbstract> class <className> extends <classToExtend> {
473    *   // Constructor
474    *   <className>(<constructorParameters>) {
475    *     super(<constructorParameterNames>);
476    *     ...
477    *   }
478    *   ...
479    * }}</pre>
480    *
481    * <p>Here, {@code <package>} is {@link Context#packageName()}; {@code <finalOrAbstract>} is the
482    * keyword {@code final} if {@code isFinal} is true or {@code abstract} otherwise; and {@code
483    * <className>} and {@code <classToExtend>} are the values of this method's parameters of the same
484    * name. The {@code <constructorParameters>} and {@code <constructorParameterNames>} are typically
485    * derived from {@link Context#propertyTypes()}.
486    *
487    * @param context The {@link Context} of the code generation for this class.
488    * @param className The simple name of the resulting class. The returned code will be written to a
489    *     file named accordingly.
490    * @param classToExtend The simple name of the direct parent of the generated class. This could be
491    *     the AutoValue generated class, or a class generated as the result of another Extension.
492    * @param isFinal True if this class is the last class in the chain, meaning it should be marked
493    *     as final. Otherwise it should be marked as abstract.
494    * @return The source code of the generated class, or {@code null} if this extension does not
495    *     generate a class in the hierarchy.
496    */
generateClass( Context context, String className, String classToExtend, boolean isFinal)497   public abstract String generateClass(
498       Context context, String className, String classToExtend, boolean isFinal);
499 }
500