// Copyright (c) 2016, 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.dex;

import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;

import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.debuginfo.DebugRepresentation;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.experimental.startup.StartupOrder;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItem;
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.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
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.InitClassLens;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
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.Function;
import java.util.function.Predicate;

public class VirtualFile {

  public static final int MAX_ENTRIES = Constants.U16BIT_MAX + 1;

  private final int id;
  public final VirtualFileIndexedItemCollection indexedItems;
  private final IndexedItemTransaction transaction;
  private final FeatureSplit featureSplit;
  private final StartupOrder startupOrder;

  private final DexString primaryClassDescriptor;
  private DebugRepresentation debugRepresentation;

  VirtualFile(int id, AppView<?> appView) {
    this(id, appView, null, null, StartupOrder.empty());
  }

  VirtualFile(
      int id,
      AppView<?> appView,
      FeatureSplit featureSplit) {
    this(id, appView, null, featureSplit, StartupOrder.empty());
  }

  private VirtualFile(
      int id,
      AppView<?> appView,
      DexProgramClass primaryClass) {
    this(id, appView, primaryClass, null, StartupOrder.empty());
  }

  private VirtualFile(
      int id,
      AppView<?> appView,
      DexProgramClass primaryClass,
      FeatureSplit featureSplit,
      StartupOrder startupOrder) {
    this.id = id;
    this.indexedItems = new VirtualFileIndexedItemCollection(appView);
    this.transaction = new IndexedItemTransaction(indexedItems, appView);
    this.primaryClassDescriptor =
        primaryClass == null
            ? null
            : appView.getNamingLens().lookupClassDescriptor(primaryClass.type);
    this.featureSplit = featureSplit;
    this.startupOrder = startupOrder;
  }

  public int getId() {
    return id;
  }

  public Set<String> getClassDescriptors() {
    Set<String> classDescriptors = new HashSet<>();
    for (DexProgramClass clazz : indexedItems.classes) {
      boolean added = classDescriptors.add(clazz.type.descriptor.toString());
      assert added;
    }
    return classDescriptors;
  }

  public FeatureSplit getFeatureSplit() {
    return featureSplit;
  }

  public StartupOrder getStartupOrder() {
    return startupOrder;
  }

  public String getPrimaryClassDescriptor() {
    return primaryClassDescriptor == null ? null : primaryClassDescriptor.toString();
  }

  public void setDebugRepresentation(DebugRepresentation debugRepresentation) {
    assert debugRepresentation != null;
    assert this.debugRepresentation == null;
    this.debugRepresentation = debugRepresentation;
  }

  public DebugRepresentation getDebugRepresentation() {
    assert debugRepresentation != null;
    return debugRepresentation;
  }

  public static String deriveCommonPrefixAndSanityCheck(List<String> fileNames) {
    Iterator<String> nameIterator = fileNames.iterator();
    String first = nameIterator.next();
    if (!first.toLowerCase().endsWith(FileUtils.DEX_EXTENSION)) {
      throw new RuntimeException("Illegal suffix for dex file: `" + first + "`.");
    }
    String prefix = first.substring(0, first.length() - FileUtils.DEX_EXTENSION.length());
    int index = 2;
    while (nameIterator.hasNext()) {
      String next = nameIterator.next();
      if (!next.toLowerCase().endsWith(FileUtils.DEX_EXTENSION)) {
        throw new RuntimeException("Illegal suffix for dex file: `" + first + "`.");
      }
      if (!next.startsWith(prefix)) {
        throw new RuntimeException("Input filenames lack common prefix.");
      }
      String numberPart =
          next.substring(prefix.length(), next.length() - FileUtils.DEX_EXTENSION.length());
      if (Integer.parseInt(numberPart) != index++) {
        throw new RuntimeException("DEX files are not numbered consecutively.");
      }
    }
    return prefix;
  }

  public void injectString(DexString string) {
    transaction.addString(string);
    commitTransaction();
  }

  private static Map<DexProgramClass, String> computeOriginalNameMapping(
      Collection<DexProgramClass> classes, GraphLens graphLens, ClassNameMapper proguardMap) {
    Map<DexProgramClass, String> originalNames = new IdentityHashMap<>(classes.size());
    classes.forEach(
        clazz -> {
          DexType originalType = graphLens.getOriginalType(clazz.getType());
          originalNames.put(
              clazz,
              DescriptorUtils.descriptorToJavaType(originalType.toDescriptorString(), proguardMap));
        });
    return originalNames;
  }

  private ObjectToOffsetMapping objectMapping = null;

  public ObjectToOffsetMapping getObjectMapping() {
    assert objectMapping != null;
    return objectMapping;
  }

  public void computeMapping(
      AppView<?> appView,
      int lazyDexStringsCount,
      Timing timing) {
    assert transaction.isEmpty();
    assert objectMapping == null;
    objectMapping =
        new ObjectToOffsetMapping(
            appView,
            transaction.rewriter,
            indexedItems.classes,
            indexedItems.protos,
            indexedItems.types,
            indexedItems.methods,
            indexedItems.fields,
            indexedItems.strings,
            indexedItems.callSites,
            indexedItems.methodHandles,
            lazyDexStringsCount,
            timing);
  }

  void addClass(DexProgramClass clazz) {
    transaction.addClassAndDependencies(clazz);
  }

  public boolean isFull(int maxEntries) {
    return (transaction.getNumberOfMethods() > maxEntries)
        || (transaction.getNumberOfFields() > maxEntries);
  }

  boolean isFull() {
    return isFull(MAX_ENTRIES);
  }

  public int getNumberOfMethods() {
    return transaction.getNumberOfMethods();
  }

  public int getNumberOfFields() {
    return transaction.getNumberOfFields();
  }

  public int getNumberOfClasses() {
    return transaction.getNumberOfClasses();
  }

  void throwIfFull(boolean hasMainDexList, Reporter reporter) {
    if (!isFull()) {
      return;
    }
    throw reporter.fatalError(
        new DexFileOverflowDiagnostic(
            hasMainDexList, transaction.getNumberOfMethods(), transaction.getNumberOfFields()));
  }

  private boolean isFilledEnough() {
    return isFull(MAX_ENTRIES);
  }

  public void abortTransaction() {
    transaction.abort();
  }

