// 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 static com.android.tools.r8.utils.InternalOptions.DETERMINISTIC_DEBUGGING;
import static com.android.tools.r8.utils.MapConsumerUtils.wrapExistingInternalMapConsumerIfNotNull;

import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.inspector.Inspector;
import com.android.tools.r8.inspector.internal.InspectorImpl;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.metadata.D8BuildMetadata;
import com.android.tools.r8.naming.InternalMapConsumer;
import com.android.tools.r8.naming.InternalMapConsumerImpl;
import com.android.tools.r8.origin.ArchiveEntryOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.profile.art.ArtProfileForRewriting;
import com.android.tools.r8.shaking.ProguardConfigurationParser;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.shaking.ProguardConfigurationSource;
import com.android.tools.r8.shaking.ProguardConfigurationSourceFile;
import com.android.tools.r8.shaking.ProguardConfigurationSourceStrings;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.synthesis.GlobalSyntheticsResourceBytes;
import com.android.tools.r8.synthesis.GlobalSyntheticsResourceFile;
import com.android.tools.r8.synthesis.GlobalSyntheticsUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
import com.android.tools.r8.utils.DumpInputFlags;
import com.android.tools.r8.utils.InternalGlobalSyntheticsProgramProvider;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.InternalOptions.HorizontalClassMergerOptions;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.android.tools.r8.utils.InternalOptions.MappingComposeOptions;
import com.android.tools.r8.utils.ProgramClassCollection;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.internal.FileUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

/**
 * Immutable command structure for an invocation of the {@link D8} compiler.
 *
 * <p>To build a D8 command use the {@link D8Command.Builder} class. For example:
 *
 * <pre>
 *   D8Command command = D8Command.builder()
 *     .addProgramFiles(path1, path2)
 *     .setMode(CompilationMode.RELEASE)
 *     .setOutput(Paths.get("output.zip", OutputMode.DexIndexed))
 *     .build();
 * </pre>
 */
@KeepForApi
public final class D8Command extends BaseCompilerCommand {

  private static class DefaultD8DiagnosticsHandler implements DiagnosticsHandler {

    @Override
    public void error(Diagnostic error) {
      if (error instanceof DexFileOverflowDiagnostic) {
        DexFileOverflowDiagnostic overflowDiagnostic = (DexFileOverflowDiagnostic) error;
        if (!overflowDiagnostic.hasMainDexSpecification()) {
          DiagnosticsHandler.super.error(
              new StringDiagnostic(
                  overflowDiagnostic.getDiagnosticMessage() + ". Try supplying a main-dex list"));
          return;
        }
      }
      DiagnosticsHandler.super.error(error);
    }
  }

  /**
   * Builder for constructing a D8Command.
   *
   * <p>A builder is obtained by calling {@link D8Command#builder}.
   */
  @KeepForApi
  public static class Builder extends BaseCompilerCommand.Builder<D8Command, Builder> {

    private boolean intermediate = false;
    private Path globalSyntheticsOutput = null;
    private GlobalSyntheticsConsumer globalSyntheticsConsumer = null;
    private final List<GlobalSyntheticsResourceProvider> globalSyntheticsResourceProviders =
        new ArrayList<>();
    private DesugarGraphConsumer desugarGraphConsumer = null;
    private SyntheticInfoConsumer syntheticInfoConsumer = null;
    private String synthesizedClassPrefix =
        System.getProperty("com.android.tools.r8.synthesizedClassPrefix", "");
    private boolean enableMainDexListCheck = true;
    private boolean minimalMainDex = false;
    private final List<ProguardConfigurationSource> mainDexRules = new ArrayList<>();
    private boolean enableMissingLibraryApiModeling = false;
    private boolean enableRewritingOfArtProfilesIsNopCheck = false;
    private Consumer<? super D8BuildMetadata> buildMetadataConsumer = null;
    // This flag represents the use case where already compiled code is recompiled via D8 to a
    // higher API level.
    private boolean reoptimizeDex = false;

    private Builder() {
      this(new DefaultD8DiagnosticsHandler());
    }

    private Builder(DiagnosticsHandler diagnosticsHandler) {
      super(diagnosticsHandler);
    }

    private Builder(AndroidApp app) {
      super(app);
    }

