// Copyright (c) 2022, 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.graph.MethodResolution.UniquePathOracle.SplitToken.NO_SPLIT_TOKEN;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.graph.MethodResolutionResult.ArrayCloneMethodResult;
import com.android.tools.r8.graph.MethodResolutionResult.ClassNotFoundResult;
import com.android.tools.r8.graph.MethodResolutionResult.IllegalAccessOrNoSuchMethodResult;
import com.android.tools.r8.graph.MethodResolutionResult.IncompatibleClassResult;
import com.android.tools.r8.graph.MethodResolutionResult.NoSuchMethodResult;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;

/**
 * Implements resolution of a method descriptor against a type.
 *
 * <p>See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
 * Section 5.4.3.3 of the JVM Spec</a>.
 */
public class MethodResolution {

  private final Function<DexType, ClassResolutionResult> definitionFor;
  private final DexItemFactory factory;
  private final boolean escapeIfLibraryHasProgramSuperType;
  private final boolean canHaveIncompletePaths;

  private MethodResolution(
      Function<DexType, ClassResolutionResult> definitionFor,
      DexItemFactory factory,
      boolean escapeIfLibraryHasProgramSuperType,
      boolean canHaveIncompletePaths) {
    this.definitionFor = definitionFor;
    this.factory = factory;
    this.escapeIfLibraryHasProgramSuperType = escapeIfLibraryHasProgramSuperType;
    this.canHaveIncompletePaths = canHaveIncompletePaths;
  }

  @Deprecated
  public static MethodResolution createLegacy(
      Function<DexType, DexClass> definitionFor, DexItemFactory factory) {
    // TODO(b/230289235): Remove this when R8/D8 can handle multiple definitions.
    return new MethodResolution(
        type -> {
          DexClass clazz = definitionFor.apply(type);
          return clazz == null ? ClassResolutionResult.NoResolutionResult.noResult() : clazz;
        },
        factory,
        false,
        false);
  }

  public static MethodResolution create(
      Function<DexType, ClassResolutionResult> definitionFor, DexItemFactory factory) {
    return new MethodResolution(definitionFor, factory, true, true);
  }

  private ClassResolutionResult definitionFor(DexType type) {
    return definitionFor.apply(type);
  }

  /**
   * This method will query the definition of the holder to decide on which resolution to use. If
   * the holder is an interface, it delegates to {@link #resolveMethodOnInterface(DexClass,
   * DexProto, DexString)}, otherwise {@link #resolveMethodOnClass(DexClass, DexProto, DexString)}
   * is used.
   *
   * <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) {
    DexType holder = method.holder;
    if (holder.isArrayType()) {
      return resolveMethodOnArray(holder, method.getProto(), method.getName());
    }
    MethodResolutionResult.Builder builder = MethodResolutionResult.builder();
    definitionFor(holder)
        .forEachClassResolutionResult(
            clazz -> {
              builder.addResolutionResult(
                  clazz.isInterface()
                      ? resolveMethodOnInterface(clazz, method.getProto(), method.getName())
                      : resolveMethodOnClass(clazz, method.getProto(), method.getName()));
            });
    return builder.buildOrIfEmpty(ClassNotFoundResult.INSTANCE, holder);
  }

  /**
   * Implements resolution of a method descriptor against an array type.
   *
   * <p>See <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html#jls-10.7">Section
   * 10.7 of the Java Language Specification</a>. All invokations will have target java.lang.Object
   * except clone which has no target.
   */
  private MethodResolutionResult resolveMethodOnArray(
      DexType holder, DexProto methodProto, DexString methodName) {
    assert holder.isArrayType();
    if (methodName == factory.cloneMethodName) {
      return ArrayCloneMethodResult.INSTANCE;
    } else {
      return resolveMethodOnClass(factory.objectType, methodProto, methodName);
    }
  }

