// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.graph;

import static com.android.tools.r8.utils.TraversalContinuation.doBreak;
import static com.android.tools.r8.utils.TraversalContinuation.doContinue;

import com.android.tools.r8.experimental.startup.StartupOrder;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.ir.analysis.type.InterfaceCollection;
import com.android.tools.r8.ir.analysis.type.InterfaceCollection.Builder;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.shaking.MissingClasses;
import com.android.tools.r8.synthesis.CommittedItems;
import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.TriConsumer;
import com.android.tools.r8.utils.TriFunction;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Function;

/* Specific subclass of AppInfo designed to support desugaring in D8. Desugaring requires a
 * minimal amount of knowledge in the overall program, provided through classpath. Basic
 * features are present, such as static and super look-ups, or isSubtype.
 */
public class AppInfoWithClassHierarchy extends AppInfo {

  private static final CreateDesugaringViewOnAppInfo WITNESS = new CreateDesugaringViewOnAppInfo();

  static class CreateDesugaringViewOnAppInfo {
    private CreateDesugaringViewOnAppInfo() {}
  }

  public static AppInfoWithClassHierarchy createInitialAppInfoWithClassHierarchy(
      DexApplication application,
      ClassToFeatureSplitMap classToFeatureSplitMap,
      MainDexInfo mainDexInfo,
      GlobalSyntheticsStrategy globalSyntheticsStrategy,
      StartupOrder startupOrder) {
    return new AppInfoWithClassHierarchy(
        SyntheticItems.createInitialSyntheticItems(application, globalSyntheticsStrategy),
        classToFeatureSplitMap,
        mainDexInfo,
        MissingClasses.empty(),
        startupOrder);
  }

  private final ClassToFeatureSplitMap classToFeatureSplitMap;
  private final StartupOrder startupOrder;

  /** Set of types that are mentioned in the program, but for which no definition exists. */
  // TODO(b/175659048): Consider hoisting to AppInfo to allow using MissingClasses in D8 desugar.
  private final MissingClasses missingClasses;

  // For AppInfoWithLiveness subclass.
  protected AppInfoWithClassHierarchy(
      CommittedItems committedItems,
      ClassToFeatureSplitMap classToFeatureSplitMap,
      MainDexInfo mainDexInfo,
      MissingClasses missingClasses,
      StartupOrder startupOrder) {
    super(committedItems, mainDexInfo);
    this.classToFeatureSplitMap = classToFeatureSplitMap;
    this.missingClasses = missingClasses;
    this.startupOrder = startupOrder;
  }

  // For desugaring.
  private AppInfoWithClassHierarchy(CreateDesugaringViewOnAppInfo witness, AppInfo appInfo) {
    super(witness, appInfo);
    this.classToFeatureSplitMap = ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap();
    // TODO(b/175659048): Migrate the reporting of missing classes in D8 desugar to MissingClasses,
    //  and use the missing classes from AppInfo instead of MissingClasses.empty().
    this.missingClasses = MissingClasses.empty();
    this.startupOrder = StartupOrder.empty();
  }

  public static AppInfoWithClassHierarchy createForDesugaring(AppInfo appInfo) {
    assert !appInfo.hasClassHierarchy();
    return new AppInfoWithClassHierarchy(WITNESS, appInfo);
  }

  public final AppInfoWithClassHierarchy rebuildWithClassHierarchy(CommittedItems commit) {
    return new AppInfoWithClassHierarchy(
        commit,
        getClassToFeatureSplitMap(),
        getMainDexInfo(),
        getMissingClasses(),
        getStartupOrder());
  }

  public AppInfoWithClassHierarchy rebuildWithClassHierarchy(
      Function<DexApplication, DexApplication> fn) {
    assert checkIfObsolete();
    return new AppInfoWithClassHierarchy(
        getSyntheticItems().commit(fn.apply(app())),
        getClassToFeatureSplitMap(),
        getMainDexInfo(),
        getMissingClasses(),
        getStartupOrder());
  }