  public void commitTransaction() {
    transaction.commit();
  }

  public boolean containsString(DexString string) {
    return indexedItems.strings.contains(string);
  }

  public boolean containsType(DexType type) {
    return indexedItems.types.contains(type);
  }

  public boolean isEmpty() {
    return indexedItems.classes.isEmpty();
  }

  public Collection<DexProgramClass> classes() {
    return indexedItems.classes;
  }

  public abstract static class Distributor {
    protected final AppView<?> appView;
    protected final ApplicationWriter writer;
    protected final List<VirtualFile> virtualFiles = new ArrayList<>();

    Distributor(ApplicationWriter writer) {
      this.appView = writer.appView;
      this.writer = writer;
    }

    public abstract List<VirtualFile> run() throws ExecutionException, IOException;

  }

  /**
   * Distribute each type to its individual virtual except for types synthesized during this
   * compilation. Synthesized classes are emitted in the individual virtual files
   * of the input classes they were generated from. Shared synthetic classes
   * may then be distributed in several individual virtual files.
   */
  public static class FilePerInputClassDistributor extends Distributor {
    private final Collection<DexProgramClass> classes;
    private final boolean combineSyntheticClassesWithPrimaryClass;

    FilePerInputClassDistributor(
        ApplicationWriter writer,
        Collection<DexProgramClass> classes,
        boolean combineSyntheticClassesWithPrimaryClass) {
      super(writer);
      this.classes = classes;
      this.combineSyntheticClassesWithPrimaryClass = combineSyntheticClassesWithPrimaryClass;
    }

    @Override
    public List<VirtualFile> run() {
      HashMap<DexProgramClass, VirtualFile> files = new HashMap<>();
      Collection<DexProgramClass> synthetics = new ArrayList<>();
      // Assign dedicated virtual files for all program classes.
      for (DexProgramClass clazz : classes) {
        // TODO(b/181636450): Simplify this making use of the assumption that synthetics are never
        //  duplicated.
        if (!combineSyntheticClassesWithPrimaryClass
            || !appView.getSyntheticItems().isSyntheticClass(clazz)) {
          VirtualFile file = new VirtualFile(virtualFiles.size(), appView, clazz);
          virtualFiles.add(file);
          file.addClass(clazz);
          files.put(clazz, file);
          // Commit this early, so that we do not keep the transaction state around longer than
          // needed and clear the underlying sets.
          file.commitTransaction();
        } else {
          synthetics.add(clazz);
        }
      }
      for (DexProgramClass synthetic : synthetics) {
        Collection<DexType> synthesizingContexts =
            appView.getSyntheticItems().getSynthesizingContextTypes(synthetic.getType());
        assert synthesizingContexts.size() == 1;
        DexProgramClass inputType =
            appView.definitionForProgramType(synthesizingContexts.iterator().next());
        VirtualFile file = files.get(inputType);
        file.addClass(synthetic);
        file.commitTransaction();
      }
      return virtualFiles;
    }
  }

  public abstract static class DistributorBase extends Distributor {
    protected Set<DexProgramClass> classes;
    protected Map<DexProgramClass, String> originalNames;
    protected final VirtualFile mainDexFile;
    protected final InternalOptions options;

    DistributorBase(
        ApplicationWriter writer,
        Collection<DexProgramClass> classes,
        InternalOptions options,
        StartupOrder startupOrder) {
      super(writer);
      this.options = options;
      this.classes = SetUtils.newIdentityHashSet(classes);

      // Create the primary dex file. The distribution will add more if needed. We use the startup
      // order (if any) to guide the layout of the primary dex file.
      mainDexFile = new VirtualFile(0, appView, null, null, startupOrder);
      assert virtualFiles.isEmpty();
      virtualFiles.add(mainDexFile);
      addMarkers(mainDexFile);

      originalNames =
          computeOriginalNameMapping(
              classes, appView.graphLens(), appView.appInfo().app().getProguardMap());
    }

    private void addMarkers(VirtualFile virtualFile) {
      if (writer.markerStrings != null && !writer.markerStrings.isEmpty()) {
        for (DexString markerString : writer.markerStrings) {
          virtualFile.transaction.addString(markerString);
        }
        virtualFile.commitTransaction();
      }
    }

    protected void fillForMainDexList(Set<DexProgramClass> classes) {
      MainDexInfo mainDexInfo = appView.appInfo().getMainDexInfo();
      if (mainDexInfo.isEmpty()) {
        return;
      }
      VirtualFile mainDexFile = virtualFiles.get(0);
      mainDexInfo.forEach(
          type -> {
            DexProgramClass clazz = asProgramClassOrNull(appView.appInfo().definitionFor(type));
            if (clazz != null) {
              mainDexFile.addClass(clazz);
              classes.remove(clazz);
            }
            mainDexFile.commitTransaction();
          });
      if (Log.ENABLED) {
        Log.info(
            VirtualFile.class, "Main dex classes: " + mainDexFile.transaction.getNumberOfClasses());
        Log.info(
            VirtualFile.class, "Main dex methods: " + mainDexFile.transaction.getNumberOfMethods());
        Log.info(
            VirtualFile.class, "Main dex fields: " + mainDexFile.transaction.getNumberOfFields());
      }
      mainDexFile.throwIfFull(true, options.reporter);
    }

    protected Map<FeatureSplit, Set<DexProgramClass>> removeFeatureSplitClassesGetMapping() {
      assert appView.appInfo().hasClassHierarchy() == appView.enableWholeProgramOptimizations();
      if (!appView.appInfo().hasClassHierarchy()) {
        return ImmutableMap.of();
      }

      AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
          appView.withClassHierarchy();
      ClassToFeatureSplitMap classToFeatureSplitMap =
          appViewWithClassHierarchy.appInfo().getClassToFeatureSplitMap();
      if (classToFeatureSplitMap.isEmpty()) {
        return ImmutableMap.of();
      }

      // Pull out the classes that should go into feature splits.
      Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses =
          classToFeatureSplitMap.getFeatureSplitClasses(classes, appViewWithClassHierarchy);
      if (featureSplitClasses.size() > 0) {
        for (Set<DexProgramClass> featureClasses : featureSplitClasses.values()) {
          classes.removeAll(featureClasses);
        }
      }
      return featureSplitClasses;
    }