  /**
   * Implements resolution of a method descriptor against a class type.
   *
   * <p>See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
   * Section 5.4.3.3 of the JVM Spec</a>.
   *
   * <p>The resolved method is not the method that will actually be invoked. Which methods gets
   * invoked depends on the invoke instruction used. However, it is always safe to rewrite any
   * invoke on the given descriptor to a corresponding invoke on the resolved descriptor, as the
   * resolved method is used as basis for dispatch.
   */
  public MethodResolutionResult resolveMethodOnClass(
      DexType holder, DexProto methodProto, DexString methodName) {
    if (holder.isArrayType()) {
      return resolveMethodOnArray(holder, methodProto, methodName);
    }
    MethodResolutionResult.Builder builder = MethodResolutionResult.builder();
    definitionFor(holder)
        .forEachClassResolutionResult(
            clazz -> {
              // Step 1: If holder is an interface, resolution fails with an ICCE.
              if (clazz.isInterface()) {
                builder.addResolutionResult(IncompatibleClassResult.INSTANCE);
              } else {
                builder.addResolutionResult(resolveMethodOnClass(clazz, methodProto, methodName));
              }
            });
    return builder.buildOrIfEmpty(ClassNotFoundResult.INSTANCE, holder);
  }

  public MethodResolutionResult resolveMethodOnClass(
      DexClass clazz, DexProto methodProto, DexString methodName) {
    assert !clazz.isInterface();
    // Step 2:
    MethodResolutionResult result =
        resolveMethodOnClassStep2(clazz, methodProto, methodName, clazz);
    if (result != null) {
      return result;
    }
    // Finally Step 3:
    return resolveMethodStep3(clazz, methodProto, methodName);
  }

  /**
   * Implements step 2 of method resolution on classes as per <a
   * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">Section
   * 5.4.3.3 of the JVM Spec</a>.
   */
  private MethodResolutionResult resolveMethodOnClassStep2(
      DexClass clazz,
      DexProto methodProto,
      DexString methodName,
      DexClass initialResolutionHolder) {
    // Pt. 1: Signature polymorphic method check.
    // See also <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">
    // Section 2.9 of the JVM Spec</a>.
    DexEncodedMethod result = clazz.lookupSignaturePolymorphicMethod(methodName, factory);
    if (result != null) {
      return MethodResolutionResult.createSingleResolutionResult(
          initialResolutionHolder, clazz, result);
    }
    // Pt 2: Find a method that matches the descriptor.
    result = clazz.lookupMethod(methodProto, methodName);
    if (result != null) {
      // If the resolved method is private, then it can only be accessed if the symbolic reference
      // that initiated the resolution was the type at which the method resolved on. If that is not
      // the case, then the error is either an IllegalAccessError, or in the case where access is
      // allowed because of nests, a NoSuchMethodError. Which error cannot be determined without
      // knowing the calling context.
      if (result.isPrivateMethod() && clazz != initialResolutionHolder) {
        return new IllegalAccessOrNoSuchMethodResult(initialResolutionHolder, result);
      }
      return MethodResolutionResult.createSingleResolutionResult(
          initialResolutionHolder, clazz, result);
    }
    // Pt 3: Apply step two to direct superclass of holder.
    if (clazz.superType != null) {
      MethodResolutionResult.Builder builder = MethodResolutionResult.builder();
      definitionFor(clazz.superType)
          .forEachClassResolutionResult(
              superClass -> {
                // Guard against going back into the program for resolution.
                if (escapeIfLibraryHasProgramSuperType
                    && clazz.isLibraryClass()
                    && !superClass.isLibraryClass()) {
                  return;
                }
                builder.addResolutionResult(
                    resolveMethodOnClassStep2(
                        superClass, methodProto, methodName, initialResolutionHolder));
              });
      return builder.buildOrIfEmpty(null, clazz.superType);
    }
    return null;
  }

  /**
   * Implements step 3 of <a
   * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">Section
   * 5.4.3.3 of the JVM Spec</a>. As this is the same for interfaces and classes, we share one
   * implementation.
   */
  private MethodResolutionResult resolveMethodStep3(
      DexClass clazz, DexProto methodProto, DexString methodName) {
    MaximallySpecificMethodsBuilder builder =
        new MaximallySpecificMethodsBuilder(definitionFor, factory);
    resolveMethodStep3Helper(methodProto, methodName, clazz, builder);
    return builder.resolve(clazz);
  }