    /**
     * Add dex program-data.
     */
    @Override
    public Builder addDexProgramData(byte[] data, Origin origin) {
      guard(() -> getAppBuilder().addDexProgramData(data, origin));
      return self();
    }

    /**
     * Add classpath file resources. These have @Override to ensure binary compatibility.
     */
    @Override
    public Builder addClasspathFiles(Path... files) {
      return super.addClasspathFiles(files);
    }

    /**
     * Add classpath file resources.
     */
    @Override
    public Builder addClasspathFiles(Collection<Path> files) {
      return super.addClasspathFiles(files);
    }

    /**
     * Add classfile resources provider for class-path resources.
     */
    @Override
    public Builder addClasspathResourceProvider(ClassFileResourceProvider provider) {
      return super.addClasspathResourceProvider(provider);
    }

    /**
     * Set input proguard map used for distribution of classes in multi-dex. Use {@link
     * #setProguardMapInputFile}
     */
    @Deprecated()
    public Builder setProguardInputMapFile(Path proguardInputMap) {
      getAppBuilder().setProguardMapInputData(proguardInputMap);
      return self();
    }

    /** Set input proguard map used for distribution of classes in multi-dex. */
    public Builder setProguardMapInputFile(Path proguardInputMap) {
      getAppBuilder().setProguardMapInputData(proguardInputMap);
      return self();
    }

    /**
     * Set a consumer for receiving the proguard-map content.
     *
     * <p>Note that when a proguard-map consumer is specified for a release build, the compiler will
     * optimize the line-number information and obtaining a source-level stacktrace will require the
     * use of a retrace tool exactly as is needed for programs built by R8.
     *
     * <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.
     */
    @Override
    public Builder setProguardMapConsumer(StringConsumer proguardMapConsumer) {
      return super.setProguardMapConsumer(proguardMapConsumer);
    }

    /**
     * Set an output destination to which proguard-map content should be written.
     *
     * <p>Note that when a proguard-map output is specified for a release build, the compiler will
     * optimize the line-number information and obtaining a source-level stacktrace will require the
     * use of a retrace tool exactly as is needed for programs built by R8.
     *
     * <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.
     */
    @Override
    public Builder setProguardMapOutputPath(Path proguardMapOutput) {
      return super.setProguardMapOutputPath(proguardMapOutput);
    }

    /**
     * Set an output destination to which partition-map content should be written.
     *
     * <p>Note that when a proguard-map output is specified for a release build, the compiler will
     * optimize the line-number information and obtaining a source-level stacktrace will require the
     * use of a retrace tool exactly as is needed for programs built by R8.
     *
     * <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.
     */
    @Override
    public Builder setPartitionMapOutputPath(Path partitionMapOutput) {
      assert partitionMapOutput != null;
      return super.setPartitionMapOutputPath(partitionMapOutput);
    }

    /**
     * Set a consumer for receiving the partition map content.
     *
     * <p>Note that when a proguard-map output is specified for a release build, the compiler will
     * optimize the line-number information and obtaining a source-level stacktrace will require the
     * use of a retrace tool exactly as is needed for programs built by R8.
     *
     * <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.
     */
    @Override
    public Builder setPartitionMapConsumer(PartitionMapConsumer partitionMapConsumer) {
      assert partitionMapConsumer != null;
      return super.setPartitionMapConsumer(partitionMapConsumer);
    }

    /**
     * Indicate if compilation is to intermediate results, i.e., intended for later merging.
     *
     * <p>When compiling to intermediate mode, the compiler will avoid sharing of synthetic items,
     * and instead annotate them as synthetics for possible later merging. For global synthetics,
     * the compiler will emit these to a separate consumer (see {@code GlobalSyntheticsConsumer}
     * with the expectation that a later build step will consume them again as part of a
     * non-intermediate build (see {@code GlobalSyntheticsResourceProvider}. Synthetic items
     * typically come from the desugaring of various language features, such as lambdas and default
     * interface methods. Global synthetics are non-local in that many compilation units may
     * reference the same synthetic. For example, desugaring records requires a global tag to
     * distinguish the class of all records.
     *
     * <p>Intermediate mode is implied if compiling results to a "file-per-class-file".
     */
    public Builder setIntermediate(boolean value) {
      this.intermediate = value;
      return self();
    }