    protected void addFeatureSplitFiles(
        Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses, StartupOrder startupOrder) {
      if (featureSplitClasses.isEmpty()) {
        return;
      }
      for (Map.Entry<FeatureSplit, Set<DexProgramClass>> featureSplitSetEntry :
          featureSplitClasses.entrySet()) {
        // Add a new virtual file, start from index 0 again
        IntBox nextFileId = new IntBox();
        VirtualFile featureFile =
            new VirtualFile(
                nextFileId.getAndIncrement(),
                appView,
                featureSplitSetEntry.getKey());
        virtualFiles.add(featureFile);
        addMarkers(featureFile);
        List<VirtualFile> files = virtualFiles;
        List<VirtualFile> filesForDistribution = ImmutableList.of(featureFile);
        new PackageSplitPopulator(
                files,
                filesForDistribution,
                appView,
                featureSplitSetEntry.getValue(),
                originalNames,
                startupOrder,
                nextFileId)
            .run();
      }
    }
  }

  public static class FillFilesDistributor extends DistributorBase {

    private final ExecutorService executorService;
    private final StartupOrder startupOrder;

    FillFilesDistributor(
        ApplicationWriter writer,
        Collection<DexProgramClass> classes,
        InternalOptions options,
        ExecutorService executorService,
        StartupOrder startupOrder) {
      super(writer, classes, options, startupOrder);
      this.executorService = executorService;
      this.startupOrder = startupOrder;
    }

    @Override
    public List<VirtualFile> run() throws IOException {
      assert virtualFiles.size() == 1;
      assert virtualFiles.get(0).isEmpty();

      int totalClassNumber = classes.size();
      // First fill required classes into the main dex file.
      fillForMainDexList(classes);
      if (classes.isEmpty()) {
        // All classes ended up in the main dex file, no more to do.
        return virtualFiles;
      }

      List<VirtualFile> filesForDistribution = virtualFiles;
      boolean multidexLegacy = !mainDexFile.isEmpty();
      if (options.minimalMainDex && multidexLegacy) {
        assert virtualFiles.size() == 1;
        assert !virtualFiles.get(0).isEmpty();
        // Don't consider the main dex for distribution.
        filesForDistribution = Collections.emptyList();
      }

      Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses =
          removeFeatureSplitClassesGetMapping();

      IntBox nextFileId = new IntBox(1);
      if (multidexLegacy && options.enableInheritanceClassInDexDistributor) {
        new InheritanceClassInDexDistributor(
                mainDexFile,
                virtualFiles,
                filesForDistribution,
                classes,
                nextFileId,
                appView,
                executorService)
            .distribute();
      } else {
        new PackageSplitPopulator(
                virtualFiles,
                filesForDistribution,
                appView,
                classes,
                originalNames,
                startupOrder,
                nextFileId)
            .run();
      }
      addFeatureSplitFiles(featureSplitClasses, startupOrder);

      assert totalClassNumber == virtualFiles.stream().mapToInt(dex -> dex.classes().size()).sum();
      return virtualFiles;
    }
  }

  public static class MonoDexDistributor extends DistributorBase {
    MonoDexDistributor(
        ApplicationWriter writer, Collection<DexProgramClass> classes, InternalOptions options) {
      super(writer, classes, options, StartupOrder.empty());
    }

    @Override
    public List<VirtualFile> run() throws ExecutionException, IOException {
      Map<FeatureSplit, Set<DexProgramClass>> featureSplitClasses =
          removeFeatureSplitClassesGetMapping();
      // Add all classes to the main dex file.
      for (DexProgramClass programClass : classes) {
        mainDexFile.addClass(programClass);
      }
      mainDexFile.commitTransaction();
      mainDexFile.throwIfFull(false, options.reporter);
      if (options.featureSplitConfiguration != null) {
        if (!featureSplitClasses.isEmpty()) {
          // TODO(141334414): Figure out if we allow multidex in features even when mono-dexing
          addFeatureSplitFiles(featureSplitClasses, StartupOrder.empty());
        }
      }
      return virtualFiles;
    }
  }

  public static class ItemUseInfo {

    private static final Set<DexProgramClass> MANY = null;
    private static final int manyCount = 3;

    private Set<DexProgramClass> use;

    ItemUseInfo(Set<DexProgramClass> initialUse) {
      use = initialUse.size() >= manyCount ? MANY : initialUse;
    }

    public void addUse(Set<DexProgramClass> moreUse) {
      if (use == MANY) {
        return;
      }
      if (moreUse.size() >= manyCount) {
        use = MANY;
        return;
      }
      use.addAll(moreUse);
      if (use.size() >= manyCount) {
        use = MANY;
      }
    }

    public static int getManyCount() {
      return manyCount;
    }

    public boolean isMany() {
      return use == MANY;
    }

    public int getSize() {
      assert use != MANY;
      return use.size();
    }

    public int getSizeOrMany() {
      if (use == MANY) return -1;
      return use.size();
    }

    public Set<DexProgramClass> getUse() {
      assert !isMany();
      return use;
    }
  }

  public static class VirtualFileIndexedItemCollection implements IndexedItemCollection {

    private final GraphLens graphLens;
    private final InitClassLens initClassLens;
    private final NamingLens namingLens;

    private final Set<DexProgramClass> classes = Sets.newIdentityHashSet();
    private final Set<DexProto> protos = Sets.newIdentityHashSet();
    private final Set<DexType> types = Sets.newIdentityHashSet();
    private final Set<DexMethod> methods = Sets.newIdentityHashSet();
    private final Set<DexField> fields = Sets.newIdentityHashSet();
    private final Set<DexString> strings = Sets.newIdentityHashSet();
    private final Set<DexCallSite> callSites = Sets.newIdentityHashSet();
    private final Set<DexMethodHandle> methodHandles = Sets.newIdentityHashSet();

    public final Map<DexString, ItemUseInfo> stringsUse = new IdentityHashMap<>();
    public final Map<DexType, ItemUseInfo> typesUse = new IdentityHashMap<>();
    public final Map<DexProto, ItemUseInfo> protosUse = new IdentityHashMap<>();
    public final Map<DexField, ItemUseInfo> fieldsUse = new IdentityHashMap<>();
    public final Map<DexMethod, ItemUseInfo> methodsUse = new IdentityHashMap<>();
    public final Map<DexCallSite, ItemUseInfo> callSitesUse = new IdentityHashMap<>();
    public final Map<DexMethodHandle, ItemUseInfo> methodHandlesUse = new IdentityHashMap<>();

