// 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.synthesis;

import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;

import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.contexts.CompilationContext.UniqueContext;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassResolutionResult;
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.MethodCollection;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.synthesis.SyntheticFinalization.Result;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.objectweb.asm.ClassWriter;

public class SyntheticItems implements SyntheticDefinitionsProvider {

  static final int INVALID_ID_AFTER_SYNTHETIC_FINALIZATION = -1;

  /** Globally incremented id for the next internal synthetic class. */
  private int nextSyntheticId;

  /** Collection of pending items. */
  private static class PendingSynthetics {

    /** Thread safe collection of synthetic items not yet committed to the application. */
    private final ConcurrentHashMap<DexType, SyntheticDefinition<?, ?, ?>> nonLegacyDefinitions =
        new ConcurrentHashMap<>();

    boolean isEmpty() {
      return nonLegacyDefinitions.isEmpty();
    }

    boolean containsType(DexType type) {
      return nonLegacyDefinitions.containsKey(type);
    }

    boolean containsTypeOfKind(DexType type, SyntheticKind kind) {
      SyntheticDefinition<?, ?, ?> definition = nonLegacyDefinitions.get(type);
      return definition != null && definition.getKind() == kind;
    }

    boolean verifyNotRewritten(NonIdentityGraphLens lens) {
      assert nonLegacyDefinitions.keySet().equals(lens.rewriteTypes(nonLegacyDefinitions.keySet()));
      return true;
    }

    Collection<DexProgramClass> getAllProgramClasses() {
      List<DexProgramClass> allPending = new ArrayList<>(nonLegacyDefinitions.size());
      for (SyntheticDefinition<?, ?, ?> item : nonLegacyDefinitions.values()) {
        if (item.isProgramDefinition()) {
          allPending.add(item.asProgramDefinition().getHolder());
        }
      }
      return Collections.unmodifiableList(allPending);
    }
  }

  private final CommittedSyntheticsCollection committed;

  private final PendingSynthetics pending = new PendingSynthetics();

  // Empty collection for use only in tests and utilities.
  public static SyntheticItems empty() {
    return new SyntheticItems(-1, CommittedSyntheticsCollection.empty());
  }

  // Only for use from initial AppInfo/AppInfoWithClassHierarchy create functions. */
  public static CommittedItems createInitialSyntheticItems(DexApplication application) {
    return new CommittedItems(
        0, application, CommittedSyntheticsCollection.empty(), ImmutableList.of());
  }

  // Only for conversion to a mutable synthetic items collection.
  SyntheticItems(CommittedItems commit) {
    this(commit.nextSyntheticId, commit.committed);
  }

  private SyntheticItems(int nextSyntheticId, CommittedSyntheticsCollection committed) {
    this.nextSyntheticId = nextSyntheticId;
    this.committed = committed;
  }

