• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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.processor;
17 
18 import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
19 import static com.google.auto.common.MoreStreams.toImmutableSet;
20 import static com.google.auto.value.processor.AutoValueishProcessor.hasAnnotationMirror;
21 import static com.google.auto.value.processor.AutoValueishProcessor.hasVisibleNoArgConstructor;
22 import static com.google.auto.value.processor.AutoValueishProcessor.nullableAnnotationFor;
23 import static com.google.auto.value.processor.ClassNames.AUTO_VALUE_BUILDER_NAME;
24 import static com.google.common.collect.Sets.immutableEnumSet;
25 import static java.util.stream.Collectors.toList;
26 import static java.util.stream.Collectors.toSet;
27 import static javax.lang.model.util.ElementFilter.methodsIn;
28 import static javax.lang.model.util.ElementFilter.typesIn;
29 
30 import com.google.auto.common.MoreElements;
31 import com.google.auto.common.MoreTypes;
32 import com.google.auto.value.extension.AutoValueExtension;
33 import com.google.auto.value.processor.AutoValueishProcessor.Property;
34 import com.google.auto.value.processor.PropertyBuilderClassifier.PropertyBuilder;
35 import com.google.common.collect.ImmutableBiMap;
36 import com.google.common.collect.ImmutableMap;
37 import com.google.common.collect.ImmutableSet;
38 import com.google.common.collect.Iterables;
39 import com.google.common.collect.Maps;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Optional;
43 import java.util.Set;
44 import java.util.function.Function;
45 import javax.annotation.processing.ProcessingEnvironment;
46 import javax.lang.model.element.Element;
47 import javax.lang.model.element.ElementKind;
48 import javax.lang.model.element.ExecutableElement;
49 import javax.lang.model.element.Modifier;
50 import javax.lang.model.element.TypeElement;
51 import javax.lang.model.element.TypeParameterElement;
52 import javax.lang.model.element.VariableElement;
53 import javax.lang.model.type.DeclaredType;
54 import javax.lang.model.type.ExecutableType;
55 import javax.lang.model.type.TypeKind;
56 import javax.lang.model.type.TypeMirror;
57 import javax.lang.model.util.Types;
58 
59 /**
60  * Support for AutoValue builders.
61  *
62  * @author Éamonn McManus
63  */
64 class BuilderSpec {
65   private final TypeElement autoValueClass;
66   private final ProcessingEnvironment processingEnv;
67   private final ErrorReporter errorReporter;
68 
BuilderSpec( TypeElement autoValueClass, ProcessingEnvironment processingEnv, ErrorReporter errorReporter)69   BuilderSpec(
70       TypeElement autoValueClass,
71       ProcessingEnvironment processingEnv,
72       ErrorReporter errorReporter) {
73     this.autoValueClass = autoValueClass;
74     this.processingEnv = processingEnv;
75     this.errorReporter = errorReporter;
76   }
77 
78   private static final ImmutableSet<ElementKind> CLASS_OR_INTERFACE =
79       immutableEnumSet(ElementKind.CLASS, ElementKind.INTERFACE);
80 
81   /**
82    * Determines if the {@code @AutoValue} class for this instance has a correct nested
83    * {@code @AutoValue.Builder} class or interface and return a representation of it in an {@code
84    * Optional} if so.
85    */
getBuilder()86   Optional<Builder> getBuilder() {
87     Optional<TypeElement> builderTypeElement = Optional.empty();
88     for (TypeElement containedClass : typesIn(autoValueClass.getEnclosedElements())) {
89       if (hasAnnotationMirror(containedClass, AUTO_VALUE_BUILDER_NAME)) {
90         findBuilderError(containedClass)
91             .ifPresent(error -> errorReporter.reportError(containedClass, "%s", error));
92         if (builderTypeElement.isPresent()) {
93           errorReporter.reportError(
94               containedClass,
95               "[AutoValueTwoBuilders] %s already has a Builder: %s",
96               autoValueClass,
97               builderTypeElement.get());
98         } else {
99           builderTypeElement = Optional.of(containedClass);
100         }
101       }
102     }
103 
104     if (builderTypeElement.isPresent()) {
105       return builderFrom(builderTypeElement.get());
106     } else {
107       return Optional.empty();
108     }
109   }
110 
111   /** Finds why this {@code @AutoValue.Builder} class is bad, if it is bad. */
findBuilderError(TypeElement builderTypeElement)112   private Optional<String> findBuilderError(TypeElement builderTypeElement) {
113     if (!CLASS_OR_INTERFACE.contains(builderTypeElement.getKind())) {
114       return Optional.of(
115           "[AutoValueBuilderClass] @AutoValue.Builder can only apply to a class or an"
116               + " interface");
117     } else if (!builderTypeElement.getModifiers().contains(Modifier.STATIC)) {
118       return Optional.of(
119           "[AutoValueInnerBuilder] @AutoValue.Builder cannot be applied to a non-static class");
120     } else if (builderTypeElement.getKind().equals(ElementKind.CLASS)
121         && !hasVisibleNoArgConstructor(builderTypeElement)) {
122       return Optional.of(
123           "[AutoValueBuilderConstructor] @AutoValue.Builder class must have a non-private no-arg"
124               + " constructor");
125     }
126     return Optional.empty();
127   }
128 
129   /** Representation of an {@code AutoValue.Builder} class or interface. */
130   class Builder implements AutoValueExtension.BuilderContext {
131     private final TypeElement builderTypeElement;
132     private ImmutableSet<ExecutableElement> toBuilderMethods;
133     private ExecutableElement buildMethod;
134     private BuilderMethodClassifier<?> classifier;
135 
Builder(TypeElement builderTypeElement)136     Builder(TypeElement builderTypeElement) {
137       this.builderTypeElement = builderTypeElement;
138     }
139 
140     @Override
builderType()141     public TypeElement builderType() {
142       return builderTypeElement;
143     }
144 
145     @Override
builderMethods()146     public Set<ExecutableElement> builderMethods() {
147       return methodsIn(autoValueClass.getEnclosedElements()).stream()
148           .filter(
149               m ->
150                   m.getParameters().isEmpty()
151                       && m.getModifiers().contains(Modifier.STATIC)
152                       && !m.getModifiers().contains(Modifier.PRIVATE)
153                       && erasedTypeIs(m.getReturnType(), builderTypeElement))
154           .collect(toSet());
155     }
156 
157     @Override
buildMethod()158     public Optional<ExecutableElement> buildMethod() {
159       Types typeUtils = processingEnv.getTypeUtils();
160       DeclaredType builderTypeMirror = MoreTypes.asDeclared(builderTypeElement.asType());
161       return MoreElements.getLocalAndInheritedMethods(
162               builderTypeElement, typeUtils, processingEnv.getElementUtils())
163           .stream()
164           .filter(
165               m ->
166                   m.getSimpleName().contentEquals("build")
167                       && !m.getModifiers().contains(Modifier.PRIVATE)
168                       && !m.getModifiers().contains(Modifier.STATIC)
169                       && m.getParameters().isEmpty())
170           .filter(
171               m -> {
172                 ExecutableType methodMirror =
173                     MoreTypes.asExecutable(typeUtils.asMemberOf(builderTypeMirror, m));
174                 return erasedTypeIs(methodMirror.getReturnType(), autoValueClass);
175               })
176           .findFirst();
177     }
178 
179     @Override
autoBuildMethod()180     public ExecutableElement autoBuildMethod() {
181       return buildMethod;
182     }
183 
184     @Override
setters()185     public Map<String, Set<ExecutableElement>> setters() {
186       return Maps.transformValues(
187           classifier.propertyNameToSetters().asMap(),
188           propertySetters ->
189               propertySetters.stream().map(PropertySetter::getSetter).collect(toSet()));
190     }
191 
192     @Override
propertyBuilders()193     public Map<String, ExecutableElement> propertyBuilders() {
194       return Maps.transformValues(
195           classifier.propertyNameToPropertyBuilder(), PropertyBuilder::getPropertyBuilderMethod);
196     }
197 
erasedTypeIs(TypeMirror type, TypeElement baseType)198     private boolean erasedTypeIs(TypeMirror type, TypeElement baseType) {
199       return type.getKind().equals(TypeKind.DECLARED)
200           && MoreTypes.asDeclared(type).asElement().equals(baseType);
201     }
202 
203     @Override
toBuilderMethods()204     public Set<ExecutableElement> toBuilderMethods() {
205       return toBuilderMethods;
206     }
207 
208     /**
209      * Finds any methods in the set that return the builder type. If the builder has type parameters
210      * {@code <A, B>}, then the return type of the method must be {@code Builder<A, B>} with the
211      * same parameter names. We enforce elsewhere that the names and bounds of the builder
212      * parameters must be the same as those of the {@code @AutoValue} class. Here's a correct
213      * example:
214      *
215      * <pre>
216      * {@code @AutoValue abstract class Foo<A extends Number, B> {
217      *   abstract int someProperty();
218      *
219      *   abstract Builder<A, B> toBuilder();
220      *
221      *   interface Builder<A extends Number, B> {...}
222      * }}
223      * </pre>
224      *
225      * <p>We currently impose that there cannot be more than one such method.
226      */
toBuilderMethods( Types typeUtils, TypeElement autoValueType, Set<ExecutableElement> abstractMethods)227     ImmutableSet<ExecutableElement> toBuilderMethods(
228         Types typeUtils, TypeElement autoValueType, Set<ExecutableElement> abstractMethods) {
229 
230       List<String> builderTypeParamNames =
231           builderTypeElement.getTypeParameters().stream()
232               .map(e -> e.getSimpleName().toString())
233               .collect(toList());
234 
235       DeclaredType autoValueTypeMirror = MoreTypes.asDeclared(autoValueType.asType());
236       ImmutableSet.Builder<ExecutableElement> methods = ImmutableSet.builder();
237       for (ExecutableElement method : abstractMethods) {
238         if (!method.getParameters().isEmpty()) {
239           continue;
240         }
241         ExecutableType methodMirror =
242             MoreTypes.asExecutable(typeUtils.asMemberOf(autoValueTypeMirror, method));
243         TypeMirror returnTypeMirror = methodMirror.getReturnType();
244         if (builderTypeElement.equals(typeUtils.asElement(returnTypeMirror))) {
245           methods.add(method);
246           DeclaredType returnType = MoreTypes.asDeclared(returnTypeMirror);
247           List<String> typeArguments =
248               returnType.getTypeArguments().stream()
249                   .filter(t -> t.getKind().equals(TypeKind.TYPEVAR))
250                   .map(t -> typeUtils.asElement(t).getSimpleName().toString())
251                   .collect(toList());
252           if (!builderTypeParamNames.equals(typeArguments)) {
253             errorReporter.reportError(
254                 method,
255                 "[AutoValueBuilderConverterReturn] Builder converter method should return %s%s",
256                 builderTypeElement,
257                 TypeSimplifier.actualTypeParametersString(builderTypeElement));
258           }
259         }
260       }
261       ImmutableSet<ExecutableElement> builderMethods = methods.build();
262       if (builderMethods.size() > 1) {
263         errorReporter.reportError(
264             builderMethods.iterator().next(),
265             "[AutoValueTwoBuilderConverters] There can be at most one builder converter method");
266       }
267       this.toBuilderMethods = builderMethods;
268       return builderMethods;
269     }
270 
defineVarsForAutoValue( AutoValueOrBuilderTemplateVars vars, ImmutableBiMap<ExecutableElement, String> getterToPropertyName)271     void defineVarsForAutoValue(
272         AutoValueOrBuilderTemplateVars vars,
273         ImmutableBiMap<ExecutableElement, String> getterToPropertyName) {
274       Iterable<ExecutableElement> builderMethods =
275           abstractMethods(builderTypeElement, processingEnv);
276       boolean autoValueHasToBuilder = toBuilderMethods != null && !toBuilderMethods.isEmpty();
277       ImmutableMap<ExecutableElement, TypeMirror> getterToPropertyType =
278           TypeVariables.rewriteReturnTypes(
279               processingEnv.getElementUtils(),
280               processingEnv.getTypeUtils(),
281               getterToPropertyName.keySet(),
282               autoValueClass,
283               builderTypeElement);
284       ImmutableMap.Builder<String, TypeMirror> rewrittenPropertyTypes = ImmutableMap.builder();
285       getterToPropertyType.forEach(
286           (getter, type) -> rewrittenPropertyTypes.put(getterToPropertyName.get(getter), type));
287       Optional<BuilderMethodClassifier<ExecutableElement>> optionalClassifier =
288           BuilderMethodClassifierForAutoValue.classify(
289               builderMethods,
290               errorReporter,
291               processingEnv,
292               autoValueClass,
293               builderTypeElement,
294               getterToPropertyName,
295               rewrittenPropertyTypes.build(),
296               autoValueHasToBuilder);
297       if (!optionalClassifier.isPresent()) {
298         return;
299       }
300       for (ExecutableElement method : methodsIn(builderTypeElement.getEnclosedElements())) {
301         if (method.getSimpleName().contentEquals("builder")
302             && method.getModifiers().contains(Modifier.STATIC)
303             && method.getAnnotationMirrors().isEmpty()
304             && !(vars instanceof AutoBuilderTemplateVars)) {
305           // For now we don't warn for methods with annotations, because for example we do want to
306           // allow Jackson's @JsonCreator. We also don't warn if this is an @AutoBuilder.
307           errorReporter.reportWarning(
308               method,
309               "[AutoValueBuilderInBuilder] Static builder() method should be in the containing"
310                   + " class");
311         }
312       }
313       defineVars(vars, optionalClassifier.get());
314     }
315 
defineVars(AutoValueOrBuilderTemplateVars vars, BuilderMethodClassifier<?> classifier)316     void defineVars(AutoValueOrBuilderTemplateVars vars, BuilderMethodClassifier<?> classifier) {
317       this.classifier = classifier;
318       Set<ExecutableElement> buildMethods = classifier.buildMethods();
319       if (buildMethods.size() != 1) {
320         Set<? extends Element> errorElements =
321             buildMethods.isEmpty() ? ImmutableSet.of(builderTypeElement) : buildMethods;
322         for (Element buildMethod : errorElements) {
323           errorReporter.reportError(
324               buildMethod,
325               "[AutoValueBuilderBuild] Builder must have a single no-argument method, typically"
326                   + " called build(), that returns %s%s",
327               autoValueClass,
328               typeParamsString());
329         }
330         return;
331       }
332       this.buildMethod = Iterables.getOnlyElement(buildMethods);
333       vars.builderIsInterface = builderTypeElement.getKind() == ElementKind.INTERFACE;
334       vars.builderTypeName = TypeSimplifier.classNameOf(builderTypeElement);
335       vars.builderFormalTypes =
336           TypeEncoder.typeParametersString(builderTypeElement.getTypeParameters());
337       vars.builderActualTypes = TypeSimplifier.actualTypeParametersString(builderTypeElement);
338       vars.buildMethod = Optional.of(new SimpleMethod(buildMethod));
339       vars.builderGetters = classifier.builderGetters();
340       vars.builderSetters = classifier.propertyNameToSetters();
341 
342       vars.builderPropertyBuilders =
343           ImmutableMap.copyOf(classifier.propertyNameToPropertyBuilder());
344 
345       vars.builderRequiredProperties =
346           vars.props.stream()
347               .filter(p -> !p.isNullable())
348               .filter(p -> p.getBuilderInitializer().isEmpty())
349               .filter(p -> !vars.builderPropertyBuilders.containsKey(p.getName()))
350               .collect(toImmutableSet());
351     }
352   }
353 
354   /**
355    * Information about a builder property getter, referenced from the autovalue.vm template. A
356    * property called foo (defined by a method {@code T foo()} or {@code T getFoo()}) can have a
357    * getter method in the builder with the same name ({@code foo()} or {@code getFoo()}) and a
358    * return type of either {@code T} or {@code Optional<T>}. The {@code Optional<T>} form can be
359    * used to tell whether the property has been set. Here, {@code Optional<T>} can be either {@code
360    * java.util.Optional} or {@code com.google.common.base.Optional}. If {@code T} is {@code int},
361    * {@code long}, or {@code double}, then instead of {@code Optional<T>} we can have {@code
362    * OptionalInt} etc. If {@code T} is a primitive type (including these ones but also the other
363    * five) then {@code Optional<T>} can be the corresponding boxed type.
364    */
365   public static class PropertyGetter {
366     private final String name;
367     private final String access;
368     private final String type;
369     private final Optionalish optional;
370 
371     /**
372      * Makes a new {@code PropertyGetter} instance.
373      *
374      * @param method the source method which this getter is implementing.
375      * @param type the type that the getter returns. This is written to take imports into account,
376      *     so it might be {@code List<String>} for example. It is either identical to the type of
377      *     the corresponding getter in the {@code @AutoValue} class, or it is an optional wrapper,
378      *     like {@code Optional<List<String>>}.
379      * @param optional a representation of the {@code Optional} type that the getter returns, if
380      *     this is an optional getter, or null otherwise. An optional getter is one that returns
381      *     {@code Optional<T>} rather than {@code T}, as explained above.
382      */
PropertyGetter(ExecutableElement method, String type, Optionalish optional)383     PropertyGetter(ExecutableElement method, String type, Optionalish optional) {
384       this.name = method.getSimpleName().toString();
385       this.access = SimpleMethod.access(method);
386       this.type = type;
387       this.optional = optional;
388     }
389 
390     // Not accessed from templates so doesn't have to be public.
getName()391     String getName() {
392       return name;
393     }
394 
getAccess()395     public String getAccess() {
396       return access;
397     }
398 
getType()399     public String getType() {
400       return type;
401     }
402 
getOptional()403     public Optionalish getOptional() {
404       return optional;
405     }
406   }
407 
408   /**
409    * Specifies how to copy a parameter value into the target type. This might be the identity, or it
410    * might be something like {@code ImmutableList.of(...)} or {@code Optional.ofNullable(...)}.
411    */
412   static class Copier {
413     static final Copier IDENTITY = acceptingNull(x -> x);
414 
415     private final Function<String, String> copy;
416     private final boolean acceptsNull;
417 
Copier(Function<String, String> copy, boolean acceptsNull)418     private Copier(Function<String, String> copy, boolean acceptsNull) {
419       this.copy = copy;
420       this.acceptsNull = acceptsNull;
421     }
422 
acceptingNull(Function<String, String> copy)423     static Copier acceptingNull(Function<String, String> copy) {
424       return new Copier(copy, true);
425     }
426 
notAcceptingNull(Function<String, String> copy)427     static Copier notAcceptingNull(Function<String, String> copy) {
428       return new Copier(copy, false);
429     }
430   }
431 
432   /**
433    * Information about a property setter, referenced from the autovalue.vm template. A property
434    * called foo (defined by a method {@code T foo()} or {@code T getFoo()}) can have a setter method
435    * {@code foo(T)} or {@code setFoo(T)} that returns the builder type. Additionally, it can have a
436    * setter with a type that can be copied to {@code T} through a {@code copyOf} method; for example
437    * a property {@code foo} of type {@code ImmutableSet<String>} can be set with a method {@code
438    * setFoo(Collection<String> foos)}. And, if {@code T} is {@code Optional}, it can have a setter
439    * with a type that can be copied to {@code T} through {@code Optional.of}.
440    */
441   public static class PropertySetter {
442     private final ExecutableElement setter;
443     private final String access;
444     private final String name;
445     private final String parameterTypeString;
446     private final boolean primitiveParameter;
447     private final String nullableAnnotation;
448     private final Copier copier;
449 
PropertySetter(ExecutableElement setter, TypeMirror parameterType, Copier copier)450     PropertySetter(ExecutableElement setter, TypeMirror parameterType, Copier copier) {
451       this.setter = setter;
452       this.copier = copier;
453       this.access = SimpleMethod.access(setter);
454       this.name = setter.getSimpleName().toString();
455       primitiveParameter = parameterType.getKind().isPrimitive();
456       this.parameterTypeString = parameterTypeString(setter, parameterType);
457       VariableElement parameterElement = Iterables.getOnlyElement(setter.getParameters());
458       Optional<String> maybeNullable = nullableAnnotationFor(parameterElement, parameterType);
459       this.nullableAnnotation = maybeNullable.orElse("");
460     }
461 
getSetter()462     ExecutableElement getSetter() {
463       return setter;
464     }
465 
parameterTypeString(ExecutableElement setter, TypeMirror parameterType)466     private static String parameterTypeString(ExecutableElement setter, TypeMirror parameterType) {
467       if (setter.isVarArgs()) {
468         TypeMirror componentType = MoreTypes.asArray(parameterType).getComponentType();
469         // This is a bit ugly. It's OK to annotate just the component type, because if it is
470         // say `@Nullable String` then we will end up with `@Nullable String...`. Unlike the
471         // normal array case, we can't have the situation where the array itself is annotated;
472         // you can write `String @Nullable []` to mean that, but you can't write
473         // `String @Nullable ...`.
474         return TypeEncoder.encodeWithAnnotations(componentType) + "...";
475       } else {
476         return TypeEncoder.encodeWithAnnotations(parameterType);
477       }
478     }
479 
getAccess()480     public String getAccess() {
481       return access;
482     }
483 
getName()484     public String getName() {
485       return name;
486     }
487 
getParameterType()488     public String getParameterType() {
489       return parameterTypeString;
490     }
491 
getPrimitiveParameter()492     public boolean getPrimitiveParameter() {
493       return primitiveParameter;
494     }
495 
getNullableAnnotation()496     public String getNullableAnnotation() {
497       return nullableAnnotation;
498     }
499 
copy(Property property)500     public String copy(Property property) {
501       String copy = copier.copy.apply(property.toString());
502       if (property.isNullable() && !copier.acceptsNull) {
503         copy = String.format("(%s == null ? null : %s)", property, copy);
504       }
505       return copy;
506     }
507   }
508 
509   /**
510    * Returns a representation of the given {@code @AutoValue.Builder} class or interface. If the
511    * class or interface has abstract methods that could not be part of any builder, emits error
512    * messages and returns Optional.empty().
513    */
builderFrom(TypeElement builderTypeElement)514   private Optional<Builder> builderFrom(TypeElement builderTypeElement) {
515 
516     // We require the builder to have the same type parameters as the @AutoValue class, meaning the
517     // same names and bounds. In principle the type parameters could have different names, but that
518     // would be confusing, and our code would reject it anyway because it wouldn't consider that
519     // the return type of Foo<U> build() was really the same as the declaration of Foo<T>. This
520     // check produces a better error message in that case and similar ones.
521 
522     if (!sameTypeParameters(autoValueClass, builderTypeElement)) {
523       errorReporter.reportError(
524           builderTypeElement,
525           "[AutoValueTypeParamMismatch] Type parameters of %s must have same names and bounds as"
526               + " type parameters of %s",
527           builderTypeElement,
528           autoValueClass);
529       return Optional.empty();
530     }
531     return Optional.of(new Builder(builderTypeElement));
532   }
533 
sameTypeParameters(TypeElement a, TypeElement b)534   private static boolean sameTypeParameters(TypeElement a, TypeElement b) {
535     return sameTypeParameters(a.getTypeParameters(), b.getTypeParameters());
536   }
537 
sameTypeParameters( List<? extends TypeParameterElement> aParams, List<? extends TypeParameterElement> bParams)538   static boolean sameTypeParameters(
539       List<? extends TypeParameterElement> aParams, List<? extends TypeParameterElement> bParams) {
540     int nTypeParameters = aParams.size();
541     if (nTypeParameters != bParams.size()) {
542       return false;
543     }
544     for (int i = 0; i < nTypeParameters; i++) {
545       TypeParameterElement aParam = aParams.get(i);
546       TypeParameterElement bParam = bParams.get(i);
547       if (!aParam.getSimpleName().equals(bParam.getSimpleName())) {
548         return false;
549       }
550       Set<TypeMirror> aBounds = new TypeMirrorSet(aParam.getBounds());
551       Set<TypeMirror> bBounds = new TypeMirrorSet(bParam.getBounds());
552       if (!aBounds.equals(bBounds)) {
553         return false;
554       }
555     }
556     return true;
557   }
558 
559   /**
560    * Returns a set of all abstract methods in the given TypeElement or inherited from ancestors. If
561    * any of the abstract methods has a return type or parameter type that is not currently defined
562    * then this method will throw an exception that will cause us to defer processing of the current
563    * class until a later annotation-processing round.
564    */
abstractMethods( TypeElement typeElement, ProcessingEnvironment processingEnv)565   static ImmutableSet<ExecutableElement> abstractMethods(
566       TypeElement typeElement, ProcessingEnvironment processingEnv) {
567     Set<ExecutableElement> methods =
568         getLocalAndInheritedMethods(
569             typeElement, processingEnv.getTypeUtils(), processingEnv.getElementUtils());
570     ImmutableSet.Builder<ExecutableElement> abstractMethods = ImmutableSet.builder();
571     for (ExecutableElement method : methods) {
572       if (method.getModifiers().contains(Modifier.ABSTRACT)) {
573         MissingTypes.deferIfMissingTypesIn(method);
574         abstractMethods.add(method);
575       }
576     }
577     return abstractMethods.build();
578   }
579 
typeParamsString()580   private String typeParamsString() {
581     return TypeSimplifier.actualTypeParametersString(autoValueClass);
582   }
583 }
584