// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.android;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType.UNQUOTED;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.TRISTATE;
import static com.google.devtools.build.lib.packages.StarlarkProviderIdentifier.forKey;
import static com.google.devtools.build.lib.rules.android.AndroidCommon.getAndroidConfig;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.IterablesChain;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.java.JavaCommon;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaCompilationInfoProvider;
import com.google.devtools.build.lib.rules.java.JavaInfo;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.JavaOutput;
import com.google.devtools.build.lib.rules.java.proto.JavaProtoAspectCommon;
import com.google.devtools.build.lib.rules.java.proto.JavaProtoLibraryAspectProvider;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.rules.proto.ProtoLangToolchainProvider;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Aspect to {@link DexArDchiveProvider build .dex Archives} from Jars. */
public class DexArchiveAspect extends NativeAspectClass implements ConfiguredAspectFactory {
  public static final String NAME = "DexArchiveAspect";

  /**
   * Function that returns a {@link Rule}'s {@code incremental_dexing} attribute for use by this
   * aspect. Must be provided when attaching this aspect to a target.
   */
  @SerializationConstant
  public static final Function<Rule, AspectParameters> PARAM_EXTRACTOR =
      (Rule rule) -> {
        AttributeMap attributes = NonconfigurableAttributeMapper.of(rule);
        AspectParameters.Builder result = new AspectParameters.Builder();
        TriState incrementalAttr = attributes.get("incremental_dexing", TRISTATE);
        result.addAttribute("incremental_dexing", incrementalAttr.name());
        return result.build();
      };
  /**
   * Function that limits this aspect to Java 8 desugaring (disabling incremental dexing) when
   * attaching this aspect to a target. This is intended for implicit attributes like the stub APKs
   * for {@code bazel mobile-install}.
   */
  @SerializationConstant
  static final Function<Rule, AspectParameters> ONLY_DESUGAR_JAVA8 =
      (Rule rule) ->
          new AspectParameters.Builder()
              .addAttribute("incremental_dexing", TriState.NO.name())
              .build();
  /** Aspect-only label for dexbuidler executable, to avoid name clashes with labels on rules. */
  private static final String ASPECT_DEXBUILDER_PREREQ = "$dex_archive_dexbuilder";
  /** Aspect-only label for desugaring executable, to avoid name clashes with labels on rules. */
  private static final String ASPECT_DESUGAR_PREREQ = "$aspect_desugar";

  private static final ImmutableList<String> TRANSITIVE_ATTRIBUTES =
      ImmutableList.of(
          "deps",
          "exports",
          "runtime_deps",
          // Propagate the aspect down legacy toolchain dependencies. This won't work for platform-
          // based toolchains, which aren't connected to an attribute. See
          // propagateDownLegacyToolchain for how this distinction is handled.
          ":android_sdk",
          "aidl_lib", // for the aidl runtime in the android_sdk rule
          "$toolchain", // this is _toolchain in Starlark rules (b/78647825)
          "$build_stamp_deps", // for build stamp runtime class deps
          "$build_stamp_mergee_manifest_lib", // for empty build stamp Service class implementation
          // To get from proto_library through proto_lang_toolchain rule to proto runtime library.
          JavaProtoAspectCommon.LITE_PROTO_TOOLCHAIN_ATTR,
          "runtime");

  private static final FlagMatcher DEXOPTS_SUPPORTED_IN_DEXBUILDER =
      new FlagMatcher(
          ImmutableList.of("--no-locals", "--no-optimize", "--no-warnings", "--positions"));

  private final RepositoryName toolsRepository;
  private final String sdkToolchainLabel;

  public DexArchiveAspect(RepositoryName toolsRepository, String sdkToolchainLabel) {
    this.toolsRepository = toolsRepository;
    this.sdkToolchainLabel = sdkToolchainLabel;
  }

