// Copyright 2014 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.analysis;

import static com.google.devtools.build.lib.analysis.ExtraActionUtils.createExtraActionProvider;
import static com.google.devtools.build.lib.packages.RuleClass.Builder.STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.Actions;
import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics;
import com.google.devtools.build.lib.analysis.constraints.EnvironmentCollection;
import com.google.devtools.build.lib.analysis.constraints.SupportedEnvironments;
import com.google.devtools.build.lib.analysis.constraints.SupportedEnvironmentsProvider;
import com.google.devtools.build.lib.analysis.constraints.SupportedEnvironmentsProvider.RemovedEnvironmentCulprit;
import com.google.devtools.build.lib.analysis.test.AnalysisTestActionBuilder;
import com.google.devtools.build.lib.analysis.test.AnalysisTestResultInfo;
import com.google.devtools.build.lib.analysis.test.ExecutionInfo;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesCollector;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo;
import com.google.devtools.build.lib.analysis.test.TestActionBuilder;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.analysis.test.TestEnvironmentInfo;
import com.google.devtools.build.lib.analysis.test.TestProvider;
import com.google.devtools.build.lib.analysis.test.TestProvider.TestParams;
import com.google.devtools.build.lib.analysis.test.TestTagsProvider;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.AllowlistChecker;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildSetting;
import com.google.devtools.build.lib.packages.Info;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.LabelClass;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
 * Builder class for analyzed rule instances.
 *
 * <p>This is used to tell Bazel which {@link TransitiveInfoProvider}s are produced by the analysis
 * of a configured target. For more information about analysis, see {@link
 * RuleConfiguredTargetFactory}.
 *
 * @see RuleConfiguredTargetFactory
 */
public final class RuleConfiguredTargetBuilder {
  private final RuleContext ruleContext;
  private final TransitiveInfoProviderMapBuilder providersBuilder =
      new TransitiveInfoProviderMapBuilder();
  private final Map<String, NestedSetBuilder<Artifact>> outputGroupBuilders = new TreeMap<>();
  private final ImmutableList.Builder<Artifact> additionalTestActionTools =
      new ImmutableList.Builder<>();

  /** These are supported by all configured targets and need to be specially handled. */
  private NestedSet<Artifact> filesToBuild = NestedSetBuilder.emptySet(Order.STABLE_ORDER);

  private final NestedSetBuilder<Artifact> filesToRunBuilder = NestedSetBuilder.stableOrder();
  private RunfilesSupport runfilesSupport;
  private Runfiles persistentTestRunnerRunfiles;
  private Artifact executable;
  private final ImmutableSet<ActionAnalysisMetadata> actionsWithoutExtraAction = ImmutableSet.of();

  public RuleConfiguredTargetBuilder(RuleContext ruleContext) {
    this.ruleContext = ruleContext;
    // Avoid building validations in analysis tests (b/143988346)
    add(LicensesProvider.class, LicensesProviderImpl.of(ruleContext));
    add(VisibilityProvider.class, new VisibilityProviderImpl(ruleContext.getVisibility()));
  }

  /**
   * Constructs the RuleConfiguredTarget instance based on the values set for this Builder. Returns
   * null if there were rule errors reported.
   */
  @Nullable
  public ConfiguredTarget build() throws ActionConflictException, InterruptedException {
    // If allowing analysis failures, the current target may not propagate all of the
    // expected providers; be lenient on such cases (for example, avoid precondition checks).
    boolean allowAnalysisFailures = ruleContext.getConfiguration().allowAnalysisFailures();

    if (ruleContext.getConfiguration().enforceConstraints()) {
      checkConstraints();
    }

    for (AllowlistChecker allowlistChecker :
        ruleContext.getRule().getRuleClassObject().getAllowlistCheckers()) {
      handleAllowlistChecker(allowlistChecker);
    }

    if (ruleContext.hasErrors() && !allowAnalysisFailures) {
      return null;
    }

    maybeAddRequiredConfigFragmentsProvider();

    NestedSetBuilder<Artifact> runfilesMiddlemenBuilder = NestedSetBuilder.stableOrder();
    if (runfilesSupport != null) {
      runfilesMiddlemenBuilder.add(runfilesSupport.getRunfilesMiddleman());
      runfilesMiddlemenBuilder.addTransitive(runfilesSupport.getRunfiles().getExtraMiddlemen());
    }
    NestedSet<Artifact> runfilesMiddlemen = runfilesMiddlemenBuilder.build();
    FilesToRunProvider filesToRunProvider =
        new FilesToRunProvider(
            buildFilesToRun(runfilesMiddlemen, filesToBuild), runfilesSupport, executable);
    addProvider(new FileProvider(filesToBuild));
    addProvider(filesToRunProvider);

    if (runfilesSupport != null) {
      // If a binary is built, build its runfiles, too
      addOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL, runfilesMiddlemen);
    } else if (providersBuilder.contains(RunfilesProvider.class)) {
      // If we don't have a RunfilesSupport (probably because this is not a binary rule), we still
      // want to build the files this rule contributes to runfiles of dependent rules so that we
      // report an error if one of these is broken.
      //
      // Note that this is a best-effort thing: there is .getDataRunfiles() and all the language-
      // specific *RunfilesProvider classes, which we don't add here for reasons that are lost in
      // the mists of time.
      addOutputGroup(
          OutputGroupInfo.HIDDEN_TOP_LEVEL,
          providersBuilder
              .getProvider(RunfilesProvider.class)
              .getDefaultRunfiles()
              .getAllArtifacts());
    }

