// Copyright (c) 2021, 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.ir.desugar.itf;

import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringCollection;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.DesugarDescription;
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.icce.AlwaysThrowingInstructionDesugaring;
import com.android.tools.r8.ir.desugar.lambda.LambdaInstructionDesugaring;
import com.android.tools.r8.ir.desugar.stringconcat.StringConcatInstructionDesugaring;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;

//
// Default and static interface method desugaring rewriter (note that lambda
// desugaring should have already processed the code before this rewriter).
//
// In short, during default and static interface method desugaring
// the following actions are performed:
//
//   (1) All static interface methods are moved into companion classes. All calls
//       to these methods are redirected appropriately. All references to these
//       methods from method handles are reported as errors.
//
// Companion class is a synthesized class (<interface-name>-CC) created to host
// static and former default interface methods (see below) from the interface.
//
//   (2) All default interface methods are made static and moved into companion
//       class.
//
//   (3) All calls to default interface methods made via 'super' are changed
//       to directly call appropriate static methods in companion classes.
//
//   (4) All other calls or references to default interface methods are not changed.
//
//   (5) For all program classes explicitly implementing interfaces we analyze the
//       set of default interface methods missing and add them, the created methods
//       forward the call to an appropriate method in interface companion class.
//
public final class InterfaceMethodRewriter implements CfInstructionDesugaring {

  private final AppView<?> appView;
  private final InternalOptions options;
  final DexItemFactory factory;
  private final InterfaceDesugaringSyntheticHelper helper;
  // The emulatedMethod set is there to avoid doing the emulated look-up too often.
  private final Set<DexString> emulatedMethods = Sets.newIdentityHashSet();

  // All forwarding methods and all throwing methods generated during desugaring.
  private final ProgramMethodSet synthesizedMethods = ProgramMethodSet.createConcurrent();

  // Caches default interface method info for already processed interfaces.
  private final Map<DexType, DefaultMethodsHelper.Collection> cache = new ConcurrentHashMap<>();

  // This is used to filter out double desugaring on backported methods.
  private final Set<CfInstructionDesugaring> precedingDesugarings;

  /** Defines a minor variation in desugaring. */
  public enum Flavor {
    /** Process all application resources. */
    IncludeAllResources,
    /** Process all but DEX application resources. */
    ExcludeDexResources
  }

  public InterfaceMethodRewriter(
      AppView<?> appView, Set<CfInstructionDesugaring> precedingDesugarings) {
    this.appView = appView;
    this.precedingDesugarings = precedingDesugarings;
    this.options = appView.options();
    this.factory = appView.dexItemFactory();
    this.helper = new InterfaceDesugaringSyntheticHelper(appView);
    initializeEmulatedInterfaceVariables();
  }

  public static void checkForAssumedLibraryTypes(AppInfo appInfo, InternalOptions options) {
    MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification =
        options.machineDesugaredLibrarySpecification;
    machineDesugaredLibrarySpecification
        .getEmulatedInterfaces()
        .forEach(
            (ei, descriptor) -> {
              registerType(appInfo, ei);
              registerType(appInfo, descriptor.getRewrittenType());
            });
    machineDesugaredLibrarySpecification
        .getCustomConversions()
        .forEach(
            (type, descriptor) -> {
              registerType(appInfo, type);
              registerType(appInfo, descriptor.getTo().getHolderType());
              registerType(appInfo, descriptor.getFrom().getHolderType());
            });
  }

  private static void registerType(AppInfo appInfo, DexType type) {
    appInfo.dexItemFactory().registerTypeNeededForDesugaring(type);
    DexClass clazz = appInfo.definitionFor(type);
    if (clazz != null && clazz.isLibraryClass() && clazz.isInterface()) {
      clazz.forEachMethod(
          m -> {
            if (m.isDefaultMethod()) {
              appInfo
                  .dexItemFactory()
                  .registerTypeNeededForDesugaring(m.getReference().proto.returnType);
              for (DexType param : m.getReference().proto.parameters.values) {
                appInfo.dexItemFactory().registerTypeNeededForDesugaring(param);
              }
            }
          });
    }
  }

  public Set<DexString> getEmulatedMethods() {
    return emulatedMethods;
  }

