// 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.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.devtools.build.android.desugar.io.BitFlags;
import com.google.devtools.build.android.desugar.io.FieldInfo;
import com.google.devtools.build.android.r8.DependencyCollector;
import java.lang.reflect.Method;
import java.util.Arrays;
import javax.annotation.Nullable;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath;

/**
 * Visitor that moves methods with bodies from interfaces into a companion class and rewrites call
 * sites accordingly (which is only needed for static interface methods). Default methods are kept
 * as abstract methods with all their annotations.
 *
 * <p>Any necessary companion classes will be added to the given {@link GeneratedClassStore}. It's
 * the caller's responsibility to write those out.
 *
 * <p>Relies on {@link DefaultMethodClassFixer} to stub in method bodies for moved default methods.
 * Assumes that lambdas are already desugared. Ignores bridge methods, which are handled specially.
 */
class InterfaceDesugaring extends ClassVisitor {

  static final String COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_NAME = "$$triggerInterfaceInit";
  static final String COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_DESC = "()V";

  static final String DEFAULT_COMPANION_METHOD_SUFFIX = "$$dflt$$";

  private final boolean generateBaseClasses;
  private final ClassVsInterface interfaceCache;
  private final DependencyCollector depsCollector;
  private final CoreLibrarySupport coreLibrarySupport;
  private final ClassReaderFactory bootclasspath;
  private final ClassLoader targetLoader;
  private final GeneratedClassStore store;
  private final boolean legacyJaCoCo;

  private String internalName;
  private int bytecodeVersion;
  private int accessFlags;
  private String[] interfaces;
  private int numberOfDefaultMethods;
  @Nullable private ClassVisitor companion;
  @Nullable private FieldInfo interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit;