  MethodResolutionResult resolveMaximallySpecificTarget(DexClass clazz, DexMethod method) {
    return resolveMaximallySpecificTargetHelper(clazz, method).resolve(clazz);
  }

  MethodResolutionResult resolveMaximallySpecificTarget(LambdaDescriptor lambda, DexMethod method) {
    return resolveMaximallySpecificTargetHelper(lambda, method).internalResolve(null);
  }

  // Non-private lookup (ie, not resolution) to find interface targets.
  DexClassAndMethod lookupMaximallySpecificTarget(DexClass clazz, DexMethod method) {
    return resolveMaximallySpecificTargetHelper(clazz, method).lookup();
  }

  // Non-private method used for emulated interface only.
  List<Entry<DexClass, DexEncodedMethod>> getAbstractInterfaceMethods(
      DexClass clazz, DexMethod method) {
    return resolveMaximallySpecificTargetHelper(clazz, method).getAbstractMethods();
  }

  private MaximallySpecificMethodsBuilder resolveMaximallySpecificTargetHelper(
      DexClass clazz, DexMethod method) {
    MaximallySpecificMethodsBuilder builder =
        new MaximallySpecificMethodsBuilder(definitionFor, factory);
    resolveMethodStep3Helper(method.getProto(), method.getName(), clazz, builder);
    return builder;
  }

  private MaximallySpecificMethodsBuilder resolveMaximallySpecificTargetHelper(
      LambdaDescriptor lambda, DexMethod method) {
    MaximallySpecificMethodsBuilder builder =
        new MaximallySpecificMethodsBuilder(definitionFor, factory);
    resolveMethodStep3Helper(
        method.getProto(), method.getName(), null, builder, factory.objectType, lambda.interfaces);
    return builder;
  }

  /**
   * UniquePathOracle will compute for all parent definitions in the hierarchy if a class is visited
   * by all paths or not depending on class resolution resolving a type to either library or
   * program/classpath definitions. It does so by visiting all paths upwards in the hierarchy and
   * when a split point is seen it will create a "left" and "right" half rooted by the split type.
   * If a definition is only seen by a single token it will always be on an incomplete path
   * otherwise if the class is seen by both the left and right token it is visited by all:
   *
   * <pre>
   *                     C_Library { left_B, right_B }
   *                    /                     \
   *     B_Program extends C { left_B }     B_Library extends C { right_B }
   *                    \                     /
   *                      A_Program extends B { }
   * </pre>
   */
  static class UniquePathOracle {

    static class SplitToken {

      static final SplitToken NO_SPLIT_TOKEN = new SplitToken(null);

      private final DexType split;

      private SplitToken(DexType split) {
        this.split = split;
      }

      boolean isSplitToken() {
        return this != NO_SPLIT_TOKEN;
      }
    }

    private final Function<DexType, ClassResolutionResult> definitionFor;
    private final boolean escapeIfLibraryHasProgramSuperType;
    private final Map<DexClass, Map<DexType, SplitToken>> incompletePaths = new IdentityHashMap<>();
    private final Set<DexType> seenTypes = Sets.newIdentityHashSet();

    public UniquePathOracle(
        Function<DexType, ClassResolutionResult> definitionFor,
        boolean escapeIfLibraryHasProgramSuperType) {
      this.definitionFor = definitionFor;
      this.escapeIfLibraryHasProgramSuperType = escapeIfLibraryHasProgramSuperType;
    }

    public boolean onIncompletePath(DexClass definition) {
      Map<DexType, SplitToken> tokenMap = incompletePaths.get(definition);
      assert tokenMap != null;
      for (SplitToken value : tokenMap.values()) {
        if (value.isSplitToken()) {
          return true;
        }
      }
      return false;
    }

    void lookupPath(DexType type, DexClass previousClass) {
      lookupPath(type, previousClass, Collections.emptySet());
    }

