// 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.Map.Entry;
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, getSyntheticItems()));
  }

  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 <B> TraversalContinuation<B, ?> traverseSuperTypes(
      final DexClass clazz,
      TriFunction<DexType, DexClass, Boolean, TraversalContinuation<B, ?>> 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<B, ?> 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<B, ?> 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<B, ?> 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.isSameVisibility(method)) {
        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);
  }

  /**
   * Helper methods used for emulated interface resolution (not in JVM specifications). Answers the
   * abstract interface methods that the resolution could but does not necessarily resolve into.
   */
  public List<Entry<DexClass, DexEncodedMethod>> getAbstractInterfaceMethods(
      DexClass clazz, DexMethod method) {
    return MethodResolution.createLegacy(this::definitionFor, dexItemFactory())
        .getAbstractInterfaceMethods(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 resolveMethodOn(DexClass clazz, DexMethod method) {
    assert checkIfObsolete();
    return clazz.isInterface()
        ? resolveMethodOnInterface(clazz, method)
        : resolveMethodOnClass(clazz, method);
  }

  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);
  }
}