  private void initializeEmulatedInterfaceVariables() {
    Set<DexType> emulateLibraryInterface =
        options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().keySet();
    for (DexType interfaceType : emulateLibraryInterface) {
      DexClass emulatedInterfaceClass = appView.definitionFor(interfaceType);
      if (emulatedInterfaceClass != null) {
        for (DexEncodedMethod encodedMethod :
            emulatedInterfaceClass.methods(DexEncodedMethod::isDefaultMethod)) {
          emulatedMethods.add(encodedMethod.getReference().name);
        }
      }
    }
  }

  private boolean isAlreadyDesugared(CfInvoke invoke, ProgramMethod context) {
    return Iterables.any(
        precedingDesugarings, desugaring -> desugaring.needsDesugaring(invoke, context));
  }

  @Override
  public boolean hasPreciseNeedsDesugaring() {
    return false;
  }

  /**
   * If the method is not required to be desugared, scanning is used to upgrade when required the
   * class file version, as well as reporting missing type.
   */
  @Override
  public void scan(ProgramMethod context, CfInstructionDesugaringEventConsumer eventConsumer) {
    if (isSyntheticMethodThatShouldNotBeDoubleProcessed(context)) {
      leavingStaticInvokeToInterface(context);
      return;
    }
    CfCode code = context.getDefinition().getCode().asCfCode();
    for (CfInstruction instruction : code.getInstructions()) {
      if (instruction.isInvokeDynamic()
          && !LambdaInstructionDesugaring.isLambdaInvoke(instruction, context, appView)
          && !StringConcatInstructionDesugaring.isStringConcatInvoke(
              instruction, appView.dexItemFactory())) {
        reportInterfaceMethodHandleCallSite(instruction.asInvokeDynamic().getCallSite(), context);
      }
      computeDescription(instruction, context).scan();
    }
  }

  @Override
  public boolean needsDesugaring(CfInstruction instruction, ProgramMethod context) {
    if (isSyntheticMethodThatShouldNotBeDoubleProcessed(context)) {
      return false;
    }
    return computeDescription(instruction, context).needsDesugaring();
  }

  @Override
  public Collection<CfInstruction> desugarInstruction(
      CfInstruction instruction,
      FreshLocalProvider freshLocalProvider,
      LocalStackAllocator localStackAllocator,
      CfInstructionDesugaringEventConsumer eventConsumer,
      ProgramMethod context,
      MethodProcessingContext methodProcessingContext,
      CfInstructionDesugaringCollection desugaringCollection,
      DexItemFactory dexItemFactory) {
    assert !isSyntheticMethodThatShouldNotBeDoubleProcessed(context);
    return computeDescription(instruction, context)
        .desugarInstruction(
            freshLocalProvider,
            localStackAllocator,
            eventConsumer,
            context,
            methodProcessingContext,
            dexItemFactory);
  }