    private void lookupPath(DexType type, DexClass previousClass, Set<SplitToken> splitTokens) {
      if (splitTokens.isEmpty() && !seenTypes.add(type)) {
        return;
      }
      ClassResolutionResult resolutionResult = definitionFor.apply(type);
      resolutionResult.forEachClassResolutionResult(
          clazz -> {
            if (escapeIfLibraryHasProgramSuperType
                && previousClass.isLibraryClass()
                && !clazz.isLibraryClass()) {
              return;
            }
            Set<SplitToken> currentSplitTokens;
            if (resolutionResult.isMultipleClassResolutionResult()) {
              currentSplitTokens = SetUtils.newIdentityHashSet(splitTokens);
              currentSplitTokens.add(new SplitToken(type));
            } else {
              currentSplitTokens = splitTokens;
            }
            Map<DexType, SplitToken> paths =
                incompletePaths.computeIfAbsent(clazz, ignoreKey(IdentityHashMap::new));
            currentSplitTokens.forEach(
                splitToken -> {
                  SplitToken otherSplitToken = paths.get(splitToken.split);
                  if (otherSplitToken == null) {
                    paths.put(splitToken.split, splitToken);
                  } else if (otherSplitToken != splitToken && otherSplitToken.isSplitToken()) {
                    // We have not seen this half of the split token, so it is visited on all paths.
                    paths.put(splitToken.split, NO_SPLIT_TOKEN);
                  }
                });
            clazz.interfaces.forEach(iface -> lookupPath(iface, clazz, currentSplitTokens));
            if (clazz.superType != null) {
              lookupPath(clazz.superType, clazz, currentSplitTokens);
            }
          });
    }
  }

  static class AllUniquePathsOracle extends UniquePathOracle {

    private static final AllUniquePathsOracle INSTANCE = new AllUniquePathsOracle();

    static AllUniquePathsOracle getInstance() {
      return INSTANCE;
    }

    private AllUniquePathsOracle() {
      super(null, false);
    }

    @Override
    void lookupPath(DexType type, DexClass previousClass) {
      // Intentionally empty
    }

    @Override
    public boolean onIncompletePath(DexClass definition) {
      return false;
    }
  }

  /** Helper method that builds the set of maximally specific methods. */
  private void resolveMethodStep3Helper(
      DexProto methodProto,
      DexString methodName,
      DexClass clazz,
      MaximallySpecificMethodsBuilder builder) {
    resolveMethodStep3Helper(
        methodProto,
        methodName,
        clazz,
        builder,
        clazz.superType,
        Arrays.asList(clazz.interfaces.values));
  }

  private void resolveMethodStep3Helper(
      DexProto methodProto,
      DexString methodName,
      DexClass clazz,
      MaximallySpecificMethodsBuilder builder,
      DexType superType,
      List<DexType> interfaces) {
    UniquePathOracle uniquePathOracle;
    if (canHaveIncompletePaths) {
      uniquePathOracle = new UniquePathOracle(definitionFor, escapeIfLibraryHasProgramSuperType);
      interfaces.forEach(iFace -> uniquePathOracle.lookupPath(iFace, clazz));
      if (superType != null) {
        uniquePathOracle.lookupPath(superType, clazz);
      }
    } else {
      uniquePathOracle = AllUniquePathsOracle.getInstance();
    }
    resolveMethodStep3Helper(
        methodProto, methodName, clazz, builder, superType, interfaces, uniquePathOracle);
  }

