// Copyright 2016 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.android.desugar;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.android.desugar.io.BitFlags;
import java.util.LinkedHashSet;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeInsnNode;

/**
 * Visitor intended to fix up lambda classes to match assumptions made in {@link LambdaDesugaring}.
 * Specifically this includes fixing visibilities and generating any missing factory methods.
 *
 * <p>Each instance can only visit one class. This is because the signature of the needed factory
 * method is passed into the constructor.
 */
class LambdaClassFixer extends ClassVisitor {

  /** Magic method name used by {@link java.lang.invoke.LambdaMetafactory}. */
  public static final String FACTORY_METHOD_NAME = "get$Lambda";
  /** Field name we'll use to hold singleton instances where possible. */
  public static final String SINGLETON_FIELD_NAME = "$instance";

  private final LambdaInfo lambdaInfo;
  private final ClassReaderFactory factory;
  private final ImmutableSet<String> interfaceLambdaMethods;
  private final boolean allowDefaultMethods;
  private final boolean copyBridgeMethods;
  private final ClassLoader classLoader;
  private final LinkedHashSet<String> implementedMethods = new LinkedHashSet<>();
  private final LinkedHashSet<String> methodsToMoveIn = new LinkedHashSet<>();

  private String originalInternalName;
  private ImmutableList<String> interfaces;

  private boolean hasState;
  private boolean hasFactory;

  private String desc;
  private String signature;

