// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.skyframe.serialization.autocodec;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.auto.service.AutoService;
import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.skyframe.serialization.CodecScanningConstants;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationCodeGenerator.Marshaller;
import com.google.devtools.build.lib.unsafe.UnsafeProvider;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
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.TypeElement;
import javax.lang.model.element.VariableElement;
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.tools.Diagnostic;

/**
 * Javac annotation processor (compiler plugin) for generating {@link ObjectCodec} implementations.
 *
 * <p>User code must never reference this class.
 */
@AutoService(Processor.class)
public class AutoCodecProcessor extends AbstractProcessor {
  /**
   * Passing {@code --javacopt=-Aautocodec_print_generated} to {@code blaze build} tells AutoCodec
   * to print the generated code.
   */
  private static final String PRINT_GENERATED_OPTION = "autocodec_print_generated";

  private ProcessingEnvironment env; // Captured from `init` method.
  private Marshallers marshallers;

  @Override
  public Set<String> getSupportedOptions() {
    return ImmutableSet.of(PRINT_GENERATED_OPTION);
  }

  @Override
  public Set<String> getSupportedAnnotationTypes() {
    return ImmutableSet.of(AutoCodecUtil.ANNOTATION.getCanonicalName());
  }

  @Override
  public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latestSupported(); // Supports all versions of Java.
  }

  @Override
  public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    this.env = processingEnv;
    this.marshallers = new Marshallers(processingEnv);
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (Element element : roundEnv.getElementsAnnotatedWith(AutoCodecUtil.ANNOTATION)) {
      AutoCodec annotation = element.getAnnotation(AutoCodecUtil.ANNOTATION);
      TypeSpec builtClass;
      if (element instanceof TypeElement) {
        TypeElement encodedType = (TypeElement) element;
        TypeSpec.Builder codecClassBuilder;
        switch (annotation.strategy()) {
          case INSTANTIATOR:
            codecClassBuilder = buildClassWithInstantiatorStrategy(encodedType, annotation);
            break;
          case AUTO_VALUE_BUILDER:
            codecClassBuilder = buildClassWithAutoValueBuilderStrategy(encodedType, annotation);
            break;
          default:
            throw new IllegalArgumentException("Unknown strategy: " + annotation.strategy());
        }
        codecClassBuilder.addMethod(
            AutoCodecUtil.initializeGetEncodedClassMethod(encodedType, env)
                .addStatement(
                    "return $T.class",
                    TypeName.get(env.getTypeUtils().erasure(encodedType.asType())))
                .build());
        builtClass = codecClassBuilder.build();
      } else {
        builtClass = buildRegisteredSingletonClass((VariableElement) element);
      }
      String packageName =
          env.getElementUtils().getPackageOf(element).getQualifiedName().toString();
      try {
        JavaFile file = JavaFile.builder(packageName, builtClass).build();
        file.writeTo(env.getFiler());
        if (env.getOptions().containsKey(PRINT_GENERATED_OPTION)) {
          note("AutoCodec generated codec for " + element + ":\n" + file);
        }
      } catch (IOException e) {
        env.getMessager()
            .printMessage(
                Diagnostic.Kind.ERROR, "Failed to generate output file: " + e.getMessage());
      }
    }
    return true;
  }

  @SuppressWarnings("MutableConstantField")
  private static final Collection<Modifier> REQUIRED_SINGLETON_MODIFIERS =
      ImmutableList.of(Modifier.STATIC, Modifier.FINAL);

  private TypeSpec buildRegisteredSingletonClass(VariableElement symbol) {
    Preconditions.checkState(
        symbol.getModifiers().containsAll(REQUIRED_SINGLETON_MODIFIERS),
        "Field must be static and final to be annotated with @AutoCodec: " + symbol);
    return TypeSpec.classBuilder(
            AutoCodecUtil.getGeneratedName(
                symbol, CodecScanningConstants.REGISTERED_SINGLETON_SUFFIX))
        .addModifiers(Modifier.PUBLIC)
        .addSuperinterface(RegisteredSingletonDoNotUse.class)
        .addField(
            FieldSpec.builder(
                    Object.class,
                    CodecScanningConstants.REGISTERED_SINGLETON_INSTANCE_VAR_NAME,
                    Modifier.PUBLIC,
                    Modifier.STATIC,
                    Modifier.FINAL)
                .initializer(
                    "$T.$L",
                    sanitizeTypeParameter(symbol.getEnclosingElement().asType()),
                    symbol.getSimpleName())
                .build())
        .build();
  }

  private TypeSpec.Builder buildClassWithInstantiatorStrategy(
      TypeElement encodedType, AutoCodec annotation) {
    ExecutableElement constructor = selectInstantiator(encodedType);
    List<? extends VariableElement> fields = constructor.getParameters();

    TypeSpec.Builder codecClassBuilder =
        AutoCodecUtil.initializeCodecClassBuilder(encodedType, env);

    if (encodedType.getAnnotation(AutoValue.class) == null) {
      initializeUnsafeOffsets(codecClassBuilder, encodedType, fields);
      codecClassBuilder.addMethod(
          buildSerializeMethodWithInstantiator(encodedType, fields, annotation));
    } else {
      codecClassBuilder.addMethod(
          buildSerializeMethodWithInstantiatorForAutoValue(encodedType, fields, annotation));
    }

    MethodSpec.Builder deserializeBuilder =
        AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType, env);
    buildDeserializeBody(deserializeBuilder, fields);
    addReturnNew(deserializeBuilder, encodedType, constructor, /*builderVar=*/ null, env);
    codecClassBuilder.addMethod(deserializeBuilder.build());

    return codecClassBuilder;
  }

  private TypeSpec.Builder buildClassWithAutoValueBuilderStrategy(
      TypeElement encodedType, AutoCodec annotation) {
    TypeElement builderType = findBuilderType(encodedType);
    List<ExecutableElement> getters = findGettersFromType(encodedType, builderType);
    ExecutableElement builderCreationMethod = findBuilderCreationMethod(encodedType, builderType);
    ExecutableElement buildMethod = findBuildMethod(encodedType, builderType);
    TypeSpec.Builder codecClassBuilder =
        AutoCodecUtil.initializeCodecClassBuilder(encodedType, env);
    MethodSpec.Builder serializeBuilder =
        AutoCodecUtil.initializeSerializeMethodBuilder(encodedType, annotation, env);
    for (ExecutableElement getter : getters) {
      marshallers.writeSerializationCode(
          new Marshaller.Context(
              serializeBuilder,
              getter.getReturnType(),
              turnGetterIntoExpression(getter.getSimpleName().toString())));
    }
    codecClassBuilder.addMethod(serializeBuilder.build());
    MethodSpec.Builder deserializeBuilder =
        AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType, env);
    String builderVarName =
        buildDeserializeBodyWithBuilder(
            encodedType, builderType, deserializeBuilder, getters, builderCreationMethod);
    addReturnNew(deserializeBuilder, encodedType, buildMethod, builderVarName, env);
    codecClassBuilder.addMethod(deserializeBuilder.build());

    return codecClassBuilder;
  }

  private ExecutableElement selectInstantiator(TypeElement encodedType) {
    List<ExecutableElement> constructors =
        ElementFilter.constructorsIn(encodedType.getEnclosedElements());
    Stream<ExecutableElement> factoryMethods =
        ElementFilter.methodsIn(encodedType.getEnclosedElements())
            .stream()
            .filter(AutoCodecProcessor::hasInstantiatorAnnotation)
            .peek(m -> verifyFactoryMethod(encodedType, m));
    ImmutableList<ExecutableElement> markedInstantiators =
        Stream.concat(
                constructors.stream().filter(AutoCodecProcessor::hasInstantiatorAnnotation),
                factoryMethods)
            .collect(toImmutableList());
    if (markedInstantiators.isEmpty()) {
      // If nothing is marked, see if there is a unique constructor.
      if (constructors.size() > 1) {
        throw new IllegalArgumentException(
            encodedType.getQualifiedName()
                + " has multiple constructors but no Instantiator annotation.");
      }
      // In Java, every class has at least one constructor, so this never fails.
      return constructors.get(0);
    }
    if (markedInstantiators.size() == 1) {
      return markedInstantiators.get(0);
    }
    throw new IllegalArgumentException(
        encodedType.getQualifiedName() + " has multiple Instantiator annotations.");
  }

  private static boolean hasInstantiatorAnnotation(Element elt) {
    return elt.getAnnotation(AutoCodec.Instantiator.class) != null;
  }

  private TypeElement findBuilderType(TypeElement encodedType) {
    TypeElement builderType = null;
    for (Element element : encodedType.getEnclosedElements()) {
      if (element instanceof TypeElement
          && element.getModifiers().contains(Modifier.STATIC)
          && element.getAnnotation(AutoValue.Builder.class) != null) {
        if (builderType != null) {
          throw new IllegalArgumentException(
              "Type "
                  + encodedType
                  + " had multiple inner classes annotated as @AutoValue.Builder: "
                  + builderType
                  + " and "
                  + element);
        }
        builderType = (TypeElement) element;
      }
    }
    if (builderType == null) {
      throw new IllegalArgumentException(
          "Couldn't find @AutoValue.Builder-annotated static class inside " + encodedType);
    }
    return builderType;
  }

  private List<ExecutableElement> findGettersFromType(
      TypeElement encodedType, TypeElement builderTypeForFiltering) {
    List<ExecutableElement> result = new ArrayList<>();
    for (ExecutableElement method :
        ElementFilter.methodsIn(env.getElementUtils().getAllMembers(encodedType))) {
      if (!method.getModifiers().contains(Modifier.STATIC)
          && method.getModifiers().contains(Modifier.ABSTRACT)
          && method.getParameters().isEmpty()
          && method.getReturnType().getKind() != TypeKind.VOID
          && (!method.getReturnType().getKind().equals(TypeKind.DECLARED)
              || !builderTypeForFiltering.equals(
                  env.getTypeUtils().asElement(method.getReturnType())))) {
        result.add(method);
      }
    }
    if (result.isEmpty()) {
      throw new IllegalArgumentException("Couldn't find any properties for " + encodedType);
    }
    return result;
  }

  private String getNameFromGetter(ExecutableElement method) {
    String name = method.getSimpleName().toString();
    if (name.startsWith("get")) {
      return name.substring(3, 4).toLowerCase() + name.substring(4);
    } else if (name.startsWith("is")) {
      return name.substring(2, 3).toLowerCase() + name.substring(3);
    } else {
      return name;
    }
  }

  private ExecutableElement findBuilderCreationMethod(
      TypeElement encodedType, TypeElement builderType) {
    ExecutableElement builderMethod = null;
    for (ExecutableElement method :
        ElementFilter.methodsIn(env.getElementUtils().getAllMembers(encodedType))) {
      if (method.getModifiers().contains(Modifier.STATIC)
          && !method.getModifiers().contains(Modifier.ABSTRACT)
          && method.getParameters().isEmpty()
          && isSameReturnType(method, builderType)) {
        if (builderMethod != null) {
          throw new IllegalArgumentException(
              "Type "
                  + encodedType
                  + " had multiple static methods to create an element of type "
                  + builderType
                  + ": "
                  + builderMethod
                  + " and "
                  + method);
        }
        builderMethod = method;
      }
    }
    if (builderMethod == null) {
      throw new IllegalArgumentException(
          "Couldn't find builder creation method for " + encodedType + " and " + builderType);
    }
    return builderMethod;
  }

  private ExecutableElement findBuildMethod(TypeElement encodedType, TypeElement builderType) {
    ExecutableElement abstractBuildMethod = null;
    for (ExecutableElement method :
        ElementFilter.methodsIn(env.getElementUtils().getAllMembers(builderType))) {
      if (method.getModifiers().contains(Modifier.STATIC)) {
        continue;
      }
      if (method.getParameters().isEmpty()
          && isSameReturnType(method, encodedType)
          && method.getModifiers().contains(Modifier.ABSTRACT)) {
          if (abstractBuildMethod != null) {
            throw new IllegalArgumentException(
                "Type "
                    + builderType
                    + " had multiple abstract methods to create an element of type "
                    + encodedType
                    + ": "
                    + abstractBuildMethod
                    + " and "
                    + method);
          }
          abstractBuildMethod = method;
      }
    }
    if (abstractBuildMethod == null) {
      throw new IllegalArgumentException(
          "Couldn't find build method for " + encodedType + " and " + builderType);
    }
    return abstractBuildMethod;
  }

  private String buildDeserializeBodyWithBuilder(
      TypeElement encodedType,
      TypeElement builderType,
      MethodSpec.Builder builder,
      List<ExecutableElement> fields,
      ExecutableElement builderCreationMethod) {
    String builderVarName = "objectBuilder";
    builder.addStatement(
        "$T $L = $T.$L()",
        builderCreationMethod.getReturnType(),
        builderVarName,
        encodedType,
        builderCreationMethod.getSimpleName());
    for (ExecutableElement getter : fields) {
      String paramName = getNameFromGetter(getter) + "_";
      marshallers.writeDeserializationCode(
          new Marshaller.Context(builder, getter.getReturnType(), paramName));
      setValueInBuilder(builderType, getter, paramName, builderVarName, builder);
    }
    return builderVarName;
  }

  private void setValueInBuilder(
      TypeElement builderType,
      ExecutableElement getter,
      String paramName,
      String builderVarName,
      MethodSpec.Builder methodBuilder) {
    ExecutableElement setterMethod = findSetterGivenGetter(getter, builderType);
    methodBuilder.addStatement(
        "$L.$L($L)", builderVarName, setterMethod.getSimpleName(), paramName);
  }

  private ExecutableElement findSetterGivenGetter(
      ExecutableElement getter, TypeElement builderType) {
    List<ExecutableElement> methods =
        ElementFilter.methodsIn(env.getElementUtils().getAllMembers(builderType));
    String varName = getNameFromGetter(getter);
    TypeMirror type = getter.getReturnType();
    ImmutableSet<String> setterNames = ImmutableSet.of(varName, addCamelCasePrefix(varName, "set"));

    ExecutableElement setterMethod = null;
    for (ExecutableElement method : methods) {
      if (!method.getModifiers().contains(Modifier.STATIC)
          && !method.getModifiers().contains(Modifier.PRIVATE)
          && setterNames.contains(method.getSimpleName().toString())
          && isSameReturnType(method, builderType)
          && method.getParameters().size() == 1
          && env.getTypeUtils()
              .isSubtype(type, Iterables.getOnlyElement(method.getParameters()).asType())) {
        if (setterMethod != null) {
          throw new IllegalArgumentException(
              "Multiple setter methods for "
                  + getter
                  + " found in "
                  + builderType
                  + ": "
                  + setterMethod
                  + " and "
                  + method);
        }
        setterMethod = method;
      }
    }
    if (setterMethod != null) {
      return setterMethod;
    }

    throw new IllegalArgumentException(
        builderType
            + ": No setter found corresponding to getter "
            + getter.getSimpleName()
            + ", "
            + type);
  }

  private enum Relation {
    INSTANCE_OF,
    EQUAL_TO,
    SUPERTYPE_OF,
    UNRELATED_TO
  }

  private Relation findRelationWithGenerics(TypeMirror type1, TypeMirror type2) {
    if (type1.getKind() == TypeKind.TYPEVAR
        || type1.getKind() == TypeKind.WILDCARD
        || type2.getKind() == TypeKind.TYPEVAR
        || type2.getKind() == TypeKind.WILDCARD) {
      return Relation.EQUAL_TO;
    }
    if (env.getTypeUtils().isAssignable(type1, type2)) {
      if (env.getTypeUtils().isAssignable(type2, type1)) {
        return Relation.EQUAL_TO;
      }
      return Relation.INSTANCE_OF;
    }
    if (env.getTypeUtils().isAssignable(type2, type1)) {
      return Relation.SUPERTYPE_OF;
    }
    // From here on out, we can't detect subtype/supertype, we're only checking for equality.
    TypeMirror erasedType1 = env.getTypeUtils().erasure(type1);
    TypeMirror erasedType2 = env.getTypeUtils().erasure(type2);
    if (!env.getTypeUtils().isSameType(erasedType1, erasedType2)) {
      // Technically, there could be a relationship, but it's too hard to figure out for now.
      return Relation.UNRELATED_TO;
    }
    List<? extends TypeMirror> genericTypes1 = ((DeclaredType) type1).getTypeArguments();
    List<? extends TypeMirror> genericTypes2 = ((DeclaredType) type2).getTypeArguments();
    if (genericTypes1.size() != genericTypes2.size()) {
      return null;
    }
    for (int i = 0; i < genericTypes1.size(); i++) {
      Relation result = findRelationWithGenerics(genericTypes1.get(i), genericTypes2.get(i));
      if (result != Relation.EQUAL_TO) {
        return Relation.UNRELATED_TO;
      }
    }
    return Relation.EQUAL_TO;
  }

  private void verifyFactoryMethod(TypeElement encodedType, ExecutableElement elt) {
    boolean success = elt.getModifiers().contains(Modifier.STATIC);
    if (success) {
      Relation equalityTest = findRelationWithGenerics(elt.getReturnType(), encodedType.asType());
      success = equalityTest == Relation.EQUAL_TO || equalityTest == Relation.INSTANCE_OF;
    }
    if (!success) {
      throw new IllegalArgumentException(
          encodedType.getQualifiedName()
              + " tags "
              + elt.getSimpleName()
              + " as an Instantiator, but it's not a valid factory method "
              + elt.getReturnType()
              + ", "
              + encodedType.asType());
    }
  }

  private MethodSpec buildSerializeMethodWithInstantiator(
      TypeElement encodedType, List<? extends VariableElement> fields, AutoCodec annotation) {
    MethodSpec.Builder serializeBuilder =
        AutoCodecUtil.initializeSerializeMethodBuilder(encodedType, annotation, env);
    for (VariableElement parameter : fields) {
      Optional<FieldValueAndClass> hasField =
          getFieldByNameRecursive(encodedType, parameter.getSimpleName().toString());
      if (hasField.isPresent()) {
        Preconditions.checkArgument(
            findRelationWithGenerics(hasField.get().value.asType(), parameter.asType())
                != Relation.UNRELATED_TO,
            "%s: parameter %s's type %s is unrelated to corresponding field type %s",
            encodedType.getQualifiedName(),
            parameter.getSimpleName(),
            parameter.asType(),
            hasField.get().value.asType());
        TypeKind typeKind = parameter.asType().getKind();
        serializeBuilder.addStatement(
            "$T unsafe_$L = ($T) $T.getInstance().get$L(input, $L_offset)",
            sanitizeTypeParameter(parameter.asType()),
            parameter.getSimpleName(),
            sanitizeTypeParameter(parameter.asType()),
            UnsafeProvider.class,
            typeKind.isPrimitive() ? firstLetterUpper(typeKind.toString().toLowerCase()) : "Object",
            parameter.getSimpleName());
            marshallers.writeSerializationCode(
                new Marshaller.Context(
                    serializeBuilder, parameter.asType(), "unsafe_" + parameter.getSimpleName()));
      } else {
        addSerializeParameterWithGetter(encodedType, parameter, serializeBuilder);
      }
    }
    return serializeBuilder.build();
  }

  // Sanitizes the type parameter. If it's a TypeVariable or WildcardType this will get the erasure.
  private TypeMirror sanitizeTypeParameter(TypeMirror type) {
    if (Marshallers.isVariableOrWildcardType(type)) {
      return env.getTypeUtils().erasure(type);
    }
    if (!(type instanceof DeclaredType)) {
      return type;
    }
    DeclaredType declaredType = (DeclaredType) type;
    for (TypeMirror typeMirror : declaredType.getTypeArguments()) {
      if (Marshallers.isVariableOrWildcardType(typeMirror)) {
        return env.getTypeUtils().erasure(type);
      }
    }
    return type;
  }

  private String findGetterForClass(VariableElement parameter, TypeElement type) {
    List<ExecutableElement> methods =
        ElementFilter.methodsIn(env.getElementUtils().getAllMembers(type));

    ImmutableSet.Builder<String> possibleGetterNamesBuilder =
        ImmutableSet.<String>builder().add(parameter.getSimpleName().toString());

    if (parameter.asType().getKind() == TypeKind.BOOLEAN) {
      possibleGetterNamesBuilder.add(
          addCamelCasePrefix(parameter.getSimpleName().toString(), "is"));
    } else {
      possibleGetterNamesBuilder.add(
          addCamelCasePrefix(parameter.getSimpleName().toString(), "get"));
    }
    ImmutableSet<String> possibleGetterNames = possibleGetterNamesBuilder.build();

    for (ExecutableElement element : methods) {
      if (!element.getModifiers().contains(Modifier.STATIC)
          && !element.getModifiers().contains(Modifier.PRIVATE)
          && possibleGetterNames.contains(element.getSimpleName().toString())
          && findRelationWithGenerics(parameter.asType(), element.getReturnType())
              != Relation.UNRELATED_TO) {
        return element.getSimpleName().toString();
      }
    }

    throw new IllegalArgumentException(
        type
            + ": No getter found corresponding to parameter "
            + parameter.getSimpleName()
            + ", "
            + parameter.asType());
  }

  private static String addCamelCasePrefix(String name, String prefix) {
    return prefix + firstLetterUpper(name);
  }

  private static String firstLetterUpper(String str) {
    return Character.toUpperCase(str.charAt(0)) + (str.length() == 1 ? "" : str.substring(1));
  }

  private void addSerializeParameterWithGetter(
      TypeElement encodedType, VariableElement parameter, MethodSpec.Builder serializeBuilder) {
    String getter = turnGetterIntoExpression(findGetterForClass(parameter, encodedType));
    marshallers.writeSerializationCode(
        new Marshaller.Context(serializeBuilder, parameter.asType(), getter));
  }

  private static String turnGetterIntoExpression(String getterName) {
    return "input." + getterName + "()";
  }

  private MethodSpec buildSerializeMethodWithInstantiatorForAutoValue(
      TypeElement encodedType, List<? extends VariableElement> fields, AutoCodec annotation) {
    MethodSpec.Builder serializeBuilder =
        AutoCodecUtil.initializeSerializeMethodBuilder(encodedType, annotation, env);
    for (VariableElement parameter : fields) {
      addSerializeParameterWithGetter(encodedType, parameter, serializeBuilder);
    }
    return serializeBuilder.build();
  }

  /**
   * Adds a body to the deserialize method that extracts serialized parameters.
   *
   * <p>Parameter values are extracted into local variables with the same name as the parameter
   * suffixed with a trailing underscore. For example, {@code target} becomes {@code target_}. This
   * is to avoid name collisions with variables used internally by AutoCodec.
   */
  private void buildDeserializeBody(
      MethodSpec.Builder builder, List<? extends VariableElement> fields) {
    for (VariableElement parameter : fields) {
      String paramName = parameter.getSimpleName() + "_";
      marshallers.writeDeserializationCode(
          new Marshaller.Context(builder, parameter.asType(), paramName));
    }
  }

  /**
   * Invokes the instantiator and returns the value.
   *
   * <p>Used by the {@link AutoCodec.Strategy#INSTANTIATOR} strategy.
   */
  private static void addReturnNew(
      MethodSpec.Builder builder,
      TypeElement type,
      ExecutableElement instantiator,
      Object builderVar,
      ProcessingEnvironment env) {
    List<? extends TypeMirror> allThrown = instantiator.getThrownTypes();
    if (!allThrown.isEmpty()) {
      builder.beginControlFlow("try");
    }
    TypeName typeName = TypeName.get(env.getTypeUtils().erasure(type.asType()));
    String parameters =
        instantiator
            .getParameters()
            .stream()
            .map(AutoCodecProcessor::handleFromParameter)
            .collect(Collectors.joining(", "));
    if (instantiator.getKind().equals(ElementKind.CONSTRUCTOR)) {
      builder.addStatement("return new $T($L)", typeName, parameters);
    } else if (builderVar == null) { // Otherwise, it's a factory method.
      builder.addStatement("return $T.$L($L)", typeName, instantiator.getSimpleName(), parameters);
    } else {
      builder.addStatement(
          "return $L.$L($L)", builderVar, instantiator.getSimpleName(), parameters);
    }
    if (!allThrown.isEmpty()) {
      for (TypeMirror thrown : allThrown) {
        builder.nextControlFlow("catch ($T e)", TypeName.get(thrown));
        builder.addStatement(
            "throw new $T(\"$L instantiator threw an exception\", e)",
            SerializationException.class,
            type.getQualifiedName());
      }
      builder.endControlFlow();
    }
  }

  /**
   * Coverts a constructor parameter to a String representing its handle within deserialize.
   */
  private static String handleFromParameter(VariableElement parameter) {
    return parameter.getSimpleName() + "_";
  }

  /**
   * Adds fields to the codec class to hold offsets and adds a constructor to initialize them.
   *
   * <p>For a parameter with name {@code target}, the field will have name {@code target_offset}.
   *
   * @param parameters constructor parameters
   */
  private void initializeUnsafeOffsets(
      TypeSpec.Builder builder,
      TypeElement encodedType,
      List<? extends VariableElement> parameters) {
    MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
    for (VariableElement param : parameters) {
      Optional<FieldValueAndClass> field =
          getFieldByNameRecursive(encodedType, param.getSimpleName().toString());
      if (!field.isPresent()) {
        // Will attempt to use a getter for this field instead.
        continue;
      }
      builder.addField(
          TypeName.LONG, param.getSimpleName() + "_offset", Modifier.PRIVATE, Modifier.FINAL);
      constructor.beginControlFlow("try");
      constructor.addStatement(
          "this.$L_offset = $T.getInstance().objectFieldOffset($T.class.getDeclaredField(\"$L\"))",
          param.getSimpleName(),
          UnsafeProvider.class,
          ClassName.get(field.get().declaringClassType),
          param.getSimpleName());
      constructor.nextControlFlow("catch ($T e)", NoSuchFieldException.class);
      constructor.addStatement("throw new $T(e)", IllegalStateException.class);
      constructor.endControlFlow();
    }
    builder.addMethod(constructor.build());
  }

  /** The value of a field, as well as the class that directly declares it. */
  private static class FieldValueAndClass {
    final VariableElement value;
    final TypeElement declaringClassType;

    FieldValueAndClass(VariableElement value, TypeElement declaringClassType) {
      this.value = value;
      this.declaringClassType = declaringClassType;
    }
  }

  private Optional<FieldValueAndClass> getFieldByNameRecursive(TypeElement type, String name) {
    Optional<VariableElement> field =
        ElementFilter.fieldsIn(type.getEnclosedElements())
            .stream()
            .filter(f -> f.getSimpleName().contentEquals(name))
            .findAny();

    if (field.isPresent()) {
      return Optional.of(new FieldValueAndClass(field.get(), type));
    }
    if (type.getSuperclass().getKind() != TypeKind.NONE) {
      // Applies the erased superclass type so that it can be used in `T.class`.
      return getFieldByNameRecursive(
          (TypeElement)
              env.getTypeUtils().asElement(env.getTypeUtils().erasure(type.getSuperclass())),
          name);
    }
    return Optional.empty();
  }

  private boolean isSameReturnType(ExecutableElement method, TypeElement typeElement) {
    return env.getTypeUtils().isSameType(method.getReturnType(), typeElement.asType());
  }

  /** Emits a note to BUILD log during annotation processing for debugging. */
  private void note(String note) {
    env.getMessager().printMessage(Diagnostic.Kind.NOTE, note);
  }
}