    public VirtualFileIndexedItemCollection(AppView<?> appView) {
      this.graphLens = appView.graphLens();
      this.initClassLens = appView.initClassLens();
      this.namingLens = appView.getNamingLens();
    }

    @Override
    public boolean addClass(DexProgramClass clazz) {
      return classes.add(clazz);
    }

    @Override
    public boolean addField(DexField field) {
      return fields.add(field);
    }

    @Override
    public boolean addMethod(DexMethod method) {
      return methods.add(method);
    }

    @Override
    public boolean addString(DexString string) {
      return strings.add(string);
    }

    @Override
    public boolean addProto(DexProto proto) {
      return protos.add(proto);
    }

    @Override
    public boolean addType(DexType type) {
      assert SyntheticNaming.verifyNotInternalSynthetic(type);
      return types.add(type);
    }

    @Override
    public boolean addCallSite(DexCallSite callSite) {
      return callSites.add(callSite);
    }

    @Override
    public boolean addMethodHandle(DexMethodHandle methodHandle) {
      return methodHandles.add(methodHandle);
    }

    int getNumberOfMethods() {
      return methods.size();
    }

    int getNumberOfFields() {
      return fields.size();
    }
  }

  public static class IndexedItemTransaction implements IndexedItemCollection {

    public interface ClassUseCollector {

      void collectClassDependencies(DexProgramClass clazz);

      void collectClassDependenciesDone();

      void clear();

      Map<DexString, Set<DexProgramClass>> getStringsUse();

      Map<DexType, Set<DexProgramClass>> getTypesUse();

      Map<DexProto, Set<DexProgramClass>> getProtosUse();

      Map<DexField, Set<DexProgramClass>> getFieldsUse();

      Map<DexMethod, Set<DexProgramClass>> getMethodsUse();

      Map<DexCallSite, Set<DexProgramClass>> getCallSitesUse();

      Map<DexMethodHandle, Set<DexProgramClass>> getMethodHandlesUse();
    }

    public static class EmptyIndexedItemUsedByClasses implements ClassUseCollector {
      @Override
      public void collectClassDependencies(DexProgramClass clazz) {
        // Do nothing.
      }

      @Override
      public void collectClassDependenciesDone() {
        // Do nothing.
      }

      @Override
      public void clear() {
        // DO nothing.
      }

      @Override
      public Map<DexString, Set<DexProgramClass>> getStringsUse() {
        assert false;
        return null;
      }

      @Override
      public Map<DexType, Set<DexProgramClass>> getTypesUse() {
        assert false;
        return null;
      }

      @Override
      public Map<DexProto, Set<DexProgramClass>> getProtosUse() {
        assert false;
        return null;
      }

      @Override
      public Map<DexField, Set<DexProgramClass>> getFieldsUse() {
        assert false;
        return null;
      }

      @Override
      public Map<DexMethod, Set<DexProgramClass>> getMethodsUse() {
        assert false;
        return null;
      }

      @Override
      public Map<DexCallSite, Set<DexProgramClass>> getCallSitesUse() {
        assert false;
        return null;
      }

      @Override
      public Map<DexMethodHandle, Set<DexProgramClass>> getMethodHandlesUse() {
        assert false;
        return null;
      }
    }

    public static class IndexedItemsUsedByClassesInTransaction
        implements IndexedItemCollection, ClassUseCollector {

      private final AppView<?> appView;
      private final LensCodeRewriterUtils rewriter;
      private final VirtualFileIndexedItemCollection base;
      private final IndexedItemTransaction transaction;

      private final Set<DexProgramClass> classes = new LinkedHashSet<>();

      private final Map<DexString, Set<DexProgramClass>> stringsUse = new IdentityHashMap<>();
      private final Map<DexType, Set<DexProgramClass>> typesUse = new IdentityHashMap<>();
      private final Map<DexProto, Set<DexProgramClass>> protosUse = new IdentityHashMap<>();
      private final Map<DexField, Set<DexProgramClass>> fieldsUse = new IdentityHashMap<>();
      private final Map<DexMethod, Set<DexProgramClass>> methodsUse = new IdentityHashMap<>();
      private final Map<DexCallSite, Set<DexProgramClass>> callSitesUse = new IdentityHashMap<>();
      private final Map<DexMethodHandle, Set<DexProgramClass>> methodHandlessUse =
          new LinkedHashMap<>();

      DexProgramClass currentClass = null;

      private IndexedItemsUsedByClassesInTransaction(
          AppView<?> appView,
          LensCodeRewriterUtils rewriter,
          VirtualFileIndexedItemCollection base,
          IndexedItemTransaction transaction) {
        this.appView = appView;
        this.rewriter = rewriter;
        this.base = base;
        this.transaction = transaction;
      }

      @Override
      public void collectClassDependencies(DexProgramClass clazz) {
        clazz.collectIndexedItems(appView, this, rewriter);
      }

      @Override
      public boolean addClass(DexProgramClass clazz) {
        assert currentClass == null;
        currentClass = clazz;
        assert !classes.contains(clazz);
        classes.add(clazz);
        return true;
      }

      @Override
      public void collectClassDependenciesDone() {
        currentClass = null;
      }

      @Override
      public boolean addString(DexString string) {
        collectUse(string, transaction.strings, base.strings, stringsUse);
        return true;
      }

      @Override
      public boolean addType(DexType type) {
        collectUse(type, transaction.types, base.types, typesUse);
        return true;
      }

      @Override
      public boolean addProto(DexProto proto) {
        collectUse(proto, transaction.protos, base.protos, protosUse);
        return true;
      }

      @Override
      public boolean addField(DexField field) {
        collectUse(field, transaction.fields, base.fields, fieldsUse);
        return true;
      }

      @Override
      public boolean addMethod(DexMethod method) {
        collectUse(method, transaction.methods, base.methods, methodsUse);
        return true;
      }

      @Override
      public boolean addCallSite(DexCallSite callSite) {
        collectUse(callSite, transaction.callSites, base.callSites, callSitesUse);
        return true;
      }

      @Override
      public boolean addMethodHandle(DexMethodHandle methodHandle) {
        collectUse(methodHandle, transaction.methodHandles, base.methodHandles, methodHandlessUse);
        return true;
      }

      private <T extends DexItem> void collectUse(
          T item, Set<T> set, Set<T> baseSet, Map<T, Set<DexProgramClass>> use) {
        assert baseSet.contains(item) || set.contains(item);
        if (set.contains(item)) {
          assert classes.contains(currentClass);
        }
        use.computeIfAbsent(item, unused -> Sets.newIdentityHashSet()).add(currentClass);
      }

      @Override
      public Map<DexString, Set<DexProgramClass>> getStringsUse() {
        return stringsUse;
      }

      @Override
      public Map<DexType, Set<DexProgramClass>> getTypesUse() {
        return typesUse;
      }

      @Override
      public Map<DexProto, Set<DexProgramClass>> getProtosUse() {
        return protosUse;
      }

      @Override
      public Map<DexField, Set<DexProgramClass>> getFieldsUse() {
        return fieldsUse;
      }

      @Override
      public Map<DexMethod, Set<DexProgramClass>> getMethodsUse() {
        return methodsUse;
      }

      @Override
      public Map<DexCallSite, Set<DexProgramClass>> getCallSitesUse() {
        return callSitesUse;
      }

      @Override
      public Map<DexMethodHandle, Set<DexProgramClass>> getMethodHandlesUse() {
        return methodHandlessUse;
      }

      @Override
      public void clear() {
        classes.clear();
        stringsUse.clear();
        typesUse.clear();
        protosUse.clear();
        fieldsUse.clear();
        methodsUse.clear();
        callSitesUse.clear();
        methodHandlessUse.clear();
      }
    }

