// 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.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import com.google.devtools.build.android.desugar.io.BitFlags;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.Nullable;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;

/**
 * Fixer of classes that extend interfaces with default methods to declare any missing methods
 * explicitly and call the corresponding companion method generated by {@link InterfaceDesugaring}.
 */
public class DefaultMethodClassFixer extends ClassVisitor {

  private final boolean useGeneratedBaseClasses;
  private final ClassReaderFactory classpath;
  private final ClassReaderFactory bootclasspath;
  private final ClassLoader targetLoader;
  private final DependencyCollector depsCollector;
  @Nullable private final CoreLibrarySupport coreLibrarySupport;
  private final LinkedHashSet<String> instanceMethods = new LinkedHashSet<>();

  private boolean isInterface;
  private String internalName;
  private ImmutableList<String> directInterfaces;
  private String superName;
  /** Interface whose companion was chosen as base class, if any. */
  @Nullable private Class<?> newSuperName;
  /** This method node caches <clinit>, and flushes out in {@code visitEnd()}; */
  private MethodNode clInitMethodNode;

  private ImmutableSortedSet<Class<?>> interfacesToStub;

  public DefaultMethodClassFixer(
      ClassVisitor dest,
      boolean useGeneratedBaseClasses,
      ClassReaderFactory classpath,
      DependencyCollector depsCollector,
      @Nullable CoreLibrarySupport coreLibrarySupport,
      ClassReaderFactory bootclasspath,
      ClassLoader targetLoader) {
    super(Opcodes.ASM7, dest);
    this.useGeneratedBaseClasses = useGeneratedBaseClasses;
    this.classpath = classpath;
    this.coreLibrarySupport = coreLibrarySupport;
    this.bootclasspath = bootclasspath;
    this.targetLoader = targetLoader;
    this.depsCollector = depsCollector;
  }

  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    checkState(this.directInterfaces == null);
    isInterface = BitFlags.isSet(access, Opcodes.ACC_INTERFACE);
    internalName = name;
    checkArgument(
        superName != null || "java/lang/Object".equals(name), // ASM promises this
        "Type without superclass: %s",
        name);
    this.directInterfaces = ImmutableList.copyOf(interfaces);
    this.superName = superName;