  @Override
  public AppInfoWithClassHierarchy rebuildWithMainDexInfo(MainDexInfo mainDexInfo) {
    assert getClass() == AppInfoWithClassHierarchy.class;
    assert checkIfObsolete();
    return new AppInfoWithClassHierarchy(
        getSyntheticItems().commit(app()),
        getClassToFeatureSplitMap(),
        mainDexInfo,
        getMissingClasses(),
        getStartupOrder());
  }

  @Override
  public AppInfoWithClassHierarchy prunedCopyFrom(
      PrunedItems prunedItems, ExecutorService executorService) throws ExecutionException {
    assert getClass() == AppInfoWithClassHierarchy.class;
    assert checkIfObsolete();
    assert prunedItems.getPrunedApp() == app();
    if (prunedItems.isEmpty()) {
      return this;
    }
    return new AppInfoWithClassHierarchy(
        getSyntheticItems().commitPrunedItems(prunedItems),
        getClassToFeatureSplitMap().withoutPrunedItems(prunedItems),
        getMainDexInfo().withoutPrunedItems(prunedItems),
        getMissingClasses(),
        getStartupOrder().withoutPrunedItems(prunedItems));
  }

  public ClassToFeatureSplitMap getClassToFeatureSplitMap() {
    return classToFeatureSplitMap;
  }

  public MissingClasses getMissingClasses() {
    return missingClasses;
  }

  public StartupOrder getStartupOrder() {
    return startupOrder;
  }

  @Override
  public boolean hasClassHierarchy() {
    assert checkIfObsolete();
    return true;
  }

  @Override
  public AppInfoWithClassHierarchy withClassHierarchy() {
    assert checkIfObsolete();
    return this;
  }

  /** Primitive traversal over all (non-interface) superclasses of a given type. */
  public <B> TraversalContinuation<B, ?> traverseSuperClasses(
      DexClass clazz, TriFunction<DexType, DexClass, DexClass, TraversalContinuation<B, ?>> fn) {
    DexClass currentClass = clazz;
    while (currentClass != null && currentClass.getSuperType() != null) {
      DexClass superclass = definitionFor(currentClass.getSuperType());
      TraversalContinuation<B, ?> stepResult =
          fn.apply(currentClass.getSuperType(), superclass, currentClass);
      if (stepResult.shouldBreak()) {
        return stepResult;
      }
      currentClass = superclass;
    }
    return doContinue();
  }

  /**
   * Primitive traversal over all supertypes of a given type.
   *
   * <p>No order is guaranteed for the traversal, but a given type will be visited at most once. The
   * given type is *not* visited. The function indicates if traversal should continue or break. The
   * result of the traversal is BREAK iff the function returned BREAK.
   */
  public TraversalContinuation<?, ?> traverseSuperTypes(
      final DexClass clazz,
      TriFunction<DexType, DexClass, Boolean, TraversalContinuation<?, ?>> fn) {
    // We do an initial zero-allocation pass over the class super chain as it does not require a
    // worklist/seen-set. Only if the traversal is not aborted and there actually are interfaces,
    // do we continue traversal over the interface types. This is assuming that the second pass
    // over the super chain is less expensive than the eager allocation of the worklist.
    int interfaceCount = 0;
    {
      DexClass currentClass = clazz;
      while (currentClass != null) {
        interfaceCount += currentClass.interfaces.values.length;
        if (currentClass.superType == null) {
          break;
        }
        TraversalContinuation<?, ?> stepResult =
            fn.apply(currentClass.superType, currentClass, false);
        if (stepResult.shouldBreak()) {
          return stepResult;
        }
        currentClass = definitionFor(currentClass.superType);
      }
    }
    if (interfaceCount == 0) {
      return doContinue();
    }
    // Interfaces exist, create a worklist and seen set to ensure single visits.
    Set<DexType> seen = Sets.newIdentityHashSet();
    Deque<DexType> worklist = new ArrayDeque<>();
    // Populate the worklist with the direct interfaces of the super chain.
    {
      DexClass currentClass = clazz;
      while (currentClass != null) {
        for (DexType iface : currentClass.interfaces.values) {
          if (seen.add(iface)) {
            TraversalContinuation<?, ?> stepResult = fn.apply(iface, currentClass, true);
            if (stepResult.shouldBreak()) {
              return stepResult;
            }
            worklist.addLast(iface);
          }
        }
        if (currentClass.superType == null) {
          break;
        }
        currentClass = definitionFor(currentClass.superType);
      }
    }
    // Iterate all interfaces.
    while (!worklist.isEmpty()) {
      DexType type = worklist.removeFirst();
      DexClass definition = definitionFor(type);
      if (definition != null) {
        for (DexType iface : definition.interfaces.values) {
          if (seen.add(iface)) {
            TraversalContinuation<?, ?> stepResult = fn.apply(iface, definition, true);
            if (stepResult.shouldBreak()) {
              return stepResult;
            }
            worklist.addLast(iface);
          }
        }
      }
    }
    return doContinue();
  }

