// Copyright (c) 2017, 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;

import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.inspector.Inspector;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecificationParser;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecification;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.profile.art.ArtProfileConsumer;
import com.android.tools.r8.profile.art.ArtProfileForRewriting;
import com.android.tools.r8.profile.art.ArtProfileProvider;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DumpInputFlags;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.PartitionMapZipContainer;
import com.android.tools.r8.utils.ProgramConsumerUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.ThreadUtils;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Base class for commands and command builders for compiler applications/tools which besides an
 * Android application (and optional main-dex list) also configure compilation output, compilation
 * mode and min API level.
 *
 * <p>For concrete builders, see for example {@link D8Command.Builder} and {@link
 * R8Command.Builder}.
 */
@KeepForApi
public abstract class BaseCompilerCommand extends BaseCommand {

  private final CompilationMode mode;
  private final ProgramConsumer programConsumer;
  private final StringConsumer mainDexListConsumer;
  private final int minApiLevel;
  private final Reporter reporter;
  private final DesugarState desugarState;
  private final boolean includeClassesChecksum;
  private final boolean optimizeMultidexForLinearAlloc;
  private final BiPredicate<String, Long> dexClassChecksumFilter;
  private final List<AssertionsConfiguration> assertionsConfiguration;
  private final List<Consumer<Inspector>> outputInspections;
  private final int threadCount;
  private final DumpInputFlags dumpInputFlags;
  private final MapIdProvider mapIdProvider;
  private final SourceFileProvider sourceFileProvider;
  private final boolean isAndroidPlatformBuild;
  private final List<ArtProfileForRewriting> artProfilesForRewriting;
  private final List<StartupProfileProvider> startupProfileProviders;
  private final ClassConflictResolver classConflictResolver;
  private final CancelCompilationChecker cancelCompilationChecker;

  BaseCompilerCommand(boolean printHelp, boolean printVersion) {
    super(printHelp, printVersion);
    programConsumer = null;
    mainDexListConsumer = null;
    mode = null;
    minApiLevel = 0;
    reporter = new Reporter();
    desugarState = DesugarState.ON;
    includeClassesChecksum = false;
    optimizeMultidexForLinearAlloc = false;
    dexClassChecksumFilter = (name, checksum) -> true;
    assertionsConfiguration = new ArrayList<>();
    outputInspections = null;
    threadCount = ThreadUtils.NOT_SPECIFIED;
    dumpInputFlags = DumpInputFlags.noDump();
    mapIdProvider = null;
    sourceFileProvider = null;
    isAndroidPlatformBuild = false;
    artProfilesForRewriting = null;
    startupProfileProviders = null;
    classConflictResolver = null;
    cancelCompilationChecker = null;
  }

  BaseCompilerCommand(
      AndroidApp app,
      CompilationMode mode,
      ProgramConsumer programConsumer,
      StringConsumer mainDexListConsumer,
      int minApiLevel,
      Reporter reporter,
      DesugarState desugarState,
      boolean optimizeMultidexForLinearAlloc,
      boolean includeClassesChecksum,
      BiPredicate<String, Long> dexClassChecksumFilter,
      List<AssertionsConfiguration> assertionsConfiguration,
      List<Consumer<Inspector>> outputInspections,
      int threadCount,
      DumpInputFlags dumpInputFlags,
      MapIdProvider mapIdProvider,
      SourceFileProvider sourceFileProvider,
      boolean isAndroidPlatformBuild,
      List<ArtProfileForRewriting> artProfilesForRewriting,
      List<StartupProfileProvider> startupProfileProviders,
      ClassConflictResolver classConflictResolver,
      CancelCompilationChecker cancelCompilationChecker) {
    super(app);
    assert minApiLevel > 0;
    assert mode != null;
    this.mode = mode;
    this.programConsumer = programConsumer;
    this.mainDexListConsumer = mainDexListConsumer;
    this.minApiLevel = minApiLevel;
    this.reporter = reporter;
    this.desugarState = desugarState;
    this.optimizeMultidexForLinearAlloc = optimizeMultidexForLinearAlloc;
    this.includeClassesChecksum = includeClassesChecksum;
    this.dexClassChecksumFilter = dexClassChecksumFilter;
    this.assertionsConfiguration = assertionsConfiguration;
    this.outputInspections = outputInspections;
    this.threadCount = threadCount;
    this.dumpInputFlags = dumpInputFlags;
    this.mapIdProvider = mapIdProvider;
    this.sourceFileProvider = sourceFileProvider;
    this.isAndroidPlatformBuild = isAndroidPlatformBuild;
    this.artProfilesForRewriting = artProfilesForRewriting;
    this.startupProfileProviders = startupProfileProviders;
    this.classConflictResolver = classConflictResolver;
    this.cancelCompilationChecker = cancelCompilationChecker;
  }