    private final AppView<?> appView;
    private final VirtualFileIndexedItemCollection base;
    private final LensCodeRewriterUtils rewriter;

    private final Set<DexProgramClass> classes = new LinkedHashSet<>();
    private final Set<DexField> fields = new LinkedHashSet<>();
    private final Set<DexMethod> methods = new LinkedHashSet<>();
    private final Set<DexType> types = new LinkedHashSet<>();
    private final Set<DexProto> protos = new LinkedHashSet<>();
    private final Set<DexString> strings = new LinkedHashSet<>();
    private final Set<DexCallSite> callSites = new LinkedHashSet<>();
    private final Set<DexMethodHandle> methodHandles = new LinkedHashSet<>();

    private final ClassUseCollector indexedItemsReferencedFromClassesInTransaction;

    private IndexedItemTransaction(VirtualFileIndexedItemCollection base, AppView<?> appView) {
      this.appView = appView;
      this.base = base;
      this.rewriter = new LensCodeRewriterUtils(appView, true);
      this.indexedItemsReferencedFromClassesInTransaction =
          appView.options().testing.calculateItemUseCountInDex
              ? new IndexedItemsUsedByClassesInTransaction(appView, rewriter, base, this)
              : new EmptyIndexedItemUsedByClasses();
    }

    private NamingLens getNamingLens() {
      return appView.getNamingLens();
    }

    private <T extends DexItem> boolean maybeInsert(T item, Set<T> set, Set<T> baseSet) {
      return maybeInsert(item, set, baseSet, true);
    }

    private <T extends DexItem> boolean maybeInsert(
        T item, Set<T> set, Set<T> baseSet, boolean requireCurrentClass) {
      if (baseSet.contains(item)) {
        return false;
      }
      boolean added = set.add(item);
      assert !added || !requireCurrentClass || classes.contains(currentClass);
      return added;
    }

    void addClassAndDependencies(DexProgramClass clazz) {
      clazz.collectIndexedItems(appView, this, rewriter);
      addClassDone();
      indexedItemsReferencedFromClassesInTransaction.collectClassDependencies(clazz);
      indexedItemsReferencedFromClassesInTransaction.collectClassDependenciesDone();
    }

    DexProgramClass currentClass = null;

    @Override
    public boolean addClass(DexProgramClass dexProgramClass) {
      assert currentClass == null;
      currentClass = dexProgramClass;
      return maybeInsert(dexProgramClass, classes, base.classes);
    }

    public void addClassDone() {
      currentClass = null;
    }

    @Override
    public boolean addField(DexField field) {
      assert currentClass != null;
      return maybeInsert(field, fields, base.fields);
    }

    @Override
    public boolean addMethod(DexMethod method) {
      assert currentClass != null;
      return maybeInsert(method, methods, base.methods);
    }

    @Override
    public boolean addString(DexString string) {
      if (currentClass == null) {
        // Only marker strings can be added outside a class context.
        assert string.startsWith("~~");
      }
      return maybeInsert(string, strings, base.strings, false);
    }

    @Override
    public boolean addProto(DexProto proto) {
      assert currentClass != null;
      return maybeInsert(proto, protos, base.protos);
    }

    @Override
    public boolean addType(DexType type) {
      assert currentClass != null;
      assert SyntheticNaming.verifyNotInternalSynthetic(type);
      return maybeInsert(type, types, base.types);
    }

    @Override
    public boolean addCallSite(DexCallSite callSite) {
      assert currentClass != null;
      return maybeInsert(callSite, callSites, base.callSites);
    }

    @Override
    public boolean addMethodHandle(DexMethodHandle methodHandle) {
      assert currentClass != null;
      return maybeInsert(methodHandle, methodHandles, base.methodHandles);
    }

    int getNumberOfMethods() {
      return methods.size() + base.getNumberOfMethods();
    }

    int getNumberOfClasses() {
      return classes.size() + base.classes.size();
    }

    int getNumberOfFields() {
      return fields.size() + base.getNumberOfFields();
    }

    private <T extends DexItem> void commitItemsIn(Set<T> set, Function<T, Boolean> hook) {
      set.forEach((item) -> {
        boolean newlyAdded = hook.apply(item);
        assert newlyAdded;
      });
      set.clear();
    }