    if (propagateValidationActionOutputGroup()) {
      propagateTransitiveValidationOutputGroups();
    }

    // Add a default provider that forwards InstrumentedFilesInfo from dependencies, even if this
    // rule doesn't configure InstrumentedFilesInfo. This needs to be done for non-test rules
    // as well, but should be done before initializeTestProvider, which uses that.
    if (ruleContext.getConfiguration().isCodeCoverageEnabled()
        && !providersBuilder.contains(InstrumentedFilesInfo.STARLARK_CONSTRUCTOR.getKey())) {
      addNativeDeclaredProvider(InstrumentedFilesCollector.forwardAll(ruleContext));
    }
    // Create test action and artifacts if target was successfully initialized
    // and is a test. Also, as an extreme hack, only bother doing this if the TestConfiguration
    // is actually present.
    if (TargetUtils.isTestRule(ruleContext.getTarget())) {
      ImmutableList<String> testTags = ImmutableList.copyOf(ruleContext.getRule().getRuleTags());
      add(TestTagsProvider.class, new TestTagsProvider(testTags));
      if (ruleContext.getConfiguration().hasFragment(TestConfiguration.class)) {
        if (runfilesSupport != null) {
          add(TestProvider.class, initializeTestProvider(filesToRunProvider));
        } else {
          if (!allowAnalysisFailures) {
            throw new IllegalStateException("Test rules must have runfiles");
          }
        }
      }
    }

    ExtraActionArtifactsProvider extraActionsProvider =
        createExtraActionProvider(actionsWithoutExtraAction, ruleContext);
    add(ExtraActionArtifactsProvider.class, extraActionsProvider);

    if (!outputGroupBuilders.isEmpty()) {
      ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
      for (Map.Entry<String, NestedSetBuilder<Artifact>> entry : outputGroupBuilders.entrySet()) {
        outputGroups.put(entry.getKey(), entry.getValue().build());
      }

      OutputGroupInfo outputGroupInfo = new OutputGroupInfo(outputGroups.build());
      addNativeDeclaredProvider(outputGroupInfo);
    }

    if (ruleContext.getConfiguration().evaluatingForAnalysisTest()) {
      if (ruleContext.getRule().isAnalysisTest()) {
        ruleContext.ruleError(
            String.format(
                "analysis_test rule '%s' cannot be transitively "
                    + "depended on by another analysis test rule",
                ruleContext.getLabel()));
        return null;
      }
      addProvider(new TransitiveLabelsInfo(transitiveLabels()));
    }

    if (ruleContext.getRule().hasAnalysisTestTransition()) {
      NestedSet<Label> labels = transitiveLabels();
      int depCount = labels.toList().size();
      if (depCount > ruleContext.getConfiguration().analysisTestingDepsLimit()) {
        ruleContext.ruleError(
            String.format(
                "analysis test rule excedeed maximum dependency edge count. "
                    + "Count: %s. Limit is %s. This limit is imposed on analysis test rules which "
                    + "use analysis_test_transition attribute transitions. Exceeding this limit "
                    + "indicates either the analysis_test has too many dependencies, or the "
                    + "underlying toolchains may be large. Try decreasing the number of test "
                    + "dependencies, (Analysis tests should not be very large!) or, if possible, "
                    + "try not using configuration transitions. If underlying toolchain size is "
                    + "to blame, it might be worth considering increasing "
                    + "--analysis_testing_deps_limit. (Beware, however, that large values of "
                    + "this flag can lead to no safeguards against giant "
                    + "test suites that can lead to Out Of Memory exceptions in the build server.)",
                depCount, ruleContext.getConfiguration().analysisTestingDepsLimit()));
        return null;
      }
    }