  /**
   * Get the compilation mode, e.g., {@link CompilationMode#DEBUG} or {@link
   * CompilationMode#RELEASE}.
   */
  public CompilationMode getMode() {
    return mode;
  }

  /** Get the minimum API level to compile against. */
  public int getMinApiLevel() {
    return minApiLevel;
  }

  void dumpBaseCommandOptions(DumpOptions.Builder builder) {
    builder
        .setBackend(ProgramConsumerUtils.getBackend(programConsumer))
        .setCompilationMode(getMode())
        .setMinApi(getMinApiLevel())
        .setOptimizeMultidexForLinearAlloc(isOptimizeMultidexForLinearAlloc())
        .setThreadCount(getThreadCount())
        .setDesugarState(getDesugarState())
        .setArtProfileProviders(
            ListUtils.map(
                getArtProfilesForRewriting(), ArtProfileForRewriting::getArtProfileProvider))
        .setStartupProfileProviders(getStartupProfileProviders());
    if (getAndroidPlatformBuild()) {
      builder.setAndroidPlatformBuild(true);
    }
  }

  /**
   * Get the program consumer that will receive the compilation output.
   *
   * <p>Note that the concrete consumer reference is final, the consumer itself is likely stateful.
   */
  public ProgramConsumer getProgramConsumer() {
    return programConsumer;
  }

  /**
   * Get the main dex list consumer that will receive the final complete main dex list.
   */
  public StringConsumer getMainDexListConsumer() {
    return mainDexListConsumer;
  }

  /** Get the use-desugaring state. True if enabled, false otherwise. */
  public boolean getEnableDesugaring() {
    return desugarState == DesugarState.ON;
  }

  DesugarState getDesugarState() {
    return desugarState;
  }

  public MapIdProvider getMapIdProvider() {
    return mapIdProvider;
  }

  public SourceFileProvider getSourceFileProvider() {
    return sourceFileProvider;
  }

  /** True if the output dex files has checksum information encoded in it. False otherwise. */
  public boolean getIncludeClassesChecksum() {
    return includeClassesChecksum;
  }

  /** Filter used to skip parsing of certain class in a dex file. */
  public BiPredicate<String, Long> getDexClassChecksumFilter() {
    return dexClassChecksumFilter;
  }

  /**
   * If true, legacy multidex partitioning will be optimized to reduce LinearAlloc usage during
   * Dalvik DexOpt.
   */
  public boolean isOptimizeMultidexForLinearAlloc() {
    return optimizeMultidexForLinearAlloc;
  }

  public List<AssertionsConfiguration> getAssertionsConfiguration() {
    return Collections.unmodifiableList(assertionsConfiguration);
  }

  public Collection<Consumer<Inspector>> getOutputInspections() {
    return Collections.unmodifiableList(outputInspections);
  }

  /** Get the number of threads to use for the compilation. */
  public int getThreadCount() {
    return threadCount;
  }