  /**
   * Iterate each super type of class.
   *
   * <p>Same as traverseSuperTypes, but unconditionally visits all.
   */
  public void forEachSuperType(DexClass clazz, TriConsumer<DexType, DexClass, Boolean> fn) {
    traverseSuperTypes(
        clazz,
        (superType, subclass, isInterface) -> {
          fn.accept(superType, subclass, isInterface);
          return doContinue();
        });
  }

  public boolean isSubtype(DexType subtype, DexType supertype) {
    assert subtype != null;
    assert supertype != null;
    assert subtype.isClassType();
    assert supertype.isClassType();
    return subtype == supertype || isStrictSubtypeOf(subtype, supertype);
  }

  public boolean isStrictSubtypeOf(DexType subtype, DexType supertype) {
    assert subtype != null;
    assert supertype != null;
    assert subtype.isClassType();
    assert supertype.isClassType();
    if (subtype == supertype) {
      return false;
    }
    // Treat object special: it is always the supertype even for broken hierarchies.
    if (subtype == dexItemFactory().objectType) {
      return false;
    }
    if (supertype == dexItemFactory().objectType) {
      return true;
    }
    if (!subtype.isClassType() || !supertype.isClassType()) {
      return false;
    }
    DexClass clazz = definitionFor(subtype);
    if (clazz == null) {
      return false;
    }
    // TODO(b/123506120): Report missing types when the predicate is inconclusive.
    return traverseSuperTypes(
            clazz,
            (superType, subclass, isInterface) -> superType == supertype ? doBreak() : doContinue())
        .shouldBreak();
  }

  public boolean isSubtype(DexClass subclass, DexClass superclass) {
    return superclass.isInterface()
        ? isSubtype(subclass.getType(), superclass.getType())
        : isSubtypeOfClass(subclass, superclass);
  }

  public boolean isSubtypeOfClass(DexClass subclass, DexClass superclass) {
    assert subclass != null;
    assert superclass != null;
    assert !superclass.isInterface();
    if (subclass.isInterface()) {
      return superclass.getType() == dexItemFactory().objectType;
    }
    return subclass == superclass || isStrictSubtypeOfClass(subclass, superclass);
  }

  public boolean isStrictSubtypeOfClass(DexClass subclass, DexClass superclass) {
    assert subclass != null;
    assert superclass != null;
    assert !subclass.isInterface();
    assert !superclass.isInterface();
    if (subclass == superclass) {
      return false;
    }
    // Treat object special: it is always the superclass even for broken hierarchies.
    if (subclass.getType() == dexItemFactory().objectType) {
      return false;
    }
    if (superclass.getType() == dexItemFactory().objectType) {
      return true;
    }
    TraversalContinuation<Boolean, ?> result =
        traverseSuperClasses(
            subclass,
            (currentType, currentClass, immediateSubclass) -> {
              if (currentType == superclass.getType()) {
                return doBreak(true);
              }
              if (currentClass == null) {
                return doBreak(false);
              }
              if (superclass.isProgramClass() && !currentClass.isProgramClass()) {
                return doBreak(false);
              }
              return doContinue();
            });
    return result.isBreak() && result.asBreak().getValue();
  }