  public static void collectSyntheticInputs(AppView<?> appView) {
    // Collecting synthetic items must be the very first task after application build.
    SyntheticItems synthetics = appView.getSyntheticItems();
    assert synthetics.nextSyntheticId == 0;
    assert synthetics.committed.isEmpty();
    assert synthetics.pending.isEmpty();
    CommittedSyntheticsCollection.Builder builder = synthetics.committed.builder();
    // TODO(b/158159959): Consider populating the input synthetics when identified.
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      SyntheticMarker marker = SyntheticMarker.stripMarkerFromClass(clazz, appView);
      if (!appView.options().intermediate && marker.getContext() != null) {
        DexClass contextClass =
            appView
                .appInfo()
                .definitionForWithoutExistenceAssert(
                    marker.getContext().getSynthesizingContextType());
        if (contextClass == null || contextClass.isNotProgramClass()) {
          appView
              .reporter()
              .error(
                  new StringDiagnostic(
                      "Attempt at compiling intermediate artifact without its context",
                      clazz.getOrigin()));
        }
      }
      if (marker.isSyntheticMethods()) {
        clazz.forEachProgramMethod(
            // TODO(b/158159959): Support having multiple methods per class.
            method ->
                builder.addNonLegacyMethod(
                    new SyntheticMethodDefinition(marker.getKind(), marker.getContext(), method)));
      } else if (marker.isSyntheticClass()) {
        builder.addNonLegacyClass(
            new SyntheticProgramClassDefinition(marker.getKind(), marker.getContext(), clazz));
      }
    }
    CommittedSyntheticsCollection committed = builder.collectSyntheticInputs().build();
    if (committed.isEmpty()) {
      return;
    }
    CommittedItems commit =
        new CommittedItems(
            synthetics.nextSyntheticId, appView.appInfo().app(), committed, ImmutableList.of());
    if (appView.appInfo().hasClassHierarchy()) {
      appView
          .withClassHierarchy()
          .setAppInfo(appView.appInfo().withClassHierarchy().rebuildWithClassHierarchy(commit));
    } else {
      appView
          .withoutClassHierarchy()
          .setAppInfo(new AppInfo(commit, appView.appInfo().getMainDexInfo()));
    }
  }

  // Predicates and accessors.

  @Override
  public ClassResolutionResult definitionFor(
      DexType type, Function<DexType, ClassResolutionResult> baseDefinitionFor) {
    DexClass clazz = null;
    SyntheticKind kind = null;
    SyntheticDefinition<?, ?, ?> item = pending.nonLegacyDefinitions.get(type);
    if (item != null) {
      clazz = item.getHolder();
      kind = item.getKind();
      assert clazz.isProgramClass() == item.isProgramDefinition();
      assert clazz.isClasspathClass() == item.isClasspathDefinition();
    }
    if (clazz != null) {
      assert kind != null;
      assert !baseDefinitionFor.apply(type).hasClassResolutionResult()
              || kind.mayOverridesNonProgramType
          : "Pending synthetic definition also present in the active program: " + type;
      return clazz;
    }
    return baseDefinitionFor.apply(type);
  }

  public boolean isFinalized() {
    return nextSyntheticId == INVALID_ID_AFTER_SYNTHETIC_FINALIZATION;
  }

  public boolean hasPendingSyntheticClasses() {
    return !pending.isEmpty();
  }

  public Collection<DexProgramClass> getPendingSyntheticClasses() {
    return pending.getAllProgramClasses();
  }

  public boolean isCommittedSynthetic(DexType type) {
    return committed.containsType(type);
  }

  private boolean isNonLegacyCommittedSynthetic(DexType type) {
    return committed.containsNonLegacyType(type);
  }

  public boolean isPendingSynthetic(DexType type) {
    return pending.containsType(type);
  }

  private boolean isNonLegacyPendingSynthetic(DexType type) {
    return pending.nonLegacyDefinitions.containsKey(type);
  }

  public boolean isNonLegacySynthetic(DexProgramClass clazz) {
    return isNonLegacySynthetic(clazz.type);
  }

  public boolean isNonLegacySynthetic(DexType type) {
    return isNonLegacyCommittedSynthetic(type) || isNonLegacyPendingSynthetic(type);
  }

  public boolean isEligibleForClassMerging(DexProgramClass clazz, HorizontalClassMerger.Mode mode) {
    assert isSyntheticClass(clazz);
    return mode.isFinal() || isSyntheticLambda(clazz);
  }

  private boolean isSyntheticLambda(DexProgramClass clazz) {
    if (!isNonLegacySynthetic(clazz)) {
      return false;
    }
    Iterable<SyntheticReference<?, ?, ?>> references = committed.getNonLegacyItems(clazz.getType());
    if (!Iterables.isEmpty(references)) {
      assert Iterables.size(references) == 1;
      return references.iterator().next().getKind() == SyntheticKind.LAMBDA;
    }
    SyntheticDefinition<?, ?, ?> definition = pending.nonLegacyDefinitions.get(clazz.getType());
    if (definition != null) {
      return definition.getKind() == SyntheticKind.LAMBDA;
    }
    assert false;
    return false;
  }

  public boolean isSubjectToKeepRules(DexProgramClass clazz) {
    assert isSyntheticClass(clazz);
    return isSyntheticInput(clazz);
  }

  public boolean isSyntheticClass(DexType type) {
    return isNonLegacySynthetic(type);
  }

  public boolean isSyntheticClass(DexProgramClass clazz) {
    return isSyntheticClass(clazz.type);
  }

  public boolean isSyntheticOfKind(DexType type, SyntheticKind kind) {
    return pending.containsTypeOfKind(type, kind) || committed.containsTypeOfKind(type, kind);
  }

  boolean isSyntheticInput(DexProgramClass clazz) {
    return committed.containsSyntheticInput(clazz.getType());
  }

  public FeatureSplit getContextualFeatureSplit(
      DexType type, ClassToFeatureSplitMap classToFeatureSplitMap) {
    if (isSyntheticOfKind(type, SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS)) {
      // Use the startup base if there is one, such that we don't merge non-startup classes with the
      // shared utility class in case it is used during startup. The use of base startup allows for
      // merging startup classes with the shared utility class, however, which could be bad for
      // startup if the shared utility class is not used during startup.
      return classToFeatureSplitMap.getBaseStartup();
    }
    List<SynthesizingContext> contexts = getSynthesizingContexts(type);
    if (contexts.isEmpty()) {
      return null;
    }
    assert verifyAllHaveSameFeature(contexts, SynthesizingContext::getFeatureSplit);
    return contexts.get(0).getFeatureSplit();
  }

  private static <T> boolean verifyAllHaveSameFeature(
      List<T> items, Function<T, FeatureSplit> getter) {
    assert !items.isEmpty();
    FeatureSplit featureSplit = getter.apply(items.get(0));
    for (int i = 1; i < items.size(); i++) {
      assert featureSplit == getter.apply(items.get(i));
    }
    return true;
  }

  private void forEachSynthesizingContext(DexType type, Consumer<SynthesizingContext> consumer) {
    for (SyntheticReference<?, ?, ?> reference : committed.getNonLegacyItems(type)) {
      consumer.accept(reference.getContext());
    }
    SyntheticDefinition<?, ?, ?> definition = pending.nonLegacyDefinitions.get(type);
    if (definition != null) {
      consumer.accept(definition.getContext());
    }
  }

  private List<SynthesizingContext> getSynthesizingContexts(DexType type) {
    return ListUtils.newImmutableList(builder -> forEachSynthesizingContext(type, builder));
  }

  public Collection<DexType> getSynthesizingContextTypes(DexType type) {
    ImmutableList.Builder<DexType> builder = ImmutableList.builder();
    forEachSynthesizingContext(
        type, synthesizingContext -> builder.add(synthesizingContext.getSynthesizingContextType()));
    return builder.build();
  }

  // TODO(b/180091213): Implement this and remove client provided the oracle.
  public Set<DexReference> getSynthesizingContextReferences(
      DexProgramClass clazz, SynthesizingContextOracle oracle) {
    assert isSyntheticClass(clazz);
    return oracle.getSynthesizingContexts(clazz);
  }

  public interface SynthesizingContextOracle {

    Set<DexReference> getSynthesizingContexts(DexProgramClass clazz);
  }

  public boolean isSyntheticMethodThatShouldNotBeDoubleProcessed(ProgramMethod method) {
    for (SyntheticMethodReference reference :
        committed
            .getNonLegacyMethods()
            .getOrDefault(method.getHolderType(), Collections.emptyList())) {
      if (reference.getKind() == SyntheticKind.STATIC_INTERFACE_CALL) {
        return true;
      }
    }
    SyntheticDefinition<?, ?, ?> definition =
        pending.nonLegacyDefinitions.get(method.getHolderType());
    if (definition != null) {
      return definition.getKind() == SyntheticKind.STATIC_INTERFACE_CALL;
    }
    return false;
  }

  // The compiler should not inspect the kind of a synthetic, so this provided only as a assertion
  // utility.
  public boolean verifySyntheticLambdaProperty(
      DexProgramClass clazz,
      Predicate<DexProgramClass> ifIsLambda,
      Predicate<DexProgramClass> ifNotLambda) {
    Iterable<SyntheticReference<?, ?, ?>> references = committed.getNonLegacyItems(clazz.getType());
    SyntheticDefinition<?, ?, ?> definition = pending.nonLegacyDefinitions.get(clazz.getType());
    if (definition != null) {
      references = Iterables.concat(references, IterableUtils.singleton(definition.toReference()));
    }
    if (Iterables.any(references, reference -> reference.getKind() == SyntheticKind.LAMBDA)) {
      assert ifIsLambda.test(clazz);
    } else {
      assert ifNotLambda.test(clazz);
    }
    return true;
  }

  private SynthesizingContext getSynthesizingContext(
      ProgramDefinition context, AppView<?> appView) {
    return getSynthesizingContext(
        context, appView.appInfoForDesugaring().getClassToFeatureSplitMap());
  }

  /** Used to find the synthesizing context for a new synthetic that is about to be created. */
  private SynthesizingContext getSynthesizingContext(
      ProgramDefinition context, ClassToFeatureSplitMap featureSplits) {
    DexType contextType = context.getContextType();
    SyntheticDefinition<?, ?, ?> existingDefinition = pending.nonLegacyDefinitions.get(contextType);
    if (existingDefinition != null) {
      return existingDefinition.getContext();
    }
    Iterable<SyntheticReference<?, ?, ?>> existingReferences =
        committed.getNonLegacyItems(contextType);
    if (!Iterables.isEmpty(existingReferences)) {
      // Use a deterministic synthesizing context from the set of contexts.
      return IterableUtils.min(
              existingReferences,
              (existingReference, other) ->
                  existingReference.getReference().compareTo(other.getReference()))
          .getContext();
    }
    // This context is not nested in an existing synthetic context so create a new "leaf" context.
    FeatureSplit featureSplit = featureSplits.getFeatureSplit(context, this);
    return SynthesizingContext.fromNonSyntheticInputContext(context, featureSplit);
  }

  public DexProgramClass addSyntheticClassWithLibraryContext(
      AppView<?> appView,
      DexLibraryClass context,
      SyntheticKind syntheticKind,
      DexType type,
      Consumer<SyntheticProgramClassBuilder> programClassBuilderConsumer) {
    SynthesizingContext synthesizingContext =
        SynthesizingContext.fromNonSyntheticInputContext(context);
    SyntheticProgramClassBuilder syntheticProgramClassBuilder =
        new SyntheticProgramClassBuilder(
                type, syntheticKind, synthesizingContext, appView.dexItemFactory())
            .setUseSortedMethodBacking(true);
    programClassBuilderConsumer.accept(syntheticProgramClassBuilder);
    DexProgramClass newSyntheticClass = syntheticProgramClassBuilder.build();
    addPendingDefinition(
        new SyntheticProgramClassDefinition(syntheticKind, synthesizingContext, newSyntheticClass));
    return newSyntheticClass;
  }

  // Addition and creation of synthetic items.

  private DexProgramClass internalEnsureFixedProgramClass(
      SyntheticKind kind,
      Consumer<SyntheticProgramClassBuilder> classConsumer,
      Consumer<DexProgramClass> onCreationConsumer,
      SynthesizingContext outerContext,
      AppView<?> appView) {
    Function<SynthesizingContext, DexType> contextToType =
        c -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
    DexType type = contextToType.apply(outerContext);
    // Fast path is that the synthetic is already present. If so it must be a program class.
    DexClass dexClass = appView.definitionFor(type);
    if (dexClass != null) {
      assert dexClass.isProgramClass();
      return dexClass.asProgramClass();
    }
    // Slow path creates the class using the context to make it thread safe.
    synchronized (type) {
      // Recheck if it is present now the lock is held.
      dexClass = appView.definitionFor(type);
      if (dexClass != null) {
        if (!dexClass.isProgramClass()) {
          errorOnInvalidSyntheticEnsure(dexClass, "program", appView);
        }
        return dexClass.asProgramClass();
      }
      assert !isSyntheticClass(type);
      DexProgramClass dexProgramClass =
          internalCreateProgramClass(
              kind,
              syntheticProgramClassBuilder -> {
                syntheticProgramClassBuilder.setUseSortedMethodBacking(true);
                classConsumer.accept(syntheticProgramClassBuilder);
              },
              outerContext,
              type,
              contextToType,
              appView);
      onCreationConsumer.accept(dexProgramClass);
      return dexProgramClass;
    }
  }

  private DexProgramClass internalCreateProgramClass(
      SyntheticKind kind,
      Consumer<SyntheticProgramClassBuilder> fn,
      SynthesizingContext outerContext,
      DexType type,
      Function<SynthesizingContext, DexType> contextToType,
      AppView<?> appView) {
    registerSyntheticTypeRewriting(outerContext, contextToType, appView, type);
    SyntheticProgramClassBuilder classBuilder =
        new SyntheticProgramClassBuilder(type, kind, outerContext, appView.dexItemFactory());
    fn.accept(classBuilder);
    DexProgramClass clazz = classBuilder.build();
    addPendingDefinition(new SyntheticProgramClassDefinition(kind, outerContext, clazz));
    return clazz;
  }

  private void registerSyntheticTypeRewriting(
      SynthesizingContext outerContext,
      Function<SynthesizingContext, DexType> contextToType,
      AppView<?> appView,
      DexType type) {
    DexType rewrittenContextType =
        appView.typeRewriter.rewrittenContextType(outerContext.getSynthesizingContextType());
    if (rewrittenContextType == null) {
      return;
    }
    SynthesizingContext synthesizingContext = SynthesizingContext.fromType(rewrittenContextType);
    DexType rewrittenType = contextToType.apply(synthesizingContext);
    appView.typeRewriter.rewriteType(type, rewrittenType);
  }

  public DexProgramClass createClass(
      SyntheticKind kind, UniqueContext context, AppView<?> appView) {
    return createClass(kind, context, appView, ConsumerUtils.emptyConsumer());
  }

  public DexProgramClass createClass(
      SyntheticKind kind,
      UniqueContext context,
      AppView<?> appView,
      Consumer<SyntheticProgramClassBuilder> fn) {
    // Obtain the outer synthesizing context in the case the context itself is synthetic.
    // This is to ensure a flat input-type -> synthetic-item mapping.
    SynthesizingContext outerContext = getSynthesizingContext(context.getClassContext(), appView);
    Function<SynthesizingContext, DexType> contextToType =
        c ->
            SyntheticNaming.createInternalType(
                kind, c, context.getSyntheticSuffix(), appView.dexItemFactory());
    return internalCreateProgramClass(
        kind, fn, outerContext, contextToType.apply(outerContext), contextToType, appView);
  }

  // TODO(b/172194101): Make this take a unique context.
  public DexProgramClass createFixedClass(
      SyntheticKind kind,
      DexProgramClass context,
      AppView<?> appView,
      Consumer<SyntheticProgramClassBuilder> fn) {
    SynthesizingContext outerContext = internalGetOuterContext(context, appView);
    Function<SynthesizingContext, DexType> contextToType =
        c -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
    return internalCreateProgramClass(
        kind, fn, outerContext, contextToType.apply(outerContext), contextToType, appView);
  }

  public DexProgramClass getExistingFixedClass(
      SyntheticKind kind, DexClass context, AppView<?> appView) {
    assert kind.isFixedSuffixSynthetic;
    SynthesizingContext outerContext = internalGetOuterContext(context, appView);
    DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
    DexClass clazz = appView.definitionFor(type);
    assert clazz != null;
    assert isSyntheticClass(type);
    assert clazz.isProgramClass();
    return clazz.asProgramClass();
  }

  // Obtain the outer synthesizing context in the case the context itself is synthetic.
  // This is to ensure a flat input-type -> synthetic-item mapping.
  private SynthesizingContext internalGetOuterContext(DexClass context, AppView<?> appView) {
    return context.isProgramClass()
        ? getSynthesizingContext(context.asProgramClass(), appView)
        : SynthesizingContext.fromNonSyntheticInputContext(context.asClasspathOrLibraryClass());
  }

  /**
   * Ensure that a fixed synthetic class exists.
   *
   * <p>This method is thread safe and will synchronize based on the context of the fixed synthetic.
   */
  public DexProgramClass ensureFixedClass(
      SyntheticKind kind,
      DexClass context,
      AppView<?> appView,
      Consumer<SyntheticProgramClassBuilder> fn,
      Consumer<DexProgramClass> onCreationConsumer) {
    assert kind.isFixedSuffixSynthetic;
    SynthesizingContext outerContext = internalGetOuterContext(context, appView);
    return internalEnsureFixedProgramClass(kind, fn, onCreationConsumer, outerContext, appView);
  }

  public ProgramMethod ensureFixedClassMethod(
      DexString name,
      DexProto proto,
      SyntheticKind kind,
      ProgramDefinition context,
      AppView<?> appView,
      Consumer<SyntheticProgramClassBuilder> buildClassCallback,
      Consumer<SyntheticMethodBuilder> buildMethodCallback) {
    return ensureFixedClassMethod(
        name,
        proto,
        kind,
        context,
        appView,
        buildClassCallback,
        buildMethodCallback,
        emptyConsumer());
  }

  public ProgramMethod ensureFixedClassMethod(
      DexString name,
      DexProto proto,
      SyntheticKind kind,
      ProgramDefinition context,
      AppView<?> appView,
      Consumer<SyntheticProgramClassBuilder> buildClassCallback,
      Consumer<SyntheticMethodBuilder> buildMethodCallback,
      Consumer<ProgramMethod> newMethodCallback) {
    DexProgramClass clazz =
        ensureFixedClass(
            kind, context.getContextClass(), appView, buildClassCallback, emptyConsumer());
    DexMethod methodReference = appView.dexItemFactory().createMethod(clazz.getType(), proto, name);
    DexEncodedMethod methodDefinition =
        internalEnsureMethod(
            methodReference, clazz, kind, appView, buildMethodCallback, newMethodCallback);
    return new ProgramMethod(clazz, methodDefinition);
  }

  private void errorOnInvalidSyntheticEnsure(DexClass dexClass, String kind, AppView<?> appView) {
    String classKind =
        dexClass.isProgramClass()
            ? "program"
            : dexClass.isClasspathClass() ? "classpath" : "library";
    throw appView
        .reporter()
        .fatalError(
            "Cannot ensure "
                + dexClass.type
                + " as a synthetic "
                + kind
                + " class, because it is already a "
                + classKind
                + " class.");
  }

  private DexClasspathClass internalEnsureFixedClasspathClass(
      SyntheticKind kind,
      Consumer<SyntheticClasspathClassBuilder> classConsumer,
      Consumer<DexClasspathClass> onCreationConsumer,
      SynthesizingContext outerContext,
      AppView<?> appView) {
    Function<SynthesizingContext, DexType> contextToType =
        (c) -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
    DexType type = contextToType.apply(outerContext);
    synchronized (type) {
      DexClass clazz = appView.definitionFor(type);
      if (clazz != null) {
        if (!clazz.isClasspathClass()) {
          errorOnInvalidSyntheticEnsure(clazz, "classpath", appView);
        }
        return clazz.asClasspathClass();
      }
      registerSyntheticTypeRewriting(outerContext, contextToType, appView, type);
      SyntheticClasspathClassBuilder classBuilder =
          new SyntheticClasspathClassBuilder(type, kind, outerContext, appView.dexItemFactory());
      classConsumer.accept(classBuilder);
      DexClasspathClass definition = classBuilder.build();
      addPendingDefinition(new SyntheticClasspathClassDefinition(kind, outerContext, definition));
      onCreationConsumer.accept(definition);
      return definition;
    }
  }

  public DexClasspathClass ensureFixedClasspathClassFromType(
      SyntheticKind kind,
      DexType contextType,
      AppView<?> appView,
      Consumer<SyntheticClasspathClassBuilder> classConsumer,
      Consumer<DexClasspathClass> onCreationConsumer) {
    SynthesizingContext outerContext = SynthesizingContext.fromType(contextType);
    return internalEnsureFixedClasspathClass(
        kind, classConsumer, onCreationConsumer, outerContext, appView);
  }

  public DexClasspathClass ensureFixedClasspathClass(
      SyntheticKind kind,
      ClasspathOrLibraryClass context,
      AppView<?> appView,
      Consumer<SyntheticClasspathClassBuilder> classConsumer,
      Consumer<DexClasspathClass> onCreationConsumer) {
    // Obtain the outer synthesizing context in the case the context itself is synthetic.
    // This is to ensure a flat input-type -> synthetic-item mapping.
    SynthesizingContext outerContext = SynthesizingContext.fromNonSyntheticInputContext(context);
    return internalEnsureFixedClasspathClass(
        kind, classConsumer, onCreationConsumer, outerContext, appView);
  }

  public ClasspathMethod ensureFixedClasspathMethodFromType(
      DexString methodName,
      DexProto methodProto,
      SyntheticKind kind,
      DexType contextType,
      AppView<?> appView,
      Consumer<SyntheticClasspathClassBuilder> classConsumer,
      Consumer<DexClasspathClass> onCreationConsumer,
      Consumer<SyntheticMethodBuilder> buildMethodCallback) {
    DexClasspathClass clazz =
        ensureFixedClasspathClassFromType(
            kind, contextType, appView, classConsumer, onCreationConsumer);
    return internalEnsureFixedClasspathMethod(
        methodName, methodProto, kind, appView, buildMethodCallback, clazz);
  }

  public ClasspathMethod ensureFixedClasspathClassMethod(
      DexString methodName,
      DexProto methodProto,
      SyntheticKind kind,
      ClasspathOrLibraryClass context,
      AppView<?> appView,
      Consumer<SyntheticClasspathClassBuilder> buildClassCallback,
      Consumer<DexClasspathClass> onClassCreationCallback,
      Consumer<SyntheticMethodBuilder> buildMethodCallback) {
    DexClasspathClass clazz =
        ensureFixedClasspathClass(
            kind, context, appView, buildClassCallback, onClassCreationCallback);
    return internalEnsureFixedClasspathMethod(
        methodName, methodProto, kind, appView, buildMethodCallback, clazz);
  }

  private ClasspathMethod internalEnsureFixedClasspathMethod(
      DexString methodName,
      DexProto methodProto,
      SyntheticKind kind,
      AppView<?> appView,
      Consumer<SyntheticMethodBuilder> buildMethodCallback,
      DexClasspathClass clazz) {
    DexMethod methodReference =
        appView.dexItemFactory().createMethod(clazz.getType(), methodProto, methodName);
    DexEncodedMethod methodDefinition =
        internalEnsureMethod(
            methodReference,
            clazz,
            kind,
            appView,
            methodBuilder -> {
              // For class path classes we always disable api level checks because we never trace
              // the code and it cannot be inlined.
              buildMethodCallback.accept(methodBuilder.disableAndroidApiLevelCheck());
            },
            emptyConsumer());
    return new ClasspathMethod(clazz, methodDefinition);
  }

  @SuppressWarnings("unchecked")
  private <T extends DexClassAndMethod> DexEncodedMethod internalEnsureMethod(
      DexMethod methodReference,
      DexClass clazz,
      SyntheticKind kind,
      AppView<?> appView,
      Consumer<SyntheticMethodBuilder> buildMethodCallback,
      Consumer<T> newMethodCallback) {
    MethodCollection methodCollection = clazz.getMethodCollection();
    synchronized (methodCollection) {
      DexEncodedMethod methodDefinition = methodCollection.getMethod(methodReference);
      if (methodDefinition != null) {
        return methodDefinition;
      }
      SyntheticMethodBuilder builder =
          new SyntheticMethodBuilder(appView.dexItemFactory(), clazz.getType(), kind);
      builder.setName(methodReference.getName());
      builder.setProto(methodReference.getProto());
      buildMethodCallback.accept(builder);
      methodDefinition = builder.build();
      methodCollection.addMethod(methodDefinition);
      newMethodCallback.accept((T) DexClassAndMethod.create(clazz, methodDefinition));
      return methodDefinition;
    }
  }

  public DexProgramClass ensureFixedClassFromType(
      SyntheticKind kind,
      DexType contextType,
      AppView<?> appView,
      Consumer<SyntheticProgramClassBuilder> fn,
      Consumer<DexProgramClass> onCreationConsumer) {
    // Obtain the outer synthesizing context in the case the context itself is synthetic.
    // This is to ensure a flat input-type -> synthetic-item mapping.
    SynthesizingContext outerContext = SynthesizingContext.fromType(contextType);
    return internalEnsureFixedProgramClass(kind, fn, onCreationConsumer, outerContext, appView);
  }

  /** Create a single synthetic method item. */
  public ProgramMethod createMethod(
      SyntheticKind kind,
      UniqueContext context,
      AppView<?> appView,
      Consumer<SyntheticMethodBuilder> fn) {
    return createMethod(kind, context.getClassContext(), appView, fn, context::getSyntheticSuffix);
  }

  private ProgramMethod createMethod(
      SyntheticKind kind,
      ProgramDefinition context,
      AppView<?> appView,
      Consumer<SyntheticMethodBuilder> fn,
      Supplier<String> syntheticIdSupplier) {
    assert nextSyntheticId != INVALID_ID_AFTER_SYNTHETIC_FINALIZATION;
    // Obtain the outer synthesizing context in the case the context itself is synthetic.
    // This is to ensure a flat input-type -> synthetic-item mapping.
    SynthesizingContext outerContext = getSynthesizingContext(context, appView);
    DexType type =
        SyntheticNaming.createInternalType(
            kind, outerContext, syntheticIdSupplier.get(), appView.dexItemFactory());
    SyntheticProgramClassBuilder classBuilder =
        new SyntheticProgramClassBuilder(type, kind, outerContext, appView.dexItemFactory());
    DexProgramClass clazz =
        classBuilder
            .addMethod(fn.andThen(m -> m.setName(SyntheticNaming.INTERNAL_SYNTHETIC_METHOD_NAME)))
            .build();
    ProgramMethod method = new ProgramMethod(clazz, clazz.methods().iterator().next());
    addPendingDefinition(new SyntheticMethodDefinition(kind, outerContext, method));
    return method;
  }

  private void addPendingDefinition(SyntheticDefinition<?, ?, ?> definition) {
    pending.nonLegacyDefinitions.put(definition.getHolder().getType(), definition);
  }

  // Commit of the synthetic items to a new fully populated application.

  public CommittedItems commit(DexApplication application) {
    return commitPrunedItems(PrunedItems.empty(application));
  }

  public CommittedItems commitPrunedItems(PrunedItems prunedItems) {
    return commit(prunedItems, pending, committed, nextSyntheticId);
  }

  public CommittedItems commitRewrittenWithLens(
      DexApplication application, NonIdentityGraphLens lens) {
    assert pending.verifyNotRewritten(lens);
    return commit(
        PrunedItems.empty(application), pending, committed.rewriteWithLens(lens), nextSyntheticId);
  }

  private static CommittedItems commit(
      PrunedItems prunedItems,
      PendingSynthetics pending,
      CommittedSyntheticsCollection committed,
      int nextSyntheticId) {
    DexApplication application = prunedItems.getPrunedApp();
    Set<DexType> removedClasses = prunedItems.getNoLongerSyntheticItems();
    CommittedSyntheticsCollection.Builder builder = committed.builder();
    // Compute the synthetic additions and add them to the application.
    ImmutableList<DexType> committedProgramTypes;
    DexApplication amendedApplication;
    if (pending.nonLegacyDefinitions.isEmpty()) {
      committedProgramTypes = ImmutableList.of();
      amendedApplication = application;
    } else {
      DexApplication.Builder<?> appBuilder = application.builder();
      ImmutableList.Builder<DexType> committedProgramTypesBuilder = ImmutableList.builder();
      for (SyntheticDefinition<?, ?, ?> definition : pending.nonLegacyDefinitions.values()) {
        if (!removedClasses.contains(definition.getHolder().getType())) {
          if (definition.isProgramDefinition()) {
            committedProgramTypesBuilder.add(definition.getHolder().getType());
            if (definition.getKind().mayOverridesNonProgramType) {
              appBuilder.addProgramClassPotentiallyOverridingNonProgramClass(
                  definition.asProgramDefinition().getHolder());
            } else {
              appBuilder.addProgramClass(definition.asProgramDefinition().getHolder());
            }
          } else if (appBuilder.isDirect()) {
            assert definition.isClasspathDefinition();
            appBuilder.asDirect().addClasspathClass(definition.asClasspathDefinition().getHolder());
          }
          builder.addItem(definition);
        }
      }
      committedProgramTypes = committedProgramTypesBuilder.build();
      amendedApplication = appBuilder.build();
    }
    return new CommittedItems(
        nextSyntheticId,
        amendedApplication,
        builder.build().pruneItems(prunedItems),
        committedProgramTypes);
  }

  public void writeAttributeIfIntermediateSyntheticClass(
      ClassWriter writer, DexProgramClass clazz, AppView<?> appView) {
    if (!appView.options().intermediate || !appView.options().isGeneratingClassFiles()) {
      return;
    }
    Iterator<SyntheticReference<?, ?, ?>> it =
        committed.getNonLegacyItems(clazz.getType()).iterator();
    if (it.hasNext()) {
      SyntheticKind kind = it.next().getKind();
      // When compiling intermediates there should not be any mergings as they may invalidate the
      // single kind of a synthetic which is required for marking synthetics. This check could be
      // relaxed to ensure that all kinds are equivalent if merging is possible.
      assert !it.hasNext();
      SyntheticMarker.writeMarkerAttribute(writer, kind);
    }
  }

  // Finalization of synthetic items.

  Result computeFinalSynthetics(AppView<?> appView) {
    assert !hasPendingSyntheticClasses();
    return new SyntheticFinalization(appView.options(), this, committed)
        .computeFinalSynthetics(appView);
  }
}