    /**
     * Set an output path for receiving the global synthetic content for the given compilation.
     *
     * <p>Note: this output is ignored if the compilation is not an "intermediate mode" compilation.
     *
     * <p>Note: setting this will clear out any consumer set by setGlobalSyntheticsConsumer.
     */
    public Builder setGlobalSyntheticsOutput(Path globalSyntheticsOutput) {
      this.globalSyntheticsConsumer = null;
      this.globalSyntheticsOutput = globalSyntheticsOutput;
      return self();
    }

    /**
     * Set a consumer for receiving the global synthetic content for the given compilation.
     *
     * <p>Note: this consumer is ignored if the compilation is not an "intermediate mode"
     * compilation.
     *
     * <p>Note: setting this will clear out any output path set by setGlobalSyntheticsOutput.
     */
    public Builder setGlobalSyntheticsConsumer(GlobalSyntheticsConsumer globalSyntheticsConsumer) {
      this.globalSyntheticsOutput = null;
      this.globalSyntheticsConsumer = globalSyntheticsConsumer;
      return self();
    }

    /** Add global synthetics resource providers. */
    public Builder addGlobalSyntheticsResourceProviders(
        GlobalSyntheticsResourceProvider... providers) {
      return addGlobalSyntheticsResourceProviders(Arrays.asList(providers));
    }

    /** Add global synthetics resource providers. */
    public Builder addGlobalSyntheticsResourceProviders(
        Collection<GlobalSyntheticsResourceProvider> providers) {
      providers.forEach(globalSyntheticsResourceProviders::add);
      return self();
    }

    /** Add global synthetics resource files. */
    public Builder addGlobalSyntheticsFiles(Path... files) {
      return addGlobalSyntheticsFiles(Arrays.asList(files));
    }

    /** Add global synthetics resource files. */
    public Builder addGlobalSyntheticsFiles(Collection<Path> files) {
      for (Path file : files) {
        addGlobalSyntheticsFileOrArchiveOfGlobalSynthetics(file);
      }
      return self();
    }

    private void addGlobalSyntheticsFileOrArchiveOfGlobalSynthetics(Path file) {
      if (!FileUtils.isZipFile(file)) {
        addGlobalSyntheticsResourceProviders(new GlobalSyntheticsResourceFile(file));
        return;
      }
      PathOrigin origin = new PathOrigin(file);
      try {
        ZipUtils.iter(
            file,
            (entry, input) ->
                addGlobalSyntheticsResourceProviders(
                    new GlobalSyntheticsResourceBytes(
                        new ArchiveEntryOrigin(entry.getName(), origin),
                        ByteStreams.toByteArray(input))));
      } catch (IOException e) {
        error(origin, e);
      }
    }

    /**
     * Get the consumer that will receive dependency information for desugaring.
     */
    public DesugarGraphConsumer getDesugarGraphConsumer() {
      return desugarGraphConsumer;
    }

    /**
     * Set the consumer that will receive dependency information for desugaring.
     *
     * <p>Setting the consumer will clear any previously set consumer.
     */
    public Builder setDesugarGraphConsumer(DesugarGraphConsumer desugarGraphConsumer) {
      this.desugarGraphConsumer = desugarGraphConsumer;
      return self();
    }

    /** Get the consumer that will receive information about compiler synthesized classes. */
    public SyntheticInfoConsumer getSyntheticInfoConsumer() {
      return syntheticInfoConsumer;
    }

    /**
     * Set the consumer that will receive information about compiler synthesized classes.
     *
     * <p>Setting the consumer will clear any previously set consumer.
     */
    public Builder setSyntheticInfoConsumer(SyntheticInfoConsumer syntheticInfoConsumer) {
      this.syntheticInfoConsumer = syntheticInfoConsumer;
      return self();
    }

    /**
     * Add a collection of startup profile providers that should be used for distributing the
     * program classes in dex.
     *
     * <p>NOTE: Startup profiles are ignored when compiling to class files or the min-API level does
     * not support native multidex (API<=20).
     */
    @Override
    public Builder addStartupProfileProviders(StartupProfileProvider... startupProfileProviders) {
      return super.addStartupProfileProviders(startupProfileProviders);
    }