    void commit() {
      commitItemsIn(classes, base::addClass);
      commitItemsIn(fields, base::addField);
      commitItemsIn(methods, base::addMethod);
      commitItemsIn(protos, base::addProto);
      commitItemsIn(types, base::addType);
      commitItemsIn(strings, base::addString);
      commitItemsIn(callSites, base::addCallSite);
      commitItemsIn(methodHandles, base::addMethodHandle);

      if (appView.options().testing.calculateItemUseCountInDex) {
        transferUsedBy(
            indexedItemsReferencedFromClassesInTransaction.getStringsUse(), base.stringsUse);
        transferUsedBy(indexedItemsReferencedFromClassesInTransaction.getTypesUse(), base.typesUse);
        transferUsedBy(
            indexedItemsReferencedFromClassesInTransaction.getProtosUse(), base.protosUse);
        transferUsedBy(
            indexedItemsReferencedFromClassesInTransaction.getFieldsUse(), base.fieldsUse);
        transferUsedBy(
            indexedItemsReferencedFromClassesInTransaction.getMethodsUse(), base.methodsUse);
        transferUsedBy(
            indexedItemsReferencedFromClassesInTransaction.getCallSitesUse(), base.callSitesUse);
        transferUsedBy(
            indexedItemsReferencedFromClassesInTransaction.getMethodHandlesUse(),
            base.methodHandlesUse);
      }
    }

    private <T extends DexItem> void transferUsedBy(
        Map<T, Set<DexProgramClass>> classesInTransactionReferringToItem,
        Map<T, ItemUseInfo> itemUse) {
      assert appView.options().testing.calculateItemUseCountInDex;
      classesInTransactionReferringToItem.forEach(
          (item, classes) -> {
            ItemUseInfo currentItemUse = itemUse.get(item);
            if (currentItemUse == null) {
              itemUse.put(item, new ItemUseInfo(classes));
            } else {
              currentItemUse.addUse(classes);
            }
          });

      classesInTransactionReferringToItem.clear();
    }

    void abort() {
      classes.clear();
      fields.clear();
      methods.clear();
      protos.clear();
      types.clear();
      strings.clear();

      indexedItemsReferencedFromClassesInTransaction.clear();
    }

    public boolean isEmpty() {
      return classes.isEmpty() && fields.isEmpty() && methods.isEmpty() && protos.isEmpty()
          && types.isEmpty() && strings.isEmpty();
    }

  }

  /**
   * Helper class to cycle through the set of virtual files.
   *
   * Iteration starts at the first file and iterates through all files.
   *
   * When {@link VirtualFileCycler#restart()} is called iteration of all files is restarted at the
   * current file.
   *
   * If the fill strategy indicate that the main dex file should be minimal, then the main dex file
   * will not be part of the iteration.
   */
  static class VirtualFileCycler {

    private final List<VirtualFile> files;
    private final List<VirtualFile> filesForDistribution;
    private final AppView<?> appView;

    private final IntBox nextFileId;
    private Iterator<VirtualFile> allFilesCyclic;
    private Iterator<VirtualFile> activeFiles;
    private FeatureSplit featureSplit;

    VirtualFileCycler(
        List<VirtualFile> files,
        List<VirtualFile> filesForDistribution,
        AppView<?> appView,
        IntBox nextFileId) {
      this.files = files;
      this.filesForDistribution = new ArrayList<>(filesForDistribution);
      this.appView = appView;
      this.nextFileId = nextFileId;

      if (filesForDistribution.size() > 0) {
        featureSplit = filesForDistribution.get(0).getFeatureSplit();
      }

      reset();
    }

    void clearFilesForDistribution() {
      filesForDistribution.clear();
      reset();
    }

    void reset() {
      allFilesCyclic = Iterators.cycle(filesForDistribution);
      restart();
    }

    boolean hasNext() {
      return activeFiles.hasNext();
    }

    VirtualFile next() {
      return activeFiles.next();
    }

    /**
     * Get next {@link VirtualFile} and create a new empty one if there is no next available.
     */
    VirtualFile nextOrCreate() {
      if (hasNext()) {
        return next();
      } else {
        VirtualFile newFile = internalAddFile();
        allFilesCyclic = Iterators.cycle(filesForDistribution);
        return newFile;
      }
    }

    /**
     * Get next {@link VirtualFile} accepted by the given filter and create a new empty one if there
     * is no next available.
     * @param filter allows to to reject some of the available {@link VirtualFile}. Rejecting empt
     * {@link VirtualFile} is not authorized since it would sometimes prevent to find a result.
     */
    VirtualFile nextOrCreate(Predicate<? super VirtualFile> filter) {
      while (true) {
        VirtualFile dex = nextOrCreate();
        if (dex.isEmpty()) {
          assert filter.test(dex);
          return dex;
        } else if (filter.test(dex)) {
          return dex;
        }
      }
    }

    // Start a new iteration over all files, starting at the current one.
    void restart() {
      activeFiles = Iterators.limit(allFilesCyclic, filesForDistribution.size());
    }

    VirtualFile addFile() {
      VirtualFile newFile = internalAddFile();
      reset();
      return newFile;
    }

    private VirtualFile internalAddFile() {
      VirtualFile newFile = new VirtualFile(nextFileId.getAndIncrement(), appView, featureSplit);
      files.add(newFile);
      filesForDistribution.add(newFile);
      return newFile;
    }

    VirtualFileCycler ensureFile() {
      if (filesForDistribution.isEmpty()) {
        addFile();
      }
      return this;
    }
  }

  /**
   * Distributes the given classes over the files in package order.
   *
   * <p>The populator avoids package splits. Big packages are split into subpackages if their size
   * exceeds 20% of the dex file. This populator also avoids filling files completely to cater for
   * future growth.
   *
   * <p>The populator cycles through the files until all classes have been successfully placed and
   * adds new files to the passed in map if it can't fit in the existing files.
   */
  private static class PackageSplitPopulator {

    static class PackageSplitClassPartioning {

      // The set of startup classes, sorted by original names so that classes in the same package
      // are adjacent. This is empty if no startup configuration is given.
      private final List<DexProgramClass> startupClasses;

      // The remaining set of classes that must be written, sorted by original names so that classes
      // in the same package are adjacent.
      private final List<DexProgramClass> nonStartupClasses;

      private PackageSplitClassPartioning(
          List<DexProgramClass> startupClasses, List<DexProgramClass> nonStartupClasses) {
        this.startupClasses = startupClasses;
        this.nonStartupClasses = nonStartupClasses;
      }

