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);
}
Aggregations