  private void resolveMethodStep3Helper(
      DexProto methodProto,
      DexString methodName,
      DexClass clazz,
      MaximallySpecificMethodsBuilder builder,
      DexType superType,
      List<DexType> interfaces,
      UniquePathOracle uniquePathOracle) {
    for (DexType iface : interfaces) {
      ClassResolutionResult classResolutionResult = definitionFor(iface);
      classResolutionResult.forEachClassResolutionResult(
          definition -> {
            // Guard against going back into the program for resolution.
            if (escapeIfLibraryHasProgramSuperType
                && clazz != null
                && clazz.isLibraryClass()
                && !definition.isLibraryClass()) {
              return;
            }
            if (classResolutionResult.isMultipleClassResolutionResult()) {
              builder.addTypeWithMultipleDefinitions(iface);
            }
            assert definition.isInterface();
            DexEncodedMethod result = definition.lookupMethod(methodProto, methodName);
            if (isMaximallySpecificCandidate(result)) {
              // The candidate is added and doing so will prohibit shadowed methods from being
              // in the set.
              builder.addCandidate(
                  definition, result, uniquePathOracle.onIncompletePath(definition));
            } else {
              // Look at the super-interfaces of this class and keep searching.
              resolveMethodStep3Helper(
                  methodProto,
                  methodName,
                  definition,
                  builder,
                  definition.superType,
                  Arrays.asList(definition.interfaces.values),
                  uniquePathOracle);
            }
          });
    }
    // Now look at indirect super interfaces.
    if (superType != null) {
      definitionFor(superType)
          .forEachClassResolutionResult(
              superClass -> {
                // Guard against going back into the program for resolution.
                if (escapeIfLibraryHasProgramSuperType
                    && clazz != null
                    && clazz.isLibraryClass()
                    && !superClass.isLibraryClass()) {
                  return;
                }
                resolveMethodStep3Helper(
                    methodProto,
                    methodName,
                    superClass,
                    builder,
                    superClass.superType,
                    Arrays.asList(superClass.interfaces.values),
                    uniquePathOracle);
              });
    }
  }

  /**
   * A candidate for being a maximally specific method must have neither its private, nor its static
   * flag set. A candidate may still not be maximally specific, which entails that no subinterfaces
   * from also contribute with a candidate to the type. That is not determined by this method.
   */
  private boolean isMaximallySpecificCandidate(DexEncodedMethod method) {
    return method != null && !method.accessFlags.isPrivate() && !method.accessFlags.isStatic();
  }

  /**
   * Implements resolution of a method descriptor against an interface type.
   *
   * <p>See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
   * Section 5.4.3.4 of the JVM Spec</a>.
   *
   * <p>The resolved method is not the method that will actually be invoked. Which methods gets
   * invoked depends on the invoke instruction used. However, it is always save to rewrite any
   * invoke on the given descriptor to a corresponding invoke on the resolved descriptor, as the
   * resolved method is used as basis for dispatch.
   */
  public MethodResolutionResult resolveMethodOnInterface(
      DexType holder, DexProto proto, DexString methodName) {
    if (holder.isArrayType()) {
      return IncompatibleClassResult.INSTANCE;
    }
    MethodResolutionResult.Builder builder = MethodResolutionResult.builder();
    // Step 1: Lookup interface.
    definitionFor(holder)
        .forEachClassResolutionResult(
            definition -> {
              // If the definition is not an interface, resolution fails with an ICCE.
              if (!definition.isInterface()) {
                builder.addResolutionResult(IncompatibleClassResult.INSTANCE);
              } else {
                builder.addResolutionResult(
                    resolveMethodOnInterface(definition, proto, methodName));
              }
            });
    return builder.buildOrIfEmpty(ClassNotFoundResult.INSTANCE, holder);
  }

  public MethodResolutionResult resolveMethodOnInterface(
      DexClass definition, DexProto methodProto, DexString methodName) {
    assert definition.isInterface();
    // Step 2: Look for exact method on interface.
    DexEncodedMethod result = definition.lookupMethod(methodProto, methodName);
    if (result != null) {
      return MethodResolutionResult.createSingleResolutionResult(definition, definition, result);
    }
    // Step 3: Look for matching method on object class.
    MethodResolutionResult.Builder builder = MethodResolutionResult.builder();
    definitionFor(factory.objectType)
        .forEachClassResolutionResult(
            objectClass -> {
              DexEncodedMethod objectResult = objectClass.lookupMethod(methodProto, methodName);
              if (objectResult != null
                  && objectResult.accessFlags.isPublic()
                  && !objectResult.accessFlags.isAbstract()) {
                builder.addResolutionResult(
                    MethodResolutionResult.createSingleResolutionResult(
                        definition, objectClass, objectResult));
              } else {
                // Step 3: Look for maximally-specific superinterface methods or any interface
                // definition. This is the same for classes and interfaces.
                builder.addResolutionResult(
                    resolveMethodStep3(definition, methodProto, methodName));
              }
            });
    return builder.buildOrIfEmpty(ClassNotFoundResult.INSTANCE, Collections.emptySet());
  }

  static class MaximallySpecificMethodsBuilder {

