/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.auto.value.processor;

import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static com.google.auto.common.GeneratedAnnotations.generatedAnnotation;
import static com.google.auto.common.MoreElements.getPackage;
import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.auto.value.processor.ClassNames.AUTO_VALUE_PACKAGE_NAME;
import static com.google.auto.value.processor.ClassNames.COPY_ANNOTATIONS_NAME;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Sets.union;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.auto.common.Visibility;
import com.google.auto.value.processor.MissingTypes.MissingTypeException;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Predicate;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.QualifiedNameable;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleAnnotationValueVisitor8;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

/**
 * Shared code between AutoValueProcessor and AutoOneOfProcessor.
 *
 * @author emcmanus@google.com (Éamonn McManus)
 */
abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
  private final String annotationClassName;

  /**
   * Qualified names of {@code @AutoValue} or {@code AutoOneOf} classes that we attempted to process
   * but had to abandon because we needed other types that they referenced and those other types
   * were missing.
   */
  private final List<String> deferredTypeNames = new ArrayList<>();

  AutoValueOrOneOfProcessor(String annotationClassName) {
    this.annotationClassName = annotationClassName;
  }

  /** The annotation we are processing, {@code AutoValue} or {@code AutoOneOf}. */
  private TypeElement annotationType;
  /** The simple name of {@link #annotationType}. */
  private String simpleAnnotationName;

  private ErrorReporter errorReporter;

  @Override
  public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    errorReporter = new ErrorReporter(processingEnv);
  }

  final ErrorReporter errorReporter() {
    return errorReporter;
  }

  final Types typeUtils() {
    return processingEnv.getTypeUtils();
  }

  final Elements elementUtils() {
    return processingEnv.getElementUtils();
  }

  /**
   * Qualified names of {@code @AutoValue} or {@code AutoOneOf} classes that we attempted to process
   * but had to abandon because we needed other types that they referenced and those other types
   * were missing. This is used by tests.
   */
  final ImmutableList<String> deferredTypeNames() {
    return ImmutableList.copyOf(deferredTypeNames);
  }

  @Override
  public final SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latestSupported();
  }

  /**
   * A property of an {@code @AutoValue} or {@code @AutoOneOf} class, defined by one of its abstract
   * methods. An instance of this class is made available to the Velocity template engine for each
   * property. The public methods of this class define JavaBeans-style properties that are
   * accessible from templates. For example {@link #getType()} means we can write {@code $p.type}
   * for a Velocity variable {@code $p} that is a {@code Property}.
   */
  public static class Property {
    private final String name;
    private final String identifier;
    private final ExecutableElement method;
    private final String type;
    private final ImmutableList<String> fieldAnnotations;
    private final ImmutableList<String> methodAnnotations;
    private final Optional<String> nullableAnnotation;
    private final Optionalish optional;

    Property(
        String name,
        String identifier,
        ExecutableElement method,
        String type,
        ImmutableList<String> fieldAnnotations,
        ImmutableList<String> methodAnnotations,
        Optional<String> nullableAnnotation) {
      this.name = name;
      this.identifier = identifier;
      this.method = method;
      this.type = type;
      this.fieldAnnotations = fieldAnnotations;
      this.methodAnnotations = methodAnnotations;
      this.nullableAnnotation = nullableAnnotation;
      TypeMirror propertyType = method.getReturnType();
      this.optional = Optionalish.createIfOptional(propertyType);
    }

    /**
     * Returns the name of the property as it should be used when declaring identifiers (fields and
     * parameters). If the original getter method was {@code foo()} then this will be {@code foo}.
     * If it was {@code getFoo()} then it will be {@code foo}. If it was {@code getPackage()} then
     * it will be something like {@code package0}, since {@code package} is a reserved word.
     */
    @Override
    public String toString() {
      return identifier;
    }

    /**
     * Returns the name of the property as it should be used in strings visible to users. This is
     * usually the same as {@code toString()}, except that if we had to use an identifier like
     * "package0" because "package" is a reserved word, the name here will be the original
     * "package".
     */
    public String getName() {
      return name;
    }

    /**
     * Returns the name of the getter method for this property as defined by the {@code @AutoValue}
     * class. For property {@code foo}, this will be {@code foo} or {@code getFoo} or {@code isFoo}.
     */
    public String getGetter() {
      return method.getSimpleName().toString();
    }

    public TypeMirror getTypeMirror() {
      return method.getReturnType();
    }

    public String getType() {
      return type;
    }

    public TypeKind getKind() {
      return method.getReturnType().getKind();
    }

    /**
     * Returns the annotations (in string form) that should be applied to the property's field
     * declaration.
     */
    public List<String> getFieldAnnotations() {
      return fieldAnnotations;
    }

    /**
     * Returns the annotations (in string form) that should be applied to the property's method
     * implementation.
     */
    public List<String> getMethodAnnotations() {
      return methodAnnotations;
    }

    /**
     * Returns an {@link Optionalish} representing the kind of Optional that this property's type
     * is, or null if the type is not an Optional of any kind.
     */
    public Optionalish getOptional() {
      return optional;
    }

    /**
     * Returns the string to use as a method annotation to indicate the nullability of this
     * property. It is either the empty string, if the property is not nullable, or an annotation
     * string with a trailing space, such as {@code "@`javax.annotation.Nullable` "}, where the
     * {@code ``} is the encoding used by {@link TypeEncoder}. If the property is nullable by virtue
     * of its <i>type</i> rather than its method being {@code @Nullable}, this method returns the
     * empty string, because the {@code @Nullable} will appear when the type is spelled out. In this
     * case, {@link #nullableAnnotation} is present but empty.
     */
    public final String getNullableAnnotation() {
      return nullableAnnotation.orElse("");
    }

    public boolean isNullable() {
      return nullableAnnotation.isPresent();
    }

    public String getAccess() {
      return SimpleMethod.access(method);
    }

    @Override
    public boolean equals(Object obj) {
      return obj instanceof Property && ((Property) obj).method.equals(method);
    }

    @Override
    public int hashCode() {
      return method.hashCode();
    }
  }

  @Override
  public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    annotationType = elementUtils().getTypeElement(annotationClassName);
    if (annotationType == null) {
      // This should not happen. If the annotation type is not found, how did the processor get
      // triggered?
      processingEnv
          .getMessager()
          .printMessage(
              Diagnostic.Kind.ERROR,
              "Did not process @"
                  + annotationClassName
                  + " because the annotation class was not found");
      return false;
    }
    simpleAnnotationName = annotationType.getSimpleName().toString();
    List<TypeElement> deferredTypes =
        deferredTypeNames
            .stream()
            .map(name -> elementUtils().getTypeElement(name))
            .collect(toList());
    if (roundEnv.processingOver()) {
      // This means that the previous round didn't generate any new sources, so we can't have found
      // any new instances of @AutoValue; and we can't have any new types that are the reason a type
      // was in deferredTypes.
      for (TypeElement type : deferredTypes) {
        errorReporter.reportError(
            type,
            "Did not generate @%s class for %s because it references undefined types",
            simpleAnnotationName,
            type.getQualifiedName());
      }
      return false;
    }
    Collection<? extends Element> annotatedElements =
        roundEnv.getElementsAnnotatedWith(annotationType);
    List<TypeElement> types =
        new ImmutableList.Builder<TypeElement>()
            .addAll(deferredTypes)
            .addAll(ElementFilter.typesIn(annotatedElements))
            .build();
    deferredTypeNames.clear();
    for (TypeElement type : types) {
      try {
        processType(type);
      } catch (AbortProcessingException e) {
        // We abandoned this type; continue with the next.
      } catch (MissingTypeException e) {
        // We abandoned this type, but only because we needed another type that it references and
        // that other type was missing. It is possible that the missing type will be generated by
        // further annotation processing, so we will try again on the next round (perhaps failing
        // again and adding it back to the list). We save the name of the @AutoValue type rather
        // than its TypeElement because it is not guaranteed that it will be represented by
        // the same TypeElement on the next round.
        deferredTypeNames.add(type.getQualifiedName().toString());
      } catch (RuntimeException e) {
        String trace = Throwables.getStackTraceAsString(e);
        errorReporter.reportError(
            type, "@%s processor threw an exception: %s", simpleAnnotationName, trace);
        throw e;
      }
    }
    return false; // never claim annotation, because who knows what other processors want?
  }

  /**
   * Analyzes a single {@code @AutoValue} or {@code @AutoOneOf} class, and outputs the corresponding
   * implementation class or classes.
   *
   * @param type the class with the {@code @AutoValue} or {@code @AutoOneOf} annotation.
   */
  abstract void processType(TypeElement type);

  /**
   * Returns the appropriate {@code @Nullable} annotation to put on the implementation of the given
   * property method, and indicates whether the property is in fact nullable. The annotation in
   * question is on the method, not its return type. If instead the return type is
   * {@code @Nullable}, this method returns {@code Optional.of("")}, to indicate that the property
   * is nullable but the <i>method</i> isn't. The {@code @Nullable} annotation will instead appear
   * when the return type of the method is spelled out in the implementation.
   */
  abstract Optional<String> nullableAnnotationForMethod(ExecutableElement propertyMethod);

  /**
   * Returns the ordered set of {@link Property} definitions for the given {@code @AutoValue} or
   * {@code AutoOneOf} type.
   *
   * @param annotatedPropertyMethods a map from property methods to the method annotations that
   *     should go on the implementation of those methods. These annotations are method annotations
   *     specifically. Type annotations do not appear because they are considered part of the return
   *     type and will appear when that is spelled out. Annotations that are excluded by {@code
   *     AutoValue.CopyAnnotations} also do not appear here.
   */
  final ImmutableSet<Property> propertySet(
      ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsAndTypes,
      ImmutableListMultimap<ExecutableElement, AnnotationMirror> annotatedPropertyFields,
      ImmutableListMultimap<ExecutableElement, AnnotationMirror> annotatedPropertyMethods) {
    ImmutableBiMap<ExecutableElement, String> methodToPropertyName =
        propertyNameToMethodMap(propertyMethodsAndTypes.keySet()).inverse();
    Map<ExecutableElement, String> methodToIdentifier = new LinkedHashMap<>(methodToPropertyName);
    fixReservedIdentifiers(methodToIdentifier);

    ImmutableSet.Builder<Property> props = ImmutableSet.builder();
    propertyMethodsAndTypes.forEach(
        (propertyMethod, returnType) -> {
          String propertyType = TypeEncoder.encodeWithAnnotations(
              returnType, getExcludedAnnotationTypes(propertyMethod));
          String propertyName = methodToPropertyName.get(propertyMethod);
          String identifier = methodToIdentifier.get(propertyMethod);
          ImmutableList<String> fieldAnnotations =
              annotationStrings(annotatedPropertyFields.get(propertyMethod));
          ImmutableList<AnnotationMirror> methodAnnotationMirrors =
              annotatedPropertyMethods.get(propertyMethod);
          ImmutableList<String> methodAnnotations = annotationStrings(methodAnnotationMirrors);
          Optional<String> nullableAnnotation = nullableAnnotationForMethod(propertyMethod);
          Property p =
              new Property(
                  propertyName,
                  identifier,
                  propertyMethod,
                  propertyType,
                  fieldAnnotations,
                  methodAnnotations,
                  nullableAnnotation);
          props.add(p);
          if (p.isNullable() && returnType.getKind().isPrimitive()) {
            errorReporter().reportError(propertyMethod, "Primitive types cannot be @Nullable");
          }
        });
    return props.build();
  }

  /** Defines the template variables that are shared by AutoValue and AutoOneOf. */
  final void defineSharedVarsForType(
      TypeElement type,
      ImmutableSet<ExecutableElement> methods,
      AutoValueOrOneOfTemplateVars vars) {
    vars.pkg = TypeSimplifier.packageNameOf(type);
    vars.origClass = TypeSimplifier.classNameOf(type);
    vars.simpleClassName = TypeSimplifier.simpleNameOf(vars.origClass);
    vars.generated =
        generatedAnnotation(elementUtils(), processingEnv.getSourceVersion())
            .map(annotation -> TypeEncoder.encode(annotation.asType()))
            .orElse("");
    vars.formalTypes = TypeEncoder.formalTypeParametersString(type);
    vars.actualTypes = TypeSimplifier.actualTypeParametersString(type);
    vars.wildcardTypes = wildcardTypeParametersString(type);
    vars.annotations = copiedClassAnnotations(type);
    Map<ObjectMethod, ExecutableElement> methodsToGenerate =
        determineObjectMethodsToGenerate(methods);
    vars.toString = methodsToGenerate.containsKey(ObjectMethod.TO_STRING);
    vars.equals = methodsToGenerate.containsKey(ObjectMethod.EQUALS);
    vars.hashCode = methodsToGenerate.containsKey(ObjectMethod.HASH_CODE);
    vars.equalsParameterType = equalsParameterType(methodsToGenerate);
  }

  /** Returns the spelling to be used in the generated code for the given list of annotations. */
  static ImmutableList<String> annotationStrings(List<? extends AnnotationMirror> annotations) {
    // TODO(b/68008628): use ImmutableList.toImmutableList() when that works.
    return ImmutableList.copyOf(
        annotations.stream().map(AnnotationOutput::sourceFormForAnnotation).collect(toList()));
  }

  /**
   * Returns the name of the generated {@code @AutoValue} or {@code @AutoOneOf} class, for example
   * {@code AutoOneOf_TaskResult} or {@code $$AutoValue_SimpleMethod}.
   *
   * @param type the name of the type bearing the {@code @AutoValue} or {@code @AutoOneOf}
   *     annotation.
   * @param prefix the prefix to use in the generated class. This may start with one or more dollar
   *     signs, for an {@code @AutoValue} implementation where there are AutoValue extensions.
   */
  static String generatedClassName(TypeElement type, String prefix) {
    String name = type.getSimpleName().toString();
    while (type.getEnclosingElement() instanceof TypeElement) {
      type = (TypeElement) type.getEnclosingElement();
      name = type.getSimpleName() + "_" + name;
    }
    String pkg = TypeSimplifier.packageNameOf(type);
    String dot = pkg.isEmpty() ? "" : ".";
    return pkg + dot + prefix + name;
  }

  private static boolean isJavaLangObject(TypeElement type) {
    return type.getSuperclass().getKind() == TypeKind.NONE && type.getKind() == ElementKind.CLASS;
  }

  enum ObjectMethod {
    NONE,
    TO_STRING,
    EQUALS,
    HASH_CODE
  }

  /**
   * Determines which of the three public non-final methods from {@code java.lang.Object}, if any,
   * is overridden by the given method.
   */
  static ObjectMethod objectMethodToOverride(ExecutableElement method) {
    String name = method.getSimpleName().toString();
    switch (method.getParameters().size()) {
      case 0:
        if (name.equals("toString")) {
          return ObjectMethod.TO_STRING;
        } else if (name.equals("hashCode")) {
          return ObjectMethod.HASH_CODE;
        }
        break;
      case 1:
        if (name.equals("equals")) {
          TypeMirror param = getOnlyElement(method.getParameters()).asType();
          if (param.getKind().equals(TypeKind.DECLARED)) {
            TypeElement paramType = MoreTypes.asTypeElement(param);
            if (paramType.getQualifiedName().contentEquals("java.lang.Object")) {
              return ObjectMethod.EQUALS;
            }
          }
        }
        break;
      default:
        // No relevant Object methods have more than one parameter.
    }
    return ObjectMethod.NONE;
  }

  /** Returns a bi-map between property names and the corresponding abstract property methods. */
  final ImmutableBiMap<String, ExecutableElement> propertyNameToMethodMap(
      Set<ExecutableElement> propertyMethods) {
    Map<String, ExecutableElement> map = new LinkedHashMap<>();
    Set<String> reportedDups = new HashSet<>();
    boolean allPrefixed = gettersAllPrefixed(propertyMethods);
    for (ExecutableElement method : propertyMethods) {
      String methodName = method.getSimpleName().toString();
      String name = allPrefixed ? nameWithoutPrefix(methodName) : methodName;
      ExecutableElement old = map.put(name, method);
      if (old != null) {
        List<ExecutableElement> contexts = new ArrayList<>(Arrays.asList(method));
        if (reportedDups.add(name)) {
          contexts.add(old);
        }
        // Report the error for both of the methods. If this is a third or further occurrence,
        // reportedDups prevents us from reporting more than one error for the same method.
        for (ExecutableElement context : contexts) {
          errorReporter.reportError(
              context, "More than one @%s property called %s", simpleAnnotationName, name);
        }
      }
    }
    return ImmutableBiMap.copyOf(map);
  }

  private static boolean gettersAllPrefixed(Set<ExecutableElement> methods) {
    return prefixedGettersIn(methods).size() == methods.size();
  }

  /**
   * Returns an appropriate annotation spelling to indicate the nullability of an element. If the
   * return value is a non-empty Optional, that indicates that the element is nullable, and the
   * string should be used to annotate it. If the return value is an empty Optional, the element is
   * not nullable. The return value can be {@code Optional.of("")}, which indicates that the element
   * is nullable but that the nullability comes from a type annotation. In this case, the annotation
   * will appear when the type is written, and must not be specified again. If the Optional contains
   * a present non-empty string then that string will end with a space.
   *
   * @param element the element that might be {@code @Nullable}, either a method or a parameter.
   * @param elementType the relevant type of the element: the return type for a method, or the
   *     parameter type for a parameter.
   */
  static Optional<String> nullableAnnotationFor(Element element, TypeMirror elementType) {
    List<? extends AnnotationMirror> typeAnnotations = elementType.getAnnotationMirrors();
    if (nullableAnnotationIndex(typeAnnotations).isPresent()) {
      return Optional.of("");
    }
    List<? extends AnnotationMirror> elementAnnotations = element.getAnnotationMirrors();
    OptionalInt nullableAnnotationIndex = nullableAnnotationIndex(elementAnnotations);
    if (nullableAnnotationIndex.isPresent()) {
      ImmutableList<String> annotations = annotationStrings(elementAnnotations);
      return Optional.of(annotations.get(nullableAnnotationIndex.getAsInt()) + " ");
    } else {
      return Optional.empty();
    }
  }

  private static OptionalInt nullableAnnotationIndex(List<? extends AnnotationMirror> annotations) {
    for (int i = 0; i < annotations.size(); i++) {
      if (isNullable(annotations.get(i))) {
        return OptionalInt.of(i);
      }
    }
    return OptionalInt.empty();
  }

  private static boolean isNullable(AnnotationMirror annotation) {
    return annotation.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable");
  }

  /**
   * Returns the subset of the given zero-arg methods whose names begin with {@code get}. Also
   * includes {@code isFoo} methods if they return {@code boolean}. This corresponds to JavaBeans
   * conventions.
   */
  static ImmutableSet<ExecutableElement> prefixedGettersIn(Iterable<ExecutableElement> methods) {
    ImmutableSet.Builder<ExecutableElement> getters = ImmutableSet.builder();
    for (ExecutableElement method : methods) {
      String name = method.getSimpleName().toString();
      // Note that getfoo() (without a capital) is still a getter.
      boolean get = name.startsWith("get") && !name.equals("get");
      boolean is =
          name.startsWith("is")
              && !name.equals("is")
              && method.getReturnType().getKind() == TypeKind.BOOLEAN;
      if (get || is) {
        getters.add(method);
      }
    }
    return getters.build();
  }

  /**
   * Returns the name of the property defined by the given getter. A getter called {@code getFoo()}
   * or {@code isFoo()} defines a property called {@code foo}. For consistency with JavaBeans, a
   * getter called {@code getHTMLPage()} defines a property called {@code HTMLPage}. The <a
   * href="https://docs.oracle.com/javase/8/docs/api/java/beans/Introspector.html#decapitalize-java.lang.String-">
   * rule</a> is: the name of the property is the part after {@code get} or {@code is}, with the
   * first letter lowercased <i>unless</i> the first two letters are uppercase. This works well for
   * the {@code HTMLPage} example, but in these more enlightened times we use {@code HtmlPage}
   * anyway, so the special behaviour is not useful, and of course it behaves poorly with examples
   * like {@code OAuth}.
   */
  private static String nameWithoutPrefix(String name) {
    if (name.startsWith("get")) {
      name = name.substring(3);
    } else {
      assert name.startsWith("is");
      name = name.substring(2);
    }
    return PropertyNames.decapitalizeLikeJavaBeans(name);
  }

  /**
   * Checks that, if the given {@code @AutoValue} or {@code @AutoOneOf} class is nested, it is
   * static and not private. This check is not necessary for correctness, since the generated code
   * would not compile if the check fails, but it produces better error messages for the user.
   */
  final void checkModifiersIfNested(TypeElement type) {
    ElementKind enclosingKind = type.getEnclosingElement().getKind();
    if (enclosingKind.isClass() || enclosingKind.isInterface()) {
      if (type.getModifiers().contains(Modifier.PRIVATE)) {
        errorReporter.abortWithError(
            type, "@%s class must not be private", simpleAnnotationName);
      } else if (Visibility.effectiveVisibilityOfElement(type).equals(Visibility.PRIVATE)) {
        // The previous case, where the class itself is private, is much commoner so it deserves
        // its own error message, even though it would be caught by the test here too.
        errorReporter.abortWithError(
            type, "@%s class must not be nested in a private class", simpleAnnotationName);
      }
      if (!type.getModifiers().contains(Modifier.STATIC)) {
        errorReporter.abortWithError(
            type, "Nested @%s class must be static", simpleAnnotationName);
      }
    }
    // In principle type.getEnclosingElement() could be an ExecutableElement (for a class
    // declared inside a method), but since RoundEnvironment.getElementsAnnotatedWith doesn't
    // return such classes we won't see them here.
  }

  /**
   * Modifies the values of the given map to avoid reserved words. If we have a getter called {@code
   * getPackage()} then we can't use the identifier {@code package} to represent its value since
   * that's a reserved word.
   */
  static void fixReservedIdentifiers(Map<?, String> methodToIdentifier) {
    for (Map.Entry<?, String> entry : methodToIdentifier.entrySet()) {
      String name = entry.getValue();
      if (SourceVersion.isKeyword(name) || !Character.isJavaIdentifierStart(name.codePointAt(0))) {
        entry.setValue(disambiguate(name, methodToIdentifier.values()));
      }
    }
  }

  private static String disambiguate(String name, Collection<String> existingNames) {
    if (!Character.isJavaIdentifierStart(name.codePointAt(0))) {
      // You've defined a getter called get1st(). What were you thinking?
      name = "_" + name;
      if (!existingNames.contains(name)) {
        return name;
      }
    }
    for (int i = 0; ; i++) {
      String candidate = name + i;
      if (!existingNames.contains(candidate)) {
        return candidate;
      }
    }
  }

  /**
   * Given a list of all methods defined in or inherited by a class, returns a map indicating which
   * of equals, hashCode, and toString should be generated. Each value in the map is the method that
   * will be overridden by the generated method, which might be a method in {@code Object} or an
   * abstract method in the {@code @AutoValue} class or an ancestor.
   */
  private static Map<ObjectMethod, ExecutableElement> determineObjectMethodsToGenerate(
      Set<ExecutableElement> methods) {
    Map<ObjectMethod, ExecutableElement> methodsToGenerate = new EnumMap<>(ObjectMethod.class);
    for (ExecutableElement method : methods) {
      ObjectMethod override = objectMethodToOverride(method);
      boolean canGenerate =
          method.getModifiers().contains(Modifier.ABSTRACT)
              || isJavaLangObject((TypeElement) method.getEnclosingElement());
      if (!override.equals(ObjectMethod.NONE) && canGenerate) {
        methodsToGenerate.put(override, method);
      }
    }
    return methodsToGenerate;
  }

  /**
   * Returns the encoded parameter type of the {@code equals(Object)} method that is to be
   * generated, or an empty string if the method is not being generated. The parameter type includes
   * any type annotations, for example {@code @Nullable}.
   */
  static String equalsParameterType(Map<ObjectMethod, ExecutableElement> methodsToGenerate) {
    ExecutableElement equals = methodsToGenerate.get(ObjectMethod.EQUALS);
    if (equals == null) {
      return ""; // this will not be referenced because no equals method will be generated
    }
    TypeMirror parameterType = equals.getParameters().get(0).asType();
    return TypeEncoder.encodeWithAnnotations(parameterType);
  }

  /**
   * Returns the subset of all abstract methods in the given set of methods. A given method
   * signature is only mentioned once, even if it is inherited on more than one path. If any of the
   * abstract methods has a return type or parameter type that is not currently defined then this
   * method will throw an exception that will cause us to defer processing of the current class
   * until a later annotation-processing round.
   */
  static ImmutableSet<ExecutableElement> abstractMethodsIn(Iterable<ExecutableElement> methods) {
    Set<Name> noArgMethods = new HashSet<>();
    ImmutableSet.Builder<ExecutableElement> abstracts = ImmutableSet.builder();
    for (ExecutableElement method : methods) {
      if (method.getModifiers().contains(Modifier.ABSTRACT)) {
        MissingTypes.deferIfMissingTypesIn(method);
        boolean hasArgs = !method.getParameters().isEmpty();
        if (hasArgs || noArgMethods.add(method.getSimpleName())) {
          // If an abstract method with the same signature is inherited on more than one path,
          // we only add it once. At the moment we only do this check for no-arg methods. All
          // methods that AutoValue will implement are either no-arg methods or equals(Object).
          // The former is covered by this check and the latter will lead to vars.equals being
          // set to true, regardless of how many times it appears. So the only case that is
          // covered imperfectly here is that of a method that is inherited on more than one path
          // and that will be consumed by an extension. We could check parameters as well, but that
          // can be a bit tricky if any of the parameters are generic.
          abstracts.add(method);
        }
      }
    }
    return abstracts.build();
  }

  /**
   * Returns the subset of property methods in the given set of abstract methods, with their actual
   * return types. A property method has no arguments, is not void, and is not {@code hashCode()} or
   * {@code toString()}.
   */
  ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsIn(
      Set<ExecutableElement> abstractMethods,
      TypeElement autoValueOrOneOfType) {
    DeclaredType declaredType = MoreTypes.asDeclared(autoValueOrOneOfType.asType());
    ImmutableSet.Builder<ExecutableElement> properties = ImmutableSet.builder();
    for (ExecutableElement method : abstractMethods) {
      if (method.getParameters().isEmpty()
          && (method.getReturnType().getKind() != TypeKind.VOID || propertiesCanBeVoid())
          && objectMethodToOverride(method) == ObjectMethod.NONE) {
        properties.add(method);
      }
    }
    return new EclipseHack(processingEnv).methodReturnTypes(properties.build(), declaredType);
  }

  /** True if void properties are allowed. */
  boolean propertiesCanBeVoid() {
    return false;
  }

  /**
   * Checks that the return type of the given property method is allowed. Currently, this means that
   * it cannot be an array, unless it is a primitive array.
   */
  final void checkReturnType(TypeElement autoValueClass, ExecutableElement getter) {
    TypeMirror type = getter.getReturnType();
    if (type.getKind() == TypeKind.ARRAY) {
      TypeMirror componentType = ((ArrayType) type).getComponentType();
      if (componentType.getKind().isPrimitive()) {
        warnAboutPrimitiveArrays(autoValueClass, getter);
      } else {
        errorReporter.reportError(
            getter,
            "An @%s class cannot define an array-valued property unless it is a primitive array",
            simpleAnnotationName);
      }
    }
  }

  private void warnAboutPrimitiveArrays(TypeElement autoValueClass, ExecutableElement getter) {
    boolean suppressed = false;
    Optional<AnnotationMirror> maybeAnnotation =
        getAnnotationMirror(getter, "java.lang.SuppressWarnings");
    if (maybeAnnotation.isPresent()) {
      AnnotationValue listValue = getAnnotationValue(maybeAnnotation.get(), "value");
      suppressed = listValue.accept(new ContainsMutableVisitor(), null);
    }
    if (!suppressed) {
      // If the primitive-array property method is defined directly inside the @AutoValue class,
      // then our error message should point directly to it. But if it is inherited, we don't
      // want to try to make the error message point to the inherited definition, since that would
      // be confusing (there is nothing wrong with the definition itself), and won't work if the
      // inherited class is not being recompiled. Instead, in this case we point to the @AutoValue
      // class itself, and we include extra text in the error message that shows the full name of
      // the inherited method.
      boolean sameClass = getter.getEnclosingElement().equals(autoValueClass);
      Element element = sameClass ? getter : autoValueClass;
      String context = sameClass ? "" : (" Method: " + getter.getEnclosingElement() + "." + getter);
      errorReporter.reportWarning(
          element,
          "An @%s property that is a primitive array returns the original array, which can"
              + " therefore be modified by the caller. If this is OK, you can suppress this warning"
              + " with @SuppressWarnings(\"mutable\"). Otherwise, you should replace the property"
              + " with an immutable type, perhaps a simple wrapper around the original array.%s",
          simpleAnnotationName,
          context);
    }
  }

  // Detects whether the visited AnnotationValue is an array that contains the string "mutable".
  // The simpler approach using Element.getAnnotation(SuppressWarnings.class) doesn't work if
  // the annotation has an undefined reference, like @SuppressWarnings(UNDEFINED).
  // TODO(emcmanus): replace with a method from auto-common when that is available.
  private static class ContainsMutableVisitor extends SimpleAnnotationValueVisitor8<Boolean, Void> {
    @Override
    public Boolean visitArray(List<? extends AnnotationValue> list, Void p) {
      return list.stream().map(av -> av.getValue()).anyMatch("mutable"::equals);
    }
  }

  /**
   * Returns a string like {@code "1234L"} if {@code type instanceof Serializable} and defines
   * {@code serialVersionUID = 1234L}; otherwise {@code ""}.
   */
  final String getSerialVersionUID(TypeElement type) {
    TypeMirror serializable = elementUtils().getTypeElement(Serializable.class.getName()).asType();
    if (typeUtils().isAssignable(type.asType(), serializable)) {
      List<VariableElement> fields = ElementFilter.fieldsIn(type.getEnclosedElements());
      for (VariableElement field : fields) {
        if (field.getSimpleName().contentEquals("serialVersionUID")) {
          Object value = field.getConstantValue();
          if (field.getModifiers().containsAll(Arrays.asList(Modifier.STATIC, Modifier.FINAL))
              && field.asType().getKind() == TypeKind.LONG
              && value != null) {
            return value + "L";
          } else {
            errorReporter.reportError(
                field, "serialVersionUID must be a static final long compile-time constant");
            break;
          }
        }
      }
    }
    return "";
  }

  /** Implements the semantics of {@code AutoValue.CopyAnnotations}; see its javadoc. */
  ImmutableList<AnnotationMirror> annotationsToCopy(
      Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations) {
    ImmutableList.Builder<AnnotationMirror> result = ImmutableList.builder();
    for (AnnotationMirror annotation : typeOrMethod.getAnnotationMirrors()) {
      String annotationFqName = getAnnotationFqName(annotation);
      // To be included, the annotation should not be in com.google.auto.value,
      // and it should not be in the excludedAnnotations set.
      if (!isInAutoValuePackage(annotationFqName)
          && !excludedAnnotations.contains(annotationFqName)
          && annotationVisibleFrom(annotation, autoValueType)) {
        result.add(annotation);
      }
    }

    return result.build();
  }

  /**
   * True if the given class name is in the com.google.auto.value package or a subpackage. False if
   * the class name contains {@code Test}, since many AutoValue tests under com.google.auto.value
   * define their own annotations.
   */
  private boolean isInAutoValuePackage(String className) {
    return className.startsWith(AUTO_VALUE_PACKAGE_NAME) && !className.contains("Test");
  }

  ImmutableList<String> copiedClassAnnotations(TypeElement type) {
    // Only copy annotations from a class if it has @AutoValue.CopyAnnotations.
    if (hasAnnotationMirror(type, COPY_ANNOTATIONS_NAME)) {
      Set<String> excludedAnnotations =
          union(getExcludedAnnotationClassNames(type), getAnnotationsMarkedWithInherited(type));

      return copyAnnotations(type, type, excludedAnnotations);
    } else {
      return ImmutableList.of();
    }
  }

  /** Implements the semantics of {@code AutoValue.CopyAnnotations}; see its javadoc. */
  private ImmutableList<String> copyAnnotations(
      Element autoValueType, Element typeOrMethod, Set<String> excludedAnnotations) {
    ImmutableList<AnnotationMirror> annotationsToCopy =
        annotationsToCopy(autoValueType, typeOrMethod, excludedAnnotations);
    return annotationStrings(annotationsToCopy);
  }

  /**
   * Returns the contents of the {@code AutoValue.CopyAnnotations.exclude} element, as a set of
   * {@code TypeMirror} where each type is an annotation type.
   */
  private Set<TypeMirror> getExcludedAnnotationTypes(Element element) {
    Optional<AnnotationMirror> maybeAnnotation =
        getAnnotationMirror(element, COPY_ANNOTATIONS_NAME);
    if (!maybeAnnotation.isPresent()) {
      return ImmutableSet.of();
    }

    @SuppressWarnings("unchecked")
    List<AnnotationValue> excludedClasses =
        (List<AnnotationValue>) getAnnotationValue(maybeAnnotation.get(), "exclude").getValue();
    return excludedClasses
        .stream()
        .map(annotationValue -> (DeclaredType) annotationValue.getValue())
        .collect(toCollection(TypeMirrorSet::new));
  }

  /**
   * Returns the contents of the {@code AutoValue.CopyAnnotations.exclude} element, as a set of
   * strings that are fully-qualified class names.
   */
  private Set<String> getExcludedAnnotationClassNames(Element element) {
    return getExcludedAnnotationTypes(element)
        .stream()
        .map(MoreTypes::asTypeElement)
        .map(typeElement -> typeElement.getQualifiedName().toString())
        .collect(toSet());
  }

  private static Set<String> getAnnotationsMarkedWithInherited(Element element) {
    return element
        .getAnnotationMirrors()
        .stream()
        .filter(a -> isAnnotationPresent(a.getAnnotationType().asElement(), Inherited.class))
        .map(a -> getAnnotationFqName(a))
        .collect(toSet());
  }

  /**
   * Returns the fully-qualified name of an annotation-mirror, e.g.
   * "com.google.auto.value.AutoValue".
   */
  private static String getAnnotationFqName(AnnotationMirror annotation) {
    return ((QualifiedNameable) annotation.getAnnotationType().asElement())
        .getQualifiedName()
        .toString();
  }

  final ImmutableListMultimap<ExecutableElement, AnnotationMirror> propertyMethodAnnotationMap(
      TypeElement type, ImmutableSet<ExecutableElement> propertyMethods) {
    ImmutableListMultimap.Builder<ExecutableElement, AnnotationMirror> builder =
        ImmutableListMultimap.builder();
    for (ExecutableElement propertyMethod : propertyMethods) {
      builder.putAll(propertyMethod, propertyMethodAnnotations(type, propertyMethod));
    }
    return builder.build();
  }

  private ImmutableList<AnnotationMirror> propertyMethodAnnotations(
      TypeElement type, ExecutableElement method) {
    ImmutableSet<String> excludedAnnotations =
        ImmutableSet.<String>builder()
            .addAll(getExcludedAnnotationClassNames(method))
            .add(Override.class.getCanonicalName())
            .build();

    // We need to exclude type annotations from the ones being output on the method, since
    // they will be output as part of the method's return type.
    Set<String> returnTypeAnnotations = getReturnTypeAnnotations(method, a -> true);
    Set<String> excluded = union(excludedAnnotations, returnTypeAnnotations);
    return annotationsToCopy(type, method, excluded);
  }

  final ImmutableListMultimap<ExecutableElement, AnnotationMirror> propertyFieldAnnotationMap(
      TypeElement type, ImmutableSet<ExecutableElement> propertyMethods) {
    ImmutableListMultimap.Builder<ExecutableElement, AnnotationMirror> builder =
        ImmutableListMultimap.builder();
    for (ExecutableElement propertyMethod : propertyMethods) {
      builder.putAll(propertyMethod, propertyFieldAnnotations(type, propertyMethod));
    }
    return builder.build();
  }

  private ImmutableList<AnnotationMirror> propertyFieldAnnotations(
      TypeElement type, ExecutableElement method) {
    if (!hasAnnotationMirror(method, COPY_ANNOTATIONS_NAME)) {
      return ImmutableList.of();
    }
    ImmutableSet<String> excludedAnnotations =
        ImmutableSet.<String>builder()
            .addAll(getExcludedAnnotationClassNames(method))
            .add(Override.class.getCanonicalName())
            .build();

    // We need to exclude type annotations from the ones being output on the method, since
    // they will be output as part of the field's type.
    Set<String> returnTypeAnnotations =
        getReturnTypeAnnotations(method, this::annotationAppliesToFields);
    Set<String> nonFieldAnnotations =
        method
            .getAnnotationMirrors()
            .stream()
            .map(a -> a.getAnnotationType().asElement())
            .map(MoreElements::asType)
            .filter(a -> !annotationAppliesToFields(a))
            .map(e -> e.getQualifiedName().toString())
            .collect(toSet());

    Set<String> excluded =
        ImmutableSet.<String>builder()
            .addAll(excludedAnnotations)
            .addAll(returnTypeAnnotations)
            .addAll(nonFieldAnnotations)
            .build();
    return annotationsToCopy(type, method, excluded);
  }

  private Set<String> getReturnTypeAnnotations(
      ExecutableElement method, Predicate<TypeElement> typeFilter) {
    return method
        .getReturnType()
        .getAnnotationMirrors()
        .stream()
        .map(a -> a.getAnnotationType().asElement())
        .map(MoreElements::asType)
        .filter(typeFilter)
        .map(e -> e.getQualifiedName().toString())
        .collect(toSet());
  }

  private boolean annotationAppliesToFields(TypeElement annotation) {
    Target target = annotation.getAnnotation(Target.class);
    return target == null || Arrays.asList(target.value()).contains(ElementType.FIELD);
  }

  private boolean annotationVisibleFrom(AnnotationMirror annotation, Element from) {
    Element annotationElement = annotation.getAnnotationType().asElement();
    Visibility visibility = Visibility.effectiveVisibilityOfElement(annotationElement);
    switch (visibility) {
      case PUBLIC:
        return true;
      case PROTECTED:
        // If the annotation is protected, it must be inside another class, call it C. If our
        // @AutoValue class is Foo then, for the annotation to be visible, either Foo must be in the
        // same package as C or Foo must be a subclass of C. If the annotation is visible from Foo
        // then it is also visible from our generated subclass AutoValue_Foo.
        // The protected case only applies to method annotations. An annotation on the AutoValue_Foo
        // class itself can't be protected, even if AutoValue_Foo ultimately inherits from the
        // class that defines the annotation. The JLS says "Access is permitted only within the
        // body of a subclass":
        // https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1
        // AutoValue_Foo is a top-level class, so an annotation on it cannot be in the body of a
        // subclass of anything.
        return getPackage(annotationElement).equals(getPackage(from))
            || typeUtils()
                .isSubtype(from.asType(), annotationElement.getEnclosingElement().asType());
      case DEFAULT:
        return getPackage(annotationElement).equals(getPackage(from));
      default:
        return false;
    }
  }

  /**
   * Returns the {@code @AutoValue} or {@code @AutoOneOf} type parameters, with a ? for every type.
   * If we have {@code @AutoValue abstract class Foo<T extends Something>} then this method will
   * return just {@code <?>}.
   */
  private static String wildcardTypeParametersString(TypeElement type) {
    List<? extends TypeParameterElement> typeParameters = type.getTypeParameters();
    if (typeParameters.isEmpty()) {
      return "";
    } else {
      return typeParameters.stream().map(e -> "?").collect(joining(", ", "<", ">"));
    }
  }

  // TODO(emcmanus,ronshapiro): move to auto-common
  static Optional<AnnotationMirror> getAnnotationMirror(Element element, String annotationName) {
    for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
      TypeElement annotationElement = MoreTypes.asTypeElement(annotation.getAnnotationType());
      if (annotationElement.getQualifiedName().contentEquals(annotationName)) {
        return Optional.of(annotation);
      }
    }
    return Optional.empty();
  }

  static boolean hasAnnotationMirror(Element element, String annotationName) {
    return getAnnotationMirror(element, annotationName).isPresent();
  }

  final void writeSourceFile(String className, String text, TypeElement originatingType) {
    try {
      JavaFileObject sourceFile =
          processingEnv.getFiler().createSourceFile(className, originatingType);
      try (Writer writer = sourceFile.openWriter()) {
        writer.write(text);
      }
    } catch (IOException e) {
      // This should really be an error, but we make it a warning in the hope of resisting Eclipse
      // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599. If that bug manifests, we may get
      // invoked more than once for the same file, so ignoring the ability to overwrite it is the
      // right thing to do. If we are unable to write for some other reason, we should get a compile
      // error later because user code will have a reference to the code we were supposed to
      // generate (new AutoValue_Foo() or whatever) and that reference will be undefined.
      errorReporter.reportWarning(
          originatingType, "Could not write generated class %s: %s", className, e);
    }
  }
}