      public static PackageSplitClassPartioning create(
          Collection<DexProgramClass> classes,
          Map<DexProgramClass, String> originalNames,
          StartupOrder startupOrder,
          SyntheticItems syntheticItems) {
        return create(
            classes,
            getClassesByPackageComparator(originalNames),
            getStartupClassPredicate(startupOrder, syntheticItems));
      }

      private static PackageSplitClassPartioning create(
          Collection<DexProgramClass> classes,
          Comparator<DexProgramClass> comparator,
          Predicate<DexProgramClass> startupClassPredicate) {
        List<DexProgramClass> startupClasses = new ArrayList<>();
        List<DexProgramClass> nonStartupClasses = new ArrayList<>(classes.size());
        for (DexProgramClass clazz : classes) {
          if (startupClassPredicate.test(clazz)) {
            startupClasses.add(clazz);
          } else {
            nonStartupClasses.add(clazz);
          }
        }
        startupClasses.sort(comparator);
        nonStartupClasses.sort(comparator);
        return new PackageSplitClassPartioning(startupClasses, nonStartupClasses);
      }

      private static Comparator<DexProgramClass> getClassesByPackageComparator(
          Map<DexProgramClass, String> originalNames) {
        return (a, b) -> {
          String originalA = originalNames.get(a);
          String originalB = originalNames.get(b);
          int indexA = originalA.lastIndexOf('.');
          int indexB = originalB.lastIndexOf('.');
          if (indexA == -1 && indexB == -1) {
            // Empty package, compare the class names.
            return originalA.compareTo(originalB);
          }
          if (indexA == -1) {
            // Empty package name comes first.
            return -1;
          }
          if (indexB == -1) {
            // Empty package name comes first.
            return 1;
          }
          String prefixA = originalA.substring(0, indexA);
          String prefixB = originalB.substring(0, indexB);
          int result = prefixA.compareTo(prefixB);
          if (result != 0) {
            return result;
          }
          return originalA.compareTo(originalB);
        };
      }

      private static Predicate<DexProgramClass> getStartupClassPredicate(
          StartupOrder startupOrder, SyntheticItems syntheticItems) {
        return clazz -> startupOrder.contains(clazz.getType(), syntheticItems);
      }

      public List<DexProgramClass> getStartupClasses() {
        return startupClasses;
      }

      public List<DexProgramClass> getNonStartupClasses() {
        return nonStartupClasses;
      }
    }

    /**
     * Android suggests com.company.product for package names, so the components will be at level 4
     */
    private static final int MINIMUM_PREFIX_LENGTH = 4;
    private static final int MAXIMUM_PREFIX_LENGTH = 7;
    /**
     * We allow 1/MIN_FILL_FACTOR of a file to remain empty when moving to the next file, i.e., a
     * rollback with less than 1/MAX_FILL_FACTOR of the total classes in a file will move to the
     * next file.
     */
    private static final int MIN_FILL_FACTOR = 5;

    private final PackageSplitClassPartioning classPartioning;
    private final Map<DexProgramClass, String> originalNames;
    private final DexItemFactory dexItemFactory;
    private final InternalOptions options;
    private final VirtualFileCycler cycler;

    PackageSplitPopulator(
        List<VirtualFile> files,
        List<VirtualFile> filesForDistribution,
        AppView<?> appView,
        Collection<DexProgramClass> classes,
        Map<DexProgramClass, String> originalNames,
        StartupOrder startupOrder,
        IntBox nextFileId) {
      this.classPartioning =
          PackageSplitClassPartioning.create(
              classes, originalNames, startupOrder, appView.getSyntheticItems());
      this.originalNames = originalNames;
      this.dexItemFactory = appView.dexItemFactory();
      this.options = appView.options();
      this.cycler = new VirtualFileCycler(files, filesForDistribution, appView, nextFileId);
    }

    static boolean coveredByPrefix(String originalName, String currentPrefix) {
      if (currentPrefix == null) {
        return false;
      }
      if (currentPrefix.endsWith(".*")) {
        return originalName.startsWith(currentPrefix.substring(0, currentPrefix.length() - 2));
      } else {
        return originalName.startsWith(currentPrefix)
            && originalName.lastIndexOf('.') == currentPrefix.length();
      }
    }

    private String getOriginalName(DexProgramClass clazz) {
      return originalNames.get(clazz);
    }

    public void run() {
      addStartupClasses();
      List<DexProgramClass> nonPackageClasses = addNonStartupClasses();
      addNonPackageClasses(cycler, nonPackageClasses);
    }

    private void addStartupClasses() {
      List<DexProgramClass> startupClasses = classPartioning.getStartupClasses();
      if (startupClasses.isEmpty()) {
        return;
      }

      assert options.getStartupOptions().hasStartupProfileProvider();

      // In practice, all startup classes should fit in a single dex file, so optimistically try to
      // commit the startup classes using a single transaction.
      VirtualFile virtualFile = cycler.next();
      for (DexProgramClass startupClass : classPartioning.getStartupClasses()) {
        virtualFile.addClass(startupClass);
      }

      if (hasSpaceForTransaction(virtualFile, options)) {
        virtualFile.commitTransaction();
      } else {
        virtualFile.abortTransaction();

        // If the above failed, then add the startup classes one by one.
        for (DexProgramClass startupClass : classPartioning.getStartupClasses()) {
          virtualFile.addClass(startupClass);
          if (hasSpaceForTransaction(virtualFile, options)) {
            virtualFile.commitTransaction();
          } else {
            virtualFile.abortTransaction();
            virtualFile = cycler.addFile();
            virtualFile.addClass(startupClass);
            assert hasSpaceForTransaction(virtualFile, options);
            virtualFile.commitTransaction();
          }
        }
      }

      if (options.getStartupOptions().isMinimalStartupDexEnabled()) {
        cycler.clearFilesForDistribution();
      } else {
        cycler.restart();
      }
    }