    // The set of actual maximally specific methods.
    // This set is linked map so that in the case where a number of methods remain a deterministic
    // choice can be made. The map is from definition classes to their maximally specific method, or
    // in the case that a type has a candidate which is shadowed by a subinterface, the map will
    // map the class to a null entry, thus any addition to the map must check for key containment
    // prior to writing.
    private final LinkedHashMap<DexClass, DexEncodedMethod>
        maximallySpecificMethodsOnCompletePaths = new LinkedHashMap<>();
    private final LinkedHashMap<DexClass, DexEncodedMethod>
        maximallySpecificMethodsOnIncompletePaths = new LinkedHashMap<>();
    private final Function<DexType, ClassResolutionResult> definitionFor;
    private final Set<DexType> typesWithMultipleDefinitions = Sets.newIdentityHashSet();
    private final DexItemFactory factory;

    private MaximallySpecificMethodsBuilder(
        Function<DexType, ClassResolutionResult> definitionFor, DexItemFactory factory) {
      this.definitionFor = definitionFor;
      this.factory = factory;
    }

    void addTypeWithMultipleDefinitions(DexType type) {
      typesWithMultipleDefinitions.add(type);
    }

    void addCandidate(DexClass holder, DexEncodedMethod method, boolean isIncompletePath) {
      // If this candidate is already a candidate or it is shadowed, then no need to continue.
      if (isIncompletePath) {
        if (!maximallySpecificMethodsOnIncompletePaths.containsKey(holder)) {
          maximallySpecificMethodsOnIncompletePaths.put(holder, method);
        }
        // Incomplete paths can shadow complete path results if all partial paths is
        // shadowing.
        //       I_L { f(); }
        //     /            \
        // J_L { f(); }  // J_P { f(); }
        // One way to track them is to count all coverings are equal to the splits. For now
        // we bail out.
        return;
      } else if (maximallySpecificMethodsOnCompletePaths.containsKey(holder)) {
        return;
      }
      maximallySpecificMethodsOnCompletePaths.put(holder, method);
      // Prune exiting candidates and prohibit future candidates in the super hierarchy.
      assert holder.isInterface();
      assert holder.superType == factory.objectType;
      for (DexType iface : holder.interfaces.values) {
        markShadowed(iface);
      }
    }

    private void markShadowed(DexType type) {
      if (type == null) {
        return;
      }
      definitionFor
          .apply(type)
          .forEachClassResolutionResult(
              clazz -> {
                assert clazz.isInterface();
                assert clazz.superType == factory.objectType;
                // A null entry signifies that the candidate is shadowed blocking future candidates.
                // If the candidate is already shadowed at this type there is no need to shadow
                // further up.
                if (maximallySpecificMethodsOnCompletePaths.getOrDefault(
                        clazz, DexEncodedMethod.SENTINEL)
                    == null) {
                  return;
                }
                maximallySpecificMethodsOnCompletePaths.put(clazz, null);
                maximallySpecificMethodsOnIncompletePaths.put(clazz, null);
                for (DexType iface : clazz.interfaces.values) {
                  markShadowed(iface);
                }
              });
    }

    DexClassAndMethod lookup() {
      return internalResolve(null).getResolutionPair();
    }

    MethodResolutionResult resolve(DexClass initialResolutionHolder) {
      assert initialResolutionHolder != null;
      return internalResolve(initialResolutionHolder);
    }