  public boolean inSameHierarchy(DexType type, DexType other) {
    assert type.isClassType();
    assert other.isClassType();
    return isSubtype(type, other) || isSubtype(other, type);
  }

  public boolean inDifferentHierarchy(DexType type1, DexType type2) {
    return !inSameHierarchy(type1, type2);
  }

  public boolean isMissingOrHasMissingSuperType(DexType type) {
    DexClass clazz = definitionFor(type);
    return clazz == null || clazz.hasMissingSuperType(this);
  }

  /** Collect all interfaces that this type directly or indirectly implements. */
  public InterfaceCollection implementedInterfaces(DexType type) {
    assert type.isClassType();
    DexClass clazz = definitionFor(type);
    if (clazz == null) {
      return InterfaceCollection.empty();
    }

    // Fast path for a type below object with no interfaces.
    if (clazz.superType == dexItemFactory().objectType && clazz.interfaces.isEmpty()) {
      return clazz.isInterface()
          ? InterfaceCollection.singleton(type)
          : InterfaceCollection.empty();
    }

    // Slow path traverses the full super type hierarchy.
    Builder builder = InterfaceCollection.builder();
    if (clazz.isInterface()) {
      builder.addInterface(type, true);
    }
    // First find all interface leafs from the class super-type chain.
    Set<DexType> seenAndKnown = Sets.newIdentityHashSet();
    Deque<Pair<DexClass, Boolean>> worklist = new ArrayDeque<>();
    {
      DexClass implementor = clazz;
      while (implementor != null) {
        for (DexType iface : implementor.interfaces) {
          if (seenAndKnown.contains(iface)) {
            continue;
          }
          boolean isKnown =
              InterfaceCollection.isKnownToImplement(iface, implementor.getType(), options());
          builder.addInterface(iface, isKnown);
          if (isKnown) {
            seenAndKnown.add(iface);
          }
          DexClass definition = definitionFor(iface);
          if (definition != null && !definition.interfaces.isEmpty()) {
            worklist.add(new Pair<>(definition, isKnown));
          }
        }
        if (implementor.superType == null
            || implementor.superType == options().dexItemFactory().objectType) {
          break;
        }
        implementor = definitionFor(implementor.superType);
      }
    }
    // Second complete the worklist of interfaces. All paths must be visited as an interface may
    // be unknown on one but not on another.
    while (!worklist.isEmpty()) {
      Pair<DexClass, Boolean> item = worklist.poll();
      DexClass implementor = item.getFirst();
      assert !implementor.interfaces.isEmpty();
      for (DexType itf : implementor.interfaces) {
        if (seenAndKnown.contains(itf)) {
          continue;
        }
        // A derived interface is known only if the full chain leading to it is known.
        boolean isKnown =
            item.getSecond()
                && InterfaceCollection.isKnownToImplement(itf, implementor.getType(), options());
        builder.addInterface(itf, isKnown);
        if (isKnown) {
          seenAndKnown.add(itf);
        }
        DexClass definition = definitionFor(itf);
        if (definition != null && !definition.interfaces.isEmpty()) {
          worklist.add(new Pair<>(definition, isKnown));
        }
      }
    }
    return builder.build();
  }

  public boolean isExternalizable(DexType type) {
    return isSubtype(type, dexItemFactory().externalizableType);
  }

  public boolean isSerializable(DexType type) {
    return isSubtype(type, dexItemFactory().serializableType);
  }

