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