  private DesugarDescription computeDescription(CfInstruction instruction, ProgramMethod context) {
    // Interface desugaring is only interested in invokes.
    CfInvoke invoke = instruction.asInvoke();
    if (invoke == null) {
      return DesugarDescription.nothing();
    }
    // Don't desugar if the invoke is to be desugared by preceeding desugar tasks.
    if (isAlreadyDesugared(invoke, context)) {
      return DesugarDescription.nothing();
    }
    // There should never be any calls to interface initializers.
    if (invoke.isInvokeSpecial() && invoke.isInvokeConstructor(factory)) {
      return DesugarDescription.nothing();
    }
    // If the invoke is not an interface invoke, then there should generally not be any desugaring.
    // However, there are some cases where the insertion of forwarding methods can change behavior
    // so we need to identify them at the various call sites here.
    if (!invoke.isInterface()) {
      return computeNonInterfaceInvoke(invoke, context);
    }
    // If the target holder does not resolve we may want to issue diagnostics.
    DexClass holder = appView.definitionForHolder(invoke.getMethod(), context);
    if (holder == null) {
      if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
        // For virtual targets we should not report anything as any virtual dispatch just remains.
        return DesugarDescription.nothing();
      }
      // For static, private and special invokes, they may require desugaring and should warn.
      return DesugarDescription.builder()
          .addScanEffect(
              () -> {
                if (invoke.isInvokeStatic()) {
                  leavingStaticInvokeToInterface(context);
                }
                warnMissingType(context, invoke.getMethod().getHolderType());
              })
          .build();
    }
    // Continue with invoke type logic.
    if (invoke.isInvokeStatic()) {
      return computeInvokeStatic(holder, invoke, context);
    }
    if (invoke.isInvokeSpecial()) {
      return computeInvokeSpecial(holder, invoke, context);
    }
    if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
      return computeInvokeVirtualDispatch(holder, invoke, context);
    }
    return DesugarDescription.nothing();
  }

  private DesugarDescription computeNonInterfaceInvoke(CfInvoke invoke, ProgramMethod context) {
    assert !invoke.isInterface();
    // Emulated interface desugaring will rewrite non-interface invokes.
    if (invoke.isInvokeSpecial()) {
      DexClass clazz = appView.definitionForHolder(invoke.getMethod(), context);
      if (clazz == null) {
        return DesugarDescription.nothing();
      }
      return computeEmulatedInterfaceInvokeSpecial(clazz, invoke.getMethod(), context);
    }
    if (!invoke.isInvokeVirtual() && !invoke.isInvokeInterface()) {
      return DesugarDescription.nothing();
    }
    DesugarDescription description = computeEmulatedInterfaceVirtualDispatchOrNull(invoke);
    if (description != null) {
      return description;
    }
    // It may be the case that a virtual invoke resolves to a static method. In such a case, if
    // a default method could give rise to a forwarding method in the resolution path, the program
    // would change behavior from throwing ICCE to dispatching to the companion class method.
    AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
    MethodResolutionResult resolution =
        appInfo.resolveMethod(invoke.getMethod(), invoke.isInterface());
    if (!resolution.isSingleResolution()
        || !resolution.asSingleResolution().getResolvedMethod().isStatic()) {
      return DesugarDescription.nothing();
    }
    DexClass holder = appInfo.definitionFor(invoke.getMethod().getHolderType(), context);
    DexClassAndMethod target = appInfo.lookupMaximallySpecificMethod(holder, invoke.getMethod());
    if (target != null && target.isDefaultMethod()) {
      // Rewrite the invoke to a throw ICCE as the default method forward would otherwise hide the
      // static / virtual mismatch.
      return computeInvokeAsThrowRewrite(invoke, resolution.asSingleResolution(), context);
    }
    return DesugarDescription.nothing();
  }

  private DesugarDescription computeInvokeSpecial(
      DexClass holder, CfInvoke invoke, ProgramMethod context) {
    if (invoke.isInvokeSuper(context.getHolderType())) {
      return rewriteInvokeSuper(invoke, context);
    }
    return computeInvokeDirect(holder, invoke, context);
  }

  private DesugarDescription computeInvokeStatic(
      DexClass holder, CfInvoke invoke, ProgramMethod context) {
    if (!holder.isInterface()) {
      return DesugarDescription.builder()
          .addScanEffect(() -> leavingStaticInvokeToInterface(context))
          .build();
    }
    // TODO(b/199135051): This should not be needed. Targeted synthetics should be in place.
    if (appView.getSyntheticItems().isPendingSynthetic(invoke.getMethod().getHolderType())) {
      // We did not create this code yet, but it will not require rewriting.
      return DesugarDescription.nothing();
    }
    if (isNonDesugaredLibraryClass(holder)) {
      // NOTE: we intentionally don't desugar static calls into static interface
      // methods coming from android.jar since it is only possible in case v24+
      // version of android.jar is provided.
      //
      // We assume such calls are properly guarded by if-checks like
      //    'if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XYZ) { ... }'
      //
      // WARNING: This may result in incorrect code on older platforms!
      // Retarget call to an appropriate method of companion class.
      if (options.canLeaveStaticInterfaceMethodInvokes()) {
        // When leaving static interface method invokes upgrade the class file version.
        return DesugarDescription.builder()
            .addScanEffect(() -> leavingStaticInvokeToInterface(context))
            .build();
      }
      // On pre-L devices static calls to interface methods result in verifier
      // rejecting the whole class. We have to create special dispatch classes,
      // so the user class is not rejected because it make this call directly.
      // TODO(b/166247515): If this an incorrect invoke-static without the interface bit
      //  we end up "fixing" the code and remove and ICCE error.
      if (synthesizedMethods.contains(context)) {
        // When reprocessing the method generated below, the desugaring asserts this method
        // does not need any new desugaring, while the interface method rewriter tries
        // to outline again the invoke-static. Just do nothing instead.
        return DesugarDescription.nothing();
      }
      return DesugarDescription.builder()
          .setDesugarRewrite(
              (freshLocalProvider,
                  localStackAllocator,
                  eventConsumer,
                  context1,
                  methodProcessingContext,
                  dexItemFactory) -> {
                ProgramMethod newProgramMethod =
                    appView
                        .getSyntheticItems()
                        .createMethod(
                            kind -> kind.STATIC_INTERFACE_CALL,
                            methodProcessingContext.createUniqueContext(),
                            appView,
                            syntheticMethodBuilder ->
                                syntheticMethodBuilder
                                    .setProto(invoke.getMethod().getProto())
                                    .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
                                    .setCode(
                                        m ->
                                            ForwardMethodBuilder.builder(factory)
                                                .setStaticTarget(invoke.getMethod(), true)
                                                .setStaticSource(m)
                                                .build()));
                synthesizedMethods.add(newProgramMethod);
                eventConsumer.acceptInvokeStaticInterfaceOutliningMethod(
                    newProgramMethod, context1);
                // The synthetic dispatch class has static interface method invokes, so set
                // the class file version accordingly.
                leavingStaticInvokeToInterface(newProgramMethod);
                return getInvokeStaticInstructions(newProgramMethod.getReference());
              })
          .build();
    }

    SingleResolutionResult resolutionResult =
        appView
            .appInfoForDesugaring()
            .resolveMethodOnInterface(holder, invoke.getMethod())
            .asSingleResolution();
    if (holder.isInterface() && shouldRewriteToInvokeToThrow(resolutionResult, true)) {
      return computeInvokeAsThrowRewrite(invoke, resolutionResult, context);
    }

    assert resolutionResult != null;
    assert resolutionResult.getResolvedMethod().isStatic();
    DexClassAndMethod method = resolutionResult.getResolutionPair();
    return DesugarDescription.builder()
        .setDesugarRewrite(
            (freshLocalProvider,
                localStackAllocator,
                eventConsumer,
                context12,
                methodProcessingContext,
                dexItemFactory) -> {
              DexClassAndMethod companionMethod =
                  helper.ensureStaticAsMethodOfCompanionClassStub(method, eventConsumer);
              return getInvokeStaticInstructions(companionMethod.getReference());
            })
        .build();
  }

  private DesugarDescription computeInvokeVirtualDispatch(
      DexClass holder, CfInvoke invoke, ProgramMethod context) {
    AppInfoWithClassHierarchy appInfoForDesugaring = appView.appInfoForDesugaring();
    SingleResolutionResult resolution =
        appInfoForDesugaring
            .resolveMethod(invoke.getMethod(), invoke.isInterface())
            .asSingleResolution();
    if (resolution != null
        && resolution.getResolvedMethod().isPrivate()
        && resolution.isAccessibleFrom(context, appInfoForDesugaring).isTrue()) {
      // TODO(b/198267586): What about the private in-accessible case?
      return computeInvokeDirect(holder, invoke, context);
    }
    if (resolution != null && resolution.getResolvedMethod().isStatic()) {
      return computeInvokeAsThrowRewrite(invoke, resolution, context);
    }
    DesugarDescription description = computeEmulatedInterfaceVirtualDispatchOrNull(invoke);
    return description != null ? description : DesugarDescription.nothing();
  }

  private DesugarDescription computeEmulatedInterfaceVirtualDispatchOrNull(CfInvoke invoke) {
    MethodResolutionResult resolutionResult =
        appView.appInfoForDesugaring().resolveMethod(invoke.getMethod(), invoke.isInterface());
    DerivedMethod emulatedDispatchMethod =
        helper.computeEmulatedInterfaceDispatchMethod(resolutionResult);
    if (emulatedDispatchMethod == null) {
      return null;
    }
    return DesugarDescription.builder()
        .setDesugarRewrite(
            (freshLocalProvider,
                localStackAllocator,
                eventConsumer,
                context1,
                methodProcessingContext,
                dexItemFactory) ->
                getInvokeStaticInstructions(
                    helper
                        .ensureEmulatedInterfaceDispatchMethod(
                            emulatedDispatchMethod, eventConsumer)
                        .getReference()))
        .build();
  }

  private DesugarDescription computeInvokeDirect(
      DexClass clazz, CfInvoke invoke, ProgramMethod context) {
    DexMethod invokedMethod = invoke.getMethod();
    if (!clazz.isInterface()) {
      return DesugarDescription.nothing();
    }

    if (clazz.isLibraryClass()) {
      throw new CompilationError(
          "Unexpected call to a private method "
              + "defined in library class "
              + clazz.toSourceString(),
          getMethodOrigin(context.getReference()));
    }

    MethodResolutionResult resolution =
        appView.appInfoForDesugaring().resolveMethod(invokedMethod, invoke.isInterface());
    if (resolution.isFailedResolution()) {
      return computeInvokeAsThrowRewrite(invoke, null, context);
    }

    SingleResolutionResult singleResolution = resolution.asSingleResolution();
    if (singleResolution == null) {
      return DesugarDescription.nothing();
    }

    DexClassAndMethod directTarget = clazz.lookupClassMethod(invokedMethod);
    if (directTarget != null) {
      // TODO(b/199135051): Replace this by use of the resolution result.
      assert directTarget.getDefinition() == singleResolution.getResolutionPair().getDefinition();
      return DesugarDescription.builder()
          .setDesugarRewrite(
              (freshLocalProvider,
                  localStackAllocator,
                  eventConsumer,
                  context1,
                  methodProcessingContext,
                  dexItemFactory) -> {
                // This can be a private instance method call. Note that the referenced
                // method is expected to be in the current class since it is private, but desugaring
                // may move some methods or their code into other classes.
                DexClassAndMethod companionMethodDefinition = null;
                DexMethod companionMethod;
                if (directTarget.getDefinition().isPrivateMethod()) {
                  if (directTarget.isProgramMethod()) {
                    companionMethodDefinition =
                        helper.ensurePrivateAsMethodOfProgramCompanionClassStub(
                            directTarget.asProgramMethod());
                    companionMethod = companionMethodDefinition.getReference();
                  } else {
                    // TODO(b/200938617): Why does this not create a stub on the class path?
                    companionMethod = helper.privateAsMethodOfCompanionClass(directTarget);
                  }
                } else {
                  companionMethodDefinition =
                      helper.ensureDefaultAsMethodOfCompanionClassStub(directTarget);
                  companionMethod = companionMethodDefinition.getReference();
                }
                if (companionMethodDefinition != null) {
                  acceptCompanionMethod(directTarget, companionMethodDefinition, eventConsumer);
                }
                return getInvokeStaticInstructions(companionMethod);
              })
          .build();
    } else {
      // The method can be a default method in the interface hierarchy.
      DexClassAndMethod virtualTarget =
          appView.appInfoForDesugaring().lookupMaximallySpecificMethod(clazz, invokedMethod);
      if (virtualTarget != null) {
        // TODO(b/199135051): Replace this by use of the resolution result.
        assert virtualTarget.getDefinition()
            == singleResolution.getResolutionPair().getDefinition();
        return DesugarDescription.builder()
            .setDesugarRewrite(
                (freshLocalProvider,
                    localStackAllocator,
                    eventConsumer,
                    context12,
                    methodProcessingContext,
                    dexItemFactory) -> {
                  // This is a invoke-direct call to a virtual method.
                  DexClassAndMethod companionMethod =
                      helper.ensureDefaultAsMethodOfCompanionClassStub(virtualTarget);
                  acceptCompanionMethod(virtualTarget, companionMethod, eventConsumer);
                  return getInvokeStaticInstructions(companionMethod.getReference());
                })
            .build();
      } else {
        // The below assert is here because a well-type program should have a target, but we
        // cannot throw a compilation error, since we have no knowledge about the input.
        assert false;
      }
    }
    return DesugarDescription.nothing();
  }

  private DesugarDescription computeInvokeAsThrowRewrite(
      CfInvoke invoke, SingleResolutionResult resolution, ProgramMethod context) {
    assert !isAlreadyDesugared(invoke, context);
    return AlwaysThrowingInstructionDesugaring.computeInvokeAsThrowRewrite(
        appView, invoke, resolution);
  }

  private Collection<CfInstruction> getInvokeStaticInstructions(DexMethod newTarget) {
    return Collections.singletonList(
        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESTATIC, newTarget, false));
  }

  private void leavingStaticInvokeToInterface(ProgramMethod method) {
    // When leaving static interface method invokes possibly upgrade the class file
    // version, but don't go above the initial class file version. If the input was
    // 1.7 or below, this will make a VerificationError on the input a VerificationError
    // on the output. If the input was 1.8 or above the runtime behaviour (potential ICCE)
    // will remain the same.
    if (method.getHolder().hasClassFileVersion()) {
      method
          .getDefinition()
          .upgradeClassFileVersion(
              Ordered.min(CfVersion.V1_8, method.getHolder().getInitialClassFileVersion()));
    } else {
      method.getDefinition().upgradeClassFileVersion(CfVersion.V1_8);
    }
  }

  private boolean isSyntheticMethodThatShouldNotBeDoubleProcessed(ProgramMethod method) {
    return appView.getSyntheticItems().isSyntheticMethodThatShouldNotBeDoubleProcessed(method);
  }

  private void reportInterfaceMethodHandleCallSite(DexCallSite callSite, ProgramMethod context) {
    // Check that static interface methods are not referenced from invoke-custom instructions via
    // method handles.
    reportStaticInterfaceMethodHandle(context, callSite.bootstrapMethod);
    for (DexValue arg : callSite.bootstrapArgs) {
      if (arg.isDexValueMethodHandle()) {
        reportStaticInterfaceMethodHandle(context, arg.asDexValueMethodHandle().value);
      }
    }
  }

  private void acceptCompanionMethod(
      DexClassAndMethod method,
      DexClassAndMethod companion,
      InterfaceMethodDesugaringEventConsumer eventConsumer) {
    assert method.isProgramMethod() == companion.isProgramMethod();
    if (method.isProgramMethod()) {
      eventConsumer.acceptCompanionMethod(method.asProgramMethod(), companion.asProgramMethod());
    }
  }

  private DesugarDescription rewriteInvokeSuper(CfInvoke invoke, ProgramMethod context) {
    DexMethod invokedMethod = invoke.getMethod();
    DexClass clazz = appView.definitionFor(invokedMethod.holder, context);
    if (clazz == null) {
      // NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
      // exception but we can not report it as error since it can also be the intended
      // behavior.
      return DesugarDescription.builder()
          .addScanEffect(() -> warnMissingType(context, invokedMethod.holder))
          .build();
    }

    SingleResolutionResult resolutionResult =
        appView.appInfoForDesugaring().resolveMethodOn(clazz, invokedMethod).asSingleResolution();
    if (clazz.isInterface() && shouldRewriteToInvokeToThrow(resolutionResult, false)) {
      return computeInvokeAsThrowRewrite(invoke, resolutionResult, context);
    }

    if (clazz.isInterface() && !clazz.isLibraryClass()) {
      // NOTE: we intentionally don't desugar super calls into interface methods
      // coming from android.jar since it is only possible in case v24+ version
      // of android.jar is provided.
      //
      // We assume such calls are properly guarded by if-checks like
      //    'if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XYZ) { ... }'
      //
      // WARNING: This may result in incorrect code on older platforms!
      // Retarget call to an appropriate method of companion class.
      if (resolutionResult.getResolvedMethod().isPrivateMethod()) {
        if (resolutionResult.isAccessibleFrom(context, appView.appInfoForDesugaring()).isFalse()) {
          // TODO(b/145775365): This should throw IAE.
          return computeInvokeAsThrowRewrite(invoke, null, context);
        }
        return DesugarDescription.builder()
            .setDesugarRewrite(
                (freshLocalProvider,
                    localStackAllocator,
                    eventConsumer,
                    context1,
                    methodProcessingContext,
                    dexItemFactory) -> {
                  DexClassAndMethod method = resolutionResult.getResolutionPair();
                  DexMethod companionMethod;
                  if (method.isProgramMethod()) {
                    ProgramMethod companionMethodDefinition =
                        helper.ensurePrivateAsMethodOfProgramCompanionClassStub(
                            method.asProgramMethod());
                    companionMethod = companionMethodDefinition.getReference();
                    eventConsumer.acceptCompanionMethod(
                        method.asProgramMethod(), companionMethodDefinition);
                  } else {
                    companionMethod = helper.privateAsMethodOfCompanionClass(method);
                  }
                  return getInvokeStaticInstructions(companionMethod);
                })
            .build();
      } else {
        return DesugarDescription.builder()
            .setDesugarRewrite(
                (freshLocalProvider,
                    localStackAllocator,
                    eventConsumer,
                    context12,
                    methodProcessingContext,
                    dexItemFactory) -> {
                  DexClassAndMethod method = resolutionResult.getResolutionPair();
                  // TODO(b/199135051): Why do this amend routine. We have done resolution, so would
                  //  that not be the correct target!? I think this is just legacy from before
                  //  resolution was implemented in full.
                  DexMethod amendedMethod =
                      amendDefaultMethod(context12.getHolder(), invokedMethod);
                  // TODO(b/234711664): The assertion below is disabled on this release branch.
                  assert true || method.getReference() == amendedMethod;
                  DexClassAndMethod companionMethod =
                      helper.ensureDefaultAsMethodOfCompanionClassStub(method);
                  acceptCompanionMethod(method, companionMethod, eventConsumer);
                  return getInvokeStaticInstructions(companionMethod.getReference());
                })
            .build();
      }
    }

    return computeEmulatedInterfaceInvokeSpecial(clazz, invokedMethod, context);
  }

  private DesugarDescription computeEmulatedInterfaceInvokeSpecial(
      DexClass clazz, DexMethod invokedMethod, ProgramMethod context) {
    DexClassAndMethod superTarget =
        appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, context);
    if (clazz.isInterface()
        && clazz.isLibraryClass()
        && helper.isInDesugaredLibrary(clazz)
        && !helper.isEmulatedInterface(clazz.type)) {
      if (superTarget != null && superTarget.getDefinition().isDefaultMethod()) {
        DexClass holder = superTarget.getHolder();
        if (holder.isLibraryClass() && holder.isInterface()) {
          return DesugarDescription.builder()
              .setDesugarRewrite(
                  (freshLocalProvider,
                      localStackAllocator,
                      eventConsumer,
                      context13,
                      methodProcessingContext,
                      dexItemFactory) -> {
                    DexClassAndMethod companionTarget =
                        helper.ensureDefaultAsMethodOfCompanionClassStub(superTarget);
                    acceptCompanionMethod(superTarget, companionTarget, eventConsumer);
                    return getInvokeStaticInstructions(companionTarget.getReference());
                  })
              .build();
        }
      }
    }
    // That invoke super may not resolve since the super method may not be present
    // since it's in the emulated interface. We need to force resolution. If it resolves
    // to a library method, then it needs to be rewritten.
    // If it resolves to a program overrides, the invoke-super can remain.
    DerivedMethod forwardingMethod =
        helper.computeEmulatedInterfaceForwardingMethod(clazz, superTarget);
    if (forwardingMethod == null) {
      return DesugarDescription.nothing();
    }
    return DesugarDescription.builder()
        .setDesugarRewrite(
            (freshLocalProvider,
                localStackAllocator,
                eventConsumer,
                context14,
                methodProcessingContext,
                dexItemFactory) ->
                getInvokeStaticInstructions(
                    helper.ensureEmulatedInterfaceForwardingMethod(forwardingMethod)))
        .build();
  }

  private boolean shouldRewriteToInvokeToThrow(
      SingleResolutionResult resolutionResult, boolean isInvokeStatic) {
    return resolutionResult == null
        || resolutionResult.getResolvedMethod().isStatic() != isInvokeStatic;
  }

  private boolean isNonDesugaredLibraryClass(DexClass clazz) {
    return clazz.isLibraryClass() && !helper.isInDesugaredLibrary(clazz);
  }

  private void reportStaticInterfaceMethodHandle(ProgramMethod context, DexMethodHandle handle) {
    if (handle.type.isInvokeStatic()) {
      DexClass holderClass = appView.definitionFor(handle.asMethod().holder);
      // NOTE: If the class definition is missing we can't check. Let it be handled as any other
      // missing call target.
      if (holderClass == null) {
        warnMissingType(context, handle.asMethod().holder);
      } else if (holderClass.isInterface()) {
        throw new Unimplemented(
            "Desugaring of static interface method handle in `"
                + context.toSourceString()
                + "` is not yet supported.");
      }
    }
  }

  // It is possible that referenced method actually points to an interface which does
  // not define this default methods, but inherits it. We are making our best effort
  // to find an appropriate method, but still use the original one in case we fail.
  private DexMethod amendDefaultMethod(DexClass classToDesugar, DexMethod method) {
    DexMethod singleCandidate =
        getOrCreateInterfaceInfo(classToDesugar, classToDesugar, method.holder)
            .getSingleCandidate(method);
    return singleCandidate != null ? singleCandidate : method;
  }

  public InterfaceMethodProcessorFacade getPostProcessingDesugaringD8(
      Flavor flavour, InterfaceProcessor interfaceProcessor) {
    return new InterfaceMethodProcessorFacade(appView, flavour, m -> true, interfaceProcessor);
  }

  public InterfaceMethodProcessorFacade getPostProcessingDesugaringR8(
      Flavor flavour,
      Predicate<ProgramMethod> isLiveMethod,
      InterfaceProcessor interfaceProcessor) {
    return new InterfaceMethodProcessorFacade(appView, flavour, isLiveMethod, interfaceProcessor);
  }

  private Origin getMethodOrigin(DexMethod method) {
    DexType holder = method.holder;
    if (InterfaceDesugaringSyntheticHelper.isCompanionClassType(holder)) {
      holder = helper.getInterfaceClassType(holder);
    }
    DexClass clazz = appView.definitionFor(holder);
    return clazz == null ? Origin.unknown() : clazz.getOrigin();
  }

  final DefaultMethodsHelper.Collection getOrCreateInterfaceInfo(
      DexClass classToDesugar, DexClass implementing, DexType iface) {
    DefaultMethodsHelper.Collection collection = cache.get(iface);
    if (collection != null) {
      return collection;
    }
    collection = createInterfaceInfo(classToDesugar, implementing, iface);
    DefaultMethodsHelper.Collection existing = cache.putIfAbsent(iface, collection);
    return existing != null ? existing : collection;
  }

  private DefaultMethodsHelper.Collection createInterfaceInfo(
      DexClass classToDesugar, DexClass implementing, DexType iface) {
    DefaultMethodsHelper helper = new DefaultMethodsHelper();
    DexClass definedInterface = appView.definitionFor(iface);
    if (definedInterface == null) {
      this.helper.warnMissingInterface(classToDesugar, implementing, iface);
      return helper.wrapInCollection();
    }
    if (!definedInterface.isInterface()) {
      throw new CompilationError(
          "Type "
              + iface.toSourceString()
              + " is referenced as an interface from `"
              + implementing.toString()
              + "`.");
    }

    if (isNonDesugaredLibraryClass(definedInterface)) {
      // NOTE: We intentionally ignore all candidates coming from android.jar
      // since it is only possible in case v24+ version of android.jar is provided.
      // WARNING: This may result in incorrect code if something else than Android bootclasspath
      // classes are given as libraries!
      return helper.wrapInCollection();
    }

    // At this point we likely have a non-library type that may depend on default method information
    // from its interfaces and the dependency should be reported.
    if (implementing.isProgramClass() && !definedInterface.isLibraryClass()) {
      reportDependencyEdge(implementing.asProgramClass(), definedInterface, appView.appInfo());
    }

    // Merge information from all superinterfaces.
    for (DexType superinterface : definedInterface.interfaces.values) {
      helper.merge(getOrCreateInterfaceInfo(classToDesugar, definedInterface, superinterface));
    }

    // Hide by virtual methods of this interface.
    for (DexEncodedMethod virtual : definedInterface.virtualMethods()) {
      helper.hideMatches(virtual.getReference());
    }

    // Add all default methods of this interface.
    for (DexEncodedMethod encoded : definedInterface.virtualMethods()) {
      if (this.helper.isCompatibleDefaultMethod(encoded)) {
        helper.addDefaultMethod(encoded);
      }
    }

    return helper.wrapInCollection();
  }

  private void warnMissingType(ProgramMethod context, DexType missing) {
    // Companion/Emulated interface/Conversion classes for desugared library won't be missing,
    // they are in the desugared library.
    if (helper.shouldIgnoreFromReports(missing)) {
      return;
    }
    DexMethod method = appView.graphLens().getOriginalMethodSignature(context.getReference());
    Origin origin = getMethodOrigin(method);
    MethodPosition position = new MethodPosition(method.asMethodReference());
    options.warningMissingTypeForDesugar(origin, position, missing, method);
  }

  public static void reportDependencyEdge(
      DexClass dependent, DexClass dependency, AppInfo appInfo) {
    assert !dependent.isLibraryClass();
    assert !dependency.isLibraryClass();
    DesugarGraphConsumer consumer = appInfo.app().options.desugarGraphConsumer;
    if (consumer != null) {
      Origin dependencyOrigin = dependency.getOrigin();
      java.util.Collection<DexType> dependents =
          appInfo.getSyntheticItems().getSynthesizingContextTypes(dependent.getType());
      if (dependents.isEmpty()) {
        reportDependencyEdge(consumer, dependencyOrigin, dependent);
      } else {
        for (DexType type : dependents) {
          reportDependencyEdge(consumer, dependencyOrigin, appInfo.definitionFor(type));
        }
      }
    }
  }

  private static void reportDependencyEdge(
      DesugarGraphConsumer consumer, Origin dependencyOrigin, DexClass clazz) {
    Origin dependentOrigin = clazz.getOrigin();
    if (dependentOrigin != dependencyOrigin) {
      consumer.accept(dependentOrigin, dependencyOrigin);
    }
  }
}