  public List<DexProgramClass> computeProgramClassRelationChain(
      DexProgramClass subClass, DexProgramClass superClass) {
    assert isSubtype(subClass.type, superClass.type);
    assert !subClass.isInterface();
    if (!superClass.isInterface()) {
      return computeChainInClassHierarchy(subClass, superClass.type);
    }
    // If the super type is an interface we first compute the program chain upwards, and in a
    // top-down order check if the interface is a super-type to the class. Computing it this way
    // guarantees to find the instantiated program-classes of the longest chain.
    List<DexProgramClass> relationChain =
        computeChainInClassHierarchy(subClass, dexItemFactory().objectType);
    WorkList<DexType> interfaceWorklist = WorkList.newIdentityWorkList();
    for (int i = relationChain.size() - 1; i >= 0; i--) {
      DexProgramClass clazz = relationChain.get(i);
      if (isInterfaceInSuperTypes(clazz, superClass.type, interfaceWorklist)) {
        return relationChain.subList(0, i + 1);
      }
    }
    return Collections.emptyList();
  }

  private boolean isInterfaceInSuperTypes(
      DexProgramClass clazz, DexType ifaceToFind, WorkList<DexType> workList) {
    workList.addIfNotSeen(clazz.allImmediateSupertypes());
    while (workList.hasNext()) {
      DexType superType = workList.next();
      if (superType == ifaceToFind) {
        return true;
      }
      DexClass superClass = definitionFor(superType);
      if (superClass != null) {
        workList.addIfNotSeen(superClass.allImmediateSupertypes());
      }
    }
    return false;
  }

  private List<DexProgramClass> computeChainInClassHierarchy(
      DexProgramClass subClass, DexType superType) {
    assert isSubtype(subClass.type, superType);
    assert !subClass.isInterface();
    assert superType == dexItemFactory().objectType
        || definitionFor(superType) == null
        || !definitionFor(superType).isInterface();
    List<DexProgramClass> relationChain = new ArrayList<>();
    DexClass current = subClass;
    while (current != null) {
      if (current.isProgramClass()) {
        relationChain.add(current.asProgramClass());
      }
      if (current.type == superType) {
        return relationChain;
      }
      current = definitionFor(current.superType);
    }
    return relationChain;
  }

  public boolean methodDefinedInInterfaces(DexEncodedMethod method, DexType implementingClass) {
    DexClass holder = definitionFor(implementingClass);
    if (holder == null) {
      return false;
    }
    for (DexType iface : holder.interfaces.values) {
      if (methodDefinedInInterface(method, iface)) {
        return true;
      }
    }
    return false;
  }