  public LambdaClassFixer(
      ClassVisitor dest,
      LambdaInfo lambdaInfo,
      ClassReaderFactory factory,
      ClassLoader classLoader,
      ImmutableSet<String> interfaceLambdaMethods,
      boolean allowDefaultMethods,
      boolean copyBridgeMethods) {
    super(Opcodes.ASM7, dest);
    checkArgument(!allowDefaultMethods || interfaceLambdaMethods.isEmpty());
    checkArgument(allowDefaultMethods || copyBridgeMethods);
    this.lambdaInfo = lambdaInfo;
    this.factory = factory;
    this.classLoader = classLoader;
    this.interfaceLambdaMethods = interfaceLambdaMethods;
    this.allowDefaultMethods = allowDefaultMethods;
    this.copyBridgeMethods = copyBridgeMethods;
  }

  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    checkArgument(BitFlags.noneSet(access, Opcodes.ACC_INTERFACE), "Not a class: %s", name);
    checkState(this.originalInternalName == null, "not intended for reuse but reused for %s", name);
    originalInternalName = name;
    hasState = false;
    hasFactory = false;
    desc = null;
    this.signature = null;
    this.interfaces = ImmutableList.copyOf(interfaces);
    // Rename to desired name
    super.visit(version, access, getInternalName(), signature, superName, interfaces);
  }

  @Override
  public FieldVisitor visitField(
      int access, String name, String desc, String signature, Object value) {
    hasState = true;
    return super.visitField(access, name, desc, signature, value);
  }

  @Override
  public MethodVisitor visitMethod(
      int access, String name, String desc, String signature, String[] exceptions) {
    if (name.equals("writeReplace")
        && BitFlags.noneSet(access, Opcodes.ACC_STATIC)
        && desc.equals("()Ljava/lang/Object;")) {
      // Lambda serialization hooks use java/lang/invoke/SerializedLambda, which isn't available on
      // Android. Since Jack doesn't do anything special for serializable lambdas we just drop these
      // serialization hooks.
      // https://docs.oracle.com/javase/8/docs/platform/serialization/spec/output.html#a5324 gives
      // details on the role and signature of this method.
      return null;
    }
    if (BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC)) {
      // Keep track of instance methods implemented in this class for later.  Since this visitor
      // is intended for lambda classes, no need to look at the superclass.
      implementedMethods.add(name + ":" + desc);
    }
    if (FACTORY_METHOD_NAME.equals(name)) {
      hasFactory = true;
      if (!lambdaInfo.needFactory()) {
        return null; // drop generated factory method if we won't call it
      }
      access &= ~Opcodes.ACC_PRIVATE; // make factory method accessible
    } else if ("<init>".equals(name)) {
      this.desc = desc;
      this.signature = signature;
      if (!lambdaInfo.needFactory() && !desc.startsWith("()")) {
        access &= ~Opcodes.ACC_PRIVATE; // make constructor accessible if we'll call it directly
      }
    }
    MethodVisitor methodVisitor =
        new LambdaClassMethodRewriter(super.visitMethod(access, name, desc, signature, exceptions));
    if (!lambdaInfo.bridgeMethod().equals(lambdaInfo.methodReference())) {
      // Skip UseBridgeMethod unless we actually need it
      methodVisitor =
          new UseBridgeMethod(
              methodVisitor, lambdaInfo, classLoader, access, name, desc, signature, exceptions);
    }
    if (!FACTORY_METHOD_NAME.equals(name) && !"<init>".equals(name)) {
      methodVisitor = new LambdaClassInvokeSpecialRewriter(methodVisitor);
    }
    return methodVisitor;
  }

  @Override
  public void visitEnd() {
    checkState(
        !hasState || hasFactory,
        "Expected factory method for capturing lambda %s",
        getInternalName());
    if (!hasState) {
      checkState(
          signature == null,
          "Didn't expect generic constructor signature %s %s",
          getInternalName(),
          signature);
      checkState(
          lambdaInfo.factoryMethodDesc().startsWith("()"),
          "Expected 0-arg factory method for %s but found %s",
          getInternalName(),
          lambdaInfo.factoryMethodDesc());
      // Since this is a stateless class we populate and use a static singleton field "$instance".
      // Field is package-private so we can read it from the class that had the invokedynamic.
      String singletonFieldDesc = lambdaInfo.factoryMethodDesc().substring("()".length());
      super.visitField(
              Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
              SINGLETON_FIELD_NAME,
              singletonFieldDesc,
              (String) null,
              (Object) null)
          .visitEnd();

      MethodVisitor codeBuilder =
          super.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", (String) null, new String[0]);
      codeBuilder.visitTypeInsn(Opcodes.NEW, getInternalName());
      codeBuilder.visitInsn(Opcodes.DUP);
      codeBuilder.visitMethodInsn(
          Opcodes.INVOKESPECIAL,
          getInternalName(),
          "<init>",
          checkNotNull(desc, "didn't see a constructor for %s", getInternalName()),
          /*isInterface=*/ false);
      codeBuilder.visitFieldInsn(
          Opcodes.PUTSTATIC, getInternalName(), SINGLETON_FIELD_NAME, singletonFieldDesc);
      codeBuilder.visitInsn(Opcodes.RETURN);
      codeBuilder.visitMaxs(2, 0); // two values are pushed onto the stack
      codeBuilder.visitEnd();
    }

    copyRewrittenLambdaMethods();
    if (copyBridgeMethods) {
      copyBridgeMethods(interfaces);
    }
    super.visitEnd();
  }

  private String getInternalName() {
    return lambdaInfo.desiredInternalName();
  }

  private void copyRewrittenLambdaMethods() {
    for (String rewritten : methodsToMoveIn) {
      String interfaceInternalName = rewritten.substring(0, rewritten.indexOf('#'));
      String methodName = rewritten.substring(interfaceInternalName.length() + 1);
      ClassReader bytecode =
          checkNotNull(
              factory.readIfKnown(interfaceInternalName),
              "Couldn't load interface with lambda method %s",
              rewritten);
      CopyOneMethod copier = new CopyOneMethod(methodName);
      // TODO(kmb): Set source file attribute for lambda classes so lambda debug info makes sense
      bytecode.accept(copier, ClassReader.SKIP_DEBUG);
      checkState(copier.copied(), "Didn't find %s", rewritten);
    }
  }

  private void copyBridgeMethods(ImmutableList<String> interfaces) {
    for (String implemented : interfaces) {
      ClassReader bytecode = factory.readIfKnown(implemented);
      if (bytecode != null) {
        // Don't copy line numbers and local variable tables.  They would be misleading or wrong
        // and other methods in generated lambda classes don't have debug info either.
        bytecode.accept(new CopyBridgeMethods(), ClassReader.SKIP_DEBUG);
      } // else the interface is defined in a different Jar, which we can ignore here
    }
  }

  /** Rewriter for methods in generated lambda classes. */
  private class LambdaClassMethodRewriter extends MethodVisitor {
    public LambdaClassMethodRewriter(MethodVisitor dest) {
      super(Opcodes.ASM7, dest);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      String method = owner + "#" + name;
      if (interfaceLambdaMethods.contains(method)) {
        // Rewrite invocations of lambda methods in interfaces to anticipate the lambda method being
        // moved into the lambda class (i.e., the class being visited here).
        checkArgument(opcode == Opcodes.INVOKESTATIC, "Cannot move instance method %s", method);
        owner = getInternalName();
        itf = false; // owner was interface but is now a class
        methodsToMoveIn.add(method);
      } else if (originalInternalName.equals(owner)) {
        // Reflect renaming of lambda classes
        owner = getInternalName();
      }

      if (name.startsWith("lambda$")) {
        // Reflect renaming of lambda$ instance methods in LambdaDesugaring.  Do this even if we'll
        // move the method into the lambda class we're processing so the renaming done in
        // LambdaDesugaring doesn't kick in if the class were desugared a second time.
        name = LambdaDesugaring.uniqueInPackage(owner, name);
      }
      super.visitMethodInsn(opcode, owner, name, desc, itf);
    }

    @Override
    public void visitTypeInsn(int opcode, String type) {
      if (originalInternalName.equals(type)) {
        // Reflect renaming of lambda classes
        type = getInternalName();
      }
      super.visitTypeInsn(opcode, type);
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      if (originalInternalName.equals(owner)) {
        // Reflect renaming of lambda classes
        owner = getInternalName();
      }
      super.visitFieldInsn(opcode, owner, name, desc);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      // Drop annotation that's part of the generated lambda class that's not available on Android.
      // Proguard complains about this otherwise.
      if ("Ljava/lang/invoke/LambdaForm$Hidden;".equals(desc)) {
        return null;
      }
      return super.visitAnnotation(desc, visible);
    }
  }

  /** Rewriter for invokespecial in generated lambda classes. */
  private static class LambdaClassInvokeSpecialRewriter extends MethodVisitor {

    public LambdaClassInvokeSpecialRewriter(MethodVisitor dest) {
      super(Opcodes.ASM7, dest);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      if (opcode == Opcodes.INVOKESPECIAL && name.startsWith("lambda$")) {
        opcode = itf ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL;
      }

      super.visitMethodInsn(opcode, owner, name, desc, itf);
    }
  }

  /**
   * Visitor that copies bridge methods from the visited interface into the class visited by the
   * surrounding {@link LambdaClassFixer}. Descends recursively into interfaces extended by the
   * visited interface.
   */
  private class CopyBridgeMethods extends ClassVisitor {

    @SuppressWarnings("hiding")
    private ImmutableList<String> interfaces;

    public CopyBridgeMethods() {
      // No delegate visitor; instead we'll add methods to the outer class's delegate where needed
      super(Opcodes.ASM7);
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      checkArgument(BitFlags.isSet(access, Opcodes.ACC_INTERFACE));
      checkState(this.interfaces == null);
      this.interfaces = ImmutableList.copyOf(interfaces);
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if ((access & (Opcodes.ACC_BRIDGE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC))
          == Opcodes.ACC_BRIDGE) {
        // Only copy bridge methods--hand-written default methods are not supported--and only if
        // we haven't seen the method already.
        if (implementedMethods.add(name + ":" + desc)) {
          MethodVisitor result =
              LambdaClassFixer.super.visitMethod(access, name, desc, signature, exceptions);
          return allowDefaultMethods ? result : new AvoidJacocoInit(result);
        }
      }
      return null;
    }

    @Override
    public void visitEnd() {
      copyBridgeMethods(this.interfaces);
    }
  }

  private class CopyOneMethod extends ClassVisitor {

    private final String methodName;
    private int copied = 0;

    public CopyOneMethod(String methodName) {
      // No delegate visitor; instead we'll add methods to the outer class's delegate where needed
      super(Opcodes.ASM7);
      checkState(!allowDefaultMethods, "Couldn't copy interface lambda bodies");
      this.methodName = methodName;
    }

    public boolean copied() {
      return copied > 0;
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      checkArgument(BitFlags.isSet(access, Opcodes.ACC_INTERFACE));
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (name.equals(methodName)) {
        checkState(copied == 0, "Found unexpected second method %s with descriptor %s", name, desc);
        ++copied;
        // Rename for consistency with what we do in LambdaClassMethodRewriter
        name = LambdaDesugaring.uniqueInPackage(getInternalName(), name);
        return new AvoidJacocoInit(
            LambdaClassFixer.super.visitMethod(access, name, desc, signature, exceptions));
      }
      return null;
    }
  }

  /**
   * Method visitor that rewrites {@code $jacocoInit()} calls to equivalent field accesses.
   *
   * <p>This class should only be used to visit interface methods and assumes that the code in
   * {@code $jacocoInit()} is always executed in the interface's static initializer, which is the
   * case in the absence of hand-written static or default interface methods (which {@link
   * Java7Compatibility} makes sure of).
   */
  private static class AvoidJacocoInit extends MethodVisitor {
    public AvoidJacocoInit(MethodVisitor dest) {
      super(Opcodes.ASM7, dest);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      if (opcode == Opcodes.INVOKESTATIC && "$jacocoInit".equals(name)) {
        // Rewrite $jacocoInit() calls to just read the $jacocoData field
        super.visitFieldInsn(Opcodes.GETSTATIC, owner, "$jacocoData", "[Z");
      } else {
        super.visitMethodInsn(opcode, owner, name, desc, itf);
      }
    }
  }

  private static class UseBridgeMethod extends MethodNode {

    private final MethodVisitor dest;
    private final LambdaInfo lambdaInfo;
    private final ClassLoader classLoader;

    public UseBridgeMethod(
        MethodVisitor dest,
        LambdaInfo lambdaInfo,
        ClassLoader classLoader,
        int access,
        String name,
        String desc,
        String signature,
        String[] exceptions) {
      super(Opcodes.ASM7, access, name, desc, signature, exceptions);
      this.dest = dest;
      this.lambdaInfo = lambdaInfo;
      this.classLoader = classLoader;
      checkArgument(
          !lambdaInfo.methodReference().equals(lambdaInfo.bridgeMethod()),
          "This class only works for a lambda that has a bridge method. lambdaInfo=%s, bridge=%s",
          lambdaInfo.methodReference(),
          lambdaInfo.bridgeMethod());
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      if (!name.equals(lambdaInfo.methodReference().getName())
          || !desc.equals(lambdaInfo.methodReference().getDesc())) {
        super.visitMethodInsn(opcode, owner, name, desc, itf);
        return;
      }

      boolean useBridgeMethod = false;
      if (owner.equals(lambdaInfo.methodReference().getOwner())) {
        if (lambdaInfo.methodReference().getTag() == Opcodes.H_NEWINVOKESPECIAL
            && lambdaInfo.bridgeMethod().getTag() != Opcodes.H_NEWINVOKESPECIAL) {
          // We're changing a constructor call to a factory method call, so we unfortunately need
          // to go find the NEW/DUP pair preceding the constructor call and remove it
          removeLastAllocation();
        }
        useBridgeMethod = true;
      } else if ((lambdaInfo.methodReference().getTag() == Opcodes.H_INVOKEVIRTUAL
              || lambdaInfo.methodReference().getTag() == Opcodes.H_INVOKESPECIAL)
          && hasAssignableRelation(owner, lambdaInfo.methodReference().getOwner())) {
        // For rewriting instance methods calls, we consider the class hierarchy.
        // This is for JDK 9: (b/62218600).
        // TODO(cnsun): revisit this to make sure Desugar is fully compatible with this change
        // in JDK: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/a3b3c7b6464d
        useBridgeMethod = true;
      }
      if (useBridgeMethod) {
        super.visitMethodInsn(
            LambdaDesugaring.invokeOpcode(lambdaInfo.bridgeMethod()),
            lambdaInfo.bridgeMethod().getOwner(),
            lambdaInfo.bridgeMethod().getName(),
            lambdaInfo.bridgeMethod().getDesc(),
            lambdaInfo.bridgeMethod().isInterface());
      } else {
        super.visitMethodInsn(opcode, owner, name, desc, itf);
      }
    }

    private void removeLastAllocation() {
      AbstractInsnNode insn = instructions.getLast();
      while (insn != null && insn.getPrevious() != null) {
        AbstractInsnNode prev = insn.getPrevious();
        if (prev.getOpcode() == Opcodes.NEW
            && insn.getOpcode() == Opcodes.DUP
            && ((TypeInsnNode) prev).desc.equals(lambdaInfo.methodReference().getOwner())) {
          instructions.remove(prev);
          instructions.remove(insn);
          return;
        }
        insn = prev;
      }
      throw new IllegalStateException(
          "Couldn't find allocation to rewrite ::new reference " + lambdaInfo.methodReference());
    }

    private boolean hasAssignableRelation(String ownerOfMethodInsn, String ownerOfMethodReference) {
      try {
        Class<?> methodInsnOwnerClass = classLoader.loadClass(ownerOfMethodInsn.replace('/', '.'));
        Class<?> methodReferenceOwnerClass =
            classLoader.loadClass(ownerOfMethodReference.replace('/', '.'));
        return methodInsnOwnerClass.isAssignableFrom(methodReferenceOwnerClass)
            || methodReferenceOwnerClass.isAssignableFrom(methodInsnOwnerClass);
      } catch (ClassNotFoundException e) {
        throw new IllegalStateException(
            "Failed to load method owners for inserting bridge method: " + lambdaInfo, e);
      }
    }

    @Override
    public void visitEnd() {
      accept(dest);
    }
  }
}