    if (!isInterface
        && (mayNeedInterfaceStubsForEmulatedSuperclass()
            || defaultMethodsDefined(directInterfaces))) {
      TreeMap<Class<?>, Long> allInterfaces = new TreeMap<>(SubtypeComparator.INSTANCE);
      for (String direct : interfaces) {
        if (InterfaceDesugaring.getCompanionClassName(direct).equals(name)) {
          checkState(useGeneratedBaseClasses, "%s shouldn't implement %s", name, direct);
          continue; // InterfaceDesugaring already made stubs for this interface
        }
        // Loading ensures all transitively implemented interfaces can be loaded, which is necessary
        // to produce correct default method stubs in all cases.  We could do without classloading
        // but it's convenient to rely on Class.isAssignableFrom to compute subtype relationships,
        // and we'd still have to insist that all transitively implemented interfaces can be loaded.
        // We don't load the visited class, however, in case it's generated.
        Class<?> itf = loadFromInternal(direct);
        collectInterfaces(itf, allInterfaces);
      }
      if (mayNeedInterfaceStubsForEmulatedSuperclass()) {
        // Collect interfaces inherited from emulated superclasses as well, to handle things like
        // extending AbstractList without explicitly implementing List.
        for (Class<?> clazz = loadFromInternal(superName);
            clazz != null;
            clazz = clazz.getSuperclass()) {
          for (Class<?> itf : clazz.getInterfaces()) {
            collectInterfaces(itf, allInterfaces);
          }
        }
      }

      if (useGeneratedBaseClasses && "java/lang/Object".equals(superName)) {
        // If the class directly extends Object, use the generated base class for the interface with
        // the most default methods instead.  This can help avoid stubbed default methods when
        // they're already defined in the base class.
        // This is an imperfect heuristic, not least b/c we don't know yet what methods would need
        // to be stubbed, but we decide this here up-front b/c that lets us fix up the class's
        // constructors' super calls when we see them.
        // Note inherited default methods are included in the count, so we will choose subtypes over
        // supertypes, which is desirable.
        long maxBaseMethodCount = 0;
        for (Map.Entry<Class<?>, Long> itf : allInterfaces.entrySet()) {
          if (itf.getValue() > maxBaseMethodCount) {
            maxBaseMethodCount = itf.getValue();
            newSuperName = itf.getKey();
            superName = InterfaceDesugaring.getCompanionClassName(internalName(itf.getKey()));
            signature = null; // Changing superclass invalidates signature
          }
        }
        if (newSuperName != null && !bootclasspath.isKnown(internalName(newSuperName))) {
          // Record dependency on the chosen companion class
          depsCollector.assumeCompanionClass(
              internalName, InterfaceDesugaring.getCompanionClassName(internalName(newSuperName)));
        }
      }
      interfacesToStub = ImmutableSortedSet.copyOfSorted(allInterfaces.navigableKeySet());
    } else {
      interfacesToStub = ImmutableSortedSet.of();
    }
    super.visit(version, access, name, signature, superName, interfaces);
  }

  @Override
  public void visitEnd() {
    if (!interfacesToStub.isEmpty()) {
      // Inherited methods take precedence over default methods, so visit all superclasses and
      // figure out what methods they declare before stubbing in any missing default methods.
      recordInheritedMethods();
      stubMissingDefaultAndBridgeMethods();
      // Check whether there are interfaces with default methods and <clinit>. If yes, the following
      // method call will return a list of interface fields to access in the <clinit> to trigger
      // the initialization of these interfaces.
      ImmutableList<String> companionsToTriggerInterfaceClinit =
          collectOrderedCompanionsToTriggerInterfaceClinit(directInterfaces);
      if (!companionsToTriggerInterfaceClinit.isEmpty()) {
        if (clInitMethodNode == null) {
          clInitMethodNode = new MethodNode(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
        }
        desugarClinitToTriggerInterfaceInitializers(companionsToTriggerInterfaceClinit);
      }
    }
    if (clInitMethodNode != null && super.cv != null) { // Write <clinit> to the chained visitor.
      clInitMethodNode.accept(super.cv);
    }
    super.visitEnd();
  }

  private boolean isClinitAlreadyDesugared(
      ImmutableList<String> companionsToAccessToTriggerInterfaceClinit) {
    InsnList instructions = clInitMethodNode.instructions;
    if (instructions.size() <= companionsToAccessToTriggerInterfaceClinit.size()) {
      // The <clinit> must end with RETURN, so if the instruction count is less than or equal to
      // the companion class count, this <clinit> has not been desugared.
      return false;
    }
    Iterator<AbstractInsnNode> iterator = instructions.iterator();
    for (String companion : companionsToAccessToTriggerInterfaceClinit) {
      if (!iterator.hasNext()) {
        return false;
      }
      AbstractInsnNode insn = iterator.next();
      if (!(insn instanceof MethodInsnNode)) {
        return false;
      }
      MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
      if (methodInsnNode.getOpcode() != Opcodes.INVOKESTATIC
          || !methodInsnNode.owner.equals(companion)
          || !methodInsnNode.name.equals(
              InterfaceDesugaring.COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_NAME)) {
        return false;
      }
      checkState(
          methodInsnNode.desc.equals(
              InterfaceDesugaring.COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_DESC),
          "Inconsistent method desc: %s vs %s",
          methodInsnNode.desc,
          InterfaceDesugaring.COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_DESC);
    }
    return true;
  }

  private void desugarClinitToTriggerInterfaceInitializers(
      ImmutableList<String> companionsToTriggerInterfaceClinit) {
    if (isClinitAlreadyDesugared(companionsToTriggerInterfaceClinit)) {
      return;
    }
    InsnList desugarInsts = new InsnList();
    for (String companionClass : companionsToTriggerInterfaceClinit) {
      desugarInsts.add(
          new MethodInsnNode(
              Opcodes.INVOKESTATIC,
              companionClass,
              InterfaceDesugaring.COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_NAME,
              InterfaceDesugaring.COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_DESC,
              false));
    }
    if (clInitMethodNode.instructions.size() == 0) {
      clInitMethodNode.instructions.insert(new InsnNode(Opcodes.RETURN));
    }
    clInitMethodNode.instructions.insertBefore(
        clInitMethodNode.instructions.getFirst(), desugarInsts);
  }

  @Override
  public MethodVisitor visitMethod(
      int access, String name, String desc, String signature, String[] exceptions) {
    // Keep track of instance methods implemented in this class for later.
    if (!isInterface) {
      recordIfInstanceMethod(access, name, desc);
    }
    if ("<clinit>".equals(name)) {
      checkState(clInitMethodNode == null, "This class fixer has been used. ");
      clInitMethodNode = new MethodNode(access, name, desc, signature, exceptions);
      return clInitMethodNode;
    }

    MethodVisitor dest = super.visitMethod(access, name, desc, signature, exceptions);
    if (newSuperName != null && "<init>".equals(name)) {
      // Since we changed the base class we need to fix up super constructor calls.
      return new ConstructorFixer(
          dest, InterfaceDesugaring.getCompanionClassName(internalName(newSuperName)));
    }
    return dest;
  }

  private boolean mayNeedInterfaceStubsForEmulatedSuperclass() {
    return coreLibrarySupport != null
        && !coreLibrarySupport.isEmulatedCoreClassOrInterface(internalName)
        && coreLibrarySupport.isEmulatedCoreClassOrInterface(superName);
  }

  private void stubMissingDefaultAndBridgeMethods() {
    Class<?> superclass = loadFromInternal(superName);
    boolean mayNeedStubsForSuperclass = mayNeedInterfaceStubsForEmulatedSuperclass();
    for (Class<?> interfaceToVisit : interfacesToStub) {
      // if J extends I, J is allowed to redefine I's default methods.  The comparator we used
      // above makes sure we visit J before I in that case so we can use J's definition.
      if (!mayNeedStubsForSuperclass && interfaceToVisit.isAssignableFrom(superclass)) {
        // superclass is also rewritten and already implements this interface, so we _must_ skip it.
        continue;
      }
      stubMissingDefaultAndBridgeMethods(internalName(interfaceToVisit), mayNeedStubsForSuperclass);
    }
  }

  private void stubMissingDefaultAndBridgeMethods(
      String implemented, boolean mayNeedStubsForSuperclass) {
    ClassReader bytecode;
    boolean isBootclasspath;
    if (bootclasspath.isKnown(implemented)) {
      if (coreLibrarySupport != null
          && (coreLibrarySupport.isRenamedCoreLibrary(implemented)
              || coreLibrarySupport.isEmulatedCoreClassOrInterface(implemented))) {
        bytecode = checkNotNull(bootclasspath.readIfKnown(implemented), implemented);
        isBootclasspath = true;
      } else {
        // Default methods from interfaces on the bootclasspath that we're not renaming or emulating
        // are assumed available at runtime, so just ignore them.
        return;
      }
    } else {
      bytecode =
          checkNotNull(
              classpath.readIfKnown(implemented),
              "Couldn't find interface %s implemented by %s",
              implemented,
              internalName);
      isBootclasspath = false;
    }
    bytecode.accept(
        new DefaultMethodStubber(isBootclasspath, mayNeedStubsForSuperclass),
        ClassReader.SKIP_DEBUG);
  }

  private Class<?> loadFromInternal(String internalName) {
    try {
      return targetLoader.loadClass(internalName.replace('/', '.'));
    } catch (ClassNotFoundException | NoClassDefFoundError e) {
      throw new IllegalStateException(
          "Couldn't load " + internalName + " to stub default methods for " + this.internalName, e);
    }
  }

  /** Returns the internal name used for this class in bytecode. */
  static String internalName(Class<?> clazz) {
    return clazz.getName().replace('.', '/');
  }

  private void collectInterfaces(Class<?> itf, Map<Class<?>, Long> dest) {
    checkArgument(itf.isInterface());
    if (dest.containsKey(itf)) {
      return;
    }
    if (useGeneratedBaseClasses && hasCompanionClass(itf)) {
      // Count inherited and declared default methods
      long defaultMethodCount = Arrays.stream(itf.getMethods()).filter(Method::isDefault).count();
      dest.put(itf, defaultMethodCount);
    } else {
      // Use -1 if there's no base class we could use.  This makes sure we don't try to use a
      // companion class as base class that doesn't exist.
      dest.put(itf, -1L);
    }
    for (Class<?> implemented : itf.getInterfaces()) {
      collectInterfaces(implemented, dest);
    }
  }

  private boolean hasCompanionClass(Class<?> itf) {
    checkArgument(itf.isInterface());
    if (Arrays.stream(itf.getDeclaredMethods()).noneMatch(m -> m.isDefault() && !m.isBridge())) {
      return false;
    }
    String implemented = internalName(itf);
    if (implemented.startsWith("java/") || implemented.startsWith("__desugar__/java/")) {
      return coreLibrarySupport != null
          && (coreLibrarySupport.isRenamedCoreLibrary(implemented)
              || coreLibrarySupport.isEmulatedCoreClassOrInterface(implemented));
    } else {
      return !bootclasspath.isKnown(implemented);
    }
  }

  private void recordInheritedMethods() {
    InstanceMethodRecorder recorder =
        new InstanceMethodRecorder(mayNeedInterfaceStubsForEmulatedSuperclass());
    if (newSuperName != null) {
      checkState(useGeneratedBaseClasses);
      // If we're using a generated base class, walk the implemented interfaces and record default
      // methods we won't need to stub.  That reflects the methods that will be in the generated
      // base class (and its superclasses, if applicable), without looking at the generated class.
      // We go through sub-interfaces before their super-interfaces (same order as when we stub)
      // to encounter overriding before overridden default methods.  We don't record methods from
      // interfaces the chosen base class doesn't implement, even if those methods also appear in
      // interfaces we would normally record later.  That ensures we generate a stub when a default
      // method is available in the base class but needs to be overridden due to an overriding
      // default method in a sub-interface not implemented by the base class.
      LinkedHashSet<String> allSeen = new LinkedHashSet<>();
      for (Class<?> itf : interfacesToStub) {
        boolean willBeInBaseClass = itf.isAssignableFrom(newSuperName);
        for (Method m : itf.getDeclaredMethods()) {
          if (!m.isDefault()) {
            continue;
          }
          String desc = Type.getMethodDescriptor(m);
          if (coreLibrarySupport != null) {
            // Foreshadow any type renaming to avoid issues with double-desugaring (b/111447199)
            desc = coreLibrarySupport.getRemapper().mapMethodDesc(desc);
          }
          String methodKey = m.getName() + ":" + desc;
          if (allSeen.add(methodKey) && willBeInBaseClass) {
            // Only record never-seen methods, and only for super-types of newSuperName (see longer
            // explanation above)
            instanceMethods.add(methodKey);
          }
        }
      }

      // Fall through to the logic below to record j.l.Object's methods.
      checkState(superName.equals("java/lang/Object"));
    }

    // Walk superclasses
    String internalName = superName;
    while (internalName != null) {
      ClassReader bytecode = bootclasspath.readIfKnown(internalName);
      if (bytecode == null) {
        bytecode =
            checkNotNull(
                classpath.readIfKnown(internalName), "Superclass not found: %s", internalName);
      }
      bytecode.accept(recorder, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG);
      internalName = bytecode.getSuperName();
    }
  }

  /**
   * Starting from the given interfaces, this method scans the interface hierarchy, finds the
   * interfaces that have default methods and <clinit>, and returns the companion class names of
   * these interfaces.
   *
   * <p>Note that the returned companion classes are ordered in the order of the interface
   * initialization, which is consistent with the JVM behavior. For example, "class A implements I1,
   * I2", the returned list would be [I1$$CC, I2$$CC], not [I2$$CC, I1$$CC].
   */
  private ImmutableList<String> collectOrderedCompanionsToTriggerInterfaceClinit(
      ImmutableList<String> interfaces) {
    ImmutableList.Builder<String> companionCollector = ImmutableList.builder();
    LinkedHashSet<String> visitedInterfaces = new LinkedHashSet<>();
    for (String anInterface : interfaces) {
      collectOrderedCompanionsToTriggerInterfaceClinit(
          anInterface, visitedInterfaces, companionCollector);
    }
    return companionCollector.build();
  }

  private void collectOrderedCompanionsToTriggerInterfaceClinit(
      String anInterface,
      LinkedHashSet<String> visitedInterfaces,
      ImmutableList.Builder<String> companionCollector) {
    if (!visitedInterfaces.add(anInterface)) {
      return;
    }
    ClassReader bytecode = classpath.readIfKnown(anInterface);
    if (bytecode == null || bootclasspath.isKnown(anInterface)) {
      return;
    }
    String[] parentInterfaces = bytecode.getInterfaces();
    if (parentInterfaces != null && parentInterfaces.length > 0) {
      for (String parentInterface : parentInterfaces) {
        collectOrderedCompanionsToTriggerInterfaceClinit(
            parentInterface, visitedInterfaces, companionCollector);
      }
    }
    InterfaceInitializationNecessityDetector necessityDetector =
        new InterfaceInitializationNecessityDetector(bytecode.getClassName());
    bytecode.accept(necessityDetector, ClassReader.SKIP_DEBUG);
    if (necessityDetector.needsToInitialize()) {
      // If we need to initialize this interface, we initialize its companion class, and its
      // companion class will initialize the interface then. This desigin decision is made to avoid
      // access issue, e.g., package-private interfaces.
      companionCollector.add(InterfaceDesugaring.getCompanionClassName(anInterface));
    }
  }

  /**
   * Recursively searches the given interfaces for default methods not implemented by this class
   * directly. If this method returns true we need to think about stubbing missing default methods.
   */
  private boolean defaultMethodsDefined(ImmutableList<String> interfaces) {
    for (String implemented : interfaces) {
      if (useGeneratedBaseClasses
          && InterfaceDesugaring.getCompanionClassName(implemented).equals(internalName)) {
        continue; // InterfaceDesugaring already made stubs for this interface
      }
      ClassReader bytecode;
      if (bootclasspath.isKnown(implemented)) {
        if (coreLibrarySupport != null
            && coreLibrarySupport.isEmulatedCoreClassOrInterface(implemented)) {
          return true; // need to stub in emulated interface methods such as Collection.stream()
        } else if (coreLibrarySupport != null
            && coreLibrarySupport.isRenamedCoreLibrary(implemented)) {
          // Check default methods of renamed interfaces
          bytecode = checkNotNull(bootclasspath.readIfKnown(implemented), implemented);
        } else {
          continue;
        }
      } else {
        bytecode = classpath.readIfKnown(implemented);
        if (bytecode == null) {
          // Interface isn't on the classpath, which indicates incomplete classpaths. Record missing
          // dependency so we can check it later.  If we don't check then we may get runtime
          // failures or wrong behavior from default methods that should've been stubbed in.
          // TODO(kmb): Print a warning so people can start fixing their deps?
          depsCollector.missingImplementedInterface(internalName, implemented);
          continue;
        }
      }

      // Class in classpath and bootclasspath is a bad idea but in any event, assume the
      // bootclasspath will take precedence like in a classloader.
      // We can skip code attributes as we just need to find default methods to stub.
      DefaultMethodFinder finder = new DefaultMethodFinder();
      bytecode.accept(finder, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG);
      if (finder.foundDefaultMethods()) {
        return true;
      }
    }
    return false;
  }

  /** Returns {@code true} for non-bridge default methods not in {@link #instanceMethods}. */
  private boolean shouldStubAsDefaultMethod(int access, String name, String desc) {
    // Ignore private methods, which technically aren't default methods and can only be called from
    // other methods defined in the interface.  This also ignores lambda body methods, which is fine
    // as we don't want or need to stub those.  Also ignore bridge methods as javac adds them to
    // concrete classes as needed anyway and we handle them separately for generated lambda classes.
    // Note that an exception is that, if a bridge method is for a default interface method, javac
    // will NOT generate the bridge method in the implementing class. So we need extra logic to
    // handle these bridge methods.
    return isNonBridgeDefaultMethod(access) && !recordedInstanceMethod(name, desc);
  }

  private static boolean isNonBridgeDefaultMethod(int access) {
    return BitFlags.noneSet(
        access,
        Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_PRIVATE);
  }

  /**
   * Check whether an interface method is a bridge method for a default interface method. This type
   * of bridge methods is special, as they are not put in the implementing classes by javac.
   */
  private boolean shouldStubAsBridgeDefaultMethod(int access, String name, String desc) {
    return BitFlags.isSet(access, Opcodes.ACC_BRIDGE | Opcodes.ACC_PUBLIC)
        && BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC)
        && !recordedInstanceMethod(name, desc);
  }

  private void recordIfInstanceMethod(int access, String name, String desc) {
    if (BitFlags.noneSet(access, Opcodes.ACC_STATIC)) {
      // Record all declared instance methods, including abstract, bridge, and native methods, as
      // they all take precedence over default methods.
      if (coreLibrarySupport != null) {
        // Foreshadow any type renaming to avoid issues with double-desugaring (b/111447199)
        desc = coreLibrarySupport.getRemapper().mapMethodDesc(desc);
      }
      instanceMethods.add(name + ":" + desc);
    }
  }

  private boolean recordedInstanceMethod(String name, String desc) {
    if (coreLibrarySupport != null) {
      // Foreshadow any type renaming to avoid issues with double-desugaring (b/111447199)
      desc = coreLibrarySupport.getRemapper().mapMethodDesc(desc);
    }
    return instanceMethods.contains(name + ":" + desc);
  }

  /**
   * Visitor for interfaces that produces delegates in the class visited by the outer {@link
   * DefaultMethodClassFixer} for every default method encountered.
   */
  private class DefaultMethodStubber extends ClassVisitor {

    private final boolean isBootclasspathInterface;
    private final boolean mayNeedStubsForSuperclass;

    private String stubbedInterfaceName;

    public DefaultMethodStubber(
        boolean isBootclasspathInterface, boolean mayNeedStubsForSuperclass) {
      super(Opcodes.ASM7);
      this.isBootclasspathInterface = isBootclasspathInterface;
      this.mayNeedStubsForSuperclass = mayNeedStubsForSuperclass;
    }

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

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (shouldStubAsDefaultMethod(access, name, desc)) {
        // Remember we stubbed this method in case it's also defined by subsequently visited
        // interfaces.  javac would force the method to be defined explicitly if there any two
        // definitions conflict, but see stubMissingDefaultMethods() for how we deal with default
        // methods redefined in interfaces extending another.
        recordIfInstanceMethod(access, name, desc);
        String owner = InterfaceDesugaring.getCompanionClassName(stubbedInterfaceName);
        if (!isBootclasspathInterface) {
          // Don't record these dependencies, as we can't check them
          depsCollector.assumeCompanionClass(internalName, owner);
        }

        // Add this method to the class we're desugaring and stub in a body to call the default
        // implementation in the interface's companion class. ijar omits these methods when setting
        // ACC_SYNTHETIC modifier, so don't.
        // Signatures can be wrong, e.g., when type variables are introduced, instantiated, or
        // refined in the class we're processing, so drop them.
        MethodVisitor stubMethod =
            DefaultMethodClassFixer.this.visitMethod(access, name, desc, (String) null, exceptions);

        String receiverName = stubbedInterfaceName;
        String calledMethodName = name + InterfaceDesugaring.DEFAULT_COMPANION_METHOD_SUFFIX;
        if (mayNeedStubsForSuperclass) {
          // Reflect what CoreLibraryInvocationRewriter would do if it encountered a super-call to a
          // moved implementation of an emulated method.  Equivalent to emitting the invokespecial
          // super call here and relying on CoreLibraryInvocationRewriter for the rest
          Class<?> emulatedImplementation =
              coreLibrarySupport.getCoreInterfaceRewritingTarget(
                  Opcodes.INVOKESPECIAL, superName, name, desc, /*itf=*/ false);
          if (emulatedImplementation != null && !emulatedImplementation.isInterface()) {
            receiverName = internalName(emulatedImplementation);
            owner = checkNotNull(coreLibrarySupport.getMoveTarget(receiverName, name));
            calledMethodName = name;
          }
        }

        int slot = 0;
        stubMethod.visitVarInsn(Opcodes.ALOAD, slot++); // load the receiver
        Type neededType = Type.getMethodType(desc);
        for (Type arg : neededType.getArgumentTypes()) {
          stubMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
          slot += arg.getSize();
        }
        stubMethod.visitMethodInsn(
            Opcodes.INVOKESTATIC,
            owner,
            calledMethodName,
            InterfaceDesugaring.companionDefaultMethodDescriptor(receiverName, desc),
            /*isInterface=*/ false);
        stubMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));

        stubMethod.visitMaxs(0, 0); // rely on class writer to compute these
        stubMethod.visitEnd();
        return null; // don't visit the visited interface's default method
      } else if (shouldStubAsBridgeDefaultMethod(access, name, desc)) {
        recordIfInstanceMethod(access, name, desc);
        MethodVisitor stubMethod =
            DefaultMethodClassFixer.this.visitMethod(access, name, desc, (String) null, exceptions);
        // If we're visiting a bootclasspath interface then we most likely don't have the code.
        // That means we can't just copy the method bodies as we're trying to do below.
        if (isBootclasspathInterface) {
          // Synthesize a "bridge" method that calls the true implementation
          Method bridged = findBridgedMethod(name, desc);
          checkState(
              bridged != null,
              "TODO: Can't stub core interface bridge method %s.%s %s in %s",
              stubbedInterfaceName,
              name,
              desc,
              internalName);

          int slot = 0;
          stubMethod.visitVarInsn(Opcodes.ALOAD, slot++); // load the receiver
          Type neededType = Type.getType(bridged);
          Type[] neededArgTypes = neededType.getArgumentTypes();
          Type[] parameterTypes = Type.getArgumentTypes(desc);
          for (int i = 0; i < neededArgTypes.length; ++i) {
            Type arg = neededArgTypes[i];
            stubMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
            if (!arg.equals(parameterTypes[i])) {
              checkState(
                  arg.getSort() == Type.ARRAY || arg.getSort() == Type.OBJECT,
                  "Can't cast parameter %s from in bridge for %s.%s%s to %s",
                  i,
                  stubbedInterfaceName,
                  name,
                  desc,
                  arg.getClassName());
              stubMethod.visitTypeInsn(Opcodes.CHECKCAST, arg.getInternalName());
            }
            slot += arg.getSize();
          }
          // Just call the bridged method directly on the visited class using invokevirtual
          stubMethod.visitMethodInsn(
              Opcodes.INVOKEVIRTUAL,
              internalName,
              name,
              neededType.getDescriptor(),
              /*isInterface=*/ false);
          stubMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));

          stubMethod.visitMaxs(0, 0); // rely on class writer to compute these
          stubMethod.visitEnd();
          return null; // don't visit the visited interface's bridge method
        } else {
          // For bridges we just copy their bodies instead of going through the companion class.
          // Meanwhile, we also need to desugar the copied method bodies, so that any calls to
          // interface methods are correctly handled.
          return new InterfaceDesugaring.InterfaceInvocationRewriter(
              stubMethod,
              stubbedInterfaceName,
              bootclasspath,
              targetLoader,
              depsCollector,
              internalName);
        }
      } else {
        return null; // not a default or bridge method or the class already defines this method.
      }
    }

    /**
     * Returns a non-bridge interface method with given name that a method with the given descriptor
     * can bridge to, if any such method can be found.
     */
    @Nullable
    private Method findBridgedMethod(String name, String desc) {
      Type[] paramTypes = Type.getArgumentTypes(desc);
      Type returnType = Type.getReturnType(desc);
      Class<?> itf = loadFromInternal(stubbedInterfaceName);
      checkArgument(itf.isInterface(), "Should be an interface: %s", stubbedInterfaceName);

      // 1. Find the bridge method we're trying to implement
      Method bridge = null;
      for (Method m : itf.getDeclaredMethods()) {
        if (m.isBridge()
            && m.getName().equals(name)
            && Arrays.equals(paramTypes, Type.getArgumentTypes(m))
            && returnType.equals(Type.getReturnType(m))) {
          bridge = m;
          break;
        }
      }
      checkState(bridge != null, "Couldn't find bridge %s.%s %s", stubbedInterfaceName, name, desc);
      checkState(bridge.getParameterCount() == paramTypes.length);

      // 2. Try to find the method being bridged
      Method result = null;
      next_method:
      for (Method m : itf.getDeclaredMethods()) {
        if (m.isBridge() || Modifier.isStatic(m.getModifiers())) {
          continue;
        }
        if (!m.getName().equals(name)) {
          continue;
        }

        if (Arrays.equals(paramTypes, Type.getArgumentTypes(m))) {
          // All argument types match, only return type will differ: this is the method we want
          return m;
        } else if (m.getParameterCount() == bridge.getParameterCount()) {
          for (int i = 0; i < m.getParameterCount(); ++i) {
            if (!bridge.getParameterTypes()[i].isAssignableFrom(m.getParameterTypes()[i])) {
              continue next_method;
            }
          }

          // All of m's parameter types are subtypes of the bridge's parameter types (or primitives)
          if (result == null) {
            result = m;
          } else {
            // Bail if we find multiple methods that could be bridged
            return null;
          }
        }
      }
      return result;
    }
  }

  /**
   * Visitor for interfaces that recursively searches interfaces for default method declarations.
   */
  private class DefaultMethodFinder extends ClassVisitor {
    @SuppressWarnings("hiding")
    private ImmutableList<String> interfaces;

    private boolean found;

    public DefaultMethodFinder() {
      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);
    }

    public boolean foundDefaultMethods() {
      return found;
    }

    @Override
    public void visitEnd() {
      if (!found) {
        found = defaultMethodsDefined(this.interfaces);
      }
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (!found && shouldStubAsDefaultMethod(access, name, desc)) {
        // Found a default method we're not ignoring (instanceMethods at this point contains methods
        // the top-level visited class implements itself).
        found = true;
      }
      return null; // we don't care about the actual code in these methods
    }
  }

  private class InstanceMethodRecorder extends ClassVisitor {

    private final boolean ignoreEmulatedMethods;

    private String className;

    public InstanceMethodRecorder(boolean ignoreEmulatedMethods) {
      super(Opcodes.ASM7);
      this.ignoreEmulatedMethods = ignoreEmulatedMethods;
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      checkArgument(!BitFlags.isInterface(access));
      className = name; // updated every time we start visiting another superclass
      super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (ignoreEmulatedMethods
          && !BitFlags.isStatic(access) // short-circuit
          && coreLibrarySupport.getCoreInterfaceRewritingTarget(
                  Opcodes.INVOKEVIRTUAL, className, name, desc, /*itf=*/ false)
              != null) {
        // *don't* record emulated core library method implementations in immediate subclasses of
        // emulated core library clasess so that they can be stubbed (since the inherited
        // implementation may be missing at runtime).
        return null;
      }
      recordIfInstanceMethod(access, name, desc);
      return null;
    }
  }

  /**
   * Detector to determine whether an interface needs to be initialized when it is loaded.
   *
   * <p>If the interface has a default method, and its <clinit> initializes any of its fields, then
   * this interface needs to be initialized.
   */
  private static class InterfaceInitializationNecessityDetector extends ClassVisitor {

    private final String internalName;
    private boolean hasFieldInitializedInClinit;
    private boolean hasDefaultMethods;

    public InterfaceInitializationNecessityDetector(String internalName) {
      super(Opcodes.ASM7);
      this.internalName = internalName;
    }

    public boolean needsToInitialize() {
      return hasDefaultMethods && hasFieldInitializedInClinit;
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      super.visit(version, access, name, signature, superName, interfaces);
      checkState(
          internalName.equals(name),
          "Inconsistent internal names: expected=%s, real=%s",
          internalName,
          name);
      checkArgument(
          BitFlags.isSet(access, Opcodes.ACC_INTERFACE),
          "This class visitor is only used for interfaces.");
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (!hasDefaultMethods) {
        hasDefaultMethods = isNonBridgeDefaultMethod(access);
      }
      if ("<clinit>".equals(name)) {
        return new MethodVisitor(Opcodes.ASM7) {
          @Override
          public void visitFieldInsn(int opcode, String owner, String name, String desc) {
            if (opcode == Opcodes.PUTSTATIC && internalName.equals(owner)) {
              hasFieldInitializedInClinit = true;
            }
          }
        };
      }
      return null; // Do not care about the code.
    }
  }

  /** Method visitor that changes super constructor calls to a new base class. */
  private static class ConstructorFixer extends MethodVisitor {

    private final String newSuperName;

    /**
     * This helps us find the very first constructor invocation we visit. We're looking for a
     * sequence ALOAD_0 ; INVOKESPECIAL java.lang.Object() while avoiding "new Object()" which
     * results in a NEW followed by the same INVOKESPECIAL for Object's constructor that we're
     * looking for. Note that anonymous inner class constructors store captured variables into
     * fields before calling super(), so we have to tolerate some unrelated logic, but since
     * Object's constructor is parameterless we thankfully don't have to worry about handwritten
     * code for constructor arguments.
     */
    private boolean looking = true;

    ConstructorFixer(MethodVisitor dest, String newSuperName) {
      super(Opcodes.ASM7, dest);
      this.newSuperName = newSuperName;
    }

    @Override
    public void visitMethodInsn(
        int opcode, String owner, String name, String descriptor, boolean isInterface) {
      if (looking
          && opcode == Opcodes.INVOKESPECIAL
          && "<init>".equals(name)
          && "java/lang/Object".equals(owner)) {
        // Call new base class's constructor instead of j.l.Object().  Note owner can be the
        // visited class for this() constructor calls, and we don't need to touch those here.
        owner = newSuperName;
      }
      // Since Object's constructor has no arguments it must be the very first INVOKE (because there
      // can't be any preceding logic to set up constructor arguments), so stop looking regardless
      // of whether we rewrote that INVOKE or not (but ignore inserted JaCoCo invocations).
      if (looking && (opcode != Opcodes.INVOKESTATIC || !"$jacocoInit".equals(name))) {
        looking = false;
      }
      super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
    }

    @Override
    public void visitTypeInsn(int opcode, String type) {
      if (opcode == Opcodes.NEW && "java/lang/Object".equals(type)) {
        // NEW java/lang/Object is followed by the very INVOKESPECIAL we're looking for, but we
        // don't want to rewrite it.  Since there can't be a super() call after this, just stop.
        looking = false;
      }
      super.visitTypeInsn(opcode, type);
    }
  }

  /** Comparator for classes and interfaces that compares by whether subtyping relationship. */
  enum SubtypeComparator implements Comparator<Class<?>> {
    /** Orders subtypes before supertypes and breaks ties lexicographically. */
    INSTANCE;

    @Override
    public int compare(Class<?> o1, Class<?> o2) {
      if (o1 == o2) {
        return 0;
      }
      // order subtypes before supertypes
      if (o1.isAssignableFrom(o2)) { // o1 is supertype of o2
        return 1; // we want o1 to come after o2
      }
      if (o2.isAssignableFrom(o1)) { // o2 is supertype of o1
        return -1; // we want o2 to come after o1
      }
      // o1 and o2 aren't comparable so arbitrarily impose lexicographical ordering
      return o1.getName().compareTo(o2.getName());
    }
  }
}