  public boolean methodDefinedInInterface(DexEncodedMethod method, DexType iface) {
    DexClass potentialHolder = definitionFor(iface);
    if (potentialHolder == null) {
      return false;
    }
    assert potentialHolder.isInterface();
    for (DexEncodedMethod virtualMethod : potentialHolder.virtualMethods()) {
      if (virtualMethod.getReference().match(method.getReference())
          && virtualMethod.accessFlags.isSameVisibility(method.accessFlags)) {
        return true;
      }
    }
    for (DexType parentInterface : potentialHolder.interfaces.values) {
      if (methodDefinedInInterface(method, parentInterface)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Helper method used for emulated interface resolution (not in JVM specifications). The result
   * may be abstract.
   */
  public DexClassAndMethod lookupMaximallySpecificMethod(DexClass clazz, DexMethod method) {
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .lookupMaximallySpecificTarget(clazz, method);
  }

  MethodResolutionResult resolveMaximallySpecificTarget(DexClass clazz, DexMethod method) {
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .resolveMaximallySpecificTarget(clazz, method);
  }

  MethodResolutionResult resolveMaximallySpecificTarget(LambdaDescriptor lambda, DexMethod method) {
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .resolveMaximallySpecificTarget(lambda, method);
  }

  /**
   * Lookup instance field starting in type and following the interface and super chain.
   *
   * <p>The result is the field that will be hit at runtime, if such field is known. A result of
   * null indicates that the field is either undefined or not an instance field.
   */
  public DexEncodedField lookupInstanceTargetOn(DexType type, DexField field) {
    assert checkIfObsolete();
    assert type.isClassType();
    DexEncodedField result = resolveFieldOn(type, field).getResolvedField();
    return result == null || result.accessFlags.isStatic() ? null : result;
  }

  public DexEncodedField lookupInstanceTarget(DexField field) {
    return lookupInstanceTargetOn(field.holder, field);
  }

  /**
   * Lookup static field starting in type and following the interface and super chain.
   *
   * <p>The result is the field that will be hit at runtime, if such field is known. A result of
   * null indicates that the field is either undefined or not a static field.
   */
  public DexClassAndField lookupStaticTargetOn(DexType type, DexField field) {
    assert checkIfObsolete();
    assert type.isClassType();
    DexClassAndField result = resolveFieldOn(type, field).getResolutionPair();
    return result == null || !result.getAccessFlags().isStatic() ? null : result;
  }

  public DexClassAndField lookupStaticTarget(DexField field) {
    return lookupStaticTargetOn(field.getHolderType(), field);
  }

  /**
   * Lookup static method following the super chain from the holder of {@code method}.
   *
   * <p>This method will resolve the method on the holder of {@code method} and only return a
   * non-null value if the result of resolution was a static, non-abstract method.
   *
   * @param method the method to lookup
   * @return The actual target for {@code method} or {@code null} if none found.
   */
  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexEncodedMethod lookupStaticTarget(DexMethod method, DexProgramClass context) {
    assert checkIfObsolete();
    return unsafeResolveMethodDueToDexFormatLegacy(method).lookupInvokeStaticTarget(context, this);
  }

  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexEncodedMethod lookupStaticTarget(DexMethod method, ProgramMethod context) {
    return lookupStaticTarget(method, context.getHolder());
  }

  /**
   * Lookup super method following the super chain from the holder of {@code method}.
   *
   * <p>This method will resolve the method on the holder of {@code method} and only return a
   * non-null value if the result of resolution was an instance (i.e. non-static) method.
   *
   * @param method the method to lookup
   * @param context the class the invoke is contained in, i.e., the holder of the caller.
   * @return The actual target for {@code method} or {@code null} if none found.
   */
  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexClassAndMethod lookupSuperTarget(DexMethod method, DexProgramClass context) {
    assert checkIfObsolete();
    return unsafeResolveMethodDueToDexFormatLegacy(method).lookupInvokeSuperTarget(context, this);
  }

  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexClassAndMethod lookupSuperTarget(DexMethod method, ProgramMethod context) {
    return lookupSuperTarget(method, context.getHolder());
  }

  /**
   * Lookup direct method following the super chain from the holder of {@code method}.
   *
   * <p>This method will lookup private and constructor methods.
   *
   * @param method the method to lookup
   * @return The actual target for {@code method} or {@code null} if none found.
   */
  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexEncodedMethod lookupDirectTarget(DexMethod method, DexProgramClass context) {
    assert checkIfObsolete();
    return unsafeResolveMethodDueToDexFormatLegacy(method).lookupInvokeDirectTarget(context, this);
  }

  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexEncodedMethod lookupDirectTarget(DexMethod method, ProgramMethod context) {
    return lookupDirectTarget(method, context.getHolder());
  }

  /**
   * This method will query the definition of the holder to decide on which resolution to use.
   *
   * <p>This is to overcome the shortcoming of the DEX file format that does not allow to encode the
   * kind of a method reference.
   */
  public MethodResolutionResult unsafeResolveMethodDueToDexFormatLegacy(DexMethod method) {
    assert checkIfObsolete();
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .unsafeResolveMethodDueToDexFormat(method);
  }

  public MethodResolutionResult resolveMethodLegacy(DexMethod invokedMethod, boolean isInterface) {
    assert checkIfObsolete();
    return resolveMethodOnLegacy(invokedMethod.getHolderType(), invokedMethod, isInterface);
  }

  public MethodResolutionResult resolveMethodOnLegacy(DexClass clazz, DexMethod method) {
    assert checkIfObsolete();
    return clazz.isInterface()
        ? resolveMethodOnInterfaceLegacy(clazz, method)
        : resolveMethodOnClassLegacy(clazz, method);
  }

  public MethodResolutionResult resolveMethodOnLegacy(
      DexClass clazz, DexMethodSignature methodSignature) {
    assert checkIfObsolete();
    return clazz.isInterface()
        ? resolveMethodOnInterfaceLegacy(clazz, methodSignature)
        : resolveMethodOnClassLegacy(clazz, methodSignature);
  }

  public MethodResolutionResult resolveMethodOnLegacy(
      DexType holder, DexMethod method, boolean isInterface) {
    assert checkIfObsolete();
    return isInterface
        ? resolveMethodOnInterfaceLegacy(holder, method)
        : resolveMethodOnClassLegacy(holder, method);
  }

  public MethodResolutionResult resolveMethodOnClassHolderLegacy(DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnClassLegacy(method.getHolderType(), method);
  }

  public MethodResolutionResult resolveMethodOnClassLegacy(DexType holder, DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnClassLegacy(holder, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnClassLegacy(
      DexType holder, DexMethodSignature signature) {
    assert checkIfObsolete();
    return resolveMethodOnClassLegacy(holder, signature.getProto(), signature.getName());
  }

  public MethodResolutionResult resolveMethodOnClassLegacy(
      DexType holder, DexProto proto, DexString name) {
    assert checkIfObsolete();
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .resolveMethodOnClass(holder, proto, name);
  }

  public MethodResolutionResult resolveMethodOnClassLegacy(DexClass clazz, DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnClassLegacy(clazz, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnClassLegacy(
      DexClass clazz, DexMethodSignature signature) {
    assert checkIfObsolete();
    return resolveMethodOnClassLegacy(clazz, signature.getProto(), signature.getName());
  }

  public MethodResolutionResult resolveMethodOnClassLegacy(
      DexClass clazz, DexProto proto, DexString name) {
    assert checkIfObsolete();
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .resolveMethodOnClass(clazz, proto, name);
  }

  public MethodResolutionResult resolveMethodOnInterfaceHolderLegacy(DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnInterfaceLegacy(method.getHolderType(), method);
  }

  public MethodResolutionResult resolveMethodOnInterfaceLegacy(DexType holder, DexMethod method) {
    assert checkIfObsolete();
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .resolveMethodOnInterface(holder, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnInterfaceLegacy(DexClass clazz, DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnInterfaceLegacy(clazz, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnInterfaceLegacy(
      DexClass clazz, DexMethodSignature methodSignature) {
    assert checkIfObsolete();
    return resolveMethodOnInterfaceLegacy(
        clazz, methodSignature.getProto(), methodSignature.getName());
  }

  public MethodResolutionResult resolveMethodOnInterfaceLegacy(
      DexClass clazz, DexProto proto, DexString name) {
    assert checkIfObsolete();
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .resolveMethodOnInterface(clazz, proto, name);
  }

  /**
   * This method will query the definition of the holder to decide on which resolution to use.
   *
   * <p>This is to overcome the shortcoming of the DEX file format that does not allow to encode the
   * kind of a method reference.
   */
  public MethodResolutionResult unsafeResolveMethodDueToDexFormat(DexMethod method) {
    assert checkIfObsolete();
    return MethodResolution.create(
            this::contextIndependentDefinitionForWithResolutionResult, dexItemFactory())
        .unsafeResolveMethodDueToDexFormat(method);
  }

  public MethodResolutionResult resolveMethod(DexMethod invokedMethod, boolean isInterface) {
    assert checkIfObsolete();
    return resolveMethodOn(invokedMethod.getHolderType(), invokedMethod, isInterface);
  }

  public MethodResolutionResult resolveMethodOn(
      DexType holder, DexMethod method, boolean isInterface) {
    assert checkIfObsolete();
    return isInterface
        ? resolveMethodOnInterface(holder, method)
        : resolveMethodOnClass(holder, method);
  }

  public MethodResolutionResult resolveMethodOnClassHolder(DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnClass(method.getHolderType(), method);
  }

  public MethodResolutionResult resolveMethodOnClass(DexType holder, DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnClass(holder, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnClass(DexType holder, DexMethodSignature signature) {
    assert checkIfObsolete();
    return resolveMethodOnClass(holder, signature.getProto(), signature.getName());
  }

  public MethodResolutionResult resolveMethodOnClass(
      DexType holder, DexProto proto, DexString name) {
    assert checkIfObsolete();
    return MethodResolution.create(
            this::contextIndependentDefinitionForWithResolutionResult, dexItemFactory())
        .resolveMethodOnClass(holder, proto, name);
  }

  public MethodResolutionResult resolveMethodOnClass(DexClass clazz, DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnClass(clazz, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnClass(DexClass clazz, DexMethodSignature signature) {
    assert checkIfObsolete();
    return resolveMethodOnClass(clazz, signature.getProto(), signature.getName());
  }

  public MethodResolutionResult resolveMethodOnClass(
      DexClass clazz, DexProto proto, DexString name) {
    assert checkIfObsolete();
    return MethodResolution.create(
            this::contextIndependentDefinitionForWithResolutionResult, dexItemFactory())
        .resolveMethodOnClass(clazz, proto, name);
  }

  public MethodResolutionResult resolveMethodOnInterfaceHolder(DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnInterface(method.getHolderType(), method);
  }

  public MethodResolutionResult resolveMethodOnInterface(DexType holder, DexMethod method) {
    assert checkIfObsolete();
    return MethodResolution.create(
            this::contextIndependentDefinitionForWithResolutionResult, dexItemFactory())
        .resolveMethodOnInterface(holder, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnInterface(DexClass clazz, DexMethod method) {
    assert checkIfObsolete();
    return resolveMethodOnInterface(clazz, method.getProto(), method.getName());
  }

  public MethodResolutionResult resolveMethodOnInterface(
      DexClass clazz, DexMethodSignature methodSignature) {
    assert checkIfObsolete();
    return resolveMethodOnInterface(clazz, methodSignature.getProto(), methodSignature.getName());
  }

  public MethodResolutionResult resolveMethodOnInterface(
      DexClass clazz, DexProto proto, DexString name) {
    assert checkIfObsolete();
    return MethodResolution.create(
            this::contextIndependentDefinitionForWithResolutionResult, dexItemFactory())
        .resolveMethodOnInterface(clazz, proto, name);
  }

  /**
   * Implements resolution of a field descriptor against the holder of the field. See also {@link
   * #resolveFieldOn}.
   */
  public FieldResolutionResult resolveField(DexField field) {
    assert checkIfObsolete();
    return resolveFieldOn(field.holder, field);
  }

  /** Intentionally drops {@param context} since this is only needed in D8. */
  @Override
  public FieldResolutionResult resolveFieldOn(DexType type, DexField field, ProgramMethod context) {
    assert checkIfObsolete();
    return resolveFieldOn(type, field);
  }

  // Keep as instance methods to ensure that one needs AppInfoWithClassHierarchy to do resolution.
  public FieldResolutionResult resolveFieldOn(DexType type, DexField field) {
    assert checkIfObsolete();
    return new FieldResolution(this).resolveFieldOn(type, field);
  }

  // Keep as instance methods to ensure that one needs AppInfoWithClassHierarchy to do resolution.
  public FieldResolutionResult resolveFieldOn(DexClass clazz, DexField field) {
    assert checkIfObsolete();
    return new FieldResolution(this).resolveFieldOn(clazz, field);
  }
}
