// 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.HashSet;
import java.util.Iterator;
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 HashSet<String> instanceMethods = new HashSet<>();

  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.
      HashSet<String> allSeen = new HashSet<>();
      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();
    HashSet<String> visitedInterfaces = new HashSet<>();
    for (String anInterface : interfaces) {
      collectOrderedCompanionsToTriggerInterfaceClinit(
          anInterface, visitedInterfaces, companionCollector);
    }
    return companionCollector.build();
  }

  private void collectOrderedCompanionsToTriggerInterfaceClinit(
      String anInterface,
      HashSet<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());
    }
  }
}