  public InterfaceDesugaring(
      ClassVisitor dest,
      boolean generateBaseClasses,
      ClassVsInterface interfaceCache,
      DependencyCollector depsCollector,
      @Nullable CoreLibrarySupport coreLibrarySupport,
      ClassReaderFactory bootclasspath,
      ClassLoader targetLoader,
      GeneratedClassStore store,
      boolean legacyJaCoCo) {
    super(Opcodes.ASM8, dest);
    this.generateBaseClasses = generateBaseClasses;
    this.interfaceCache = interfaceCache;
    this.depsCollector = depsCollector;
    this.coreLibrarySupport = coreLibrarySupport;
    this.bootclasspath = bootclasspath;
    this.targetLoader = targetLoader;
    this.store = store;
    this.legacyJaCoCo = legacyJaCoCo;
  }

  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    companion = null;
    numberOfDefaultMethods = 0;
    internalName = name;
    bytecodeVersion = version;
    accessFlags = access;
    this.interfaces = interfaces;
    if (isInterface()) {
      interfaceCache.addKnownInterfaces(name);
      // Record interface hierarchy.  This helps avoid parsing .class files when double-checking
      // desugaring results later using collected dependency information.
      depsCollector.recordExtendedInterfaces(name, interfaces);
    } else {
      interfaceCache.addKnownClass(name);
    }
    interfaceCache.addKnownClass(superName).addKnownInterfaces(interfaces);
    super.visit(version, access, name, signature, superName, interfaces);
  }

  @Override
  public void visitEnd() {
    if (companion != null) {
      // Record classes with default methods.  This increases precision when double-checking
      // desugaring results later, without parsing .class files again, compared to just looking
      // for companion classes in a given desugared Jar which may only contain static methods.
      depsCollector.recordDefaultMethods(internalName, numberOfDefaultMethods);

      // Emit a method to access the fields of the interfaces that need initialization.
      emitInterfaceFieldAccessInCompanionMethodToTriggerInterfaceClinit();
      companion.visitEnd();
    }
    super.visitEnd();
  }

  private void emitInterfaceFieldAccessInCompanionMethodToTriggerInterfaceClinit() {
    if (companion == null
        || interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit == null) {
      return;
    }

    // Create a method to access the interface fields
    MethodVisitor visitor =
        checkNotNull(
            companion.visitMethod(
                Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC,
                COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_NAME,
                COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_DESC,
                null,
                null),
            "Cannot get a method visitor to write out %s to the companion class.",
            COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_NAME);
    // Visit the interface field to triger <clinit> of the interface.

    visitor.visitFieldInsn(
        Opcodes.GETSTATIC,
        interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit.owner(),
        interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit.name(),
        interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit.desc());
    Type fieldType =
        Type.getType(interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit.desc());
    if (fieldType.getSort() == Type.LONG || fieldType.getSort() == Type.DOUBLE) {
      visitor.visitInsn(Opcodes.POP2);
    } else {
      visitor.visitInsn(Opcodes.POP);
    }
    visitor.visitInsn(Opcodes.RETURN);
  }

  @Override
  public FieldVisitor visitField(
      int access, String name, String desc, String signature, Object value) {
    if (legacyJaCoCo
        && isInterface()
        && BitFlags.isSet(access, Opcodes.ACC_FINAL)
        && "$jacocoData".equals(name)) {
      // Move $jacocoData field to companion class and remove final modifier. We'll rewrite field
      // accesses accordingly. Code generated by older JaCoCo versions tried to assign to this
      // final field in methods, and interface fields have to be private, so we move the field
      // to a class, which ends up looking pretty similar to what JaCoCo generates for classes.
      access &= ~Opcodes.ACC_FINAL;
      return companion().visitField(access, name, desc, signature, value);
    } else {
      return super.visitField(access, name, desc, signature, value);
    }
  }

  @Override
  public MethodVisitor visitMethod(
      int access, String name, String desc, String signature, String[] exceptions) {
    String codeOwner = internalName;
    MethodVisitor result;
    if (isInterface() && isStaticInitializer(name)) {
      result =
          new InterfaceFieldWriteCollector(
              super.visitMethod(access, name, desc, signature, exceptions));
      if (result != null && legacyJaCoCo) {
        result = new MoveJacocoFieldAccess(result);
      }
    } else if (isInterface()
        && BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_BRIDGE)) {
      checkArgument(BitFlags.noneSet(access, Opcodes.ACC_NATIVE), "Forbidden per JLS ch 9.4");

      boolean isLambdaBody = name.startsWith("lambda$") && BitFlags.isSynthetic(access);
      if (isLambdaBody) {
        access &= ~Opcodes.ACC_PUBLIC; // undo visibility change from LambdaDesugaring
      }
      String companionMethodName =
          normalizeInterfaceMethodName(
              name,
              isLambdaBody,
              BitFlags.isStatic(access) ? Opcodes.INVOKESTATIC : Opcodes.INVOKESPECIAL);
      codeOwner = getCompanionClassName(internalName);

      if (BitFlags.isStatic(access)) {
        // Completely move static interface methods, which requires rewriting call sites
        result =
            companion()
                .visitMethod(
                    access & ~Opcodes.ACC_PRIVATE,
                    companionMethodName,
                    desc,
                    signature,
                    exceptions);
      } else {
        MethodVisitor abstractDest;
        if (isLambdaBody) {
          // Completely move lambda bodies, which requires rewriting call sites
          access &= ~Opcodes.ACC_PRIVATE;
          abstractDest = null;
        } else {
          // Make default methods abstract but move their implementation into a static method with
          // corresponding signature.  Doesn't require callsite rewriting but implementing classes
          // may need to implement default methods explicitly.
          checkArgument(
              BitFlags.noneSet(access, Opcodes.ACC_PRIVATE),
              "Unexpected private interface method %s.%s : %s",
              name,
              internalName,
              desc);
          ++numberOfDefaultMethods;
          if (coreLibrarySupport != null) {
            coreLibrarySupport.registerIfEmulatedCoreInterface(
                access, internalName, name, desc, exceptions);
          }
          abstractDest =
              super.visitMethod(access | Opcodes.ACC_ABSTRACT, name, desc, signature, exceptions);

          if (generateBaseClasses) {
            // Generate base class stub here and now...  Write this extra method first so we can
            // return the visitor to receive the actual default method body below.
            generateStub(
                companion().visitMethod(access, name, desc, (String) null, exceptions),
                companionMethodName,
                companionDefaultMethodDescriptor(internalName, desc));
          }
        }

        // TODO(b/37110951): adjust signature with explicit receiver type, which may be generic
        // Method visitor that passes through all code but sends annotations into a second given
        // MethodVisitor instead.
        MethodVisitor codeDest =
            companion()
                .visitMethod(
                    access | Opcodes.ACC_STATIC,
                    companionMethodName,
                    companionDefaultMethodDescriptor(internalName, desc),
                    (String) null, // drop signature, since given one doesn't include the new param
                    exceptions);

        result = abstractDest != null ? new MultiplexAnnotations(codeDest, abstractDest) : codeDest;
      }
      if (result != null && legacyJaCoCo) {
        result = new MoveJacocoFieldAccess(result);
      }
    } else if (generateBaseClasses
        && isInterface()
        && ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_BRIDGE | Opcodes.ACC_STATIC))
            == Opcodes.ACC_BRIDGE)) {
      // Straight-up move bridge methods to companion alongside other stubs; we would drop them in
      // Java7Compatibility anyways
      result = companion().visitMethod(access, name, desc, (String) null, exceptions);
    } else {
      result = super.visitMethod(access, name, desc, signature, exceptions);
    }
    return result != null
        ? new InterfaceInvocationRewriter(
            result,
            isInterface() ? internalName : null,
            bootclasspath,
            targetLoader,
            depsCollector,
            codeOwner)
        : null;
  }

  private void generateStub(MethodVisitor stubMethod, String calledMethodName, String desc) {
    int slot = 0;
    Type neededType = Type.getMethodType(desc);
    for (Type arg : neededType.getArgumentTypes()) {
      stubMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
      slot += arg.getSize();
    }
    stubMethod.visitMethodInsn(
        Opcodes.INVOKESTATIC,
        getCompanionClassName(internalName),
        calledMethodName,
        desc,
        /*isInterface=*/ false);
    stubMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));
    stubMethod.visitMaxs(slot, slot);
    stubMethod.visitEnd();
  }

  @Override
  public void visitOuterClass(String owner, String name, String desc) {
    // Proguard gets grumpy if an outer method doesn't exist, which can be the result of moving
    // interface methods to companion classes (b/68260836).  In that case (for which we need to
    // figure out if "owner" is an interface) need to adjust the outer method information.
    if (name != null && interfaceCache.isOuterInterface(owner, internalName)) {
      // Just drop outer method info.  That's unfortunate, but the only alternative would be to
      // change the outer method to point to the companion class, which would mean the
      // reflection methods that use this information would return a companion ($$CC) class name
      // as well as a possibly-modified method name and signature, so it seems better to return
      // the correct original interface name and no method information.  Doing this also saves
      // us from doing even more work to figure out whether the method is static and a lambda
      // method, which we'd need to known to adjust name and descriptor correctly.
      name = null;
      desc = null;
    } // otherwise there's no enclosing method that could've been moved, or owner is a class
    super.visitOuterClass(owner, name, desc);
  }

  private boolean isInterface() {
    return BitFlags.isInterface(accessFlags);
  }

  private static boolean isStaticInitializer(String methodName) {
    return "<clinit>".equals(methodName);
  }

  static String normalizeInterfaceMethodName(String name, boolean isLambda, int opcode) {
    if (isLambda) {
      // Rename lambda method to reflect the new owner.  Not doing so confuses LambdaDesugaring
      // if it's run over this class again. LambdaDesugaring has already renamed the method from
      // its original name to include the interface name at this point.
      return name + DependencyCollector.INTERFACE_COMPANION_SUFFIX;
    }

    switch (opcode) {
      case Opcodes.INVOKESPECIAL:
        // Rename static methods holding default method implementations since their descriptor
        // differs from the original method (due to explicit receiver parameter). This avoids
        // possible clashes with static interface methods or generated stubs for default methods
        // that could otherwise have the same name and descriptor by coincidence.
        return name + DEFAULT_COMPANION_METHOD_SUFFIX;
      case Opcodes.INVOKESTATIC: // moved but with same name
        return name + "$$STATIC$$"; // TODO(b/117453106): Stop renaming static interface methods
      case Opcodes.INVOKEINTERFACE: // not moved
      case Opcodes.INVOKEVIRTUAL: // tolerate being called for non-interface methods
        return name;
      default:
        throw new IllegalArgumentException("Unexpected opcode calling " + name + ": " + opcode);
    }
  }

  static String getCompanionClassName(String interfaceName) {
    return interfaceName + DependencyCollector.INTERFACE_COMPANION_SUFFIX;
  }

  /**
   * Returns the descriptor of a static method for an instance method with the given receiver and
   * description, simply by pre-pending the given descriptor's parameter list with the given
   * receiver type.
   */
  static String companionDefaultMethodDescriptor(String interfaceName, String desc) {
    Type type = Type.getMethodType(desc);
    Type[] companionArgs = new Type[type.getArgumentTypes().length + 1];
    companionArgs[0] = Type.getObjectType(interfaceName);
    System.arraycopy(type.getArgumentTypes(), 0, companionArgs, 1, type.getArgumentTypes().length);
    return Type.getMethodDescriptor(type.getReturnType(), companionArgs);
  }

  private ClassVisitor companion() {
    if (companion == null) {
      checkState(isInterface());
      String companionName = getCompanionClassName(internalName);
      String[] companionInterfaces;
      if (generateBaseClasses) {
        // Implement the interface so DefaultMethodClassFixer generates stubs for default methods
        // (in addition to the static methods we create here). Thereby the companion class can
        // be used as a base class.
        companionInterfaces = Arrays.copyOf(interfaces, interfaces.length + 1);
        companionInterfaces[interfaces.length] = internalName;
      } else {
        companionInterfaces = new String[0];
      }

      companion = store.add(companionName);
      companion.visit(
          bytecodeVersion,
          // Companion class must be public so moved methods can be called from anywhere
          (accessFlags | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT)
              & ~Opcodes.ACC_INTERFACE,
          companionName,
          (String) null,
          "java/lang/Object",
          companionInterfaces);

      if (generateBaseClasses) {
        MethodVisitor constructor =
            companion.visitMethod(
                Opcodes.ACC_PUBLIC, "<init>", "()V", (String) null, new String[0]);
        constructor.visitCode();
        constructor.visitVarInsn(Opcodes.ALOAD, 0);
        constructor.visitMethodInsn(
            Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        constructor.visitInsn(Opcodes.RETURN);
        constructor.visitMaxs(1, 1);
        constructor.visitEnd();
      }
    }
    return companion;
  }

  /**
   * Interface field scanner to get the first field of the current interface that is written in the
   * initializer.
   */
  private class InterfaceFieldWriteCollector extends MethodVisitor {

    public InterfaceFieldWriteCollector(MethodVisitor mv) {
      super(Opcodes.ASM8, mv);
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      if (interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit == null
          && opcode == Opcodes.PUTSTATIC
          && owner.equals(internalName)) {
        // It is possible that an interface initializer can sets fields of other classes.
        // (b/64290760), so we test whether the owner is the same as the internalName.
        interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit =
            FieldInfo.create(owner, name, desc);
      }
      super.visitFieldInsn(opcode, owner, name, desc);
    }
  }

  /**
   * Rewriter for calls to static interface methods and super calls to default methods, unless
   * they're part of the bootclasspath, as well as all lambda body methods. Keeps calls to interface
   * methods declared in the bootclasspath as-is (but note that these would presumably fail on
   * devices without those methods).
   */
  static class InterfaceInvocationRewriter extends MethodVisitor {

    /**
     * If we're visiting a method declared in an interface, the internal name of that interface.
     * That lets us rewrite invocations of other methods within that interface even if the bytecode
     * fails to indicate them as interface method invocations, as older versions of JaCoCo failed to
     * do (b/62623509).
     */
    @Nullable private final String interfaceName;

    private final ClassReaderFactory bootclasspath;
    private final ClassLoader targetLoader;
    private final DependencyCollector depsCollector;
    /** Internal name that'll be used to record any dependencies on interface methods. */
    private final String declaringClass;

    public InterfaceInvocationRewriter(
        MethodVisitor dest,
        @Nullable String knownInterfaceName,
        ClassReaderFactory bootclasspath,
        ClassLoader targetLoader,
        DependencyCollector depsCollector,
        String declaringClass) {
      super(Opcodes.ASM8, dest);
      this.interfaceName = knownInterfaceName;
      this.bootclasspath = bootclasspath;
      this.targetLoader = targetLoader;
      this.depsCollector = depsCollector;
      this.declaringClass = declaringClass;
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      // Assume that any static interface methods on the classpath are moved
      if ((itf || owner.equals(interfaceName)) && !bootclasspath.isKnown(owner)) {
        if (name.startsWith("lambda$")) {
          // Redirect lambda invocations to completely remove all lambda methods from interfaces.
          checkArgument(
              !owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX),
              "shouldn't consider %s an interface",
              owner);
          if (opcode == Opcodes.INVOKEINTERFACE) {
            opcode = Opcodes.INVOKESTATIC;
            desc = companionDefaultMethodDescriptor(owner, desc);
          } else {
            checkArgument(
                opcode == Opcodes.INVOKESTATIC,
                "Unexpected opcode %s to invoke %s.%s",
                opcode,
                owner,
                name);
          }
          // Reflect that InterfaceDesugaring moves and renames the lambda body method
          name = normalizeInterfaceMethodName(name, /*isLambda=*/ true, opcode);
          owner += DependencyCollector.INTERFACE_COMPANION_SUFFIX;
          itf = false;
          // Record dependency on companion class
          depsCollector.assumeCompanionClass(declaringClass, owner);

          String expectedLambdaMethodName = LambdaDesugaring.uniqueInPackage(owner, name);
          checkState(
              name.equals(expectedLambdaMethodName),
              "Unexpected lambda body method name for %s: real=%s, expected=%s",
              owner,
              name,
              expectedLambdaMethodName);
        } else if ((opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKESPECIAL)) {
          checkArgument(
              !owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX),
              "shouldn't consider %s an interface",
              owner);
          if (opcode == Opcodes.INVOKESPECIAL) {
            // Turn Interface.super.m() into DefiningInterface$$CC.m(receiver). Note that owner
            // always refers to the current type's immediate super-interface, but the default method
            // may be inherited by that interface, so we have to figure out where the method is
            // defined and invoke it in the corresponding companion class (b/73355452).  Note that
            // we're always dealing with interfaces here, and all interface methods are public,
            // so using Class.getMethods should suffice to find inherited methods.  Also note this
            // can only be a default method invocation, no abstract method invocation.
            owner =
                findDefaultMethod(owner, name, desc)
                    .getDeclaringClass()
                    .getName()
                    .replace('.', '/');
            desc = companionDefaultMethodDescriptor(owner, desc);
          }
          name = normalizeInterfaceMethodName(name, /*isLambda=*/ false, opcode);
          owner += DependencyCollector.INTERFACE_COMPANION_SUFFIX;
          opcode = Opcodes.INVOKESTATIC;
          itf = false;
          // Record dependency on companion class
          depsCollector.assumeCompanionClass(declaringClass, owner);
        } // else non-lambda INVOKEINTERFACE, which needs no rewriting
      }
      super.visitMethodInsn(opcode, owner, name, desc, itf);
    }

    private Method findDefaultMethod(String owner, String name, String desc) {
      try {
        Class<?> clazz = targetLoader.loadClass(owner.replace('/', '.'));
        // otherwise getting public methods with getMethods() below isn't enough
        checkArgument(clazz.isInterface(), "Not an interface: %s", owner);
        for (Method m : clazz.getMethods()) {
          if (m.getName().equals(name) && Type.getMethodDescriptor(m).equals(desc)) {
            checkState(m.isDefault(), "Found non-default method: %s", m);
            return m;
          }
        }
      } catch (ClassNotFoundException e) {
        throw new IllegalStateException("Couldn't load " + owner, e);
      }
      throw new IllegalArgumentException("Method not found: " + owner + "." + name + desc);
    }
  }

  /**
   * Method visitor intended for interface method bodies that rewrites jacoco field accesses to
   * expect the field in the companion class, to work around problematic bytecode emitted by older
   * JaCoCo versions (b/62623509).
   */
  private static class MoveJacocoFieldAccess extends MethodVisitor {

    public MoveJacocoFieldAccess(MethodVisitor mv) {
      super(Opcodes.ASM8, mv);
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      if ("$jacocoData".equals(name)) {
        checkState(
            !owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX),
            "Expected interface: %s",
            owner);
        owner = getCompanionClassName(owner);
      }
      super.visitFieldInsn(opcode, owner, name, desc);
    }
  }

  /**
   * Method visitor that behaves like a passthrough but additionally duplicates all annotations into
   * a second given {@link MethodVisitor}.
   */
  private static class MultiplexAnnotations extends MethodVisitor {

    /** Method visitor for creating desugared interfaces (with static/default methods). */
    private final MethodVisitor annotationOnlyDest;

    public MultiplexAnnotations(@Nullable MethodVisitor dest, MethodVisitor annotationOnlyDest) {
      super(Opcodes.ASM8, dest);
      this.annotationOnlyDest = annotationOnlyDest;
    }

    @Override
    public void visitParameter(String name, int access) {
      annotationOnlyDest.visitParameter(name, access);
      // Intentionally without super call: Method parameter attributes are not supported in Java 7.
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      AnnotationVisitor dest = super.visitAnnotation(desc, visible);
      AnnotationVisitor annoDest = annotationOnlyDest.visitAnnotation(desc, visible);
      return new MultiplexAnnotationVisitor(dest, annoDest);
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(
        int typeRef, TypePath typePath, String desc, boolean visible) {
      // Intentionally without super call: Type annotations are not supported in Java 7.
      return annotationOnlyDest.visitTypeAnnotation(typeRef, typePath, desc, visible);
    }

    @Override
    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
      // Intentionally without super call: Production code should depend on the parameter annotation
      // attributes of the desugared class instead of the companion class instead, and therefore
      // dropping the parameter annotations. Note in the companion class, the corresponding method
      // contains one more parameter than the method in the desugared class, a direct propagation
      // would cause position mismatch. see b/129719629.
      return annotationOnlyDest.visitParameterAnnotation(parameter, desc, visible);
    }
  }

  /**
   * Annotation visitor that recursively passes the visited annotations to any number of given
   * {@link AnnotationVisitor}s.
   */
  private static class MultiplexAnnotationVisitor extends AnnotationVisitor {

    private final AnnotationVisitor[] moreDestinations;

    public MultiplexAnnotationVisitor(
        @Nullable AnnotationVisitor dest, AnnotationVisitor... moreDestinations) {
      super(Opcodes.ASM8, dest);
      this.moreDestinations = moreDestinations;
    }

    @Override
    public void visit(String name, Object value) {
      super.visit(name, value);
      for (AnnotationVisitor dest : moreDestinations) {
        dest.visit(name, value);
      }
    }

    @Override
    public void visitEnum(String name, String desc, String value) {
      super.visitEnum(name, desc, value);
      for (AnnotationVisitor dest : moreDestinations) {
        dest.visitEnum(name, desc, value);
      }
    }

    @Override
    public AnnotationVisitor visitAnnotation(String name, String desc) {
      AnnotationVisitor[] subVisitors = new AnnotationVisitor[moreDestinations.length];
      AnnotationVisitor dest = super.visitAnnotation(name, desc);
      for (int i = 0; i < subVisitors.length; ++i) {
        subVisitors[i] = moreDestinations[i].visitAnnotation(name, desc);
      }
      return new MultiplexAnnotationVisitor(dest, subVisitors);
    }

    @Override
    public AnnotationVisitor visitArray(String name) {
      AnnotationVisitor[] subVisitors = new AnnotationVisitor[moreDestinations.length];
      AnnotationVisitor dest = super.visitArray(name);
      for (int i = 0; i < subVisitors.length; ++i) {
        subVisitors[i] = moreDestinations[i].visitArray(name);
      }
      return new MultiplexAnnotationVisitor(dest, subVisitors);
    }

    @Override
    public void visitEnd() {
      super.visitEnd();
      for (AnnotationVisitor dest : moreDestinations) {
        dest.visitEnd();
      }
    }
  }
}
