Search in sources :

Example 1 with AutoValue

use of com.google.auto.value.AutoValue in project auto by google.

the class AutoValueProcessor method processType.

private void processType(TypeElement type) {
    AutoValue autoValue = type.getAnnotation(AutoValue.class);
    if (autoValue == null) {
        // This shouldn't happen unless the compilation environment is buggy,
        // but it has happened in the past and can crash the compiler.
        errorReporter.abortWithError("annotation processor for @AutoValue was invoked with a type" + " that does not have that annotation; this is probably a compiler bug", type);
    }
    if (type.getKind() != ElementKind.CLASS) {
        errorReporter.abortWithError("@" + AutoValue.class.getName() + " only applies to classes", type);
    }
    if (ancestorIsAutoValue(type)) {
        errorReporter.abortWithError("One @AutoValue class may not extend another", type);
    }
    if (implementsAnnotation(type)) {
        errorReporter.abortWithError("@AutoValue may not be used to implement an annotation" + " interface; try using @AutoAnnotation instead", type);
    }
    checkModifiersIfNested(type);
    // We are going to classify the methods of the @AutoValue class into several categories.
    // This covers the methods in the class itself and the ones it inherits from supertypes.
    // First, the only concrete (non-abstract) methods we are interested in are overrides of
    // Object methods (equals, hashCode, toString), which signal that we should not generate
    // an implementation of those methods.
    // Then, each abstract method is one of the following:
    // (1) A property getter, like "abstract String foo()" or "abstract String getFoo()".
    // (2) A toBuilder() method, which is any abstract no-arg method returning the Builder for
    //     this @AutoValue class.
    // (3) An abstract method that will be consumed by an extension, such as
    //     Parcelable.describeContents() or Parcelable.writeToParcel(Parcel, int).
    // The describeContents() example shows a quirk here: initially we will identify it as a
    // property, which means that we need to reconstruct the list of properties after allowing
    // extensions to consume abstract methods.
    // If there are abstract methods that don't fit any of the categories above, that is an error
    // which we signal explicitly to avoid confusion.
    ImmutableSet<ExecutableElement> methods = getLocalAndInheritedMethods(type, processingEnv.getTypeUtils(), processingEnv.getElementUtils());
    ImmutableSet<ExecutableElement> abstractMethods = abstractMethodsIn(methods);
    BuilderSpec builderSpec = new BuilderSpec(type, processingEnv, errorReporter);
    Optional<BuilderSpec.Builder> builder = builderSpec.getBuilder();
    ImmutableSet<ExecutableElement> toBuilderMethods;
    if (builder.isPresent()) {
        toBuilderMethods = builder.get().toBuilderMethods(typeUtils, abstractMethods);
    } else {
        toBuilderMethods = ImmutableSet.of();
    }
    ImmutableSet<ExecutableElement> propertyMethods = propertyMethodsIn(immutableSetDifference(abstractMethods, toBuilderMethods));
    ImmutableBiMap<String, ExecutableElement> properties = propertyNameToMethodMap(propertyMethods);
    ExtensionContext context = new ExtensionContext(processingEnv, type, properties, abstractMethods);
    ImmutableList<AutoValueExtension> applicableExtensions = applicableExtensions(type, context);
    ImmutableSet<ExecutableElement> consumedMethods = methodsConsumedByExtensions(type, applicableExtensions, context, abstractMethods, properties);
    if (!consumedMethods.isEmpty()) {
        ImmutableSet<ExecutableElement> allAbstractMethods = abstractMethods;
        abstractMethods = immutableSetDifference(abstractMethods, consumedMethods);
        toBuilderMethods = immutableSetDifference(toBuilderMethods, consumedMethods);
        propertyMethods = propertyMethodsIn(immutableSetDifference(abstractMethods, toBuilderMethods));
        properties = propertyNameToMethodMap(propertyMethods);
        context = new ExtensionContext(processingEnv, type, properties, allAbstractMethods);
    }
    boolean extensionsPresent = !applicableExtensions.isEmpty();
    validateMethods(type, abstractMethods, toBuilderMethods, propertyMethods, extensionsPresent);
    String finalSubclass = generatedSubclassName(type, 0);
    AutoValueTemplateVars vars = new AutoValueTemplateVars();
    vars.pkg = TypeSimplifier.packageNameOf(type);
    vars.origClass = TypeSimplifier.classNameOf(type);
    vars.simpleClassName = TypeSimplifier.simpleNameOf(vars.origClass);
    vars.finalSubclass = TypeSimplifier.simpleNameOf(finalSubclass);
    vars.types = processingEnv.getTypeUtils();
    determineObjectMethodsToGenerate(methods, vars);
    TypeSimplifier typeSimplifier = defineVarsForType(type, vars, toBuilderMethods, propertyMethods, builder);
    // Only copy annotations from a class if it has @AutoValue.CopyAnnotations.
    if (isAnnotationPresent(type, AutoValue.CopyAnnotations.class)) {
        Set<String> excludedAnnotations = union(getFieldOfClasses(type, AutoValue.CopyAnnotations.class, "exclude", processingEnv.getElementUtils()), getAnnotationsMarkedWithInherited(type));
        vars.annotations = copyAnnotations(type, typeSimplifier, excludedAnnotations);
    } else {
        vars.annotations = ImmutableList.of();
    }
    GwtCompatibility gwtCompatibility = new GwtCompatibility(type);
    vars.gwtCompatibleAnnotation = gwtCompatibility.gwtCompatibleAnnotationString();
    int subclassDepth = writeExtensions(type, context, applicableExtensions);
    String subclass = generatedSubclassName(type, subclassDepth);
    vars.subclass = TypeSimplifier.simpleNameOf(subclass);
    vars.isFinal = (subclassDepth == 0);
    String text = vars.toText();
    text = Reformatter.fixup(text);
    writeSourceFile(subclass, text, type);
    GwtSerialization gwtSerialization = new GwtSerialization(gwtCompatibility, processingEnv, type);
    gwtSerialization.maybeWriteGwtSerializer(vars);
}
Also used : ExecutableElement(javax.lang.model.element.ExecutableElement) AutoValueExtension(com.google.auto.value.extension.AutoValueExtension) AutoValue(com.google.auto.value.AutoValue)

Aggregations

AutoValue (com.google.auto.value.AutoValue)1 AutoValueExtension (com.google.auto.value.extension.AutoValueExtension)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1