// 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.google.common.base.Predicates.alwaysTrue;

import com.android.tools.r8.features.ClassToFeatureSplitMap;
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.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.TreeFixerBase;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.synthesis.SyntheticNaming.Phase;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
import com.android.tools.r8.utils.structural.RepresentativeMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.hash.HashCode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class SyntheticFinalization {

  public static class Result {
    public final CommittedItems commit;
    public final NonIdentityGraphLens lens;
    public final PrunedItems prunedItems;
    public final MainDexInfo mainDexInfo;

    public Result(
        CommittedItems commit,
        SyntheticFinalizationGraphLens lens,
        PrunedItems prunedItems,
        MainDexInfo mainDexInfo) {
      this.commit = commit;
      this.lens = lens;
      this.prunedItems = prunedItems;
      this.mainDexInfo = mainDexInfo;
    }
  }

  public static class SyntheticFinalizationGraphLens extends NestedGraphLens {

    private SyntheticFinalizationGraphLens(
        AppView<?> appView,
        BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
        BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap,
        Map<DexType, DexType> typeMap) {
      super(appView, fieldMap, methodMap, typeMap);
    }

    @Override
    public boolean isSyntheticFinalizationGraphLens() {
      return true;
    }
  }

  private static class Builder {

    private final BidirectionalManyToOneRepresentativeHashMap<DexField, DexField> fieldMap =
        BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
    private final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap =
        BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
    private final Map<DexType, DexType> typeMap = new IdentityHashMap<>();

    boolean isEmpty() {
      if (typeMap.isEmpty()) {
        assert fieldMap.isEmpty();
        assert methodMap.isEmpty();
        return true;
      }
      return false;
    }

    void move(DexType from, DexType to) {
      DexType old = typeMap.put(from, to);
      assert old == null || old == to;
    }

    void move(DexField from, DexField to) {
      DexField old = fieldMap.put(from, to);
      assert old == null || old == to;
    }

    void move(DexMethod from, DexMethod to) {
      methodMap.put(from, to);
    }

    void setRepresentative(DexField field, DexField representative) {
      fieldMap.setRepresentative(field, representative);
    }

    void setRepresentative(DexMethod method, DexMethod representative) {
      methodMap.setRepresentative(method, representative);
    }

    SyntheticFinalizationGraphLens build(AppView<?> appView) {
      if (typeMap.isEmpty() && fieldMap.isEmpty() && methodMap.isEmpty()) {
        return null;
      }
      return new SyntheticFinalizationGraphLens(appView, fieldMap, methodMap, typeMap);
    }
  }

  private final InternalOptions options;
  private final SyntheticItems synthetics;
  private final CommittedSyntheticsCollection committed;

  SyntheticFinalization(
      InternalOptions options, SyntheticItems synthetics, CommittedSyntheticsCollection committed) {
    this.options = options;
    this.synthetics = synthetics;
    this.committed = committed;
  }

  public static void finalize(AppView<AppInfo> appView, ExecutorService executorService)
      throws ExecutionException {
    assert !appView.appInfo().hasClassHierarchy();
    assert !appView.appInfo().hasLiveness();
    Result result = appView.getSyntheticItems().computeFinalSynthetics(appView);
    appView.setAppInfo(new AppInfo(result.commit, result.mainDexInfo));
    if (result.lens != null) {
      appView.setAppInfo(
          appView
              .appInfo()
              .rebuildWithMainDexInfo(
                  appView
                      .appInfo()
                      .getMainDexInfo()
                      .rewrittenWithLens(appView.getSyntheticItems(), result.lens)));
      appView.setGraphLens(result.lens);
    }
    appView.pruneItems(result.prunedItems, executorService);
  }

  public static void finalizeWithClassHierarchy(
      AppView<AppInfoWithClassHierarchy> appView, ExecutorService executorService)
      throws ExecutionException {
    assert !appView.appInfo().hasLiveness();
    Result result = appView.getSyntheticItems().computeFinalSynthetics(appView);
    appView.setAppInfo(appView.appInfo().rebuildWithClassHierarchy(result.commit));
    appView.setAppInfo(appView.appInfo().rebuildWithMainDexInfo(result.mainDexInfo));
    if (result.lens != null) {
      appView.setGraphLens(result.lens);
      appView.setAppInfo(
          appView
              .appInfo()
              .rebuildWithMainDexInfo(
                  appView
                      .appInfo()
                      .getMainDexInfo()
                      .rewrittenWithLens(appView.getSyntheticItems(), result.lens)));
    }
    appView.pruneItems(result.prunedItems, executorService);
  }

  public static void finalizeWithLiveness(
      AppView<AppInfoWithLiveness> appView, ExecutorService executorService)
      throws ExecutionException {
    appView.options().testing.checkDeterminism(appView);
    Result result = appView.getSyntheticItems().computeFinalSynthetics(appView);
    appView.setAppInfo(appView.appInfo().rebuildWithMainDexInfo(result.mainDexInfo));
    if (result.lens != null) {
      appView.rewriteWithLensAndApplication(result.lens, result.commit.getApplication().asDirect());
    } else {
      assert result.commit.getApplication() == appView.appInfo().app();
    }
    appView.setAppInfo(appView.appInfo().rebuildWithLiveness(result.commit));
    appView.pruneItems(result.prunedItems, executorService);
  }

  Result computeFinalSynthetics(AppView<?> appView) {
    assert verifyNoNestedSynthetics(appView.dexItemFactory());
    assert verifyOneSyntheticPerSyntheticClass();
    DexApplication application;
    Builder lensBuilder = new Builder();
    ImmutableMap.Builder<DexType, List<SyntheticMethodReference>> finalMethodsBuilder =
        ImmutableMap.builder();
    ImmutableMap.Builder<DexType, List<SyntheticProgramClassReference>> finalClassesBuilder =
        ImmutableMap.builder();
    Set<DexType> derivedMainDexTypes = Sets.newIdentityHashSet();
    {
      Map<String, NumberGenerator> generators = new HashMap<>();
      application =
          buildLensAndProgram(
              appView,
              computeEquivalences(
                  appView, committed.getNonLegacyMethods(), generators, lensBuilder),
              computeEquivalences(
                  appView, committed.getNonLegacyClasses(), generators, lensBuilder),
              lensBuilder,
              (clazz, reference) ->
                  finalClassesBuilder.put(clazz.getType(), ImmutableList.of(reference)),
              (clazz, reference) ->
                  finalMethodsBuilder.put(clazz.getType(), ImmutableList.of(reference)),
              derivedMainDexTypes);
    }
    ImmutableMap<DexType, List<SyntheticMethodReference>> finalMethods =
        finalMethodsBuilder.build();
    ImmutableMap<DexType, List<SyntheticProgramClassReference>> finalClasses =
        finalClassesBuilder.build();

    Set<DexType> prunedSynthetics = Sets.newIdentityHashSet();
    committed.forEachNonLegacyItem(
        reference -> {
          DexType type = reference.getHolder();
          if (!finalMethods.containsKey(type) && !finalClasses.containsKey(type)) {
            prunedSynthetics.add(type);
          }
        });

    SyntheticFinalizationGraphLens syntheticFinalizationGraphLens = lensBuilder.build(appView);

    ImmutableSet<DexType> finalInputSynthetics =
        syntheticFinalizationGraphLens != null
            ? SetUtils.newImmutableSet(
                builder ->
                    committed.forEachSyntheticInput(
                        syntheticInputType ->
                            builder.accept(
                                syntheticFinalizationGraphLens.lookupType(syntheticInputType))))
            : committed.syntheticInputs;

    // TODO(b/181858113): Remove once deprecated main-dex-list is removed.
    MainDexInfo.Builder mainDexInfoBuilder = appView.appInfo().getMainDexInfo().builderFromCopy();
    derivedMainDexTypes.forEach(mainDexInfoBuilder::addList);

    return new Result(
        new CommittedItems(
            SyntheticItems.INVALID_ID_AFTER_SYNTHETIC_FINALIZATION,
            application,
            new CommittedSyntheticsCollection(
                synthetics.getNaming(), finalMethods, finalClasses, finalInputSynthetics),
            ImmutableList.of()),
        syntheticFinalizationGraphLens,
        PrunedItems.builder().setPrunedApp(application).addRemovedClasses(prunedSynthetics).build(),
        mainDexInfoBuilder.build());
  }

  private <R extends SyntheticReference<R, D, ?>, D extends SyntheticDefinition<R, D, ?>>
      Map<DexType, EquivalenceGroup<D>> computeEquivalences(
          AppView<?> appView,
          ImmutableMap<DexType, List<R>> references,
          Map<String, NumberGenerator> generators,
          Builder lensBuilder) {
    boolean intermediate = appView.options().intermediate;
    Map<DexType, D> definitions = lookupDefinitions(appView, references);
    ClassToFeatureSplitMap classToFeatureSplitMap =
        appView.appInfo().hasClassHierarchy()
            ? appView.appInfo().withClassHierarchy().getClassToFeatureSplitMap()
            : ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap();
    Collection<List<D>> potentialEquivalences =
        computePotentialEquivalences(
            definitions,
            intermediate,
            appView.dexItemFactory(),
            appView.graphLens(),
            classToFeatureSplitMap,
            synthetics);
    return computeActualEquivalences(
        potentialEquivalences,
        generators,
        appView,
        intermediate,
        classToFeatureSplitMap,
        lensBuilder);
  }

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

  private boolean verifyNoNestedSynthetics(DexItemFactory dexItemFactory) {
    // Check that the prefix of each synthetic is never itself synthetic.
    committed.forEachNonLegacyItem(
        item -> {
          if (item.getKind().allowSyntheticContext()) {
            return;
          }
          String prefix =
              SyntheticNaming.getPrefixForExternalSyntheticType(item.getKind(), item.getHolder());
          assert !prefix.contains(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
          DexType context =
              dexItemFactory.createType(DescriptorUtils.getDescriptorFromClassBinaryName(prefix));
          assert isNotSyntheticType(context);
        });
    return true;
  }

  private boolean verifyOneSyntheticPerSyntheticClass() {
    Set<DexType> seen = Sets.newIdentityHashSet();
    committed
        .getNonLegacyClasses()
        .forEach(
            (type, references) -> {
              assert seen.add(type);
              assert references.size() == 1;
            });
    committed
        .getNonLegacyMethods()
        .forEach(
            (type, references) -> {
              assert seen.add(type);
              assert references.size() == 1;
            });
    return true;
  }

  private static void ensureSourceFile(
      DexProgramClass externalSyntheticClass, DexString syntheticSourceFileName) {
    if (externalSyntheticClass.getSourceFile() == null) {
      externalSyntheticClass.setSourceFile(syntheticSourceFileName);
    }
  }

  private static DexApplication buildLensAndProgram(
      AppView<?> appView,
      Map<DexType, EquivalenceGroup<SyntheticMethodDefinition>> syntheticMethodGroups,
      Map<DexType, EquivalenceGroup<SyntheticProgramClassDefinition>> syntheticClassGroups,
      Builder lensBuilder,
      BiConsumer<DexProgramClass, SyntheticProgramClassReference> addFinalSyntheticClass,
      BiConsumer<DexProgramClass, SyntheticMethodReference> addFinalSyntheticMethod,
      Set<DexType> derivedMainDexSynthetics) {
    DexApplication application = appView.appInfo().app();
    MainDexInfo mainDexInfo = appView.appInfo().getMainDexInfo();
    Set<DexProgramClass> pruned = Sets.newIdentityHashSet();

    TreeFixerBase treeFixer =
        new TreeFixerBase(appView) {
          @Override
          public DexType mapClassType(DexType type) {
            return lensBuilder.typeMap.getOrDefault(type, type);
          }

          @Override
          public void recordFieldChange(DexField from, DexField to) {
            lensBuilder.move(from, to);
          }

          @Override
          public void recordMethodChange(DexMethod from, DexMethod to) {
            lensBuilder.move(from, to);
          }

          @Override
          public void recordClassChange(DexType from, DexType to) {
            lensBuilder.move(from, to);
          }
        };

    List<DexProgramClass> deduplicatedClasses = new ArrayList<>();
    syntheticMethodGroups.forEach(
        (syntheticType, syntheticGroup) -> {
          SyntheticMethodDefinition representative = syntheticGroup.getRepresentative();
          SynthesizingContext context = representative.getContext();
          context.registerPrefixRewriting(syntheticType, appView);
          addSyntheticMarker(representative.getKind(), representative.getHolder(), appView);
          if (syntheticGroup.isDerivedFromMainDexList(mainDexInfo)) {
            derivedMainDexSynthetics.add(syntheticType);
          }
          syntheticGroup.forEachNonRepresentativeMember(
              member -> {
                pruned.add(member.getHolder());
                deduplicatedClasses.add(member.getHolder());
              });
        });

    syntheticClassGroups.forEach(
        (syntheticType, syntheticGroup) -> {
          SyntheticProgramClassDefinition representative = syntheticGroup.getRepresentative();
          SynthesizingContext context = representative.getContext();
          context.registerPrefixRewriting(syntheticType, appView);
          addSyntheticMarker(representative.getKind(), representative.getHolder(), appView);
          if (syntheticGroup.isDerivedFromMainDexList(mainDexInfo)) {
            derivedMainDexSynthetics.add(syntheticType);
          }
          syntheticGroup.forEachNonRepresentativeMember(
              member -> {
                pruned.add(member.getHolder());
                deduplicatedClasses.add(member.getHolder());
              });
        });

    // Only create a new application if anything changed.
    if (lensBuilder.isEmpty()) {
      assert deduplicatedClasses.isEmpty();
      assert pruned.isEmpty();
    } else {
      if (!pruned.isEmpty()) {
        List<DexProgramClass> newProgramClasses = new ArrayList<>();
        for (DexProgramClass clazz : application.classes()) {
          if (!pruned.contains(clazz)) {
            newProgramClasses.add(clazz);
          }
        }
        assert newProgramClasses.size() < application.classes().size();
        application = application.builder().replaceProgramClasses(newProgramClasses).build();
      }

      // Assert that the non-representatives have been removed from the app.
      assert verifyNonRepresentativesRemovedFromApplication(application, syntheticClassGroups);
      assert verifyNonRepresentativesRemovedFromApplication(application, syntheticMethodGroups);

      DexApplication.Builder<?> builder = application.builder();
      treeFixer.fixupClasses(deduplicatedClasses);
      builder.replaceProgramClasses(treeFixer.fixupClasses(application.classes()));
      application = builder.build();
    }

    DexString syntheticSourceFileName =
        appView.enableWholeProgramOptimizations()
            ? appView.dexItemFactory().createString("R8$$SyntheticClass")
            : appView.dexItemFactory().createString("D8$$SyntheticClass");

    // Add the synthesized from after repackaging which changed class definitions.
    final DexApplication appForLookup = application;
    syntheticClassGroups.forEach(
        (syntheticType, syntheticGroup) -> {
          DexProgramClass externalSyntheticClass = appForLookup.programDefinitionFor(syntheticType);
          assert externalSyntheticClass != null
              : "Expected definition for " + syntheticType.getTypeName();
          ensureSourceFile(externalSyntheticClass, syntheticSourceFileName);
          SyntheticProgramClassDefinition representative = syntheticGroup.getRepresentative();
          addFinalSyntheticClass.accept(
              externalSyntheticClass,
              new SyntheticProgramClassReference(
                  representative.getKind(),
                  representative.getContext(),
                  externalSyntheticClass.type));
        });
    syntheticMethodGroups.forEach(
        (syntheticType, syntheticGroup) -> {
          DexProgramClass externalSyntheticClass = appForLookup.programDefinitionFor(syntheticType);
          ensureSourceFile(externalSyntheticClass, syntheticSourceFileName);
          SyntheticMethodDefinition representative = syntheticGroup.getRepresentative();
          assert externalSyntheticClass.getMethodCollection().size() == 1;
          assert externalSyntheticClass.getMethodCollection().hasDirectMethods();
          DexEncodedMethod syntheticMethodDefinition =
              externalSyntheticClass.getMethodCollection().getDirectMethod(alwaysTrue());
          addFinalSyntheticMethod.accept(
              externalSyntheticClass,
              new SyntheticMethodReference(
                  representative.getKind(),
                  representative.getContext(),
                  syntheticMethodDefinition.getReference()));
        });

    Iterables.<EquivalenceGroup<? extends SyntheticDefinition<?, ?, DexProgramClass>>>concat(
            syntheticClassGroups.values(), syntheticMethodGroups.values())
        .forEach(
            syntheticGroup ->
                syntheticGroup
                    .getRepresentative()
                    .getHolder()
                    .forEachProgramMember(
                        member -> {
                          if (member.isProgramField()) {
                            DexField field = member.asProgramField().getReference();
                            DexField rewrittenField = treeFixer.fixupFieldReference(field);
                            lensBuilder.setRepresentative(rewrittenField, field);
                          } else {
                            DexMethod method = member.asProgramMethod().getReference();
                            DexMethod rewrittenMethod = treeFixer.fixupMethodReference(method);
                            lensBuilder.setRepresentative(rewrittenMethod, method);
                          }
                        }));

    for (DexType key : syntheticMethodGroups.keySet()) {
      assert application.definitionFor(key) != null;
    }

    for (DexType key : syntheticClassGroups.keySet()) {
      assert application.definitionFor(key) != null;
    }

    return application;
  }

  private static <T extends SyntheticDefinition<?, T, ?>>
      boolean verifyNonRepresentativesRemovedFromApplication(
          DexApplication application, Map<DexType, EquivalenceGroup<T>> syntheticGroups) {
    for (EquivalenceGroup<?> syntheticGroup : syntheticGroups.values()) {
      syntheticGroup.forEachNonRepresentativeMember(
          member -> {
            assert application.definitionFor(member.getHolder().getType()) == null;
          });
    }
    return true;
  }

  private static void addSyntheticMarker(
      SyntheticKind kind,
      DexProgramClass externalSyntheticClass,
      AppView<?> appView) {
    if (shouldAnnotateSynthetics(appView.options())) {
      SyntheticMarker.addMarkerToClass(externalSyntheticClass, kind, appView.options());
    }
  }

  private static boolean shouldAnnotateSynthetics(InternalOptions options) {
    // Only intermediate builds have annotated synthetics to allow later sharing.
    // Also, CF builds are marked in the writer using an attribute.
    return options.intermediate && options.isGeneratingDex();
  }

  private <T extends SyntheticDefinition<?, T, ?>>
      Map<DexType, EquivalenceGroup<T>> computeActualEquivalences(
          Collection<List<T>> potentialEquivalences,
          Map<String, NumberGenerator> generators,
          AppView<?> appView,
          boolean intermediate,
          ClassToFeatureSplitMap classToFeatureSplitMap,
          Builder lensBuilder) {
    Map<String, List<EquivalenceGroup<T>>> groupsPerPrefix = new HashMap<>();
    Map<DexType, EquivalenceGroup<T>> equivalences = new IdentityHashMap<>();
    potentialEquivalences.forEach(
        members -> {
          List<EquivalenceGroup<T>> groups =
              groupEquivalent(appView, members, intermediate, classToFeatureSplitMap);
          for (EquivalenceGroup<T> group : groups) {
            // If the group already has a representative, then this representative is pinned.
            // Otherwise, we select a deterministic representative.
            if (group.hasRepresentative()) {
              EquivalenceGroup<T> previous =
                  equivalences.put(group.getRepresentative().getHolder().getType(), group);
              assert previous == null;
            } else {
              group.selectDeterministicRepresentative();
              groupsPerPrefix
                  .computeIfAbsent(
                      group.getRepresentative().getPrefixForExternalSyntheticType(),
                      k -> new ArrayList<>())
                  .add(group);
            }
          }
        });
    groupsPerPrefix.forEach(
        (externalSyntheticTypePrefix, groups) -> {
          Comparator<EquivalenceGroup<T>> comparator = this::compareForFinalGroupSorting;
          ListUtils.destructiveSort(groups, comparator);
          for (int i = 0; i < groups.size(); i++) {
            EquivalenceGroup<T> group = groups.get(i);
            assert group
                .getRepresentative()
                .getPrefixForExternalSyntheticType()
                .equals(externalSyntheticTypePrefix);
            // Two equivalence groups in same context type must be distinct otherwise the assignment
            // of the synthetic name will be non-deterministic between the two.
            assert i == 0 || checkGroupsAreDistinct(groups.get(i - 1), group, comparator);
            SyntheticKind kind = group.getRepresentative().getKind();
            DexType representativeType =
                intermediate
                        && synthetics.isSyntheticInput(
                            group.getRepresentative().getHolder().asProgramClass())
                    ? group.getRepresentative().getHolder().getType()
                    : createExternalType(
                        kind,
                        externalSyntheticTypePrefix,
                        generators,
                        appView,
                        candidateType ->
                            equivalences.containsKey(candidateType)
                                || appView
                                    .horizontallyMergedClasses()
                                    .hasBeenMergedIntoDifferentType(candidateType));
            equivalences.put(representativeType, group);
          }
        });
    equivalences.forEach(
        (representativeType, group) ->
            group.forEach(
                member -> lensBuilder.move(member.getHolder().getType(), representativeType)));
    return equivalences;
  }

  private <T extends SyntheticDefinition<?, T, ?>> int compareForFinalGroupSorting(
      EquivalenceGroup<T> a, EquivalenceGroup<T> b) {
    // Sort the equivalence groups based on the representative types. The representatives are
    // deterministically chosen and the internal synthetics deterministically named so using
    // the internal type as the order is deterministic.
    return a.getRepresentative()
        .getHolder()
        .getType()
        .compareTo(b.getRepresentative().getHolder().getType());
  }

  private static <T extends SyntheticDefinition<?, T, ?>> List<EquivalenceGroup<T>> groupEquivalent(
      AppView<?> appView,
      List<T> potentialEquivalence,
      boolean intermediate,
      ClassToFeatureSplitMap classToFeatureSplitMap) {
    List<EquivalenceGroup<T>> groups = new ArrayList<>();
    // Each other member is in a shared group if it is actually equivalent to the first member.
    for (T synthetic : potentialEquivalence) {
      boolean mustBeRepresentative = isPinned(appView, synthetic);
      EquivalenceGroup<T> equivalenceGroup = null;
      for (EquivalenceGroup<T> group : groups) {
        if (synthetic.isEquivalentTo(
            group.hasRepresentative()
                ? group.getRepresentative()
                : group.getFirstNonRepresentativeMember(),
            intermediate,
            appView.graphLens(),
            classToFeatureSplitMap)) {
          if (mustBeRepresentative && group.hasRepresentative()) {
            // Check if the current synthetic is smaller than the group's representative. If so,
            // then replace the representative, to ensure deterministic groups, and create a new
            // singleton group containing the old representative. Otherwise, just add a singleton
            // group containing the new synthetic.
            T representative = group.getRepresentative();
            if (representative
                    .toReference()
                    .getReference()
                    .compareTo(synthetic.toReference().getReference())
                > 0) {
              group.replaceAndRemoveRepresentative(synthetic);
              synthetic = representative;
            }
          } else {
            equivalenceGroup = group;
          }
          break;
        }
      }
      if (equivalenceGroup != null) {
        equivalenceGroup.add(synthetic, mustBeRepresentative);
      } else {
        groups.add(new EquivalenceGroup<>(synthetic, mustBeRepresentative));
      }
    }
    return groups;
  }

  /**
   * In R8, keep rules may apply to synthetics from the input, if the input has been compiled using
   * intermediate mode.
   */
  private static <D extends SyntheticDefinition<?, D, ?>> boolean isPinned(
      AppView<?> appView, D definition) {
    if (!appView.enableWholeProgramOptimizations()) {
      return false;
    }
    if (!definition.getHolder().isProgramClass()) {
      return true;
    }
    DexProgramClass holder = definition.getHolder().asProgramClass();
    // TODO(b/192924387): Change such that the keep info for internal synthetics is always bottom.
    if (!appView.getSyntheticItems().isSubjectToKeepRules(holder)) {
      return false;
    }
    KeepInfoCollection keepInfo = appView.getKeepInfo();
    InternalOptions options = appView.options();
    if (keepInfo.getClassInfo(holder).isPinned(options)) {
      return true;
    }
    for (DexEncodedMember<?, ?> member : holder.members()) {
      if (keepInfo.getMemberInfo(member, holder).isPinned(options)) {
        return true;
      }
    }
    return false;
  }

  private static <T extends SyntheticDefinition<?, T, ?>> boolean checkGroupsAreDistinct(
      EquivalenceGroup<T> g1, EquivalenceGroup<T> g2, Comparator<EquivalenceGroup<T>> comparator) {
    int smaller = comparator.compare(g1, g2);
    assert smaller < 0;
    int bigger = comparator.compare(g2, g1);
    assert bigger > 0;
    return true;
  }

  private DexType createExternalType(
      SyntheticKind kind,
      String externalSyntheticTypePrefix,
      Map<String, NumberGenerator> generators,
      AppView<?> appView,
      Predicate<DexType> reserved) {
    DexItemFactory factory = appView.dexItemFactory();
    if (kind.isFixedSuffixSynthetic()) {
      return SyntheticNaming.createExternalType(kind, externalSyntheticTypePrefix, "", factory);
    }
    NumberGenerator generator =
        generators.computeIfAbsent(externalSyntheticTypePrefix, k -> new NumberGenerator());
    DexType externalType;
    do {
      externalType =
          SyntheticNaming.createExternalType(
              kind, externalSyntheticTypePrefix, Integer.toString(generator.next()), factory);
      // If the generated external type matches an external synthetic from the input, which is kept,
      // then continue.
      if (reserved.test(externalType)) {
        externalType = null;
        continue;
      }
      DexClass clazz = appView.appInfo().definitionForWithoutExistenceAssert(externalType);
      if (clazz != null && isNotSyntheticType(clazz.type)) {
        assert options.testing.allowConflictingSyntheticTypes
            : "Unexpected creation of an existing external synthetic type: " + clazz;
        externalType = null;
      }
    } while (externalType == null);
    return externalType;
  }

  private static <T extends SyntheticDefinition<?, T, ?>>
      Collection<List<T>> computePotentialEquivalences(
          Map<DexType, T> definitions,
          boolean intermediate,
          DexItemFactory factory,
          GraphLens graphLens,
          ClassToFeatureSplitMap classToFeatureSplitMap,
          SyntheticItems syntheticItems) {
    if (definitions.isEmpty()) {
      return Collections.emptyList();
    }
    // Map all synthetic types to the java 'void' type. This is not an actual valid type, so it
    // cannot collide with any valid java type providing a good hashing key for the synthetics.
    Set<DexType> syntheticTypes;
    if (graphLens.isIdentityLens()) {
      syntheticTypes = definitions.keySet();
    } else {
      // If the synthetics are renamed include their original names in the equivalence too.
      syntheticTypes = SetUtils.newIdentityHashSet(definitions.size() * 2);
      definitions
          .keySet()
          .forEach(
              t -> {
                syntheticTypes.add(t);
                syntheticTypes.add(graphLens.getOriginalType(t));
              });
    }
    RepresentativeMap map = t -> syntheticTypes.contains(t) ? factory.voidType : t;
    Map<HashCode, List<T>> equivalences = new HashMap<>(definitions.size());
    for (T definition : definitions.values()) {
      HashCode hash =
          definition.computeHash(map, intermediate, classToFeatureSplitMap, syntheticItems);
      equivalences.computeIfAbsent(hash, k -> new ArrayList<>()).add(definition);
    }
    return equivalences.values();
  }

  private <R extends SyntheticReference<R, D, ?>, D extends SyntheticDefinition<R, D, ?>>
      Map<DexType, D> lookupDefinitions(
          AppView<?> appView, ImmutableMap<DexType, List<R>> references) {
    Map<DexType, D> definitions = new IdentityHashMap<>(references.size());
    for (R reference : IterableUtils.flatten(references.values())) {
      D definition = reference.lookupDefinition(appView::definitionFor);
      if (definition == null) {
        // We expect pruned definitions to have been removed.
        assert false;
        continue;
      }
      if (definition.isValid()) {
        definitions.put(reference.getHolder(), definition);
      } else {
        // Failing this check indicates that an optimization has modified the synthetic in a
        // disruptive way.
        assert false;
      }
    }
    return definitions;
  }

  private static class EquivalenceGroup<T extends SyntheticDefinition<?, T, ?>> {

    // The members of the equivalence group, *excluding* the representative.
    private List<T> members = new ArrayList<>();
    private T representative;

    EquivalenceGroup(T member, boolean isRepresentative) {
      add(member, isRepresentative);
    }

    void add(T member, boolean isRepresentative) {
      if (isRepresentative) {
        assert !hasRepresentative();
        representative = member;
      } else {
        members.add(member);
      }
    }

    int compareToIncludingContext(
        EquivalenceGroup<T> other,
        GraphLens graphLens,
        ClassToFeatureSplitMap classToFeatureSplitMap) {
      return getRepresentative()
          .compareTo(other.getRepresentative(), true, graphLens, classToFeatureSplitMap);
    }

    public void forEach(Consumer<T> consumer) {
      consumer.accept(getRepresentative());
      members.forEach(consumer);
    }

    public void forEachNonRepresentativeMember(Consumer<T> consumer) {
      members.forEach(consumer);
    }

    T getFirstNonRepresentativeMember() {
      assert !members.isEmpty();
      return members.get(0);
    }

    T getRepresentative() {
      assert hasRepresentative();
      return representative;
    }

    boolean hasRepresentative() {
      return representative != null;
    }

    boolean isDerivedFromMainDexList(MainDexInfo mainDexInfo) {
      return getRepresentative().getContext().isDerivedFromMainDexList(mainDexInfo)
          || Iterables.any(
              members, member -> member.getContext().isDerivedFromMainDexList(mainDexInfo));
    }

    void replaceAndRemoveRepresentative(T representative) {
      assert hasRepresentative();
      this.representative = representative;
    }

    void selectDeterministicRepresentative() {
      // Pick a deterministic member as representative.
      assert !hasRepresentative();
      int representativeIndex = 0;
      for (int i = 1; i < members.size(); i++) {
        T next = members.get(i);
        T representative = members.get(representativeIndex);
        if (next.toReference().getReference().compareTo(representative.toReference().getReference())
            < 0) {
          representativeIndex = i;
        }
      }
      T representative = members.get(representativeIndex);
      members.set(representativeIndex, ListUtils.last(members));
      ListUtils.removeLast(members);
      setRepresentative(representative);
    }

    void setRepresentative(T representative) {
      assert !hasRepresentative();
      this.representative = representative;
    }

    @Override
    public String toString() {
      if (hasRepresentative()) {
        return "EquivalenceGroup{ size = "
            + (members.size() + 1)
            + ", repr = "
            + getRepresentative()
            + " }";
      }
      return "EquivalenceGroup{ size = " + members.size() + " }";
    }
  }
}