    if (ruleContext.getRule().isBuildSetting()) {
      BuildSetting buildSetting = ruleContext.getRule().getRuleClassObject().getBuildSetting();
      Object defaultValue =
          ruleContext
              .attributes()
              .get(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, buildSetting.getType());
      addProvider(
          BuildSettingProvider.class,
          new BuildSettingProvider(buildSetting, defaultValue, ruleContext.getLabel()));
    }
    TransitiveInfoProviderMap providers = providersBuilder.build();

    if (ruleContext.getRule().isAnalysisTest()) {
      // If the target is an analysis test that returned AnalysisTestResultInfo, register a
      // test pass/fail action on behalf of the target.
      AnalysisTestResultInfo testResultInfo =
          providers.get(AnalysisTestResultInfo.STARLARK_CONSTRUCTOR);

      if (testResultInfo == null) {
        ruleContext.ruleError(
            "rules with analysis_test=true must return an instance of AnalysisTestResultInfo");
        return null;
      }

      AnalysisTestActionBuilder.writeAnalysisTestAction(ruleContext, testResultInfo);
    }

    AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
    GeneratingActions generatingActions =
        Actions.assignOwnersAndFilterSharedActionsAndThrowActionConflict(
            analysisEnvironment.getActionKeyContext(),
            analysisEnvironment.getRegisteredActions(),
            ruleContext.getOwner(),
            ((Rule) ruleContext.getTarget()).getOutputFiles());
    return new RuleConfiguredTarget(
        ruleContext,
        providers,
        generatingActions.getActions(),
        generatingActions.getArtifactsByOutputLabel());
  }

  private boolean propagateValidationActionOutputGroup() {
    return !ruleContext.getRule().isAnalysisTest();
  }

  /** Actually process */
  private void handleAllowlistChecker(AllowlistChecker allowlistChecker) {
    if (allowlistChecker.attributeSetTrigger() != null
        && !ruleContext
            .getRule()
            .isAttributeValueExplicitlySpecified(allowlistChecker.attributeSetTrigger())) {
      return;
    }
    boolean passing = false;
    switch (allowlistChecker.locationCheck()) {
      case INSTANCE:
        passing = Allowlist.isAvailable(ruleContext, allowlistChecker.allowlistAttr());
        break;
      case DEFINITION:
        passing =
            Allowlist.isAvailableBasedOnRuleLocation(ruleContext, allowlistChecker.allowlistAttr());
        break;
      case INSTANCE_OR_DEFINITION:
        passing =
            Allowlist.isAvailable(ruleContext, allowlistChecker.allowlistAttr())
                || Allowlist.isAvailableBasedOnRuleLocation(
                    ruleContext, allowlistChecker.allowlistAttr());
        break;
    }
    if (!passing) {
      ruleContext.ruleError(allowlistChecker.errorMessage());
    }
  }

  /**
   * Adds {@link RequiredConfigFragmentsProvider} if {@link
   * CoreOptions#includeRequiredConfigFragmentsProvider} isn't {@link
   * CoreOptions.IncludeConfigFragmentsEnum#OFF}.
   *
   * <p>See {@link com.google.devtools.build.lib.analysis.config.RequiredFragmentsUtil} for a
   * description of the meaning of this provider's content. That class contains methods that
   * populate the results of {@link RuleContext#getRequiredConfigFragments}.
   */
  private void maybeAddRequiredConfigFragmentsProvider() {
    if (ruleContext.shouldIncludeRequiredConfigFragmentsProvider()) {
      addProvider(ruleContext.getRequiredConfigFragments());
    }
  }

  private NestedSet<Label> transitiveLabels() {
    NestedSetBuilder<Label> nestedSetBuilder = NestedSetBuilder.stableOrder();

    for (String attributeName : ruleContext.attributes().getAttributeNames()) {
      Type<?> attributeType =
          ruleContext.attributes().getAttributeDefinition(attributeName).getType();
      if (attributeType.getLabelClass() == LabelClass.DEPENDENCY) {
        for (TransitiveLabelsInfo labelsInfo :
            ruleContext.getPrerequisites(attributeName, TransitiveLabelsInfo.class)) {
          nestedSetBuilder.addTransitive(labelsInfo.getLabels());
        }
      }
    }
    nestedSetBuilder.add(ruleContext.getLabel());
    return nestedSetBuilder.build();
  }

  /**
   * Collects the validation action output groups from every dependency-type attribute of this
   * target and adds them to this target's output groups.
   *
   * <p>This is done within {@link RuleConfiguredTargetBuilder} so that every rule always and
   * automatically propagates the validation action output group.
   *
   * <p>Note that in addition to {@link LabelClass#DEPENDENCY}, there is also {@link
   * LabelClass#FILESET_ENTRY}, however the fileset implementation takes care of propagating the
   * validation action output group itself.
   */
  private void propagateTransitiveValidationOutputGroups() {
    if (outputGroupBuilders.containsKey(OutputGroupInfo.VALIDATION_TRANSITIVE)) {
      Label rdeLabel =
          ruleContext.getRule().getRuleClassObject().getRuleDefinitionEnvironmentLabel();
      // only allow native and builtins to override transitive validation propagation
      if (rdeLabel != null && !"@_builtins".equals(rdeLabel.getRepository().getName())) {
        ruleContext.ruleError(rdeLabel + " cannot access the _transitive_validation private API");
        return;
      }
      addOutputGroup(
          OutputGroupInfo.VALIDATION,
          outputGroupBuilders.remove(OutputGroupInfo.VALIDATION_TRANSITIVE).build());
    } else {
      collectTransitiveValidationOutputGroups(
          ruleContext,
          unused -> true,
          validationArtifacts -> addOutputGroup(OutputGroupInfo.VALIDATION, validationArtifacts));
    }
  }

  /**
   * Collects the validation action output groups from every dependency-type attribute of the given
   * target that matches the given predicate and passes them to the given consumer.
   *
   * <p>This function can be used to implement custom validation action propagation logic that for
   * example ignores some attributes.
   */
  public static void collectTransitiveValidationOutputGroups(
      RuleContext ruleContext,
      Predicate<String> includeAttribute,
      Consumer<NestedSet<Artifact>> consumer) {
    for (String attributeName : ruleContext.attributes().getAttributeNames()) {
      if (!includeAttribute.test(attributeName)) {
        continue;
      }

      // Validation actions for tools, or from implicit deps should
      // not fail the overall build, since those dependencies should have their own builds
      // and tests that should surface any failing validations.
      Attribute attribute = ruleContext.attributes().getAttributeDefinition(attributeName);
      if (!attribute.isToolDependency()
          && !attribute.isImplicit()
          && attribute.getType().getLabelClass() == LabelClass.DEPENDENCY) {

        for (OutputGroupInfo outputGroup :
            ruleContext.getPrerequisites(attributeName, OutputGroupInfo.STARLARK_CONSTRUCTOR)) {

          NestedSet<Artifact> validationArtifacts =
              outputGroup.getOutputGroup(OutputGroupInfo.VALIDATION);

          if (!validationArtifacts.isEmpty()) {
            consumer.accept(validationArtifacts);
          }
        }
      }
    }
  }

  /**
   * Compute the artifacts to put into the {@link FilesToRunProvider} for this target. These are the
   * filesToBuild, any artifacts added by the rule with {@link #addFilesToRun}, and the runfiles'
   * middlemen if they exists.
   */
  private NestedSet<Artifact> buildFilesToRun(
      NestedSet<Artifact> runfilesMiddlemen, NestedSet<Artifact> filesToBuild) {
    filesToRunBuilder.addTransitive(filesToBuild);
    filesToRunBuilder.addTransitive(runfilesMiddlemen);
    if (executable != null && ruleContext.getRule().getRuleClassObject().isStarlark()) {
      filesToRunBuilder.add(executable);
    }
    return filesToRunBuilder.build();
  }

  /**
   * Invokes Blaze's constraint enforcement system: checks that this rule's dependencies
   * support its environments and reports appropriate errors if violations are found. Also
   * publishes this rule's supported environments for the rules that depend on it.
   */
  private void checkConstraints() {
    if (!ruleContext.getRule().getRuleClassObject().supportsConstraintChecking()) {
      return;
    }
    ConstraintSemantics<RuleContext> constraintSemantics = ruleContext.getConstraintSemantics();
    EnvironmentCollection supportedEnvironments =
        constraintSemantics.getSupportedEnvironments(ruleContext);
    if (supportedEnvironments != null) {
      EnvironmentCollection.Builder refinedEnvironments = new EnvironmentCollection.Builder();
      Map<Label, RemovedEnvironmentCulprit> removedEnvironmentCulprits = new LinkedHashMap<>();
      constraintSemantics.checkConstraints(ruleContext, supportedEnvironments, refinedEnvironments,
          removedEnvironmentCulprits);
      add(SupportedEnvironmentsProvider.class,
          new SupportedEnvironments(supportedEnvironments, refinedEnvironments.build(),
              removedEnvironmentCulprits));
    }
  }

  private TestProvider initializeTestProvider(FilesToRunProvider filesToRunProvider)
      throws InterruptedException {
    int explicitShardCount =
        ruleContext.attributes().get("shard_count", Type.INTEGER).toIntUnchecked();
    if (explicitShardCount < 0
        && ruleContext.getRule().isAttributeValueExplicitlySpecified("shard_count")) {
      ruleContext.attributeError("shard_count", "Must not be negative.");
    }
    if (explicitShardCount > 50) {
      ruleContext.attributeError("shard_count",
          "Having more than 50 shards is indicative of poor test organization. "
          + "Please reduce the number of shards.");
    }
    TestActionBuilder testActionBuilder =
        new TestActionBuilder(ruleContext)
            .setInstrumentedFiles(
                (InstrumentedFilesInfo)
                    providersBuilder.getProvider(
                        InstrumentedFilesInfo.STARLARK_CONSTRUCTOR.getKey()));

    TestEnvironmentInfo environmentProvider =
        (TestEnvironmentInfo)
            providersBuilder.getProvider(TestEnvironmentInfo.PROVIDER.getKey());
    if (environmentProvider != null) {
      testActionBuilder.addExtraEnv(environmentProvider.getEnvironment());
    }

    TestParams testParams =
        testActionBuilder
            .setFilesToRunProvider(filesToRunProvider)
            .setPersistentTestRunnerRunfiles(persistentTestRunnerRunfiles)
            .addTools(additionalTestActionTools.build())
            .setExecutionRequirements(
                (ExecutionInfo) providersBuilder.getProvider(ExecutionInfo.PROVIDER.getKey()))
            .setShardCount(explicitShardCount)
            .build();
    return new TestProvider(testParams);
  }

  /**
   * Add files required to run the target. Artifacts from {@link #setFilesToBuild} and the runfiles
   * middleman, if any, are added automatically.
   */
  public RuleConfiguredTargetBuilder addFilesToRun(NestedSet<Artifact> files) {
    filesToRunBuilder.addTransitive(files);
    return this;
  }

  /**
   * Add a specific provider with a given value.
   *
   * @deprecated use {@link #addProvider}
   */
  @Deprecated
  public <T extends TransitiveInfoProvider> RuleConfiguredTargetBuilder add(Class<T> key, T value) {
    return addProvider(key, value);
  }

  /** Add a specific provider with a given value. */
  public <T extends TransitiveInfoProvider> RuleConfiguredTargetBuilder addProvider(
      Class<? extends T> key, T value) {
    providersBuilder.put(key, value);
    return this;
  }

  /** Adds a specific provider. */
  public RuleConfiguredTargetBuilder addProvider(TransitiveInfoProvider provider) {
    providersBuilder.add(provider);
    return this;
  }

  /** Add a collection of specific providers. */
  public RuleConfiguredTargetBuilder addProviders(TransitiveInfoProviderMap providers) {
    providersBuilder.addAll(providers);
    return this;
  }
  /**
   * Adds a "declared provider" defined in Starlark to the rule. Use this method for declared
   * providers defined in Starlark. The provider symbol must be exported.
   *
   * <p>Has special handling for {@link OutputGroupInfo}: that provider is not added from Starlark
   * directly, instead its output groups are added.
   *
   * <p>Use {@link #addNativeDeclaredProvider(Info)} in definitions of native rules.
   */
  public RuleConfiguredTargetBuilder addStarlarkDeclaredProvider(Info provider) {
    Provider constructor = provider.getProvider();
    // Starlark providers are already exported (enforced by SRCTU.getProviderKey).
    Preconditions.checkArgument(constructor.isExported());
    if (OutputGroupInfo.STARLARK_CONSTRUCTOR.getKey().equals(constructor.getKey())) {
      OutputGroupInfo outputGroupInfo = (OutputGroupInfo) provider;
      for (String outputGroup : outputGroupInfo) {
        addOutputGroup(outputGroup, outputGroupInfo.getOutputGroup(outputGroup));
      }
    } else {
      providersBuilder.put(provider);
    }
    return this;
  }

  /**
   * Adds "declared providers" defined in native code to the rule. Use this method for declared
   * providers in definitions of native rules.
   *
   * <p>Use {@link #addStarlarkDeclaredProvider(Info)} for Starlark rule implementations.
   */
  public RuleConfiguredTargetBuilder addNativeDeclaredProviders(Iterable<Info> providers) {
    for (Info provider : providers) {
      addNativeDeclaredProvider(provider);
    }
    return this;
  }

  /**
   * Adds a "declared provider" defined in native code to the rule. Use this method for declared
   * providers in definitions of native rules.
   *
   * <p>Use {@link #addStarlarkDeclaredProvider(Info)} for Starlark rule implementations.
   */
  public RuleConfiguredTargetBuilder addNativeDeclaredProvider(Info provider) {
    Provider constructor = provider.getProvider();
    Preconditions.checkState(constructor.isExported());
    providersBuilder.put(provider);
    return this;
  }

  /**
   * Returns true if a provider matching the given provider key has already been added to the
   * configured target builder.
   */
  public boolean containsProviderKey(Provider.Key providerKey) {
    return providersBuilder.contains(providerKey);
  }

  /**
   * Returns true if a provider matching the given legacy key has already been added to the
   * configured target builder.
   */
  public boolean containsLegacyKey(String legacyId) {
    return providersBuilder.contains(legacyId);
  }

  /** Add a Starlark transitive info. The provider value must be safe. */
  public RuleConfiguredTargetBuilder addStarlarkTransitiveInfo(String name, Object value) {
    providersBuilder.put(name, value);
    return this;
  }

  /**
   * Set the runfiles support for executable targets.
   */
  public RuleConfiguredTargetBuilder setRunfilesSupport(
      RunfilesSupport runfilesSupport, Artifact executable) {
    this.runfilesSupport = runfilesSupport;
    this.executable = executable;
    return this;
  }

  public RuleConfiguredTargetBuilder setPersistentTestRunnerRunfiles(Runfiles testSupportRunfiles) {
    this.persistentTestRunnerRunfiles = testSupportRunfiles;
    return this;
  }

  public RuleConfiguredTargetBuilder addTestActionTools(List<Artifact> tools) {
    this.additionalTestActionTools.addAll(tools);
    return this;
  }

  /**
   * Set the files to build.
   */
  public RuleConfiguredTargetBuilder setFilesToBuild(NestedSet<Artifact> filesToBuild) {
    this.filesToBuild = filesToBuild;
    return this;
  }

  private NestedSetBuilder<Artifact> getOutputGroupBuilder(String name) {
    NestedSetBuilder<Artifact> result = outputGroupBuilders.get(name);
    if (result != null) {
      return result;
    }

    result = NestedSetBuilder.stableOrder();
    outputGroupBuilders.put(name, result);
    return result;
  }

  /**
   * Adds a set of files to an output group.
   */
  public RuleConfiguredTargetBuilder addOutputGroup(String name, NestedSet<Artifact> artifacts) {
    getOutputGroupBuilder(name).addTransitive(artifacts);
    return this;
  }

  /**
   * Adds a file to an output group.
   */
  public RuleConfiguredTargetBuilder addOutputGroup(String name, Artifact artifact) {
    getOutputGroupBuilder(name).add(artifact);
    return this;
  }

  /**
   * Adds multiple output groups.
   */
  public RuleConfiguredTargetBuilder addOutputGroups(Map<String, NestedSet<Artifact>> groups) {
    for (Map.Entry<String, NestedSet<Artifact>> group : groups.entrySet()) {
      getOutputGroupBuilder(group.getKey()).addTransitive(group.getValue());
    }

    return this;
  }

  /**
   * Contains a nested set of transitive dependencies of the target which propagated this object.
   *
   * <p>This is automatically provided by all targets which are being evaluated in analysis testing.
   *
   * <p>For large builds, this object will become <i>very large</i>, but analysis tests are required
   * to be very small. The small-size of analysis tests are enforced by evaluating the size of this
   * object.
   */
  private static final class TransitiveLabelsInfo implements TransitiveInfoProvider {
    private final NestedSet<Label> labels;

    TransitiveLabelsInfo(NestedSet<Label> labels) {
      this.labels = labels;
    }

    public NestedSet<Label> getLabels() {
      return labels;
    }
  }
}
