// 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.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.Timing;
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) {
    return new AppInfoWithClassHierarchy(
        SyntheticItems.createInitialSyntheticItems(application, globalSyntheticsStrategy),
        classToFeatureSplitMap,
        mainDexInfo,
        MissingClasses.empty());
  }

  private final ClassToFeatureSplitMap classToFeatureSplitMap;

  /** 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) {
    super(committedItems, mainDexInfo);
    this.classToFeatureSplitMap = classToFeatureSplitMap;
    this.missingClasses = missingClasses;
  }

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

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

  public final AppInfoWithClassHierarchy rebuildWithClassHierarchy(DexApplication application) {
    return rebuildWithClassHierarchy(getSyntheticItems().commit(application));
  }

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

  public void notifyMinifierFinished() {
    // Intentionally empty.
  }

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

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

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

  public ClassToFeatureSplitMap getClassToFeatureSplitMap() {
    return classToFeatureSplitMap;
  }

  public MissingClasses getMissingClasses() {
    return missingClasses;
  }

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

  @SuppressWarnings("ReferenceEquality")
  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);
  }

  @SuppressWarnings("ReferenceEquality")
  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);
  }

  @SuppressWarnings("ReferenceEquality")
  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);
  }

  @SuppressWarnings("ReferenceEquality")
  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. */
  @SuppressWarnings({"BadImport", "ReferenceEquality"})
  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();
    @SuppressWarnings("ReferenceEquality")
    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();
  }

  @SuppressWarnings("ReferenceEquality")
  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;
  }

  @SuppressWarnings("ReferenceEquality")
  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 DexClassAndMethod lookupStaticTarget(
      DexMethod method,
      DexProgramClass context,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    return lookupStaticTarget(method, context, appView, appView.appInfo());
  }

  public DexClassAndMethod lookupStaticTarget(
      DexMethod method,
      DexProgramClass context,
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo) {
    assert checkIfObsolete();
    return unsafeResolveMethodDueToDexFormatLegacy(method)
        .lookupInvokeStaticTarget(context, appView, appInfo);
  }

  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexClassAndMethod lookupStaticTarget(
      DexMethod method,
      ProgramMethod context,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    return lookupStaticTarget(method, context.getHolder(), appView);
  }

  public DexClassAndMethod lookupStaticTarget(
      DexMethod method,
      ProgramMethod context,
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo) {
    return lookupStaticTarget(method, context.getHolder(), appView, appInfo);
  }

  /**
   * 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,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    return lookupSuperTarget(method, context, appView, appView.appInfo());
  }

  public DexClassAndMethod lookupSuperTarget(
      DexMethod method,
      DexProgramClass context,
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo) {
    assert checkIfObsolete();
    return unsafeResolveMethodDueToDexFormatLegacy(method)
        .lookupInvokeSuperTarget(context, appView, appInfo);
  }

  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public final DexClassAndMethod lookupSuperTarget(
      DexMethod method,
      ProgramMethod context,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    return lookupSuperTarget(method, context, appView, appView.appInfo());
  }

  public final DexClassAndMethod lookupSuperTarget(
      DexMethod method,
      ProgramMethod context,
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo) {
    return lookupSuperTarget(method, context.getHolder(), appView, appInfo);
  }

  /**
   * 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 DexClassAndMethod lookupDirectTarget(
      DexMethod method,
      DexProgramClass context,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    return lookupDirectTarget(method, context, appView, appView.appInfo());
  }

  public DexClassAndMethod lookupDirectTarget(
      DexMethod method,
      DexProgramClass context,
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo) {
    assert checkIfObsolete();
    return unsafeResolveMethodDueToDexFormatLegacy(method)
        .lookupInvokeDirectTarget(context, appView, appInfo);
  }

  // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
  public DexClassAndMethod lookupDirectTarget(
      DexMethod method,
      ProgramMethod context,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    return lookupDirectTarget(method, context, appView, appView.appInfo());
  }

  public DexClassAndMethod lookupDirectTarget(
      DexMethod method,
      ProgramMethod context,
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo) {
    return lookupDirectTarget(method, context.getHolder(), appView, appInfo);
  }

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