    private MethodResolutionResult internalResolve(DexClass initialResolutionHolder) {
      if (maximallySpecificMethodsOnCompletePaths.isEmpty()
          && maximallySpecificMethodsOnIncompletePaths.isEmpty()) {
        return NoSuchMethodResult.INSTANCE;
      }
      List<Entry<DexClass, DexEncodedMethod>> nonAbstractOnComplete =
          getNonAbstractMethods(maximallySpecificMethodsOnCompletePaths);
      if (nonAbstractOnComplete.size() > 1) {
        return IncompatibleClassResult.create(
            ListUtils.map(nonAbstractOnComplete, Entry::getValue));
      }
      List<Entry<DexClass, DexEncodedMethod>> nonAbstractOnIncomplete =
          getNonAbstractMethods(maximallySpecificMethodsOnIncompletePaths);
      if (nonAbstractOnIncomplete.isEmpty()) {
        // If there are no non-abstract methods, then any candidate on a complete path will suffice
        // as a target. For deterministic resolution, we return the first mapped method (of the
        // linked map).
        if (nonAbstractOnComplete.isEmpty()) {
          Entry<DexClass, DexEncodedMethod> abstractMethod =
              firstNonNullEntry(maximallySpecificMethodsOnCompletePaths);
          if (abstractMethod == null) {
            abstractMethod = firstNonNullEntry(maximallySpecificMethodsOnIncompletePaths);
          }
          assert abstractMethod != null && abstractMethod.getValue().isAbstract();
          return singleResultHelper(initialResolutionHolder, abstractMethod);
        } else {
          // If there is exactly one non-abstract method (a default method) it is the resolution
          // target.
          return singleResultHelper(initialResolutionHolder, nonAbstractOnComplete.get(0));
        }
      } else {
        // We cannot guarantee a single target or an error, so we have to report all on incomplete
        // paths.
        MethodResolutionResult.Builder builder =
            MethodResolutionResult.builder().allowMultipleProgramResults();
        if (nonAbstractOnComplete.isEmpty()) {
          assert !typesWithMultipleDefinitions.isEmpty();
          builder.addResolutionResult(NoSuchMethodResult.INSTANCE);
        } else {
          nonAbstractOnComplete.forEach(
              entry ->
                  builder.addResolutionResult(singleResultHelper(initialResolutionHolder, entry)));
        }
        nonAbstractOnIncomplete.forEach(
            entry ->
                builder.addResolutionResult(singleResultHelper(initialResolutionHolder, entry)));
        return builder.buildOrIfEmpty(NoSuchMethodResult.INSTANCE, typesWithMultipleDefinitions);
      }
    }

    private List<Entry<DexClass, DexEncodedMethod>> getNonAbstractMethods(
        Map<DexClass, DexEncodedMethod> candidates) {
      List<Entry<DexClass, DexEncodedMethod>> nonAbstractMethods = new ArrayList<>();
      for (Entry<DexClass, DexEncodedMethod> entry : candidates.entrySet()) {
        DexEncodedMethod method = entry.getValue();
        if (method == null) {
          // Ignore shadowed candidates.
          continue;
        }
        if (method.isNonAbstractVirtualMethod()) {
          nonAbstractMethods.add(entry);
        }
      }
      return nonAbstractMethods;
    }

    List<Entry<DexClass, DexEncodedMethod>> getAbstractMethods() {
      List<Entry<DexClass, DexEncodedMethod>> abstractMethods = new ArrayList<>();
      addAbstractMethods(abstractMethods, maximallySpecificMethodsOnCompletePaths);
      addAbstractMethods(abstractMethods, maximallySpecificMethodsOnIncompletePaths);
      return abstractMethods;
    }

    private void addAbstractMethods(
        List<Entry<DexClass, DexEncodedMethod>> abstractMethods,
        Map<DexClass, DexEncodedMethod> candidates) {
      for (Entry<DexClass, DexEncodedMethod> entry : candidates.entrySet()) {
        DexEncodedMethod method = entry.getValue();
        if (method == null) {
          // Ignore shadowed candidates.
          continue;
        }
        if (method.isAbstract()) {
          abstractMethods.add(entry);
        }
      }
    }

    private static SingleResolutionResult<?> singleResultHelper(
        DexClass initialResolutionResult, Entry<DexClass, DexEncodedMethod> entry) {
      return MethodResolutionResult.createSingleResolutionResult(
          initialResolutionResult != null ? initialResolutionResult : entry.getKey(),
          entry.getKey(),
          entry.getValue());
    }

    private static Entry<DexClass, DexEncodedMethod> firstNonNullEntry(
        Map<DexClass, DexEncodedMethod> candidates) {
      for (Entry<DexClass, DexEncodedMethod> entry : candidates.entrySet()) {
        DexEncodedMethod method = entry.getValue();
        if (method != null) {
          return entry;
        }
      }
      return null;
    }
  }
}