    /**
     * Add a collection of startup profile providers that should be used for distributing the
     * program classes in dex.
     *
     * <p>NOTE: Startup profiles are ignored when compiling to class files or the min-API level does
     * not support native multidex (API<=20).
     */
    @Override
    public Builder addStartupProfileProviders(
        Collection<StartupProfileProvider> startupProfileProviders) {
      return super.addStartupProfileProviders(startupProfileProviders);
    }

    @Override
    Builder self() {
      return this;
    }

    @Override
    CompilationMode defaultCompilationMode() {
      return CompilationMode.DEBUG;
    }

    Builder setSynthesizedClassesPrefix(String prefix) {
      synthesizedClassPrefix = prefix;
      return self();
    }

    @Deprecated
    // Internal helper for supporting bazel integration.
    Builder setEnableMainDexListCheck(boolean value) {
      enableMainDexListCheck = value;
      return self();
    }

    @Deprecated
    // Internal helper for supporting bazel integration.
    Builder setMinimalMainDex(boolean value) {
      minimalMainDex = value;
      return self();
    }

    /** Add proguard configuration files with rules for automatic main-dex-list calculation. */
    public Builder addMainDexRulesFiles(Path... paths) {
      return addMainDexRulesFiles(Arrays.asList(paths));
    }

    /** Add proguard configuration files with rules for automatic main-dex-list calculation. */
    public Builder addMainDexRulesFiles(Collection<Path> paths) {
      guard(() -> paths.forEach(p -> mainDexRules.add(new ProguardConfigurationSourceFile(p))));
      return self();
    }

    /** Add proguard rules for automatic main-dex-list calculation. */
    public Builder addMainDexRules(List<String> lines, Origin origin) {
      String config = String.join(System.lineSeparator(), lines);
      mainDexRules.add(new ProguardConfigurationSourceStrings(config, Paths.get("."), origin));
      return self();
    }

    /**
     * Enable experimental/pre-release support for modeling missing library APIs.
     *
     * <p>This allows enabling the feature while it is still default disabled by the compiler. Once
     * the feature is default enabled, calling this method will have no affect.
     */
    @Deprecated
    public Builder setEnableExperimentalMissingLibraryApiModeling(boolean enable) {
      this.enableMissingLibraryApiModeling = enable;
      return self();
    }

    Builder setEnableRewritingOfArtProfilesIsNopCheck() {
      enableRewritingOfArtProfilesIsNopCheck = true;
      return self();
    }

    /**
     * Set a consumer for receiving metadata about the current build intended for being stored in
     * the app bundle.
     */
    public Builder setBuildMetadataConsumer(
        Consumer<? super D8BuildMetadata> buildMetadataConsumer) {
      this.buildMetadataConsumer = buildMetadataConsumer;
      return self();
    }

    /**
     * Enable experimental/pre-release support for reoptimizing dex code to a new minimum android
     * API.
     */
    @Deprecated
    public Builder setExperimentalReoptimizeDex(boolean reoptimizeDex) {
      this.reoptimizeDex = reoptimizeDex;
      return self();
    }

    /**
     * By default, D8 uses the same naming scheme for synthetic classes as javac uses for anonymous
     * inner classes. By enabling verbose synthetic names, the synthetic classes will include a
     * "$$ExternalSynthetic" marker, which includes the synthetic kind (e.g., "Lambda").
     */
    @Override
    public Builder setEnableVerboseSyntheticNames(boolean enableVerboseSyntheticNames) {
      return super.setEnableVerboseSyntheticNames(enableVerboseSyntheticNames);
    }