    private List<DexProgramClass> addNonStartupClasses() {
      int prefixLength = MINIMUM_PREFIX_LENGTH;
      int transactionStartIndex = 0;
      String currentPrefix = null;
      Object2IntMap<String> packageAssignments = new Object2IntOpenHashMap<>();
      VirtualFile current = cycler.ensureFile().next();
      List<DexProgramClass> classes = classPartioning.getNonStartupClasses();
      List<DexProgramClass> nonPackageClasses = new ArrayList<>();
      for (int classIndex = 0; classIndex < classes.size(); classIndex++) {
        DexProgramClass clazz = classes.get(classIndex);
        String originalName = getOriginalName(clazz);
        if (!coveredByPrefix(originalName, currentPrefix)) {
          if (currentPrefix != null) {
            current.commitTransaction();
            assert verifyPackageToVirtualFileAssignment(packageAssignments, currentPrefix, current);
            // Reset the cycler to again iterate over all files, starting with the current one.
            cycler.restart();
            // Try to reduce the prefix length if possible. Only do this on a successful commit.
            prefixLength = MINIMUM_PREFIX_LENGTH - 1;
          }
          String newPrefix;
          // Also, we need to avoid new prefixes that are a prefix of previously used prefixes, as
          // otherwise we might generate an overlap that will trigger problems when reusing the
          // package mapping generated here. For example, if an existing map contained
          //   com.android.foo.*
          // but we now try to place some new subpackage
          //   com.android.bar.*,
          // we locally could use
          //   com.android.*.
          // However, when writing out the final package map, we get overlapping patterns
          // com.android.* and com.android.foo.*.
          do {
            newPrefix = extractPrefixToken(++prefixLength, originalName, false);
          } while (currentPrefix != null && currentPrefix.startsWith(newPrefix));
          // Don't set the current prefix if we did not extract one.
          if (!newPrefix.equals("")) {
            currentPrefix = extractPrefixToken(prefixLength, originalName, true);
          }
          transactionStartIndex = classIndex;
        }

        if (currentPrefix == null) {
          assert clazz.superType != null;
          // We don't have a package, add this to a list of classes that we will add last.
          assert current.transaction.isEmpty();
          nonPackageClasses.add(clazz);
          continue;
        }

        assert clazz.superType != null || clazz.type == dexItemFactory.objectType;
        current.addClass(clazz);

        if (hasSpaceForTransaction(current, options)) {
          continue;
        }

        int numberOfClassesInTransaction = classIndex - transactionStartIndex + 1;
        int numberOfClassesInVirtualFileWithTransaction = current.getNumberOfClasses();

        current.abortTransaction();

        // We allow for a final rollback that has at most 20% of classes in it.
        // This is a somewhat random number that was empirically chosen.
        if (numberOfClassesInTransaction
                > numberOfClassesInVirtualFileWithTransaction / MIN_FILL_FACTOR
            && prefixLength < MAXIMUM_PREFIX_LENGTH) {
          // Go back to previous start index.
          classIndex = transactionStartIndex - 1;
          currentPrefix = null;
          prefixLength++;
          continue;
        }

        // Reset the state to after the last commit and cycle through files.
        // The idea is that we do not increase the number of files, so it has to fit somewhere.
        if (!cycler.hasNext()) {
          // Special case where we simply will never be able to fit the current package into
          // one dex file. This is currently the case for Strings in jumbo tests, see b/33227518.
          if (current.isEmpty()) {
            for (int j = transactionStartIndex; j <= classIndex; j++) {
              nonPackageClasses.add(classes.get(j));
            }
            transactionStartIndex = classIndex + 1;
          }
          // All files are filled up to the 20% mark.
          cycler.addFile();
        }

        // Go back to previous start index.
        classIndex = transactionStartIndex - 1;
        current = cycler.next();
        currentPrefix = null;
        prefixLength = MINIMUM_PREFIX_LENGTH;
      }

      current.commitTransaction();
      assert currentPrefix == null
          || verifyPackageToVirtualFileAssignment(packageAssignments, currentPrefix, current);

      return nonPackageClasses;
    }

    private static String extractPrefixToken(int prefixLength, String className, boolean addStar) {
      int index = 0;
      int lastIndex = 0;
      int segmentCount = 0;
      while (lastIndex != -1 && segmentCount++ < prefixLength) {
        index = lastIndex;
        lastIndex = className.indexOf('.', index + 1);
      }
      String prefix = className.substring(0, index);
      if (addStar && segmentCount >= prefixLength) {
        // Full match, add a * to also match sub-packages.
        prefix += ".*";
      }
      return prefix;
    }

    private boolean verifyPackageToVirtualFileAssignment(
        Object2IntMap<String> packageAssignments, String packageName, VirtualFile virtualFile) {
      assert !packageAssignments.containsKey(packageName);
      packageAssignments.put(packageName, virtualFile.getId());
      return true;
    }

    private boolean hasSpaceForTransaction(VirtualFile current, InternalOptions options) {
      return !isFullEnough(current, options);
    }

    private boolean isFullEnough(VirtualFile current, InternalOptions options) {
      if (options.testing.limitNumberOfClassesPerDex > 0
          && current.getNumberOfClasses() > options.testing.limitNumberOfClassesPerDex) {
        return true;
      }
      return current.isFull();
    }

    private void addNonPackageClasses(
        VirtualFileCycler cycler, List<DexProgramClass> nonPackageClasses) {
      if (nonPackageClasses.isEmpty()) {
        return;
      }
      cycler.restart();
      VirtualFile current;
      current = cycler.next();
      for (DexProgramClass clazz : nonPackageClasses) {
        if (current.isFull()) {
          current = getVirtualFile(cycler);
        }
        current.addClass(clazz);
        while (current.isFull()) {
          // This only happens if we have a huge class, that takes up more than 20% of a dex file.
          current.abortTransaction();
          current = getVirtualFile(cycler);
          boolean wasEmpty = current.isEmpty();
          current.addClass(clazz);
          if (wasEmpty && current.isFull()) {
            throw new InternalCompilerError(
                "Class " + clazz.toString() + " does not fit into a single dex file.");
          }
        }
        current.commitTransaction();
      }
    }

    private VirtualFile getVirtualFile(VirtualFileCycler cycler) {
      VirtualFile current = null;
      while (cycler.hasNext() && isFullEnough(current = cycler.next(), options)) {}
      if (current == null || isFullEnough(current, options)) {
        current = cycler.addFile();
      }
      return current;
    }
  }

}