  /**
   * Don't propagate down the legacy toolchain attribute when using platform-based toolchains.
   *
   * <p>With platform-based toolchains, propagating down the legacy toolchain attribute means we'll
   * dex the legacy toolchain, not the platform-based toolchain. Aside from being conceptually
   * wrong, this breaks builds if the toolchains aren't configured the same way.
   *
   * <p>For example, platform-based toolchains evaluate in the host configuration while legacy
   * toolchains evaluate in the target configuration (--incompatible_override_toolchain_transition
   * would reduce this difference but that's not enabled). This produces "Dependencies on .jar
   * artifacts are not allowed in Android binaries" errors ({@link AndroidBinary}). This happens
   * because that logic compares classpaths, which use platform-based toolchains, with dexed paths,
   * which in this example use legacy toolchains. If the paths don't match everything blows up.
   *
   * <p>Even if that worked, platform-based toolchain logic isn't complete unless legacy toolchains
   * are never used anywhere. For that reason alone we also need to skip propagation.
   */
  private static boolean propagateDownLegacyToolchain(Object obj, String attrName) {
    if (!attrName.equals(":android_sdk")) {
      // Not the toolchain attribute. Carry on as usual.
      return true;
    }
    AndroidConfiguration androidConfig =
        ((BuildConfigurationValue) obj).getFragment(AndroidConfiguration.class);
    return !androidConfig.incompatibleUseToolchainResolution();
  }

  @Override
  public AspectDefinition getDefinition(AspectParameters params) {
    AspectDefinition.Builder result =
        new AspectDefinition.Builder(this)
            .propagateViaAttribute(DexArchiveAspect::propagateDownLegacyToolchain)
            .requireStarlarkProviders(forKey(JavaInfo.PROVIDER.getKey()))
            // Latch onto Starlark toolchains in case they have a "runtime" (b/78647825)
            .requireStarlarkProviders(forKey(ToolchainInfo.PROVIDER.getKey()))
            // For android_sdk rules, where we just want to get at aidl runtime deps.
            .requireStarlarkProviders(forKey(AndroidSdkProvider.PROVIDER.getKey()))
            .requireStarlarkProviders(forKey(ProtoInfo.PROVIDER.getKey()))
            .requireStarlarkProviderSets(
                ImmutableList.of(
                    // For proto_lang_toolchain rules, where we just want to get at their runtime
                    // deps.
                    ImmutableSet.of(ProtoLangToolchainProvider.PROVIDER.id())))
            .addToolchainTypes(
                ToolchainTypeRequirement.create(
                    Label.parseAbsoluteUnchecked(toolsRepository + sdkToolchainLabel)))
            // Parse labels since we don't have RuleDefinitionEnvironment.getLabel like in a rule
            .add(
                attr(ASPECT_DESUGAR_PREREQ, LABEL)
                    .cfg(ExecutionTransitionFactory.create())
                    .exec()
                    .value(
                        Label.parseAbsoluteUnchecked(
                            toolsRepository + "//tools/android:desugar_java8")))
            // Access to --android_sdk so we can stub in a bootclasspath for desugaring if missing
            .add(
                attr(":dex_archive_android_sdk", LABEL)
                    .allowedRuleClasses("android_sdk", "filegroup")
                    .value(
                        AndroidRuleClasses.getAndroidSdkLabel(
                            Label.parseAbsoluteUnchecked(
                                toolsRepository + AndroidRuleClasses.DEFAULT_SDK))))
            .requiresConfigurationFragments(AndroidConfiguration.class)
            .requireAspectsWithProviders(
                ImmutableList.of(ImmutableSet.of(forKey(JavaInfo.PROVIDER.getKey()))))
            .requireAspectsWithBuiltinProviders(JavaProtoLibraryAspectProvider.class);
    if (TriState.valueOf(params.getOnlyValueOfAttribute("incremental_dexing")) != TriState.NO) {
      // Marginally improves "query2" precision for targets that disable incremental dexing
      result.add(
          attr(ASPECT_DEXBUILDER_PREREQ, LABEL)
              .cfg(ExecutionTransitionFactory.create())
              .exec()
              .value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/android:dexbuilder")));
    }
    for (String attr : TRANSITIVE_ATTRIBUTES) {
      result.propagateAlongAttribute(attr);
    }
    return result.build();
  }

  /**
   * Returns toolchain .jars that need dexing for platform-based toolchains.
   *
   * <p>Legacy toolchains handle these .jars recursively by propagating the aspect down the
   * ":android_sdk" attribute. So they don't need this method.
   */
  private static Iterable<Artifact> getPlatformBasedToolchainJars(RuleContext ruleContext) {
    if (!ruleContext
        .getConfiguration()
        .getFragment(AndroidConfiguration.class)
        .incompatibleUseToolchainResolution()) {
      // Legacy toolchains: toolchain .jars are dexed by propagating the aspect down the
      // ":android_sdk" attribute. That makes them transitive deps, so no special logic is needed
      // in the parent target to process them.
      return ImmutableList.of();

    } else if (!ruleContext.attributes().has(":android_sdk")) {
      // If we're dexing a non-Android target (like a java_library), there's no Android toolchain to
      // include.
      return ImmutableList.of();
    }

    AndroidSdkProvider androidSdk = AndroidSdkProvider.fromRuleContext(ruleContext);
    if (androidSdk == null || androidSdk.getAidlLib() == null) {
      // If the Android SDK is null, we don't have a valid toolchain. Expect a rule error reported
      // from AndroidSdkProvider.
      return ImmutableList.of();
    }
    return ImmutableList.copyOf(
        JavaInfo.getJavaInfo(androidSdk.getAidlLib()).getDirectRuntimeJars());
  }

  @Override
  public ConfiguredAspect create(
      ConfiguredTargetAndData ctadBase,
      RuleContext ruleContext,
      AspectParameters params,
      RepositoryName toolsRepository)
      throws InterruptedException, ActionConflictException {
    ConfiguredAspect.Builder result = new ConfiguredAspect.Builder(ruleContext);

    Iterable<Artifact> extraToolchainJars = getPlatformBasedToolchainJars(ruleContext);

    Function<Artifact, Artifact> desugaredJars =
        desugarJarsIfRequested(
            ctadBase.getConfiguredTarget(), ruleContext, result, extraToolchainJars);

    TriState incrementalAttr =
        TriState.valueOf(params.getOnlyValueOfAttribute("incremental_dexing"));
    if (incrementalAttr == TriState.NO
        || (!getAndroidConfig(ruleContext).useIncrementalDexing()
            && incrementalAttr == TriState.AUTO)) {
      // Dex archives will never be used, so don't bother setting them up.
      return result.build();
    }

    if (JavaCommon.isNeverLink(ruleContext)) {
      return result.addProvider(DexArchiveProvider.NEVERLINK).build();
    }

    DexArchiveProvider.Builder dexArchives =
        new DexArchiveProvider.Builder()
            .addTransitiveProviders(collectPrerequisites(ruleContext, DexArchiveProvider.class));
    Iterable<Artifact> runtimeJars =
        getProducedRuntimeJars(ctadBase.getConfiguredTarget(), ruleContext, extraToolchainJars);
    if (runtimeJars != null) {
      boolean basenameClash = checkBasenameClash(runtimeJars);
      Set<Set<String>> aspectDexopts = aspectDexopts(ruleContext);
      for (Artifact jar : runtimeJars) {
        for (Set<String> incrementalDexopts : aspectDexopts) {
          // Since we're potentially dexing the same jar multiple times with different flags, we
          // need to write unique artifacts for each flag combination. Here, it is convenient to
          // distinguish them by putting the flags that were used for creating the artifacts into
          // their filenames.
          String uniqueFilename =
              (basenameClash ? jar.getRootRelativePathString() : jar.getFilename())
                  + Joiner.on("").join(incrementalDexopts)
                  + ".dex.zip";
          Artifact dexArchive =
              createDexArchiveAction(
                  ruleContext,
                  ASPECT_DEXBUILDER_PREREQ,
                  desugaredJars.apply(jar),
                  incrementalDexopts,
                  AndroidBinary.getDxArtifact(ruleContext, uniqueFilename));
          dexArchives.addDexArchive(incrementalDexopts, dexArchive, jar);
        }
      }
    }
    return result.addProvider(dexArchives.build()).build();
  }

  /**
   * Runs Jars in {@link JavaInfo#getDirectRuntimeJars()} through desugaring action if flag is set
   * and adds the result to {@code result}. Note that this cannot happen in a separate aspect
   * because aspects don't see providers added by other aspects executed on the same target.
   */
  private Function<Artifact, Artifact> desugarJarsIfRequested(
      ConfiguredTarget base,
      RuleContext ruleContext,
      ConfiguredAspect.Builder result,
      Iterable<Artifact> extraToolchainJars) {
    if (!getAndroidConfig(ruleContext).desugarJava8()) {
      return Functions.identity();
    }
    Map<Artifact, Artifact> newlyDesugared = new HashMap<>();
    if (JavaCommon.isNeverLink(ruleContext)) {
      result.addProvider(AndroidRuntimeJarProvider.NEVERLINK);
      return Functions.forMap(newlyDesugared);
    }
    AndroidRuntimeJarProvider.Builder desugaredJars =
        new AndroidRuntimeJarProvider.Builder()
            .addTransitiveProviders(
                collectPrerequisites(ruleContext, AndroidRuntimeJarProvider.class));
    if (isProtoLibrary(ruleContext)) {
      // TODO(b/33557068): Desugar protos if needed instead of assuming they don't need desugaring
      result.addProvider(desugaredJars.build());
      return Functions.identity();
    }

    JavaInfo javaInfo = JavaInfo.getJavaInfo(base);
    if (javaInfo != null) {
      // These are all transitive hjars of dependencies and hjar of the jar itself
      NestedSet<Artifact> compileTimeClasspath =
          getJavaCompilationArgsProvider(base, ruleContext).getTransitiveCompileTimeJars();
      ImmutableSet.Builder<Artifact> jars = ImmutableSet.builder();
      jars.addAll(javaInfo.getDirectRuntimeJars());

      Artifact rJar = getAndroidLibraryRJar(base);
      if (rJar != null) {
        // TODO(b/124540821): Disable R.jar desugaring (with a flag).
        jars.add(rJar);
      }

      Artifact buildStampJar = getAndroidBuildStampJar(base);
      if (buildStampJar != null) {
        jars.add(buildStampJar);
      }

      // For android_* targets we need to honor their bootclasspath (nicer in general to do so)
      NestedSet<Artifact> bootclasspath = getBootclasspath(base, ruleContext);

      jars.addAll(extraToolchainJars);
      ImmutableSet<Artifact> jarsToProcess = jars.build();
      boolean basenameClash = checkBasenameClash(jarsToProcess);
      for (Artifact jar : jarsToProcess) {
        Artifact desugared =
            createDesugarAction(
                ruleContext, basenameClash, jar, bootclasspath, compileTimeClasspath);
        newlyDesugared.put(jar, desugared);
        desugaredJars.addDesugaredJar(jar, desugared);
      }
    }
    result.addProvider(desugaredJars.build());
    return Functions.forMap(newlyDesugared);
  }

  private static Iterable<Artifact> getProducedRuntimeJars(
      ConfiguredTarget base, RuleContext ruleContext, Iterable<Artifact> extraToolchainJars) {
    if (isProtoLibrary(ruleContext)) {
      if (!ruleContext.getPrerequisites("srcs").isEmpty()) {
        JavaRuleOutputJarsProvider outputJarsProvider =
            base.getProvider(JavaRuleOutputJarsProvider.class);
        if (outputJarsProvider != null) {
          return outputJarsProvider.getJavaOutputs().stream()
              .map(JavaOutput::getClassJar)
              .collect(toImmutableList());
        } else {
          JavaInfo javaInfo = JavaInfo.getJavaInfo(base);
          if (javaInfo != null) {
            return javaInfo.getDirectRuntimeJars();
          }
        }
      }
    } else {
      ImmutableSet.Builder<Artifact> jars = ImmutableSet.builder();
      JavaInfo javaInfo = JavaInfo.getJavaInfo(base);
      if (javaInfo != null) {
        jars.addAll(javaInfo.getDirectRuntimeJars());
      }

      Artifact rJar = getAndroidLibraryRJar(base);
      if (rJar != null) {
          jars.add(rJar);
      }

      Artifact buildStampJar = getAndroidBuildStampJar(base);
      if (buildStampJar != null) {
        jars.add(buildStampJar);
      }

      jars.addAll(extraToolchainJars);
      return jars.build();
    }
    return null;
  }

  private static JavaCompilationArgsProvider getJavaCompilationArgsProvider(
      ConfiguredTarget base, RuleContext ruleContext) {
    JavaCompilationArgsProvider provider =
        JavaInfo.getProvider(JavaCompilationArgsProvider.class, base);
    if (provider != null) {
      return provider;
    }
    return isProtoLibrary(ruleContext) ? base.getProvider(JavaCompilationArgsProvider.class) : null;
  }

  private static boolean isProtoLibrary(RuleContext ruleContext) {
    return "proto_library".equals(ruleContext.getRule().getRuleClass());
  }

  private static Artifact getAndroidLibraryRJar(ConfiguredTarget base) {
    AndroidIdeInfoProvider provider =
        (AndroidIdeInfoProvider) base.get(AndroidIdeInfoProvider.PROVIDER.getKey());
    if (provider != null && provider.getResourceJarJavaOutput() != null) {
      return provider.getResourceJarJavaOutput().getClassJar();
    }
    return null;
  }

  private static Artifact getAndroidBuildStampJar(ConfiguredTarget base) {
    AndroidApplicationResourceInfo provider =
        (AndroidApplicationResourceInfo) base.get(AndroidApplicationResourceInfo.PROVIDER.getKey());
    if (provider != null && provider.getBuildStampJar() != null) {
      return provider.getBuildStampJar();
    }
    return null;
  }

  private static boolean checkBasenameClash(Iterable<Artifact> artifacts) {
    HashSet<String> seen = new HashSet<>();
    for (Artifact artifact : artifacts) {
      if (!seen.add(artifact.getFilename())) {
        return true;
      }
    }
    return false;
  }

  private static <T extends TransitiveInfoProvider> Iterable<T> collectPrerequisites(
      RuleContext ruleContext, Class<T> classType) {
    IterablesChain.Builder<T> result = IterablesChain.builder();
    for (String attr : TRANSITIVE_ATTRIBUTES) {
      if (ruleContext.attributes().getAttributeType(attr) != null) {
        result.add(ruleContext.getPrerequisites(attr, classType));
      }
    }
    return result.build();
  }

  private static NestedSet<Artifact> getBootclasspath(
      ConfiguredTarget base, RuleContext ruleContext) {
    JavaCompilationInfoProvider compilationInfo =
        JavaInfo.getProvider(JavaCompilationInfoProvider.class, base);
    if (compilationInfo == null || compilationInfo.getBootClasspath().isEmpty()) {
      return NestedSetBuilder.<Artifact>naiveLinkOrder()
          .add(
              ruleContext
                  .getPrerequisite(
                      ":dex_archive_android_sdk",
                      AndroidSdkProvider.PROVIDER)
                  .getAndroidJar())
          .build();
    }
    return compilationInfo.getBootClasspathAsNestedSet();
  }

  private Artifact createDesugarAction(
      RuleContext ruleContext,
      boolean disambiguateBasenames,
      Artifact jar,
      NestedSet<Artifact> bootclasspath,
      NestedSet<Artifact> compileTimeClasspath) {
    return createDesugarAction(
        ruleContext,
        ASPECT_DESUGAR_PREREQ,
        jar,
        bootclasspath,
        compileTimeClasspath,
        AndroidBinary.getDxArtifact(
            ruleContext,
            (disambiguateBasenames ? jar.getRootRelativePathString() : jar.getFilename())
                + "_desugared.jar"));
  }

  private static Artifact createDesugarAction(
      RuleContext ruleContext,
      String desugarPrereqName,
      Artifact jar,
      NestedSet<Artifact> bootclasspath,
      NestedSet<Artifact> classpath,
      Artifact result) {
    CustomCommandLine.Builder args =
        new CustomCommandLine.Builder()
            .addExecPath("--input", jar)
            .addExecPath("--output", result)
            .addExecPaths(VectorArg.addBefore("--classpath_entry").each(classpath))
            .addExecPaths(VectorArg.addBefore("--bootclasspath_entry").each(bootclasspath));
    if (getAndroidConfig(ruleContext).checkDesugarDeps()) {
      args.add("--emit_dependency_metadata_as_needed");
    }
    if (getAndroidConfig(ruleContext).desugarJava8Libs()) {
      args.add("--desugar_supported_core_libs");
    }

    ruleContext.registerAction(
        new SpawnAction.Builder()
            .useDefaultShellEnvironment()
            .setExecutable(ruleContext.getExecutablePrerequisite(desugarPrereqName))
            .addInput(jar)
            .addTransitiveInputs(bootclasspath)
            .addTransitiveInputs(classpath)
            .addOutput(result)
            .setMnemonic("Desugar")
            .setProgressMessage("Desugaring %s for Android", jar.prettyPrint())
            .setExecutionInfo(ExecutionRequirements.WORKER_MODE_ENABLED)
            .addCommandLine(
                // Always use params file, so we don't need to compute command line length first
                args.build(), ParamFileInfo.builder(UNQUOTED).setUseAlways(true).build())
            .build(ruleContext));
    return result;
  }

  /**
   * Desugars the given Jar using an executable prerequisite {@code "$desugar"}. Rules calling this
   * method must declare the appropriate prerequisite, similar to how {@link #getDefinition} does it
   * for {@link DexArchiveAspect} under a different name.
   *
   * <p>It's useful to have this action separately since callers need to look up classpath and
   * bootclasspath in a different way than this aspect does it.
   *
   * @return the artifact given as {@code result}, which can simplify calling code
   */
  static Artifact desugar(
      RuleContext ruleContext,
      Artifact jar,
      NestedSet<Artifact> bootclasspath,
      NestedSet<Artifact> classpath,
      Artifact result) {
    return createDesugarAction(ruleContext, "$desugar", jar, bootclasspath, classpath, result);
  }

  /**
   * Creates a dexbuilder action with the given input, output, and flags. Flags must have been
   * filtered and normalized to a set that the dexbuilder tool can understand.
   *
   * @return the artifact given as {@code result}, which can simplify calling code
   */
  // Package-private method for use in AndroidBinary
  static Artifact createDexArchiveAction(
      RuleContext ruleContext,
      String dexbuilderPrereq,
      Artifact jar,
      Set<String> incrementalDexopts,
      Artifact dexArchive) {
    CustomCommandLine args =
        new CustomCommandLine.Builder()
            .addExecPath("--input_jar", jar)
            .addExecPath("--output_zip", dexArchive)
            .addAll(ImmutableList.copyOf(incrementalDexopts))
            .build();
    SpawnAction.Builder dexbuilder =
        new SpawnAction.Builder()
            .useDefaultShellEnvironment()
            .setExecutable(ruleContext.getExecutablePrerequisite(dexbuilderPrereq))
            .setExecutionInfo(
                TargetUtils.getExecutionInfo(
                    ruleContext.getRule(), ruleContext.isAllowTagsPropagation()))
            // WorkerSpawnStrategy expects the last argument to be @paramfile
            .addInput(jar)
            .addOutput(dexArchive)
            .setMnemonic("DexBuilder")
            .setProgressMessage(
                "Dexing %s with applicable dexopts %s", jar.prettyPrint(), incrementalDexopts)
            // Always use params file for compatibility with WorkerSpawnStrategy
            .addCommandLine(args, ParamFileInfo.builder(UNQUOTED).setUseAlways(true).build());
    if (getAndroidConfig(ruleContext).useWorkersWithDexbuilder()) {
      dexbuilder.setExecutionInfo(ExecutionRequirements.WORKER_MODE_ENABLED);
    }
    ruleContext.registerAction(dexbuilder.build(ruleContext));
    return dexArchive;
  }

  private static Set<Set<String>> aspectDexopts(RuleContext ruleContext) {
    return Sets.powerSet(
        normalizeDexopts(getAndroidConfig(ruleContext).getDexoptsSupportedInIncrementalDexing()));
  }

  /**
   * Derives options to use in incremental dexing actions from the given context and dx flags, where
   * the latter typically come from a {@code dexopts} attribute on a top-level target. This method
   * only works reliably if the given dexopts were tokenized, e.g., using {@link
   * RuleContext#getTokenizedStringListAttr}.
   */
  static ImmutableSet<String> incrementalDexopts(
      RuleContext ruleContext, Iterable<String> tokenizedDexopts) {
    return normalizeDexopts(
        Iterables.filter(
            tokenizedDexopts,
            // dexopts have to match exactly since aspect only creates archives for listed ones
            Predicates.in(getAndroidConfig(ruleContext).getDexoptsSupportedInIncrementalDexing())));
  }

  /**
   * Returns the subset of the given dexopts that are forbidden from using incremental dexing by
   * default.
   */
  static Iterable<String> forbiddenDexopts(RuleContext ruleContext, List<String> dexopts) {
    return Iterables.filter(
        dexopts,
        new FlagMatcher(
            getAndroidConfig(ruleContext).getTargetDexoptsThatPreventIncrementalDexing()));
  }

  /**
   * Derives options to use in DexBuilder actions from the given context and dx flags, where the
   * latter typically come from a {@code dexopts} attribute on a top-level target. This should be a
   * superset of {@link #incrementalDexopts}.
   */
  static ImmutableSet<String> topLevelDexbuilderDexopts(Iterable<String> tokenizedDexopts) {
    // We don't need an ordered set but might as well.
    return normalizeDexopts(Iterables.filter(tokenizedDexopts, DEXOPTS_SUPPORTED_IN_DEXBUILDER));
  }

  /**
   * Derives options to use in DexFileMerger actions from the given context and dx flags, where the
   * latter typically come from a {@code dexopts} attribute on a top-level target.
   */
  static ImmutableSet<String> mergerDexopts(
      RuleContext ruleContext, Iterable<String> tokenizedDexopts) {
    // We don't need an ordered set but might as well.  Note we don't need to worry about coverage
    // builds since the merger doesn't use --no-locals.
    return normalizeDexopts(
        Iterables.filter(
            tokenizedDexopts,
            new FlagMatcher(getAndroidConfig(ruleContext).getDexoptsSupportedInDexMerger())));
  }

  /**
   * Derives options to use in DexFileSharder actions from the given context and dx flags, where the
   * latter typically come from a {@code dexopts} attribute on a top-level target.
   */
  static ImmutableSet<String> sharderDexopts(
      RuleContext ruleContext, Iterable<String> tokenizedDexopts) {
    // We don't need an ordered set but might as well.  Note we don't need to worry about coverage
    // builds since the merger doesn't use --no-locals.
    return normalizeDexopts(
        Iterables.filter(
            tokenizedDexopts,
            new FlagMatcher(getAndroidConfig(ruleContext).getDexoptsSupportedInDexSharder())));
  }

  private static ImmutableSet<String> normalizeDexopts(Iterable<String> tokenizedDexopts) {
    // Sort and use ImmutableSet to drop duplicates and get fixed (sorted) order.  Fixed order is
    // important so we generate one dex archive per set of flag in create() method, regardless of
    // how those flags are listed in all the top-level targets being built.
    return Streams.stream(tokenizedDexopts)
        .map(FlagConverter.DX_TO_DEXBUILDER)
        .sorted()
        .collect(ImmutableSet.toImmutableSet()); // collector with dedupe
  }

  private static class FlagMatcher implements Predicate<String> {
    private final ImmutableList<String> matching;

    FlagMatcher(ImmutableList<String> matching) {
      this.matching = matching;
    }

    @Override
    public boolean apply(String input) {
      for (String match : matching) {
        if (input.contains(match)) {
          return true;
        }
      }
      return false;
    }
  }

  private enum FlagConverter implements Function<String, String> {
    DX_TO_DEXBUILDER;

    @Override
    public String apply(String input) {
      return input.replace("--no-", "--no");
    }
  }
}