    @Override
    void validate() {
      if (isPrintHelp()) {
        return;
      }
      Reporter reporter = getReporter();
      if (getAppBuilder().hasMainDexList()) {
        if (intermediate) {
          reporter.error("Option --main-dex-list cannot be used with --intermediate");
        }
        if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
          reporter.error("Option --main-dex-list cannot be used with --file-per-class");
        }
      }
      if (!mainDexRules.isEmpty()) {
        if (intermediate) {
          reporter.error("Option --main-dex-rules cannot be used with --intermediate");
        }
        if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
          reporter.error("Option --main-dex-rules cannot be used with --file-per-class");
        }
      }
      if (getMainDexListConsumer() != null
          && mainDexRules.isEmpty()
          && !getAppBuilder().hasMainDexList()) {
        reporter.error(
            "Option --main-dex-list-output requires --main-dex-rules and/or --main-dex-list");
      }
      if (getMinApiLevel() >= AndroidApiLevel.L_MR1.getLevel()) {
        if (getMainDexListConsumer() != null || getAppBuilder().hasMainDexList()) {
          reporter.error(
              "D8 does not support main-dex inputs and outputs when compiling to API level "
                  + AndroidApiLevel.L_MR1.getLevel()
                  + " and above (min API level "
                  + getMinApiLevel()
                  + " was provided)");
        }
      }
      if (hasDesugaredLibraryConfiguration() && getDisableDesugaring()) {
        reporter.error("Using desugared library configuration requires desugaring to be enabled");
      }
      if (getProgramConsumer() instanceof ClassFileConsumer
          && getDisableDesugaring()
          && isMinApiLevelSet()) {
        reporter.error("Compiling to CF with --min-api and --no-desugaring is not supported");
      }
      if (!getStartupProfileProviders().isEmpty()) {
        if (intermediate) {
          reporter.error("D8 startup layout is not supported in intermediate mode");
        }
        if (getMinApiLevel() < AndroidApiLevel.L.getLevel()) {
          reporter.error(
              "D8 startup layout requires native multi dex support (API level "
                  + AndroidApiLevel.L.getLevel()
                  + " and above, min API level "
                  + getMinApiLevel()
                  + " was provided)");
        }
      }
      if (reoptimizeDex) {
        if (!isMinApiLevelSet()) {
          reporter.error("Option --reoptimize-dex requires --min-api");
        }
        if (intermediate) {
          reporter.error("Option --reoptimize-dex cannot be used with --intermediate");
        }
        if (getMode() != CompilationMode.RELEASE) {
          reporter.error("Option --reoptimize-dex requires --release");
        }
        if (proguardMapConsumer != null) {
          reporter.error("Option --reoptimize-dex cannot be used with an output mapping file");
        }
      }
      super.validate();
    }

    @Override
    D8Command makeCommand() {
      if (isPrintHelp() || isPrintVersion()) {
        return new D8Command(isPrintHelp(), isPrintVersion());
      }
      return makeD8Command(new DexItemFactory());
    }

    D8Command makeD8Command(DexItemFactory factory) {
      final ProgramConsumer programConsumer = getProgramConsumer();
      intermediate |= programConsumer instanceof DexFilePerClassFileConsumer;

      DesugaredLibrarySpecification desugaredLibrarySpecification =
          getDesugaredLibraryConfiguration(factory, false);

      ImmutableList<ProguardConfigurationRule> mainDexKeepRules =
          ProguardConfigurationParser.parseMainDex(mainDexRules, factory, getReporter());

      if (!globalSyntheticsResourceProviders.isEmpty()) {
        addProgramResourceProvider(
            new InternalGlobalSyntheticsProgramProvider(globalSyntheticsResourceProviders));
      }

      // If compiling to CF with --no-desugaring then the target API is B for consistency with R8.
      int minApiLevel =
          programConsumer instanceof ClassFileConsumer && getDisableDesugaring()
              ? AndroidApiLevel.B.getLevel()
              : getMinApiLevel();

      GlobalSyntheticsConsumer globalConsumer =
          GlobalSyntheticsUtils.determineGlobalSyntheticsConsumer(
              intermediate, globalSyntheticsOutput, globalSyntheticsConsumer, programConsumer);

      return new D8Command(
          getAppBuilder().build(),
          getMode(),
          programConsumer,
          getMainDexListConsumer(),
          minApiLevel,
          getReporter(),
          getDesugaringState(),
          intermediate,
          reoptimizeDex,
          globalConsumer,
          isOptimizeMultidexForLinearAlloc(),
          getIncludeClassesChecksum(),
          getDexClassChecksumFilter(),
          getDesugarGraphConsumer(),
          getSyntheticInfoConsumer(),
          desugaredLibrarySpecification,
          getAssertionsConfiguration(),
          getOutputInspections(),
          synthesizedClassPrefix,
          enableMainDexListCheck,
          minimalMainDex,
          mainDexKeepRules,
          getThreadCount(),
          getDumpInputFlags(),
          getMapIdProvider(),
          proguardMapConsumer,
          partitionMapConsumer,
          enableMissingLibraryApiModeling,
          enableRewritingOfArtProfilesIsNopCheck,
          enableVerboseSyntheticNames,
          buildMetadataConsumer,
          getAndroidPlatformBuild(),
          getArtProfilesForRewriting(),
          getStartupProfileProviders(),
          getClassConflictResolver(),
          getCancelCompilationChecker(),
          factory);
    }
  }

  private final boolean intermediate;
  private final boolean reoptimizeDex;
  private final GlobalSyntheticsConsumer globalSyntheticsConsumer;
  private final SyntheticInfoConsumer syntheticInfoConsumer;
  private final DesugarGraphConsumer desugarGraphConsumer;
  private final DesugaredLibrarySpecification desugaredLibrarySpecification;
  private final String synthesizedClassPrefix;
  private final boolean enableMainDexListCheck;
  private final boolean minimalMainDex;
  private final ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
  private final MapConsumer proguardMapConsumer;
  private final PartitionMapConsumer partitionMapConsumer;
  private final boolean enableMissingLibraryApiModeling;
  private final boolean enableRewritingOfArtProfilesIsNopCheck;
  private final DexItemFactory factory;
  private final Consumer<? super D8BuildMetadata> buildMetadataConsumer;

  public static Builder builder() {
    return new Builder();
  }

  public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
    return new Builder(diagnosticsHandler);
  }

  // Internal builder to start from an existing AndroidApp.
  static Builder builder(AndroidApp app) {
    return new Builder(app);
  }

  /**
   * Parse the D8 command-line.
   *
   * <p>Parsing will set the supplied options or their default value if they have any.
   *
   * @param args Command-line arguments array.
   * @param origin Origin description of the command-line arguments.
   * @return D8 command builder with state set up according to parsed command line.
   */
  public static Builder parse(String[] args, Origin origin) {
    return D8CommandParser.parse(args, origin);
  }

  /**
   * Parse the D8 command-line.
   *
   * <p>Parsing will set the supplied options or their default value if they have any.
   *
   * @param args Command-line arguments array.
   * @param origin Origin description of the command-line arguments.
   * @param handler Custom defined diagnostics handler.
   * @return D8 command builder with state set up according to parsed command line.
   */
  public static Builder parse(String[] args, Origin origin, DiagnosticsHandler handler) {
    return D8CommandParser.parse(args, origin, handler);
  }

  /** Get the help description for the D8 supported flags. */
  public static List<ParseFlagInfo> getParseFlagsInformation() {
    return D8CommandParser.getFlags();
  }

  private D8Command(
      AndroidApp inputApp,
      CompilationMode mode,
      ProgramConsumer programConsumer,
      StringConsumer mainDexListConsumer,
      int minApiLevel,
      Reporter diagnosticsHandler,
      DesugarState enableDesugaring,
      boolean intermediate,
      boolean reoptimizeDex,
      GlobalSyntheticsConsumer globalSyntheticsConsumer,
      boolean optimizeMultidexForLinearAlloc,
      boolean encodeChecksum,
      BiPredicate<String, Long> dexClassChecksumFilter,
      DesugarGraphConsumer desugarGraphConsumer,
      SyntheticInfoConsumer syntheticInfoConsumer,
      DesugaredLibrarySpecification desugaredLibrarySpecification,
      List<AssertionsConfiguration> assertionsConfiguration,
      List<Consumer<Inspector>> outputInspections,
      String synthesizedClassPrefix,
      boolean enableMainDexListCheck,
      boolean minimalMainDex,
      ImmutableList<ProguardConfigurationRule> mainDexKeepRules,
      int threadCount,
      DumpInputFlags dumpInputFlags,
      MapIdProvider mapIdProvider,
      MapConsumer proguardMapConsumer,
      PartitionMapConsumer partitionMapConsumer,
      boolean enableMissingLibraryApiModeling,
      boolean enableRewritingOfArtProfilesIsNopCheck,
      boolean enableVerboseSyntheticNames,
      Consumer<? super D8BuildMetadata> buildMetadataConsumer,
      boolean isAndroidPlatformBuild,
      List<ArtProfileForRewriting> artProfilesForRewriting,
      List<StartupProfileProvider> startupProfileProviders,
      ClassConflictResolver classConflictResolver,
      CancelCompilationChecker cancelCompilationChecker,
      DexItemFactory factory) {
    super(
        inputApp,
        mode,
        programConsumer,
        mainDexListConsumer,
        minApiLevel,
        diagnosticsHandler,
        enableDesugaring,
        optimizeMultidexForLinearAlloc,
        encodeChecksum,
        dexClassChecksumFilter,
        assertionsConfiguration,
        outputInspections,
        threadCount,
        dumpInputFlags,
        mapIdProvider,
        null,
        isAndroidPlatformBuild,
        artProfilesForRewriting,
        startupProfileProviders,
        classConflictResolver,
        cancelCompilationChecker,
        enableVerboseSyntheticNames);
    this.intermediate = intermediate;
    this.reoptimizeDex = reoptimizeDex;
    this.globalSyntheticsConsumer = globalSyntheticsConsumer;
    this.syntheticInfoConsumer = syntheticInfoConsumer;
    this.desugarGraphConsumer = desugarGraphConsumer;
    this.desugaredLibrarySpecification = desugaredLibrarySpecification;
    this.synthesizedClassPrefix = synthesizedClassPrefix;
    this.enableMainDexListCheck = enableMainDexListCheck;
    this.minimalMainDex = minimalMainDex;
    this.mainDexKeepRules = mainDexKeepRules;
    this.proguardMapConsumer = proguardMapConsumer;
    this.partitionMapConsumer = partitionMapConsumer;
    this.enableMissingLibraryApiModeling = enableMissingLibraryApiModeling;
    this.enableRewritingOfArtProfilesIsNopCheck = enableRewritingOfArtProfilesIsNopCheck;
    this.factory = factory;
    this.buildMetadataConsumer = buildMetadataConsumer;
  }

  private D8Command(boolean printHelp, boolean printVersion) {
    super(printHelp, printVersion);
    intermediate = false;
    reoptimizeDex = false;
    globalSyntheticsConsumer = null;
    syntheticInfoConsumer = null;
    desugarGraphConsumer = null;
    desugaredLibrarySpecification = null;
    synthesizedClassPrefix = null;
    enableMainDexListCheck = true;
    minimalMainDex = false;
    mainDexKeepRules = null;
    proguardMapConsumer = null;
    partitionMapConsumer = null;
    enableMissingLibraryApiModeling = false;
    enableRewritingOfArtProfilesIsNopCheck = false;
    factory = null;
    buildMetadataConsumer = null;
  }

  @Override
  InternalOptions getInternalOptions() {
    InternalOptions internal = new InternalOptions(factory, getReporter());
    assert !internal.debug;
    internal.d8BuildMetadataConsumer = buildMetadataConsumer;
    internal.debug = getMode() == CompilationMode.DEBUG;
    internal.programConsumer = getProgramConsumer();
    if (internal.isGeneratingClassFiles()) {
      // Turn off switch optimizations when generating class files.
      assert internal.enableSwitchRewriting;
      internal.enableSwitchRewriting = false;
      assert internal.enableStringSwitchConversion;
      internal.enableStringSwitchConversion = false;
    } else {
      assert !internal.desugarSpecificOptions().allowAllDesugaredInput
          || getDesugarState() == DesugarState.OFF;
    }
    internal.mainDexListConsumer = getMainDexListConsumer();
    internal.minimalMainDex = internal.debug || minimalMainDex;
    internal.enableMainDexListCheck = enableMainDexListCheck;
    internal.setMinApiLevel(AndroidApiLevel.getAndroidApiLevel(getMinApiLevel()));
    internal.intermediate = intermediate;
    if (reoptimizeDex) { // Respect potential system property.
      internal.enableDexToDexCodeOptimizations = reoptimizeDex;
    }
    internal.retainCompileTimeAnnotations = intermediate;
    internal.setGlobalSyntheticsConsumer(globalSyntheticsConsumer);
    internal.setSyntheticInfoConsumer(syntheticInfoConsumer);
    internal.desugarGraphConsumer = desugarGraphConsumer;
    internal.mainDexKeepRules = mainDexKeepRules;
    internal.emitLambdaMethodAnnotations =
        !internal.disableLambdaMethodAnnotations
            && (internal.emitLambdaMethodAnnotations
                || (internal.debug
                    && (!internal.intermediate || internal.hasGlobalSyntheticsConsumer())));
    InternalMapConsumer mapConsumer =
        wrapExistingInternalMapConsumerIfNotNull(
            internal.mapConsumer, partitionMapConsumer, MapConsumerToPartitionMapConsumer::new);
    internal.mapConsumer =
        wrapExistingInternalMapConsumerIfNotNull(
            mapConsumer,
            proguardMapConsumer,
            nonNullStringConsumer ->
                InternalMapConsumerImpl.builder().setMapConsumer(proguardMapConsumer).build());
    internal.lineNumberOptimization =
        !internal.debug && proguardMapConsumer != null
            ? LineNumberOptimization.ON
            : LineNumberOptimization.OFF;
    MappingComposeOptions mappingComposeOptions = internal.mappingComposeOptions();
    mappingComposeOptions.enableExperimentalMappingComposition = true;
    // Assert and fixup defaults.
    assert !internal.isShrinking();
    assert !internal.isMinifying();
    assert !internal.passthroughDexCode;
    internal.passthroughDexCode = true;

    // Assert some of R8 optimizations are disabled.
    assert !internal.enableClassInlining;
    assert !internal.enableEnumValueOptimization;
    assert !internal.outline.enabled;
    assert !internal.enableTreeShakingOfLibraryMethodOverrides;

    internal.desugarState = getDesugarState();
    internal.desugarSpecificOptions().enableVerboseSyntheticNames = enableVerboseSyntheticNames;
    internal.encodeChecksums = getIncludeClassesChecksum();
    internal.dexClassChecksumFilter = getDexClassChecksumFilter();
    internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();

    internal
        .getLibraryDesugaringOptions()
        .configureDesugaredLibrary(desugaredLibrarySpecification, synthesizedClassPrefix);

    if (internal.isGeneratingClassFiles()
        || (System.getProperty("com.android.tools.r8.enableApiOutliningAndStubbing") == null
            && !enableMissingLibraryApiModeling)) {
      internal.apiModelingOptions().disableApiModeling();
    }

    if (enableRewritingOfArtProfilesIsNopCheck) {
      internal.getArtProfileOptions().setEnableNopCheckForTesting();
    }

    // Default is to remove all javac generated assertion code when generating dex.
    assert internal.assertionsConfiguration == null;
    internal.assertionsConfiguration =
        new AssertionConfigurationWithDefault(
            AssertionsConfiguration.builder(getReporter())
                .setCompileTimeDisable()
                .setScopeAll()
                .build(),
            getAssertionsConfiguration());

    internal.outputInspections = InspectorImpl.wrapInspections(getOutputInspections());

    if (!DETERMINISTIC_DEBUGGING) {
      assert internal.threadCount == ThreadUtils.NOT_SPECIFIED;
      internal.threadCount = getThreadCount();
    }

    // Disable global optimizations.
    internal.disableGlobalOptimizations();

    HorizontalClassMergerOptions horizontalClassMergerOptions =
        internal.horizontalClassMergerOptions();
    if (internal.isGeneratingDex()) {
      horizontalClassMergerOptions.setRestrictToSynthetics();
    } else {
      assert internal.isGeneratingClassFiles();
      horizontalClassMergerOptions.disable();
    }

    internal.configureAndroidPlatformBuild(getAndroidPlatformBuild());

    internal.getArtProfileOptions().setArtProfilesForRewriting(getArtProfilesForRewriting());
    if (!getStartupProfileProviders().isEmpty()) {
      internal.getStartupOptions().setStartupProfileProviders(getStartupProfileProviders());
    }

    internal.programClassConflictResolver =
        ProgramClassCollection.wrappedConflictResolver(
            getClassConflictResolver(), internal.reporter);

    internal.cancelCompilationChecker = getCancelCompilationChecker();

    internal.tool = Tool.D8;
    internal.setDumpInputFlags(getDumpInputFlags());
    internal.dumpOptions = dumpOptions();

    return internal;
  }

  private DumpOptions dumpOptions() {
    DumpOptions.Builder builder = DumpOptions.builder(Tool.D8).readCurrentSystemProperties();
    dumpBaseCommandOptions(builder);
    return builder
        .setIntermediate(intermediate)
        .setDesugaredLibraryConfiguration(desugaredLibrarySpecification)
        .setMainDexKeepRules(mainDexKeepRules)
        .setEnableMissingLibraryApiModeling(enableMissingLibraryApiModeling)
        .setHasProguardMapConsumer(proguardMapConsumer != null)
        .build();
  }

}
