All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.auto.value.extension.AutoValueExtension Maven / Gradle / Ivy

/*
 * Copyright (C) 2015 Google Inc.
 *
 * 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 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;

/**
 * An AutoValueExtension allows for extra functionality to be created during the generation
 * of an AutoValue class.
 *
 * 

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}. * *

An Extension can extend the AutoValue implementation by generating a subclass 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. * *

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, * and to call the superclass constructor with the same arguments. This constructor must have at * least package visibility. */ 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. * *

Given {@code @AutoValue public class Foo {...}}, this will be {@code Foo}. */ TypeElement autoValueClass(); /** * 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()}. */ Map properties(); /** * 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 abstractMethods(); } /** * 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. If an Extension * returns false for a given class, it will not be called again during the processing * of that 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. * *

Each returned string must be one of the property names in {@link Context#properties()}. * *

Returning a property name from this method is equivalent to returning the property's * getter method from {@link #consumeMethods}. * *

For example, Android's {@code Parcelable} interface includes a * method * {@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 consumeProperties(Context context) { return Collections.emptySet(); } /** * 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. * *

Each returned method must be one of the abstract methods in * {@link Context#abstractMethods()}. * *

For example, Android's {@code Parcelable} interface includes a * method * {@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 consumeMethods(Context context) { return Collections.emptySet(); } /** * 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()}. * *

The returned string will typically look like this: * *

{@code
   * package ;
   * ...
   *  class  extends  {...}
   * }
* *

Here, {@code } is {@link Context#packageName()}; {@code } is the * keyword {@code final} if {@code isFinal} is true or {@code abstract} otherwise; and {@code * } and {@code } are the values of this method's parameters of the same * name. * * @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); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy