• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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.AnnotationMirrors.getAnnotationValue;
19 import static com.google.auto.common.GeneratedAnnotations.generatedAnnotation;
20 import static com.google.auto.common.MoreElements.getPackage;
21 import static com.google.auto.common.MoreElements.isAnnotationPresent;
22 import static com.google.auto.common.MoreStreams.toImmutableList;
23 import static com.google.auto.common.MoreStreams.toImmutableSet;
24 import static com.google.auto.value.processor.ClassNames.AUTO_VALUE_PACKAGE_NAME;
25 import static com.google.auto.value.processor.ClassNames.COPY_ANNOTATIONS_NAME;
26 import static com.google.common.collect.Iterables.getOnlyElement;
27 import static com.google.common.collect.Sets.union;
28 import static java.util.stream.Collectors.joining;
29 import static java.util.stream.Collectors.toCollection;
30 import static java.util.stream.Collectors.toList;
31 import static java.util.stream.Collectors.toSet;
32 
33 import com.google.auto.common.MoreElements;
34 import com.google.auto.common.MoreTypes;
35 import com.google.auto.common.Visibility;
36 import com.google.auto.value.processor.MissingTypes.MissingTypeException;
37 import com.google.common.base.Throwables;
38 import com.google.common.collect.ImmutableBiMap;
39 import com.google.common.collect.ImmutableList;
40 import com.google.common.collect.ImmutableListMultimap;
41 import com.google.common.collect.ImmutableMap;
42 import com.google.common.collect.ImmutableSet;
43 import java.io.IOException;
44 import java.io.Serializable;
45 import java.io.Writer;
46 import java.lang.annotation.ElementType;
47 import java.lang.annotation.Inherited;
48 import java.lang.annotation.Target;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Collection;
52 import java.util.EnumMap;
53 import java.util.HashSet;
54 import java.util.LinkedHashMap;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Optional;
58 import java.util.OptionalInt;
59 import java.util.Set;
60 import java.util.function.Predicate;
61 import java.util.stream.IntStream;
62 import javax.annotation.processing.AbstractProcessor;
63 import javax.annotation.processing.ProcessingEnvironment;
64 import javax.annotation.processing.RoundEnvironment;
65 import javax.lang.model.SourceVersion;
66 import javax.lang.model.element.AnnotationMirror;
67 import javax.lang.model.element.AnnotationValue;
68 import javax.lang.model.element.Element;
69 import javax.lang.model.element.ElementKind;
70 import javax.lang.model.element.ExecutableElement;
71 import javax.lang.model.element.Modifier;
72 import javax.lang.model.element.Name;
73 import javax.lang.model.element.QualifiedNameable;
74 import javax.lang.model.element.TypeElement;
75 import javax.lang.model.element.TypeParameterElement;
76 import javax.lang.model.element.VariableElement;
77 import javax.lang.model.type.DeclaredType;
78 import javax.lang.model.type.TypeKind;
79 import javax.lang.model.type.TypeMirror;
80 import javax.lang.model.util.ElementFilter;
81 import javax.lang.model.util.Elements;
82 import javax.lang.model.util.SimpleAnnotationValueVisitor8;
83 import javax.lang.model.util.Types;
84 import javax.tools.Diagnostic;
85 import javax.tools.JavaFileObject;
86 
87 /**
88  * Shared code between {@link AutoValueProcessor}, {@link AutoOneOfProcessor}, and {@link
89  * AutoBuilderProcessor}.
90  *
91  * @author emcmanus@google.com (Éamonn McManus)
92  */
93 abstract class AutoValueishProcessor extends AbstractProcessor {
94   private final String annotationClassName;
95 
96   /**
97    * Qualified names of {@code @AutoValue} or {@code AutoOneOf} classes that we attempted to process
98    * but had to abandon because we needed other types that they referenced and those other types
99    * were missing.
100    */
101   private final List<String> deferredTypeNames = new ArrayList<>();
102 
AutoValueishProcessor(String annotationClassName)103   AutoValueishProcessor(String annotationClassName) {
104     this.annotationClassName = annotationClassName;
105   }
106 
107   /** The annotation we are processing, {@code AutoValue} or {@code AutoOneOf}. */
108   private TypeElement annotationType;
109   /** The simple name of {@link #annotationType}. */
110   private String simpleAnnotationName;
111 
112   private ErrorReporter errorReporter;
113   private Nullables nullables;
114 
115   @Override
init(ProcessingEnvironment processingEnv)116   public synchronized void init(ProcessingEnvironment processingEnv) {
117     super.init(processingEnv);
118     errorReporter = new ErrorReporter(processingEnv);
119     nullables = new Nullables(processingEnv);
120   }
121 
errorReporter()122   final ErrorReporter errorReporter() {
123     return errorReporter;
124   }
125 
typeUtils()126   final Types typeUtils() {
127     return processingEnv.getTypeUtils();
128   }
129 
elementUtils()130   final Elements elementUtils() {
131     return processingEnv.getElementUtils();
132   }
133 
134   /**
135    * Qualified names of {@code @AutoValue} or {@code AutoOneOf} classes that we attempted to process
136    * but had to abandon because we needed other types that they referenced and those other types
137    * were missing. This is used by tests.
138    */
deferredTypeNames()139   final ImmutableList<String> deferredTypeNames() {
140     return ImmutableList.copyOf(deferredTypeNames);
141   }
142 
143   @Override
getSupportedSourceVersion()144   public final SourceVersion getSupportedSourceVersion() {
145     return SourceVersion.latestSupported();
146   }
147 
148   /**
149    * A property of an {@code @AutoValue} or {@code @AutoOneOf} class, defined by one of its abstract
150    * methods. An instance of this class is made available to the Velocity template engine for each
151    * property. The public methods of this class define JavaBeans-style properties that are
152    * accessible from templates. For example {@link #getType()} means we can write {@code $p.type}
153    * for a Velocity variable {@code $p} that is a {@code Property}.
154    */
155   public static class Property {
156     private final String name;
157     private final String identifier;
158     private final String type;
159     private final TypeMirror typeMirror;
160     private final Optional<String> nullableAnnotation;
161     private final Optionalish optional;
162     private final String getter;
163 
Property( String name, String identifier, String type, TypeMirror typeMirror, Optional<String> nullableAnnotation, String getter)164     Property(
165         String name,
166         String identifier,
167         String type,
168         TypeMirror typeMirror,
169         Optional<String> nullableAnnotation,
170         String getter) {
171       this.name = name;
172       this.identifier = identifier;
173       this.type = type;
174       this.typeMirror = typeMirror;
175       this.nullableAnnotation = nullableAnnotation;
176       this.optional = Optionalish.createIfOptional(typeMirror);
177       this.getter = getter;
178     }
179 
180     /**
181      * Returns the name of the property as it should be used when declaring identifiers (fields and
182      * parameters). If the original getter method was {@code foo()} then this will be {@code foo}.
183      * If it was {@code getFoo()} then it will be {@code foo}. If it was {@code getPackage()} then
184      * it will be something like {@code package0}, since {@code package} is a reserved word.
185      */
186     @Override
toString()187     public String toString() {
188       return identifier;
189     }
190 
191     /**
192      * Returns the name of the property as it should be used in strings visible to users. This is
193      * usually the same as {@code toString()}, except that if we had to use an identifier like
194      * "package0" because "package" is a reserved word, the name here will be the original
195      * "package".
196      */
getName()197     public String getName() {
198       return name;
199     }
200 
getTypeMirror()201     public TypeMirror getTypeMirror() {
202       return typeMirror;
203     }
204 
getType()205     public String getType() {
206       return type;
207     }
208 
getKind()209     public TypeKind getKind() {
210       return typeMirror.getKind();
211     }
212 
213     /**
214      * Returns an {@link Optionalish} representing the kind of Optional that this property's type
215      * is, or null if the type is not an Optional of any kind.
216      */
getOptional()217     public Optionalish getOptional() {
218       return optional;
219     }
220 
221     /**
222      * Returns the string to use as a method annotation to indicate the nullability of this
223      * property. It is either the empty string, if the property is not nullable, or an annotation
224      * string with a trailing space, such as {@code "@`javax.annotation.Nullable` "}, where the
225      * {@code ``} is the encoding used by {@link TypeEncoder}. If the property is nullable by virtue
226      * of its <i>type</i> rather than its method being {@code @Nullable}, this method returns the
227      * empty string, because the {@code @Nullable} will appear when the type is spelled out. In this
228      * case, {@link #nullableAnnotation} is present but empty.
229      */
getNullableAnnotation()230     public final String getNullableAnnotation() {
231       return nullableAnnotation.orElse("");
232     }
233 
isNullable()234     public boolean isNullable() {
235       return nullableAnnotation.isPresent();
236     }
237 
238     /**
239      * Returns the name of the getter method for this property as defined by the {@code @AutoValue}
240      * or {@code @AutoBuilder} class. For property {@code foo}, this will be {@code foo} or {@code
241      * getFoo} or {@code isFoo}. For AutoValue, this will also be the name of a getter method in a
242      * builder; in the case of AutoBuilder it will only be that and may be null.
243      */
getGetter()244     public String getGetter() {
245       return getter;
246     }
247   }
248 
249   /** A {@link Property} that corresponds to an abstract getter method in the source. */
250   public static class GetterProperty extends Property {
251     private final ExecutableElement method;
252     private final ImmutableList<String> fieldAnnotations;
253     private final ImmutableList<String> methodAnnotations;
254 
GetterProperty( String name, String identifier, ExecutableElement method, String type, ImmutableList<String> fieldAnnotations, ImmutableList<String> methodAnnotations, Optional<String> nullableAnnotation)255     GetterProperty(
256         String name,
257         String identifier,
258         ExecutableElement method,
259         String type,
260         ImmutableList<String> fieldAnnotations,
261         ImmutableList<String> methodAnnotations,
262         Optional<String> nullableAnnotation) {
263       super(
264           name,
265           identifier,
266           type,
267           method.getReturnType(),
268           nullableAnnotation,
269           method.getSimpleName().toString());
270       this.method = method;
271       this.fieldAnnotations = fieldAnnotations;
272       this.methodAnnotations = methodAnnotations;
273     }
274 
275     /**
276      * Returns the annotations (in string form) that should be applied to the property's field
277      * declaration.
278      */
getFieldAnnotations()279     public List<String> getFieldAnnotations() {
280       return fieldAnnotations;
281     }
282 
283     /**
284      * Returns the annotations (in string form) that should be applied to the property's method
285      * implementation.
286      */
getMethodAnnotations()287     public List<String> getMethodAnnotations() {
288       return methodAnnotations;
289     }
290 
getAccess()291     public String getAccess() {
292       return SimpleMethod.access(method);
293     }
294 
295     @Override
equals(Object obj)296     public boolean equals(Object obj) {
297       return obj instanceof GetterProperty && ((GetterProperty) obj).method.equals(method);
298     }
299 
300     @Override
hashCode()301     public int hashCode() {
302       return method.hashCode();
303     }
304   }
305 
306   @Override
process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)307   public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
308     annotationType = elementUtils().getTypeElement(annotationClassName);
309     if (annotationType == null) {
310       // This should not happen. If the annotation type is not found, how did the processor get
311       // triggered?
312       processingEnv
313           .getMessager()
314           .printMessage(
315               Diagnostic.Kind.ERROR,
316               "Did not process @"
317                   + annotationClassName
318                   + " because the annotation class was not found");
319       return false;
320     }
321     simpleAnnotationName = annotationType.getSimpleName().toString();
322     List<TypeElement> deferredTypes =
323         deferredTypeNames.stream()
324             .map(name -> elementUtils().getTypeElement(name))
325             .collect(toList());
326     if (roundEnv.processingOver()) {
327       // This means that the previous round didn't generate any new sources, so we can't have found
328       // any new instances of @AutoValue; and we can't have any new types that are the reason a type
329       // was in deferredTypes.
330       for (TypeElement type : deferredTypes) {
331         errorReporter.reportError(
332             type,
333             "[AutoValueUndefined] Did not generate @%s class for %s because it references"
334                 + " undefined types",
335             simpleAnnotationName,
336             type.getQualifiedName());
337       }
338       return false;
339     }
340     Collection<? extends Element> annotatedElements =
341         roundEnv.getElementsAnnotatedWith(annotationType);
342     List<TypeElement> types =
343         new ImmutableList.Builder<TypeElement>()
344             .addAll(deferredTypes)
345             .addAll(ElementFilter.typesIn(annotatedElements))
346             .build();
347     deferredTypeNames.clear();
348     for (TypeElement type : types) {
349       try {
350         processType(type);
351       } catch (AbortProcessingException e) {
352         // We abandoned this type; continue with the next.
353       } catch (MissingTypeException e) {
354         // We abandoned this type, but only because we needed another type that it references and
355         // that other type was missing. It is possible that the missing type will be generated by
356         // further annotation processing, so we will try again on the next round (perhaps failing
357         // again and adding it back to the list). We save the name of the @AutoValue type rather
358         // than its TypeElement because it is not guaranteed that it will be represented by
359         // the same TypeElement on the next round.
360         deferredTypeNames.add(type.getQualifiedName().toString());
361       } catch (RuntimeException e) {
362         String trace = Throwables.getStackTraceAsString(e);
363         errorReporter.reportError(
364             type,
365             "[AutoValueException] @%s processor threw an exception: %s",
366             simpleAnnotationName,
367             trace);
368         throw e;
369       }
370     }
371     return false; // never claim annotation, because who knows what other processors want?
372   }
373 
374   /**
375    * Analyzes a single {@code @AutoValue} or {@code @AutoOneOf} class, and outputs the corresponding
376    * implementation class or classes.
377    *
378    * @param type the class with the {@code @AutoValue} or {@code @AutoOneOf} annotation.
379    */
processType(TypeElement type)380   abstract void processType(TypeElement type);
381 
382   /**
383    * Returns the appropriate {@code @Nullable} annotation to put on the implementation of the given
384    * property method, and indicates whether the property is in fact nullable. The annotation in
385    * question is on the method, not its return type. If instead the return type is
386    * {@code @Nullable}, this method returns {@code Optional.of("")}, to indicate that the property
387    * is nullable but the <i>method</i> isn't. The {@code @Nullable} annotation will instead appear
388    * when the return type of the method is spelled out in the implementation.
389    */
nullableAnnotationForMethod(ExecutableElement propertyMethod)390   abstract Optional<String> nullableAnnotationForMethod(ExecutableElement propertyMethod);
391 
392   /**
393    * Returns the ordered set of {@link Property} definitions for the given {@code @AutoValue} or
394    * {@code AutoOneOf} type.
395    *
396    * @param annotatedPropertyMethods a map from property methods to the method annotations that
397    *     should go on the implementation of those methods. These annotations are method annotations
398    *     specifically. Type annotations do not appear because they are considered part of the return
399    *     type and will appear when that is spelled out. Annotations that are excluded by {@code
400    *     AutoValue.CopyAnnotations} also do not appear here.
401    */
propertySet( ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsAndTypes, ImmutableListMultimap<ExecutableElement, AnnotationMirror> annotatedPropertyFields, ImmutableListMultimap<ExecutableElement, AnnotationMirror> annotatedPropertyMethods)402   final ImmutableSet<Property> propertySet(
403       ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsAndTypes,
404       ImmutableListMultimap<ExecutableElement, AnnotationMirror> annotatedPropertyFields,
405       ImmutableListMultimap<ExecutableElement, AnnotationMirror> annotatedPropertyMethods) {
406     ImmutableBiMap<ExecutableElement, String> methodToPropertyName =
407         propertyNameToMethodMap(propertyMethodsAndTypes.keySet()).inverse();
408     Map<ExecutableElement, String> methodToIdentifier = new LinkedHashMap<>(methodToPropertyName);
409     fixReservedIdentifiers(methodToIdentifier);
410 
411     ImmutableSet.Builder<Property> props = ImmutableSet.builder();
412     propertyMethodsAndTypes.forEach(
413         (propertyMethod, returnType) -> {
414           String propertyType =
415               TypeEncoder.encodeWithAnnotations(
416                   returnType, ImmutableList.of(), getExcludedAnnotationTypes(propertyMethod));
417           String propertyName = methodToPropertyName.get(propertyMethod);
418           String identifier = methodToIdentifier.get(propertyMethod);
419           ImmutableList<String> fieldAnnotations =
420               annotationStrings(annotatedPropertyFields.get(propertyMethod));
421           ImmutableList<AnnotationMirror> methodAnnotationMirrors =
422               annotatedPropertyMethods.get(propertyMethod);
423           ImmutableList<String> methodAnnotations = annotationStrings(methodAnnotationMirrors);
424           Optional<String> nullableAnnotation = nullableAnnotationForMethod(propertyMethod);
425           Property p =
426               new GetterProperty(
427                   propertyName,
428                   identifier,
429                   propertyMethod,
430                   propertyType,
431                   fieldAnnotations,
432                   methodAnnotations,
433                   nullableAnnotation);
434           props.add(p);
435           if (p.isNullable() && returnType.getKind().isPrimitive()) {
436             errorReporter()
437                 .reportError(
438                     propertyMethod, "[AutoValueNullPrimitive] Primitive types cannot be @Nullable");
439           }
440         });
441     return props.build();
442   }
443 
444   /** Defines the template variables that are shared by AutoValue, AutoOneOf, and AutoBuilder. */
defineSharedVarsForType( TypeElement type, ImmutableSet<ExecutableElement> methods, AutoValueishTemplateVars vars)445   final void defineSharedVarsForType(
446       TypeElement type, ImmutableSet<ExecutableElement> methods, AutoValueishTemplateVars vars) {
447     vars.pkg = TypeSimplifier.packageNameOf(type);
448     vars.origClass = TypeSimplifier.classNameOf(type);
449     vars.simpleClassName = TypeSimplifier.simpleNameOf(vars.origClass);
450     vars.generated =
451         generatedAnnotation(elementUtils(), processingEnv.getSourceVersion())
452             .map(annotation -> TypeEncoder.encode(annotation.asType()))
453             .orElse("");
454     vars.formalTypes = TypeEncoder.typeParametersString(type.getTypeParameters());
455     vars.actualTypes = TypeSimplifier.actualTypeParametersString(type);
456     vars.wildcardTypes = wildcardTypeParametersString(type);
457     vars.annotations = copiedClassAnnotations(type);
458     Map<ObjectMethod, ExecutableElement> methodsToGenerate =
459         determineObjectMethodsToGenerate(methods);
460     vars.toString = methodsToGenerate.containsKey(ObjectMethod.TO_STRING);
461     vars.equals = methodsToGenerate.containsKey(ObjectMethod.EQUALS);
462     vars.hashCode = methodsToGenerate.containsKey(ObjectMethod.HASH_CODE);
463     Optional<AnnotationMirror> nullable = nullables.appropriateNullableGivenMethods(methods);
464     vars.equalsParameterType = equalsParameterType(methodsToGenerate, nullable);
465     vars.serialVersionUID = getSerialVersionUID(type);
466   }
467 
468   /** Returns the spelling to be used in the generated code for the given list of annotations. */
annotationStrings(List<? extends AnnotationMirror> annotations)469   static ImmutableList<String> annotationStrings(List<? extends AnnotationMirror> annotations) {
470     // TODO(b/68008628): use ImmutableList.toImmutableList() when that works.
471     return annotations.stream()
472         .map(AnnotationOutput::sourceFormForAnnotation)
473         .collect(toImmutableList());
474   }
475 
476   /**
477    * Returns the name of the generated {@code @AutoValue} or {@code @AutoOneOf} class, for example
478    * {@code AutoOneOf_TaskResult} or {@code $$AutoValue_SimpleMethod}.
479    *
480    * @param type the name of the type bearing the {@code @AutoValue} or {@code @AutoOneOf}
481    *     annotation.
482    * @param prefix the prefix to use in the generated class. This may start with one or more dollar
483    *     signs, for an {@code @AutoValue} implementation where there are AutoValue extensions.
484    */
generatedClassName(TypeElement type, String prefix)485   static String generatedClassName(TypeElement type, String prefix) {
486     String name = type.getSimpleName().toString();
487     while (type.getEnclosingElement() instanceof TypeElement) {
488       type = MoreElements.asType(type.getEnclosingElement());
489       name = type.getSimpleName() + "_" + name;
490     }
491     String pkg = TypeSimplifier.packageNameOf(type);
492     String dot = pkg.isEmpty() ? "" : ".";
493     return pkg + dot + prefix + name;
494   }
495 
isJavaLangObject(TypeElement type)496   private static boolean isJavaLangObject(TypeElement type) {
497     return type.getSuperclass().getKind() == TypeKind.NONE && type.getKind() == ElementKind.CLASS;
498   }
499 
500   enum ObjectMethod {
501     NONE,
502     TO_STRING,
503     EQUALS,
504     HASH_CODE
505   }
506 
507   /**
508    * Determines which of the three public non-final methods from {@code java.lang.Object}, if any,
509    * is overridden by the given method.
510    */
objectMethodToOverride(ExecutableElement method)511   static ObjectMethod objectMethodToOverride(ExecutableElement method) {
512     String name = method.getSimpleName().toString();
513     switch (method.getParameters().size()) {
514       case 0:
515         if (name.equals("toString")) {
516           return ObjectMethod.TO_STRING;
517         } else if (name.equals("hashCode")) {
518           return ObjectMethod.HASH_CODE;
519         }
520         break;
521       case 1:
522         if (name.equals("equals")) {
523           TypeMirror param = getOnlyElement(method.getParameters()).asType();
524           if (param.getKind().equals(TypeKind.DECLARED)) {
525             TypeElement paramType = MoreTypes.asTypeElement(param);
526             if (paramType.getQualifiedName().contentEquals("java.lang.Object")) {
527               return ObjectMethod.EQUALS;
528             }
529           }
530         }
531         break;
532       default:
533         // No relevant Object methods have more than one parameter.
534     }
535     return ObjectMethod.NONE;
536   }
537 
538   /** Returns a bi-map between property names and the corresponding abstract property methods. */
propertyNameToMethodMap( Set<ExecutableElement> propertyMethods)539   final ImmutableBiMap<String, ExecutableElement> propertyNameToMethodMap(
540       Set<ExecutableElement> propertyMethods) {
541     Map<String, ExecutableElement> map = new LinkedHashMap<>();
542     Set<String> reportedDups = new HashSet<>();
543     boolean allPrefixed = gettersAllPrefixed(propertyMethods);
544     for (ExecutableElement method : propertyMethods) {
545       String methodName = method.getSimpleName().toString();
546       String name = allPrefixed ? nameWithoutPrefix(methodName) : methodName;
547       ExecutableElement old = map.put(name, method);
548       if (old != null) {
549         List<ExecutableElement> contexts = new ArrayList<>(Arrays.asList(method));
550         if (reportedDups.add(name)) {
551           contexts.add(old);
552         }
553         // Report the error for both of the methods. If this is a third or further occurrence,
554         // reportedDups prevents us from reporting more than one error for the same method.
555         for (ExecutableElement context : contexts) {
556           errorReporter.reportError(
557               context,
558               "[AutoValueDupProperty] More than one @%s property called %s",
559               simpleAnnotationName,
560               name);
561         }
562       }
563     }
564     return ImmutableBiMap.copyOf(map);
565   }
566 
gettersAllPrefixed(Set<ExecutableElement> methods)567   private static boolean gettersAllPrefixed(Set<ExecutableElement> methods) {
568     return prefixedGettersIn(methods).size() == methods.size();
569   }
570 
571   /**
572    * Returns an appropriate annotation spelling to indicate the nullability of an element. If the
573    * return value is a non-empty Optional, that indicates that the element is nullable, and the
574    * string should be used to annotate it. If the return value is an empty Optional, the element is
575    * not nullable. The return value can be {@code Optional.of("")}, which indicates that the element
576    * is nullable but that the nullability comes from a type annotation. In this case, the annotation
577    * will appear when the type is written, and must not be specified again. If the Optional contains
578    * a present non-empty string then that string will end with a space.
579    *
580    * @param element the element that might be {@code @Nullable}, either a method or a parameter.
581    * @param elementType the relevant type of the element: the return type for a method, or the
582    *     parameter type for a parameter.
583    */
nullableAnnotationFor(Element element, TypeMirror elementType)584   static Optional<String> nullableAnnotationFor(Element element, TypeMirror elementType) {
585     List<? extends AnnotationMirror> typeAnnotations = elementType.getAnnotationMirrors();
586     if (nullableAnnotationIndex(typeAnnotations).isPresent()) {
587       return Optional.of("");
588     }
589     List<? extends AnnotationMirror> elementAnnotations = element.getAnnotationMirrors();
590     OptionalInt nullableAnnotationIndex = nullableAnnotationIndex(elementAnnotations);
591     if (nullableAnnotationIndex.isPresent()) {
592       ImmutableList<String> annotations = annotationStrings(elementAnnotations);
593       return Optional.of(annotations.get(nullableAnnotationIndex.getAsInt()) + " ");
594     } else {
595       return Optional.empty();
596     }
597   }
598 
nullableAnnotationIndex(List<? extends AnnotationMirror> annotations)599   private static OptionalInt nullableAnnotationIndex(List<? extends AnnotationMirror> annotations) {
600     return IntStream.range(0, annotations.size())
601         .filter(i -> isNullable(annotations.get(i)))
602         .findFirst();
603   }
604 
isNullable(AnnotationMirror annotation)605   private static boolean isNullable(AnnotationMirror annotation) {
606     return annotation.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable");
607   }
608 
609   /**
610    * Returns the subset of the given zero-arg methods whose names begin with {@code get}. Also
611    * includes {@code isFoo} methods if they return {@code boolean}. This corresponds to JavaBeans
612    * conventions.
613    */
prefixedGettersIn(Collection<ExecutableElement> methods)614   static ImmutableSet<ExecutableElement> prefixedGettersIn(Collection<ExecutableElement> methods) {
615     return methods.stream()
616         .filter(AutoValueishProcessor::isPrefixedGetter)
617         .collect(toImmutableSet());
618   }
619 
isPrefixedGetter(ExecutableElement method)620   static boolean isPrefixedGetter(ExecutableElement method) {
621     String name = method.getSimpleName().toString();
622     // Note that getfoo() (without a capital) is still a getter.
623     return (name.startsWith("get") && !name.equals("get"))
624         || (name.startsWith("is")
625             && !name.equals("is")
626             && method.getReturnType().getKind() == TypeKind.BOOLEAN);
627   }
628 
629   /**
630    * Returns the name of the property defined by the given getter. A getter called {@code getFoo()}
631    * or {@code isFoo()} defines a property called {@code foo}. For consistency with JavaBeans, a
632    * getter called {@code getHTMLPage()} defines a property called {@code HTMLPage}. The <a
633    * href="https://docs.oracle.com/javase/8/docs/api/java/beans/Introspector.html#decapitalize-java.lang.String-">
634    * rule</a> is: the name of the property is the part after {@code get} or {@code is}, with the
635    * first letter lowercased <i>unless</i> the first two letters are uppercase. This works well for
636    * the {@code HTMLPage} example, but in these more enlightened times we use {@code HtmlPage}
637    * anyway, so the special behaviour is not useful, and of course it behaves poorly with examples
638    * like {@code OAuth}.
639    */
nameWithoutPrefix(String name)640   static String nameWithoutPrefix(String name) {
641     if (name.startsWith("get")) {
642       name = name.substring(3);
643     } else {
644       assert name.startsWith("is");
645       name = name.substring(2);
646     }
647     return PropertyNames.decapitalizeLikeJavaBeans(name);
648   }
649 
650   /**
651    * Checks that, if the given {@code @AutoValue}, {@code @AutoOneOf}, or {@code @AutoBuilder} class
652    * is nested, it is static and not private. This check is not necessary for correctness, since the
653    * generated code would not compile if the check fails, but it produces better error messages for
654    * the user.
655    */
checkModifiersIfNested(TypeElement type)656   final void checkModifiersIfNested(TypeElement type) {
657     checkModifiersIfNested(type, type, simpleAnnotationName);
658   }
659 
checkModifiersIfNested(TypeElement type, TypeElement reportedType, String what)660   final void checkModifiersIfNested(TypeElement type, TypeElement reportedType, String what) {
661     ElementKind enclosingKind = type.getEnclosingElement().getKind();
662     if (enclosingKind.isClass() || enclosingKind.isInterface()) {
663       if (type.getModifiers().contains(Modifier.PRIVATE)) {
664         errorReporter.abortWithError(
665             reportedType, "[%sPrivate] @%s class must not be private", simpleAnnotationName, what);
666       } else if (Visibility.effectiveVisibilityOfElement(type).equals(Visibility.PRIVATE)) {
667         // The previous case, where the class itself is private, is much commoner so it deserves
668         // its own error message, even though it would be caught by the test here too.
669         errorReporter.abortWithError(
670             reportedType,
671             "[%sInPrivate] @%s class must not be nested in a private class",
672             simpleAnnotationName,
673             what);
674       }
675       if (!type.getModifiers().contains(Modifier.STATIC)) {
676         errorReporter.abortWithError(
677             reportedType, "[%sInner] Nested @%s class must be static", simpleAnnotationName, what);
678       }
679     }
680     // In principle type.getEnclosingElement() could be an ExecutableElement (for a class
681     // declared inside a method), but since RoundEnvironment.getElementsAnnotatedWith doesn't
682     // return such classes we won't see them here.
683   }
684 
685   /**
686    * Modifies the values of the given map to avoid reserved words. If we have a getter called {@code
687    * getPackage()} then we can't use the identifier {@code package} to represent its value since
688    * that's a reserved word.
689    */
fixReservedIdentifiers(Map<?, String> methodToIdentifier)690   static void fixReservedIdentifiers(Map<?, String> methodToIdentifier) {
691     for (Map.Entry<?, String> entry : methodToIdentifier.entrySet()) {
692       String name = entry.getValue();
693       if (SourceVersion.isKeyword(name) || !Character.isJavaIdentifierStart(name.codePointAt(0))) {
694         entry.setValue(disambiguate(name, methodToIdentifier.values()));
695       }
696     }
697   }
698 
disambiguate(String name, Collection<String> existingNames)699   private static String disambiguate(String name, Collection<String> existingNames) {
700     if (!Character.isJavaIdentifierStart(name.codePointAt(0))) {
701       // You've defined a getter called get1st(). What were you thinking?
702       name = "_" + name;
703       if (!existingNames.contains(name)) {
704         return name;
705       }
706     }
707     for (int i = 0; ; i++) {
708       String candidate = name + i;
709       if (!existingNames.contains(candidate)) {
710         return candidate;
711       }
712     }
713   }
714 
715   /**
716    * Given a list of all methods defined in or inherited by a class, returns a map indicating which
717    * of equals, hashCode, and toString should be generated. Each value in the map is the method that
718    * will be overridden by the generated method, which might be a method in {@code Object} or an
719    * abstract method in the {@code @AutoValue} class or an ancestor.
720    */
determineObjectMethodsToGenerate( Set<ExecutableElement> methods)721   private static Map<ObjectMethod, ExecutableElement> determineObjectMethodsToGenerate(
722       Set<ExecutableElement> methods) {
723     Map<ObjectMethod, ExecutableElement> methodsToGenerate = new EnumMap<>(ObjectMethod.class);
724     for (ExecutableElement method : methods) {
725       ObjectMethod override = objectMethodToOverride(method);
726       boolean canGenerate =
727           method.getModifiers().contains(Modifier.ABSTRACT)
728               || isJavaLangObject(MoreElements.asType(method.getEnclosingElement()));
729       if (!override.equals(ObjectMethod.NONE) && canGenerate) {
730         methodsToGenerate.put(override, method);
731       }
732     }
733     return methodsToGenerate;
734   }
735 
736   /**
737    * Returns the encoded parameter type of the {@code equals(Object)} method that is to be
738    * generated, or an empty string if the method is not being generated. The parameter type includes
739    * any type annotations, for example {@code @Nullable}.
740    *
741    * @param methodsToGenerate the Object methods that are being generated
742    * @param nullable the type of a {@code @Nullable} type annotation that we have found, if any
743    */
equalsParameterType( Map<ObjectMethod, ExecutableElement> methodsToGenerate, Optional<AnnotationMirror> nullable)744   static String equalsParameterType(
745       Map<ObjectMethod, ExecutableElement> methodsToGenerate, Optional<AnnotationMirror> nullable) {
746     ExecutableElement equals = methodsToGenerate.get(ObjectMethod.EQUALS);
747     if (equals == null) {
748       return ""; // this will not be referenced because no equals method will be generated
749     }
750     TypeMirror parameterType = equals.getParameters().get(0).asType();
751     // Add @Nullable if we know one and the parameter doesn't already have one.
752     // The @Nullable we add will be a type annotation, but if the parameter already has @Nullable
753     // then that might be a type annotation or an annotation on the parameter.
754     ImmutableList<AnnotationMirror> extraAnnotations =
755         nullable.isPresent() && !nullableAnnotationFor(equals, parameterType).isPresent()
756             ? ImmutableList.of(nullable.get())
757             : ImmutableList.of();
758     return TypeEncoder.encodeWithAnnotations(parameterType, extraAnnotations, ImmutableSet.of());
759   }
760 
761   /**
762    * Returns the subset of all abstract methods in the given set of methods. A given method
763    * signature is only mentioned once, even if it is inherited on more than one path. If any of the
764    * abstract methods has a return type or parameter type that is not currently defined then this
765    * method will throw an exception that will cause us to defer processing of the current class
766    * until a later annotation-processing round.
767    */
abstractMethodsIn(Iterable<ExecutableElement> methods)768   static ImmutableSet<ExecutableElement> abstractMethodsIn(Iterable<ExecutableElement> methods) {
769     Set<Name> noArgMethods = new HashSet<>();
770     ImmutableSet.Builder<ExecutableElement> abstracts = ImmutableSet.builder();
771     for (ExecutableElement method : methods) {
772       if (method.getModifiers().contains(Modifier.ABSTRACT)) {
773         MissingTypes.deferIfMissingTypesIn(method);
774         boolean hasArgs = !method.getParameters().isEmpty();
775         if (hasArgs || noArgMethods.add(method.getSimpleName())) {
776           // If an abstract method with the same signature is inherited on more than one path,
777           // we only add it once. At the moment we only do this check for no-arg methods. All
778           // methods that AutoValue will implement are either no-arg methods or equals(Object).
779           // The former is covered by this check and the latter will lead to vars.equals being
780           // set to true, regardless of how many times it appears. So the only case that is
781           // covered imperfectly here is that of a method that is inherited on more than one path
782           // and that will be consumed by an extension. We could check parameters as well, but that
783           // can be a bit tricky if any of the parameters are generic.
784           abstracts.add(method);
785         }
786       }
787     }
788     return abstracts.build();
789   }
790 
791   /**
792    * Returns the subset of property methods in the given set of abstract methods, with their actual
793    * return types. A property method has no arguments, is not void, and is not {@code hashCode()} or
794    * {@code toString()}.
795    */
propertyMethodsIn( Set<ExecutableElement> abstractMethods, TypeElement autoValueOrOneOfType)796   ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsIn(
797       Set<ExecutableElement> abstractMethods, TypeElement autoValueOrOneOfType) {
798     DeclaredType declaredType = MoreTypes.asDeclared(autoValueOrOneOfType.asType());
799     ImmutableSet.Builder<ExecutableElement> properties = ImmutableSet.builder();
800     for (ExecutableElement method : abstractMethods) {
801       if (method.getParameters().isEmpty()
802           && (method.getReturnType().getKind() != TypeKind.VOID || propertiesCanBeVoid())
803           && objectMethodToOverride(method) == ObjectMethod.NONE) {
804         properties.add(method);
805       }
806     }
807     return new EclipseHack(processingEnv).methodReturnTypes(properties.build(), declaredType);
808   }
809 
810   /** True if void properties are allowed. */
propertiesCanBeVoid()811   boolean propertiesCanBeVoid() {
812     return false;
813   }
814 
815   /**
816    * Checks that the return type of the given property method is allowed. Currently, this means that
817    * it cannot be an array, unless it is a primitive array.
818    */
checkReturnType(TypeElement autoValueClass, ExecutableElement getter)819   final void checkReturnType(TypeElement autoValueClass, ExecutableElement getter) {
820     TypeMirror type = getter.getReturnType();
821     if (type.getKind() == TypeKind.ARRAY) {
822       TypeMirror componentType = MoreTypes.asArray(type).getComponentType();
823       if (componentType.getKind().isPrimitive()) {
824         warnAboutPrimitiveArrays(autoValueClass, getter);
825       } else {
826         errorReporter.reportError(
827             getter,
828             "[AutoValueArray] An @%s class cannot define an array-valued property unless it is a"
829                 + " primitive array",
830             simpleAnnotationName);
831       }
832     }
833   }
834 
warnAboutPrimitiveArrays(TypeElement autoValueClass, ExecutableElement getter)835   private void warnAboutPrimitiveArrays(TypeElement autoValueClass, ExecutableElement getter) {
836     boolean suppressed = false;
837     Optional<AnnotationMirror> maybeAnnotation =
838         getAnnotationMirror(getter, "java.lang.SuppressWarnings");
839     if (maybeAnnotation.isPresent()) {
840       AnnotationValue listValue = getAnnotationValue(maybeAnnotation.get(), "value");
841       suppressed = listValue.accept(new ContainsMutableVisitor(), null);
842     }
843     if (!suppressed) {
844       // If the primitive-array property method is defined directly inside the @AutoValue class,
845       // then our error message should point directly to it. But if it is inherited, we don't
846       // want to try to make the error message point to the inherited definition, since that would
847       // be confusing (there is nothing wrong with the definition itself), and won't work if the
848       // inherited class is not being recompiled. Instead, in this case we point to the @AutoValue
849       // class itself, and we include extra text in the error message that shows the full name of
850       // the inherited method.
851       boolean sameClass = getter.getEnclosingElement().equals(autoValueClass);
852       Element element = sameClass ? getter : autoValueClass;
853       String context = sameClass ? "" : (" Method: " + getter.getEnclosingElement() + "." + getter);
854       errorReporter.reportWarning(
855           element,
856           "[AutoValueMutable] An @%s property that is a primitive array returns the original"
857               + " array, which can therefore be modified by the caller. If this is OK, you can"
858               + " suppress this warning with @SuppressWarnings(\"mutable\"). Otherwise, you should"
859               + " replace the property with an immutable type, perhaps a simple wrapper around the"
860               + " original array.%s",
861           simpleAnnotationName,
862           context);
863     }
864   }
865 
866   // Detects whether the visited AnnotationValue is an array that contains the string "mutable".
867   // The simpler approach using Element.getAnnotation(SuppressWarnings.class) doesn't work if
868   // the annotation has an undefined reference, like @SuppressWarnings(UNDEFINED).
869   // TODO(emcmanus): replace with a method from auto-common when that is available.
870   private static class ContainsMutableVisitor extends SimpleAnnotationValueVisitor8<Boolean, Void> {
871     @Override
visitArray(List<? extends AnnotationValue> list, Void p)872     public Boolean visitArray(List<? extends AnnotationValue> list, Void p) {
873       return list.stream().map(AnnotationValue::getValue).anyMatch("mutable"::equals);
874     }
875   }
876 
877   /**
878    * Returns a string like {@code "private static final long serialVersionUID = 1234L"} if {@code
879    * type instanceof Serializable} and defines {@code serialVersionUID = 1234L}; otherwise {@code
880    * ""}.
881    */
getSerialVersionUID(TypeElement type)882   final String getSerialVersionUID(TypeElement type) {
883     TypeMirror serializable = elementUtils().getTypeElement(Serializable.class.getName()).asType();
884     if (typeUtils().isAssignable(type.asType(), serializable)) {
885       List<VariableElement> fields = ElementFilter.fieldsIn(type.getEnclosedElements());
886       for (VariableElement field : fields) {
887         if (field.getSimpleName().contentEquals("serialVersionUID")) {
888           Object value = field.getConstantValue();
889           if (field.getModifiers().containsAll(Arrays.asList(Modifier.STATIC, Modifier.FINAL))
890               && field.asType().getKind() == TypeKind.LONG
891               && value != null) {
892             return "private static final long serialVersionUID = " + value + "L;";
893           } else {
894             errorReporter.reportError(
895                 field, "serialVersionUID must be a static final long compile-time constant");
896             break;
897           }
898         }
899       }
900     }
901     return "";
902   }
903 
904   /** Implements the semantics of {@code AutoValue.CopyAnnotations}; see its javadoc. */
annotationsToCopy( Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations)905   ImmutableList<AnnotationMirror> annotationsToCopy(
906       Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations) {
907     ImmutableList.Builder<AnnotationMirror> result = ImmutableList.builder();
908     for (AnnotationMirror annotation : typeOrMethod.getAnnotationMirrors()) {
909       String annotationFqName = getAnnotationFqName(annotation);
910       // To be included, the annotation should not be in com.google.auto.value,
911       // and it should not be in the excludedAnnotations set.
912       if (!isInAutoValuePackage(annotationFqName)
913           && !excludedAnnotations.contains(annotationFqName)
914           && annotationVisibleFrom(annotation, autoValueType)) {
915         result.add(annotation);
916       }
917     }
918 
919     return result.build();
920   }
921 
922   /**
923    * True if the given class name is in the com.google.auto.value package or a subpackage. False if
924    * the class name contains {@code Test}, since many AutoValue tests under com.google.auto.value
925    * define their own annotations.
926    */
isInAutoValuePackage(String className)927   private boolean isInAutoValuePackage(String className) {
928     return className.startsWith(AUTO_VALUE_PACKAGE_NAME) && !className.contains("Test");
929   }
930 
copiedClassAnnotations(TypeElement type)931   ImmutableList<String> copiedClassAnnotations(TypeElement type) {
932     // Only copy annotations from a class if it has @AutoValue.CopyAnnotations.
933     if (hasAnnotationMirror(type, COPY_ANNOTATIONS_NAME)) {
934       Set<String> excludedAnnotations =
935           ImmutableSet.<String>builder()
936               .addAll(getExcludedAnnotationClassNames(type))
937               .addAll(getAnnotationsMarkedWithInherited(type))
938               //
939               // Kotlin classes have an intrinsic @Metadata annotation generated
940               // onto them by kotlinc. This annotation is specific to the annotated
941               // class and should not be implicitly copied. Doing so can mislead
942               // static analysis or metaprogramming tooling that reads the data
943               // contained in these annotations.
944               //
945               // It may be surprising to see AutoValue classes written in Kotlin
946               // when they could be written as Kotlin data classes, but this can
947               // come up in cases where consumers rely on AutoValue features or
948               // extensions that are not available in data classes.
949               //
950               // See: https://github.com/google/auto/issues/1087
951               //
952               .add(ClassNames.KOTLIN_METADATA_NAME)
953               .build();
954 
955       return copyAnnotations(type, type, excludedAnnotations);
956     } else {
957       return ImmutableList.of();
958     }
959   }
960 
961   /** Implements the semantics of {@code AutoValue.CopyAnnotations}; see its javadoc. */
copyAnnotations( Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations)962   private ImmutableList<String> copyAnnotations(
963       Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations) {
964     ImmutableList<AnnotationMirror> annotationsToCopy =
965         annotationsToCopy(autoValueType, typeOrMethod, excludedAnnotations);
966     return annotationStrings(annotationsToCopy);
967   }
968 
969   /**
970    * Returns the contents of the {@code AutoValue.CopyAnnotations.exclude} element, as a set of
971    * {@code TypeMirror} where each type is an annotation type.
972    */
getExcludedAnnotationTypes(Element element)973   private Set<TypeMirror> getExcludedAnnotationTypes(Element element) {
974     Optional<AnnotationMirror> maybeAnnotation =
975         getAnnotationMirror(element, COPY_ANNOTATIONS_NAME);
976     if (!maybeAnnotation.isPresent()) {
977       return ImmutableSet.of();
978     }
979 
980     @SuppressWarnings("unchecked")
981     List<AnnotationValue> excludedClasses =
982         (List<AnnotationValue>) getAnnotationValue(maybeAnnotation.get(), "exclude").getValue();
983     return excludedClasses.stream()
984         .map(annotationValue -> (DeclaredType) annotationValue.getValue())
985         .collect(toCollection(TypeMirrorSet::new));
986   }
987 
988   /**
989    * Returns the contents of the {@code AutoValue.CopyAnnotations.exclude} element, as a set of
990    * strings that are fully-qualified class names.
991    */
getExcludedAnnotationClassNames(Element element)992   private Set<String> getExcludedAnnotationClassNames(Element element) {
993     return getExcludedAnnotationTypes(element).stream()
994         .map(MoreTypes::asTypeElement)
995         .map(typeElement -> typeElement.getQualifiedName().toString())
996         .collect(toSet());
997   }
998 
getAnnotationsMarkedWithInherited(Element element)999   private static Set<String> getAnnotationsMarkedWithInherited(Element element) {
1000     return element.getAnnotationMirrors().stream()
1001         .filter(a -> isAnnotationPresent(a.getAnnotationType().asElement(), Inherited.class))
1002         .map(a -> getAnnotationFqName(a))
1003         .collect(toSet());
1004   }
1005 
1006   /**
1007    * Returns the fully-qualified name of an annotation-mirror, e.g.
1008    * "com.google.auto.value.AutoValue".
1009    */
getAnnotationFqName(AnnotationMirror annotation)1010   private static String getAnnotationFqName(AnnotationMirror annotation) {
1011     return ((QualifiedNameable) annotation.getAnnotationType().asElement())
1012         .getQualifiedName()
1013         .toString();
1014   }
1015 
propertyMethodAnnotationMap( TypeElement type, ImmutableSet<ExecutableElement> propertyMethods)1016   final ImmutableListMultimap<ExecutableElement, AnnotationMirror> propertyMethodAnnotationMap(
1017       TypeElement type, ImmutableSet<ExecutableElement> propertyMethods) {
1018     ImmutableListMultimap.Builder<ExecutableElement, AnnotationMirror> builder =
1019         ImmutableListMultimap.builder();
1020     for (ExecutableElement propertyMethod : propertyMethods) {
1021       builder.putAll(propertyMethod, propertyMethodAnnotations(type, propertyMethod));
1022     }
1023     return builder.build();
1024   }
1025 
propertyMethodAnnotations( TypeElement type, ExecutableElement method)1026   private ImmutableList<AnnotationMirror> propertyMethodAnnotations(
1027       TypeElement type, ExecutableElement method) {
1028     ImmutableSet<String> excludedAnnotations =
1029         ImmutableSet.<String>builder()
1030             .addAll(getExcludedAnnotationClassNames(method))
1031             .add(Override.class.getCanonicalName())
1032             .build();
1033 
1034     // We need to exclude type annotations from the ones being output on the method, since
1035     // they will be output as part of the method's return type.
1036     Set<String> returnTypeAnnotations = getReturnTypeAnnotations(method, a -> true);
1037     Set<String> excluded = union(excludedAnnotations, returnTypeAnnotations);
1038     return annotationsToCopy(type, method, excluded);
1039   }
1040 
propertyFieldAnnotationMap( TypeElement type, ImmutableSet<ExecutableElement> propertyMethods)1041   final ImmutableListMultimap<ExecutableElement, AnnotationMirror> propertyFieldAnnotationMap(
1042       TypeElement type, ImmutableSet<ExecutableElement> propertyMethods) {
1043     ImmutableListMultimap.Builder<ExecutableElement, AnnotationMirror> builder =
1044         ImmutableListMultimap.builder();
1045     for (ExecutableElement propertyMethod : propertyMethods) {
1046       builder.putAll(propertyMethod, propertyFieldAnnotations(type, propertyMethod));
1047     }
1048     return builder.build();
1049   }
1050 
propertyFieldAnnotations( TypeElement type, ExecutableElement method)1051   private ImmutableList<AnnotationMirror> propertyFieldAnnotations(
1052       TypeElement type, ExecutableElement method) {
1053     if (!hasAnnotationMirror(method, COPY_ANNOTATIONS_NAME)) {
1054       return ImmutableList.of();
1055     }
1056     ImmutableSet<String> excludedAnnotations =
1057         ImmutableSet.<String>builder()
1058             .addAll(getExcludedAnnotationClassNames(method))
1059             .add(Override.class.getCanonicalName())
1060             .build();
1061 
1062     // We need to exclude type annotations from the ones being output on the method, since
1063     // they will be output as part of the field's type.
1064     Set<String> returnTypeAnnotations =
1065         getReturnTypeAnnotations(method, this::annotationAppliesToFields);
1066     Set<String> nonFieldAnnotations =
1067         method.getAnnotationMirrors().stream()
1068             .map(a -> a.getAnnotationType().asElement())
1069             .map(MoreElements::asType)
1070             .filter(a -> !annotationAppliesToFields(a))
1071             .map(e -> e.getQualifiedName().toString())
1072             .collect(toSet());
1073 
1074     Set<String> excluded =
1075         ImmutableSet.<String>builder()
1076             .addAll(excludedAnnotations)
1077             .addAll(returnTypeAnnotations)
1078             .addAll(nonFieldAnnotations)
1079             .build();
1080     return annotationsToCopy(type, method, excluded);
1081   }
1082 
getReturnTypeAnnotations( ExecutableElement method, Predicate<TypeElement> typeFilter)1083   private Set<String> getReturnTypeAnnotations(
1084       ExecutableElement method, Predicate<TypeElement> typeFilter) {
1085     return method.getReturnType().getAnnotationMirrors().stream()
1086         .map(a -> a.getAnnotationType().asElement())
1087         .map(MoreElements::asType)
1088         .filter(typeFilter)
1089         .map(e -> e.getQualifiedName().toString())
1090         .collect(toSet());
1091   }
1092 
annotationAppliesToFields(TypeElement annotation)1093   private boolean annotationAppliesToFields(TypeElement annotation) {
1094     Target target = annotation.getAnnotation(Target.class);
1095     return target == null || Arrays.asList(target.value()).contains(ElementType.FIELD);
1096   }
1097 
annotationVisibleFrom(AnnotationMirror annotation, Element from)1098   private boolean annotationVisibleFrom(AnnotationMirror annotation, Element from) {
1099     Element annotationElement = annotation.getAnnotationType().asElement();
1100     Visibility visibility = Visibility.effectiveVisibilityOfElement(annotationElement);
1101     switch (visibility) {
1102       case PUBLIC:
1103         return true;
1104       case PROTECTED:
1105         // If the annotation is protected, it must be inside another class, call it C. If our
1106         // @AutoValue class is Foo then, for the annotation to be visible, either Foo must be in the
1107         // same package as C or Foo must be a subclass of C. If the annotation is visible from Foo
1108         // then it is also visible from our generated subclass AutoValue_Foo.
1109         // The protected case only applies to method annotations. An annotation on the AutoValue_Foo
1110         // class itself can't be protected, even if AutoValue_Foo ultimately inherits from the
1111         // class that defines the annotation. The JLS says "Access is permitted only within the
1112         // body of a subclass":
1113         // https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1
1114         // AutoValue_Foo is a top-level class, so an annotation on it cannot be in the body of a
1115         // subclass of anything.
1116         return getPackage(annotationElement).equals(getPackage(from))
1117             || typeUtils()
1118                 .isSubtype(from.asType(), annotationElement.getEnclosingElement().asType());
1119       case DEFAULT:
1120         return getPackage(annotationElement).equals(getPackage(from));
1121       default:
1122         return false;
1123     }
1124   }
1125 
1126   /**
1127    * Returns the {@code @AutoValue} or {@code @AutoOneOf} type parameters, with a ? for every type.
1128    * If we have {@code @AutoValue abstract class Foo<T extends Something>} then this method will
1129    * return just {@code <?>}.
1130    */
wildcardTypeParametersString(TypeElement type)1131   private static String wildcardTypeParametersString(TypeElement type) {
1132     List<? extends TypeParameterElement> typeParameters = type.getTypeParameters();
1133     if (typeParameters.isEmpty()) {
1134       return "";
1135     } else {
1136       return typeParameters.stream().map(e -> "?").collect(joining(", ", "<", ">"));
1137     }
1138   }
1139 
1140   // TODO(emcmanus,ronshapiro): move to auto-common
getAnnotationMirror(Element element, String annotationName)1141   static Optional<AnnotationMirror> getAnnotationMirror(Element element, String annotationName) {
1142     for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
1143       TypeElement annotationElement = MoreTypes.asTypeElement(annotation.getAnnotationType());
1144       if (annotationElement.getQualifiedName().contentEquals(annotationName)) {
1145         return Optional.of(annotation);
1146       }
1147     }
1148     return Optional.empty();
1149   }
1150 
hasAnnotationMirror(Element element, String annotationName)1151   static boolean hasAnnotationMirror(Element element, String annotationName) {
1152     return getAnnotationMirror(element, annotationName).isPresent();
1153   }
1154 
writeSourceFile(String className, String text, TypeElement originatingType)1155   final void writeSourceFile(String className, String text, TypeElement originatingType) {
1156     try {
1157       JavaFileObject sourceFile =
1158           processingEnv.getFiler().createSourceFile(className, originatingType);
1159       try (Writer writer = sourceFile.openWriter()) {
1160         writer.write(text);
1161       }
1162     } catch (IOException e) {
1163       // This should really be an error, but we make it a warning in the hope of resisting Eclipse
1164       // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599. If that bug manifests, we may get
1165       // invoked more than once for the same file, so ignoring the ability to overwrite it is the
1166       // right thing to do. If we are unable to write for some other reason, we should get a compile
1167       // error later because user code will have a reference to the code we were supposed to
1168       // generate (new AutoValue_Foo() or whatever) and that reference will be undefined.
1169       errorReporter.reportWarning(
1170           originatingType,
1171           "[AutoValueCouldNotWrite] Could not write generated class %s: %s",
1172           className,
1173           e);
1174     }
1175   }
1176 }
1177