  public boolean getAndroidPlatformBuild() {
    return isAndroidPlatformBuild;
  }

  List<ArtProfileForRewriting> getArtProfilesForRewriting() {
    return artProfilesForRewriting;
  }

  List<StartupProfileProvider> getStartupProfileProviders() {
    return startupProfileProviders;
  }

  ClassConflictResolver getClassConflictResolver() {
    return classConflictResolver;
  }

  public CancelCompilationChecker getCancelCompilationChecker() {
    return cancelCompilationChecker;
  }

  DumpInputFlags getDumpInputFlags() {
    return dumpInputFlags;
  }

  Reporter getReporter() {
    return reporter;
  }

  /**
   * Base builder for compilation commands.
   *
   * @param <C> Command the builder is building, e.g., {@link R8Command} or {@link D8Command}.
   * @param <B> Concrete builder extending this base, e.g., {@link R8Command.Builder} or {@link
   *     D8Command.Builder}.
   */
  @KeepForApi
  public abstract static class Builder<C extends BaseCompilerCommand, B extends Builder<C, B>>
      extends BaseCommand.Builder<C, B> {

    private ProgramConsumer programConsumer = null;
    private StringConsumer mainDexListConsumer = null;
    private Path outputPath = null;
    // TODO(b/70656566): Remove default output mode when deprecated API is removed.
    private OutputMode outputMode = OutputMode.DexIndexed;

    private CompilationMode mode;
    private int minApiLevel = 0;
    private int threadCount = ThreadUtils.NOT_SPECIFIED;
    protected DesugarState desugarState = DesugarState.ON;
    private final List<StringResource> desugaredLibrarySpecificationResources = new ArrayList<>();
    private boolean includeClassesChecksum = false;
    private boolean optimizeMultidexForLinearAlloc = false;
    private BiPredicate<String, Long> dexClassChecksumFilter = (name, checksum) -> true;
    private final List<AssertionsConfiguration> assertionsConfiguration = new ArrayList<>();
    private final List<Consumer<Inspector>> outputInspections = new ArrayList<>();
    protected StringConsumer proguardMapConsumer = null;
    protected PartitionMapConsumer partitionMapConsumer = null;
    private DumpInputFlags dumpInputFlags = DumpInputFlags.getDefault();
    private MapIdProvider mapIdProvider = null;
    private SourceFileProvider sourceFileProvider = null;
    private boolean isAndroidPlatformBuild = false;
    private final List<ArtProfileForRewriting> artProfilesForRewriting = new ArrayList<>();
    private final List<StartupProfileProvider> startupProfileProviders = new ArrayList<>();
    private ClassConflictResolver classConflictResolver = null;
    private CancelCompilationChecker cancelCompilationChecker = null;

    abstract CompilationMode defaultCompilationMode();

    Builder(DiagnosticsHandler diagnosticsHandler) {
      super(diagnosticsHandler);
      mode = defaultCompilationMode();
    }

    // Internal constructor for testing.
    Builder(AndroidApp app) {
      super(AndroidApp.builder(app));
      mode = defaultCompilationMode();
    }

    // Internal constructor for testing.
    Builder(AndroidApp app, DiagnosticsHandler diagnosticsHandler) {
      super(AndroidApp.builder(app, new Reporter(diagnosticsHandler)));
      mode = defaultCompilationMode();
    }

    /**
     * Get current compilation mode.
     */
    public CompilationMode getMode() {
      return mode;
    }

    /**
     * Set compilation mode.
     */
    public B setMode(CompilationMode mode) {
      assert mode != null;
      this.mode = mode;
      return self();
    }

    /**
     * Get the output path.
     *
     * @return Current output path, null if no output path-and-mode have been set.
     * @see #setOutput(Path, OutputMode)
     */
    public Path getOutputPath() {
      return outputPath;
    }

    /**
     * Get the output mode.
     *
     * @return Currently set output mode, null if no output path-and-mode have been set.
     * @see #setOutput(Path, OutputMode)
     */
    public OutputMode getOutputMode() {
      return outputMode;
    }

    /**
     * Get the program consumer.
     *
     * @return The currently set program consumer, null if no program consumer or output
     *     path-and-mode is set, e.g., neither {@link #setProgramConsumer} nor {@link #setOutput}
     *     have been called.
     */
    public ProgramConsumer getProgramConsumer() {
      return programConsumer;
    }

    /**
     * Set an output destination to which proguard-map content should be written.
     *
     * <p>This is a short-hand for setting a {@link StringConsumer.FileConsumer} using {@link
     * #setProguardMapConsumer}. Note that any subsequent call to this method or {@link
     * #setProguardMapConsumer} will override the previous setting.
     *
     * @param proguardMapOutput File-system path to write output at.
     */
    B setProguardMapOutputPath(Path proguardMapOutput) {
      assert proguardMapOutput != null;
      return setProguardMapConsumer(new StringConsumer.FileConsumer(proguardMapOutput));
    }

    /**
     * Set a consumer for receiving the proguard-map content.
     *
     * <p>Note that any subsequent call to this method or {@link #setProguardMapOutputPath} will
     * override the previous setting.
     *
     * @param proguardMapConsumer Consumer to receive the content once produced.
     */
    B setProguardMapConsumer(StringConsumer proguardMapConsumer) {
      this.proguardMapConsumer = proguardMapConsumer;
      return self();
    }

    /** Get the consumer for receiving the proguard-map content or null if unset. */
    public StringConsumer getProguardMapConsumer() {
      return proguardMapConsumer;
    }

    /**
     * Set an output destination to which partition-map content should be written.
     *
     * <p>This is a short-hand for setting a {@link PartitionMapConsumer} using {@link
     * #setPartitionMapConsumer}. Note that any subsequent call to this method or {@link
     * #setPartitionMapConsumer} will override the previous setting.
     *
     * @param partitionMapOutput File-system path to write output at.
     */
    public B setPartitionMapOutputPath(Path partitionMapOutput) {
      assert partitionMapOutput != null;
      return setPartitionMapConsumer(
          PartitionMapZipContainer.createPartitionMapZipContainerConsumer(partitionMapOutput));
    }

    /**
     * Set a consumer for receiving the partition map content.
     *
     * <p>Note that any subsequent call to this method or {@link #setPartitionMapOutputPath} will
     * override the previous setting.
     *
     * @param partitionMapConsumer Consumer to receive the content once produced.
     */
    public B setPartitionMapConsumer(PartitionMapConsumer partitionMapConsumer) {
      this.partitionMapConsumer = partitionMapConsumer;
      return self();
    }

    /**
     * Get the main dex list consumer that will receive the final complete main dex list.
     */
    public StringConsumer getMainDexListConsumer() {
      return mainDexListConsumer;
    }

    /**
     * Filter used to skip parsing of certain class in a dex file.
     */
    public BiPredicate<String, Long> getDexClassChecksumFilter() {
      return dexClassChecksumFilter;
    }

    /**
     * If set to true, legacy multidex partitioning will be optimized to reduce LinearAlloc usage
     * during Dalvik DexOpt. Has no effect when compiling for a target with native multidex support
     * or without main dex list specification.
     */
    public B setOptimizeMultidexForLinearAlloc(boolean optimizeMultidexForLinearAlloc) {
      this.optimizeMultidexForLinearAlloc = optimizeMultidexForLinearAlloc;
      return self();
    }

    /**
     * If true, legacy multidex partitioning will be optimized to reduce LinearAlloc usage during
     * Dalvik DexOpt.
     */
    protected boolean isOptimizeMultidexForLinearAlloc() {
      return optimizeMultidexForLinearAlloc;
    }

    /**
     * Set the program consumer.
     *
     * <p>Setting the program consumer will override any previous set consumer or any previous set
     * output path & mode.
     *
     * @param programConsumer Program consumer to set as current. A null argument will clear the
     *     program consumer / output.
     */
    public B setProgramConsumer(ProgramConsumer programConsumer) {
      // Setting an explicit program consumer resets any output-path/mode setup.
      outputPath = null;
      outputMode = null;
      this.programConsumer = programConsumer;
      return self();
    }

    /**
     * Set an output destination to which main-dex-list content should be written.
     *
     * <p>This is a short-hand for setting a {@link StringConsumer.FileConsumer} using {@link
     * #setMainDexListConsumer}. Note that any subsequent call to this method or {@link
     * #setMainDexListConsumer} will override the previous setting.
     *
     * @param mainDexListOutputPath File-system path to write output at.
     */
    public B setMainDexListOutputPath(Path mainDexListOutputPath) {
      mainDexListConsumer = new StringConsumer.FileConsumer(mainDexListOutputPath);
      return self();
    }

    /**
     * Set a consumer for receiving the main-dex-list content.
     *
     * <p>Note that any subsequent call to this method or {@link #setMainDexListOutputPath} will
     * override the previous setting.
     *
     * @param mainDexListConsumer Consumer to receive the content once produced.
     */
    public B setMainDexListConsumer(StringConsumer mainDexListConsumer) {
      this.mainDexListConsumer = mainDexListConsumer;
      return self();
    }

    /**
     * Set the output path-and-mode.
     *
     * <p>Setting the output path-and-mode will override any previous set consumer or any previous
     * output path-and-mode, and implicitly sets the appropriate program consumer to write the
     * output.
     *
     * @param outputPath Path to write the output to. Must be an archive or and existing directory.
     * @param outputMode Mode in which to write the output.
     */
    public B setOutput(Path outputPath, OutputMode outputMode) {
      return setOutput(outputPath, outputMode, false);
    }

    // This is only public in R8Command.
    protected B setOutput(Path outputPath, OutputMode outputMode, boolean includeDataResources) {
      assert outputPath != null;
      assert outputMode != null;
      this.outputPath = outputPath;
      this.outputMode = outputMode;
      programConsumer = createProgramOutputConsumer(outputPath, outputMode, includeDataResources);
      return self();
    }

    /**
     * Setting a dex class filter.
     *
     * A filter is a function that given a name of a class and a checksum can return false the user
     * decides to skip parsing and ignore that class in the dex file.
     */
    public B setDexClassChecksumFilter(BiPredicate<String, Long> filter) {
      assert filter != null;
      this.dexClassChecksumFilter = filter;
      return self();
    }

    protected InternalProgramOutputPathConsumer createProgramOutputConsumer(
        Path path,
        OutputMode mode,
        boolean consumeDataResources) {
      if (mode == OutputMode.DexIndexed) {
        return FileUtils.isArchive(path)
            ? new DexIndexedConsumer.ArchiveConsumer(path, consumeDataResources)
            : new DexIndexedConsumer.DirectoryConsumer(path, consumeDataResources);
      }
      if (mode == OutputMode.DexFilePerClass) {
        if (FileUtils.isArchive(path)) {
          return new DexFilePerClassFileConsumer.ArchiveConsumer(path, consumeDataResources) {
            @Override
            public boolean combineSyntheticClassesWithPrimaryClass() {
              return false;
            }
          };
        } else {
          return new DexFilePerClassFileConsumer.DirectoryConsumer(path, consumeDataResources) {
            @Override
            public boolean combineSyntheticClassesWithPrimaryClass() {
              return false;
            }
          };
        }
      }
      if (mode == OutputMode.DexFilePerClassFile) {
        return FileUtils.isArchive(path)
            ? new DexFilePerClassFileConsumer.ArchiveConsumer(path, consumeDataResources)
            : new DexFilePerClassFileConsumer.DirectoryConsumer(path, consumeDataResources);
      }
      if (mode == OutputMode.ClassFile) {
        return FileUtils.isArchive(path)
            ? new ClassFileConsumer.ArchiveConsumer(path, consumeDataResources)
            : new ClassFileConsumer.DirectoryConsumer(path, consumeDataResources);
      }
      throw new Unreachable("Unexpected output mode: " + mode);
    }

    /** Get the minimum API level (aka SDK version). */
    public int getMinApiLevel() {
      return isMinApiLevelSet() ? minApiLevel : AndroidApiLevel.getDefault().getLevel();
    }

    boolean isMinApiLevelSet() {
      return minApiLevel != 0;
    }

    /** Set the minimum required API level (aka SDK version). */
    public B setMinApiLevel(int minApiLevel) {
      if (minApiLevel <= 0) {
        getReporter().error("Invalid minApiLevel: " + minApiLevel);
      } else {
        this.minApiLevel = minApiLevel;
      }
      return self();
    }

    @Deprecated
    public B setEnableDesugaring(boolean enableDesugaring) {
      this.desugarState = enableDesugaring ? DesugarState.ON : DesugarState.OFF;
      return self();
    }

    /**
     * Force disable desugaring.
     *
     * <p>There are a few use cases where it makes sense to force disable desugaring, such as:
     * <ul>
     * <li>if all inputs are known to be at most Java 7; or
     * <li>if a separate desugar tool has been used prior to compiling with D8.
     * </ul>
     *
     * <p>Note that even for API 27, desugaring is still required for closures support on ART.
     */
    public B setDisableDesugaring(boolean disableDesugaring) {
      this.desugarState = disableDesugaring ? DesugarState.OFF : DesugarState.ON;
      return self();
    }

    /** Is desugaring forcefully disabled. */
    public boolean getDisableDesugaring() {
      return desugarState == DesugarState.OFF;
    }

    DesugarState getDesugaringState() {
      return desugarState;
    }

    /** Set a custom provider for defining the map id for the build. */
    public B setMapIdProvider(MapIdProvider mapIdProvider) {
      this.mapIdProvider = mapIdProvider;
      return self();
    }

    public MapIdProvider getMapIdProvider() {
      return mapIdProvider;
    }

    /** Set a custom provider for defining source-file attributes for classes. */
    public B setSourceFileProvider(SourceFileProvider sourceFileProvider) {
      this.sourceFileProvider = sourceFileProvider;
      return self();
    }

    public SourceFileProvider getSourceFileProvider() {
      return sourceFileProvider;
    }

    @Deprecated
    @SuppressWarnings("InlineMeSuggester")
    public B addSpecialLibraryConfiguration(String configuration) {
      return addDesugaredLibraryConfiguration(configuration);
    }

    /** Desugared library configuration */
    // Configuration "default" is for testing only and support will be dropped.
    public B addDesugaredLibraryConfiguration(String configuration) {
      this.desugaredLibrarySpecificationResources.add(
          StringResource.fromString(configuration, Origin.unknown()));
      return self();
    }

    /** Desugared library configuration */
    public B addDesugaredLibraryConfiguration(StringResource configuration) {
      this.desugaredLibrarySpecificationResources.add(configuration);
      return self();
    }

    DesugaredLibrarySpecification getDesugaredLibraryConfiguration(
        DexItemFactory factory, boolean libraryCompilation) {
      if (desugaredLibrarySpecificationResources.isEmpty()) {
        return HumanDesugaredLibrarySpecification.empty();
      }
      if (desugaredLibrarySpecificationResources.size() > 1) {
        throw new CompilationError("Only one desugared library configuration is supported.");
      }
      StringResource desugaredLibrarySpecificationResource =
          desugaredLibrarySpecificationResources.get(0);
      return DesugaredLibrarySpecificationParser.parseDesugaredLibrarySpecification(
          desugaredLibrarySpecificationResource,
          factory,
          getReporter(),
          libraryCompilation,
          getMinApiLevel());
    }

    boolean hasDesugaredLibraryConfiguration() {
      return !desugaredLibrarySpecificationResources.isEmpty();
    }

    /** Encodes checksum for each class when generating dex files. */
    public B setIncludeClassesChecksum(boolean enabled) {
      this.includeClassesChecksum = enabled;
      return self();
    }

    /** Set the number of threads to use for the compilation */
    B setThreadCount(int threadCount) {
      if (threadCount <= 0) {
        getReporter().error("Invalid threadCount: " + threadCount);
      } else {
        this.threadCount = threadCount;
      }
      return self();
    }

    int getThreadCount() {
      return threadCount;
    }

    /** Encodes the checksums into the dex output. */
    public boolean getIncludeClassesChecksum() {
      return includeClassesChecksum;
    }

    List<AssertionsConfiguration> getAssertionsConfiguration() {
      return assertionsConfiguration;
    }

    /** Configure compile time assertion enabling through a {@link AssertionsConfiguration}. */
    public B addAssertionsConfiguration(
        Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
            assertionsConfigurationGenerator) {
      assertionsConfiguration.add(
          assertionsConfigurationGenerator.apply(AssertionsConfiguration.builder(getReporter())));
      return self();
    }

    /**
     * Configure the present build as a "Android platform build".
     *
     * <p>A platform build, is a build where the runtime "bootclasspath" is known at compile time.
     * In other words, the specified <i>min-api</i> is also known to be the <i>max-api</i>. In this
     * mode the compiler will disable various features that provide support for newer runtimes as
     * well as disable workarounds for older runtimes.
     */
    public B setAndroidPlatformBuild(boolean isAndroidPlatformBuild) {
      this.isAndroidPlatformBuild = isAndroidPlatformBuild;
      return self();
    }

    public boolean getAndroidPlatformBuild() {
      return isAndroidPlatformBuild;
    }

    /**
     * Add an ART profiles that should be rewritten to match the residual application. The ART
     * profile is given to the compiler by the {@link ArtProfileProvider} and passed back to the
     * {@link ArtProfileConsumer} at the end of compilation when the ART profile has been fully
     * rewritten to match the residual application.
     */
    public B addArtProfileForRewriting(
        ArtProfileProvider artProfileProvider, ArtProfileConsumer residualArtProfileProvider) {
      return addArtProfileForRewriting(
          new ArtProfileForRewriting(artProfileProvider, residualArtProfileProvider));
    }

    B addArtProfileForRewriting(ArtProfileForRewriting artProfileForRewriting) {
      artProfilesForRewriting.add(artProfileForRewriting);
      return self();
    }

    List<ArtProfileForRewriting> getArtProfilesForRewriting() {
      return artProfilesForRewriting;
    }

    B addStartupProfileProviders(StartupProfileProvider... startupProfileProviders) {
      return addStartupProfileProviders(Arrays.asList(startupProfileProviders));
    }

    B addStartupProfileProviders(Collection<StartupProfileProvider> startupProfileProviders) {
      this.startupProfileProviders.addAll(startupProfileProviders);
      return self();
    }

    List<StartupProfileProvider> getStartupProfileProviders() {
      return startupProfileProviders;
    }

    /**
     * Set a cancellation checker.
     *
     * <p>The cancellation checker will be periodically called to check if the compilation should be
     * cancelled before completion.
     */
    public B setCancelCompilationChecker(CancelCompilationChecker checker) {
      this.cancelCompilationChecker = checker;
      return self();
    }

    public CancelCompilationChecker getCancelCompilationChecker() {
      return cancelCompilationChecker;
    }

    /**
     * Allow to skip to dump into file and dump into directory instruction, this is primarily used
     * for chained compilation in L8 so there are no duplicated dumps.
     */
    B skipDump() {
      dumpInputFlags = DumpInputFlags.noDump();
      return self();
    }

    B dumpInputToFile(Path file) {
      dumpInputFlags = DumpInputFlags.dumpToFile(file);
      return self();
    }

    B dumpInputToDirectory(Path directory) {
      dumpInputFlags = DumpInputFlags.dumpToDirectory(directory);
      return self();
    }

    DumpInputFlags getDumpInputFlags() {
      return dumpInputFlags;
    }

    @Override
    void validate() {
      Reporter reporter = getReporter();
      if (mode == null) {
        reporter.error("Expected valid compilation mode, was null");
      }
      FileUtils.validateOutputFile(outputPath, reporter);
      if (getProgramConsumer() == null) {
        // This is never the case for a command-line parse, so we report using API references.
        reporter.error("A ProgramConsumer or Output is required for compilation");
      }
      List<Class> programConsumerClasses = new ArrayList<>(3);
      if (programConsumer instanceof DexIndexedConsumer) {
        programConsumerClasses.add(DexIndexedConsumer.class);
      }
      if (programConsumer instanceof DexFilePerClassFileConsumer) {
        programConsumerClasses.add(DexFilePerClassFileConsumer.class);
      }
      if (programConsumer instanceof ClassFileConsumer) {
        programConsumerClasses.add(ClassFileConsumer.class);
      }
      if (programConsumerClasses.size() > 1) {
        StringBuilder builder = new StringBuilder()
            .append("Invalid program consumer.")
            .append(" A program consumer can implement at most one consumer type but ")
            .append(programConsumer.getClass().getName())
            .append(" implements types:");
        for (Class clazz : programConsumerClasses) {
          builder.append(" ").append(clazz.getName());
        }
        reporter.error(builder.toString());
      }
      if (getMinApiLevel() > AndroidApiLevel.LATEST.getLevel()) {
        if (getMinApiLevel() != AndroidApiLevel.ANDROID_PLATFORM_CONSTANT) {
          reporter.warning(
              "An API level of "
                  + getMinApiLevel()
                  + " is not supported by this compiler. Please use an API level of "
                  + AndroidApiLevel.LATEST.getLevel()
                  + " or earlier");
        }
      }
      if (hasDesugaredLibraryConfiguration() && getAndroidPlatformBuild()) {
        reporter.error("Android platform builds cannot use desugared library");
      }
      super.validate();
    }

    /**
     * Add an inspection of the output program.
     *
     * <p>On a successful compilation the inspection is guaranteed to be called with inspectors that
     * combined cover all of the output program. The inspections may be called multiple times with
     * inspectors that have overlapping content (eg, classes synthesized based on multiple inputs
     * can lead to this). Any overlapping content will be consistent, e.g., the inspection of type T
     * will be the same (equality, not identify) as any other inspection of type T.
     *
     * <p>There is no guarantee of the order inspections are called or on which thread they are
     * called.
     *
     * <p>The validity of an {@code Inspector} and all of its sub-inspectors, eg,
     * {@MethodInspector}, is that of the callback. If any inspector object escapes the scope of the
     * callback, the behavior of that inspector is undefined.
     *
     * @param inspection Inspection callback receiving inspectors denoting parts of the output.
     */
    public B addOutputInspection(Consumer<Inspector> inspection) {
      outputInspections.add(inspection);
      return self();
    }

    List<Consumer<Inspector>> getOutputInspections() {
      return outputInspections;
    }

    /**
     * Set a conflict resolver to determine which class definition to use in case of duplicates.
     *
     * <p>If no resolver is set, the compiler will fail compilation in case of duplicates.
     *
     * @param resolver Resolver for choosing between duplicate classes.
     */
    public B setClassConflictResolver(ClassConflictResolver resolver) {
      this.classConflictResolver = resolver;
      return self();
    }

    ClassConflictResolver getClassConflictResolver() {
      return classConflictResolver;
    }
  }
}
