// Copyright 2023 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.producers;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.devtools.build.lib.buildeventstream.BuildEventIdUtil.configurationId;

import com.google.auto.value.AutoOneOf;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.ExecGroupCollection;
import com.google.devtools.build.lib.analysis.InconsistentNullConfigException;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
import com.google.devtools.build.lib.analysis.TransitiveDependencyState;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.ConfigConditions;
import com.google.devtools.build.lib.analysis.config.ConfigurationTransitionEvent;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.StarlarkTransitionCache;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.config.transitions.ComposingTransition;
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.TransitionException;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId;
import com.google.devtools.build.lib.causes.AnalysisFailedCause;
import com.google.devtools.build.lib.causes.Cause;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleTransitionData;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.server.FailureDetails.Analysis;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ConfiguredValueCreationException;
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.toolchains.PlatformLookupUtil.InvalidPlatformException;
import com.google.devtools.build.lib.skyframe.toolchains.ToolchainContextKey;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.state.StateMachine;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.starlark.java.syntax.Location;

/**
 * Computes the target and configuration for a configured target key.
 *
 * <p>If the key has a configuration and the target is configurable, attempts to apply a rule side
 * transition. If the configuration changes, delegates to a target with the new configuration. If
 * the target is not configurable, directly delegates to the null configuration.
 */
public final class TargetAndConfigurationProducer
    implements StateMachine,
        StateMachine.ValueOrExceptionSink<InvalidConfigurationException>,
        Consumer<SkyValue>,
        TargetProducer.ResultSink {
  /** Accepts results of this producer. */
  public interface ResultSink {
    void acceptTargetAndConfiguration(TargetAndConfiguration value, ConfiguredTargetKey fullKey);

    void acceptTargetAndConfigurationDelegatedValue(ConfiguredTargetValue value);

    void acceptTargetAndConfigurationError(TargetAndConfigurationError error);
  }

  /** Tagged union of possible errors. */
  @AutoOneOf(TargetAndConfigurationError.Kind.class)
  public abstract static class TargetAndConfigurationError {
    /** Tags the error type. */
    public enum Kind {
      CONFIGURED_VALUE_CREATION,
      NO_SUCH_THING,
      INCONSISTENT_NULL_CONFIG
    }

    public abstract Kind kind();

    public abstract ConfiguredValueCreationException configuredValueCreation();

    public abstract NoSuchThingException noSuchThing();

    public abstract InconsistentNullConfigException inconsistentNullConfig();

    private static TargetAndConfigurationError of(ConfiguredValueCreationException e) {
      return AutoOneOf_TargetAndConfigurationProducer_TargetAndConfigurationError
          .configuredValueCreation(e);
    }

    private static TargetAndConfigurationError of(NoSuchThingException e) {
      return AutoOneOf_TargetAndConfigurationProducer_TargetAndConfigurationError.noSuchThing(e);
    }

    private static TargetAndConfigurationError of(InconsistentNullConfigException e) {
      return AutoOneOf_TargetAndConfigurationProducer_TargetAndConfigurationError
          .inconsistentNullConfig(e);
    }
  }

  // -------------------- Input --------------------
  private final ConfiguredTargetKey preRuleTransitionKey;
  @Nullable private final TransitionFactory<RuleTransitionData> trimmingTransitionFactory;
  private final PatchTransition toolchainTaggedTrimmingTransition;
  private final StarlarkTransitionCache transitionCache;

  private final TransitiveDependencyState transitiveState;

  // -------------------- Output --------------------
  private final ResultSink sink;
  private final ExtendedEventHandler eventHandler;

  // -------------------- Internal State --------------------
  private Target target;

  public TargetAndConfigurationProducer(
      ConfiguredTargetKey preRuleTransitionKey,
      @Nullable TransitionFactory<RuleTransitionData> trimmingTransitionFactory,
      PatchTransition toolchainTaggedTrimmingTransition,
      StarlarkTransitionCache transitionCache,
      TransitiveDependencyState transitiveState,
      ResultSink sink,
      ExtendedEventHandler eventHandler) {
    this.preRuleTransitionKey = preRuleTransitionKey;
    this.trimmingTransitionFactory = trimmingTransitionFactory;
    this.toolchainTaggedTrimmingTransition = toolchainTaggedTrimmingTransition;
    this.transitionCache = transitionCache;
    this.transitiveState = transitiveState;
    this.sink = sink;
    this.eventHandler = eventHandler;
  }

  @Override
  public StateMachine step(Tasks tasks) {
    return new TargetProducer(
        preRuleTransitionKey.getLabel(),
        transitiveState,
        (TargetProducer.ResultSink) this,
        /* runAfter= */ this::determineConfiguration);
  }

  @Override
  public void acceptTarget(Target target) {
    this.target = target;
  }

  @Override
  public void acceptTargetError(NoSuchPackageException e) {
    eventHandler.handle(Event.error(e.getMessage()));
    sink.acceptTargetAndConfigurationError(TargetAndConfigurationError.of(e));
  }

  @Override
  public void acceptTargetError(NoSuchTargetException e, Location location) {
    eventHandler.handle(Event.error(location, e.getMessage()));
    sink.acceptTargetAndConfigurationError(TargetAndConfigurationError.of(e));
  }

  private StateMachine determineConfiguration(Tasks tasks) {
    if (target == null) {
      return DONE; // A target could not be determined.
    }

    BuildConfigurationKey configurationKey = preRuleTransitionKey.getConfigurationKey();
    if (configurationKey == null) {
      if (target.isConfigurable()) {
        // We somehow ended up in a target that requires a non-null configuration but with a key
        // that doesn't have a configuration. This is always an error, but we need to bubble this
        // up to the parent to provide more context.
        sink.acceptTargetAndConfigurationError(
            TargetAndConfigurationError.of(new InconsistentNullConfigException()));
        return DONE;
      }
      sink.acceptTargetAndConfiguration(
          new TargetAndConfiguration(target, /* configuration= */ null), preRuleTransitionKey);
      return DONE;
    }

    if (!target.isConfigurable()) {
      // If target is not configurable, but requested with a configuration. Delegates to a key with
      // the null configuration. This is expected to be uncommon. The common case of a
      // non-configurable target is an input file, but those are usually package local and requested
      // correctly with the null configuration.
      delegateTo(
          tasks,
          ConfiguredTargetKey.builder()
              .setLabel(preRuleTransitionKey.getLabel())
              .setExecutionPlatformLabel(preRuleTransitionKey.getExecutionPlatformLabel())
              .build());
      return DONE;
    }

    if (!preRuleTransitionKey.shouldApplyRuleTransition()) {
      lookUpConfigurationValue(tasks);
      return DONE;
    }

    return new RuleTransitionApplier();
  }

  private void delegateTo(Tasks tasks, ActionLookupKey delegate) {
    tasks.lookUp(delegate, (Consumer<SkyValue>) this);
  }

  @Override
  public void accept(SkyValue value) {
    sink.acceptTargetAndConfigurationDelegatedValue((ConfiguredTargetValue) value);
  }

  private void lookUpConfigurationValue(Tasks tasks) {
    tasks.lookUp(
        preRuleTransitionKey.getConfigurationKey(),
        InvalidConfigurationException.class,
        (ValueOrExceptionSink<InvalidConfigurationException>) this);
  }

  @Override
  public void acceptValueOrException(
      @Nullable SkyValue value, @Nullable InvalidConfigurationException error) {
    if (value != null) {
      sink.acceptTargetAndConfiguration(
          new TargetAndConfiguration(target, (BuildConfigurationValue) value),
          preRuleTransitionKey);
      return;
    }
    emitError(
        error.getMessage(), TargetUtils.getLocationMaybe(target), error.getDetailedExitCode());
  }

  /** Applies any requested rule transition before producing the final configuration. */
  private class RuleTransitionApplier
      implements StateMachine,
          TransitionApplier.ResultSink,
          ConfigConditionsProducer.ResultSink,
          PlatformInfoProducer.ResultSink {
    // -------------------- Internal State --------------------
    @Nullable private PlatformInfo platformInfo;
    private ConfigConditions configConditions;
    private ConfigurationTransition ruleTransition;
    private BuildConfigurationKey configurationKey;
        
    @Override
    public StateMachine step(Tasks tasks) throws InterruptedException {

      UnloadedToolchainContextsInputs unloadedToolchainContextsInputs =
          getUnloadedToolchainContextsInputs(
              target, preRuleTransitionKey.getExecutionPlatformLabel());

      if (unloadedToolchainContextsInputs.targetToolchainContextKey() != null) {
        PlatformConfiguration platformConfiguration =
            new PlatformConfiguration(preRuleTransitionKey.getConfigurationKey().getOptions());
        tasks.enqueue(
            new PlatformInfoProducer(
                platformConfiguration.getTargetPlatform(),
                (PlatformInfoProducer.ResultSink) this,
                this::computeConfigConditions));
      } else {
        this.platformInfo = null;
        computeConfigConditions(tasks);
      }

      return DONE;
    }

    // TODO: @aranguyen b/297077082
    public UnloadedToolchainContextsInputs getUnloadedToolchainContextsInputs(
        Target target, @Nullable Label parentExecutionPlatformLabel) throws InterruptedException {
      if (!(target instanceof Rule)) {
        return UnloadedToolchainContextsInputs.empty();
      }

      Rule rule = (Rule) target;

      if (!preRuleTransitionKey
          .getConfigurationKey()
          .getOptions()
          .contains(PlatformOptions.class)) {
        return UnloadedToolchainContextsInputs.empty();
      }
      PlatformConfiguration platformConfiguration =
          new PlatformConfiguration(preRuleTransitionKey.getConfigurationKey().getOptions());
      var defaultExecConstraintLabels =
          getExecutionPlatformConstraints(rule, platformConfiguration);
      var ruleClass = rule.getRuleClassObject();
      boolean useAutoExecGroups =
          rule.isAttrDefined("$use_auto_exec_groups", Type.BOOLEAN)
              ? (boolean) rule.getAttr("$use_auto_exec_groups")
              : preRuleTransitionKey
                  .getConfigurationKey()
                  .getOptions()
                  .get(CoreOptions.class)
                  .useAutoExecGroups;

      var processedExecGroups =
          ExecGroupCollection.process(
              ruleClass.getExecGroups(),
              defaultExecConstraintLabels,
              ruleClass.getToolchainTypes(),
              useAutoExecGroups);

      if (!rule.useToolchainResolution()) {
        return UnloadedToolchainContextsInputs.create(processedExecGroups, null);
      }

      return UnloadedToolchainContextsInputs.create(
          processedExecGroups,
          createDefaultToolchainContextKey(
              computeToolchainConfigurationKey(
                  preRuleTransitionKey.getConfigurationKey().getOptions(),
                  toolchainTaggedTrimmingTransition),
              defaultExecConstraintLabels,
              /* debugTarget= */ platformConfiguration.debugToolchainResolution(rule.getLabel()),
              /* useAutoExecGroups= */ useAutoExecGroups,
              ruleClass.getToolchainTypes(),
              parentExecutionPlatformLabel));
    }

    public ToolchainContextKey createDefaultToolchainContextKey(
        BuildConfigurationKey configurationKey,
        ImmutableSet<Label> defaultExecConstraintLabels,
        boolean debugTarget,
        boolean useAutoExecGroups,
        ImmutableSet<ToolchainTypeRequirement> toolchainTypes,
        @Nullable Label parentExecutionPlatformLabel) {
      ToolchainContextKey.Builder toolchainContextKeyBuilder =
          ToolchainContextKey.key()
              .configurationKey(configurationKey)
              .execConstraintLabels(defaultExecConstraintLabels)
              .debugTarget(debugTarget);

      // Add toolchain types only if automatic exec groups are not created for this target.
      if (!useAutoExecGroups) {
        toolchainContextKeyBuilder.toolchainTypes(toolchainTypes);
      }

      if (parentExecutionPlatformLabel != null) {
        // Find out what execution platform the parent used, and force that.
        // This should only be set for direct toolchain dependencies.
        toolchainContextKeyBuilder.forceExecutionPlatform(parentExecutionPlatformLabel);
      }
      return toolchainContextKeyBuilder.build();
    }

    private BuildConfigurationKey computeToolchainConfigurationKey(
        BuildOptions buildOptions, PatchTransition toolchainTaggedTrimmingTransition)
        throws InterruptedException {
      // The toolchain context's options are the parent rule's options with manual trimming
      // auto-applied. This means toolchains don't inherit feature flags. This helps build
      // performance: if the toolchain context had the exact same configuration of its parent and
      // that
      // included feature flags, all the toolchain's dependencies would apply this transition
      // individually. That creates a lot more potentially expensive applications of that transition
      // (especially since manual trimming applies to every configured target in the build).
      //
      // In other words: without this modification:
      // parent rule -> toolchain context -> toolchain
      //     -> toolchain dep 1 # applies manual trimming to remove feature flags
      //     -> toolchain dep 2 # applies manual trimming to remove feature flags
      //     ...
      //
      // With this modification:
      // parent rule -> toolchain context # applies manual trimming to remove feature flags
      //     -> toolchain
      //         -> toolchain dep 1
      //         -> toolchain dep 2
      //         ...
      //
      // None of this has any effect on rules that don't utilize manual trimming.
      BuildOptions toolchainOptions =
          toolchainTaggedTrimmingTransition.patch(
              new BuildOptionsView(
                  buildOptions, toolchainTaggedTrimmingTransition.requiresOptionFragments()),
              eventHandler);
      return BuildConfigurationKey.create(toolchainOptions);
    }

    private ImmutableSet<Label> getExecutionPlatformConstraints(
        Rule rule, @Nullable PlatformConfiguration platformConfiguration) {
      if (platformConfiguration == null) {
        return ImmutableSet.of(); // See NoConfigTransition.
      }
      NonconfigurableAttributeMapper mapper = NonconfigurableAttributeMapper.of(rule);
      ImmutableSet.Builder<Label> execConstraintLabels = new ImmutableSet.Builder<>();

      execConstraintLabels.addAll(rule.getRuleClassObject().getExecutionPlatformConstraints());
      if (rule.getRuleClassObject()
          .hasAttr(RuleClass.EXEC_COMPATIBLE_WITH_ATTR, BuildType.LABEL_LIST)) {
        execConstraintLabels.addAll(
            mapper.get(RuleClass.EXEC_COMPATIBLE_WITH_ATTR, BuildType.LABEL_LIST));
      }

      execConstraintLabels.addAll(
          platformConfiguration.getAdditionalExecutionConstraintsFor(rule.getLabel()));

      return execConstraintLabels.build();
    }

    @CanIgnoreReturnValue
    public StateMachine computeConfigConditions(Tasks tasks) {
      // TODO @aranguyen b/297077082
      tasks.enqueue(
          new ConfigConditionsProducer(
              target,
              preRuleTransitionKey.getLabel(),
              preRuleTransitionKey.getConfigurationKey(),
              platformInfo,
              transitiveState,
              (ConfigConditionsProducer.ResultSink) this,
              this::computeTransition));
      return DONE;
    }

    @Override
    public void acceptConfigConditions(ConfigConditions configConditions) {
      this.configConditions = configConditions;
    }

    @Override
    public void acceptConfigConditionsError(ConfiguredValueCreationException e) {
      emitTransitionErrorMessage(e.getMessage());
    }

    public StateMachine computeTransition(Tasks tasks) {
      if (configConditions == null) {
        return DONE;
      }

      // logic to compute transition with ConfigConditions
      var transitionData =
          RuleTransitionData.create(
              target.getAssociatedRule(),
              configConditions.asProviders(),
              preRuleTransitionKey.getConfigurationKey().getOptionsChecksum());

      ConfigurationTransition transition = null;

      TransitionFactory<RuleTransitionData> transitionFactory =
          target.getAssociatedRule().getRuleClassObject().getTransitionFactory();
      if (transitionFactory != null) {
        transition = transitionFactory.create(transitionData);
      }

      if (trimmingTransitionFactory != null) {
        var trimmingTransition = trimmingTransitionFactory.create(transitionData);
        if (transition != null) {
          transition = ComposingTransition.of(transition, trimmingTransition);
        } else {
          transition = trimmingTransition;
        }
      }

      if (transition == null) {
        lookUpConfigurationValue(tasks);
        return DONE;
      }

      this.ruleTransition = transition;

      return new TransitionApplier(
          preRuleTransitionKey.getConfigurationKey(),
          ruleTransition,
          transitionCache,
          (TransitionApplier.ResultSink) this,
          eventHandler,
          /* runAfter= */ this::processTransitionedKey);
    }

    @Override
    public void acceptTransitionedConfigurations(
        ImmutableMap<String, BuildConfigurationKey> transitionResult) {
      checkState(transitionResult.size() == 1, "Expected exactly one result: %s", transitionResult);
      this.configurationKey =
          checkNotNull(
              transitionResult.get(ConfigurationTransition.PATCH_TRANSITION_KEY),
              "Transition result missing patch transition entry: %s",
              transitionResult);
    }

    @Override
    public void acceptTransitionError(TransitionException e) {
      emitTransitionErrorMessage(e.getMessage());
    }

    @Override
    public void acceptTransitionError(OptionsParsingException e) {
      emitTransitionErrorMessage(e.getMessage());
    }

    @Override
    public void acceptPlatformInfo(PlatformInfo info) {
      this.platformInfo = info;
    }

    @Override
    public void acceptPlatformInfoError(InvalidPlatformException error) {
      emitTransitionErrorMessage(error.getMessage());
    }

    private StateMachine processTransitionedKey(Tasks tasks) {
      if (configurationKey == null) {
        return DONE; // There was an error.
      }

      BuildConfigurationKey parentConfiguration = preRuleTransitionKey.getConfigurationKey();
      if (configurationKey.equals(parentConfiguration)) {
        // This key owns the configuration and the computation completes normally.
        lookUpConfigurationValue(tasks);
        return DONE;
      }

      eventHandler.post(
          ConfigurationTransitionEvent.create(
              parentConfiguration.getOptionsChecksum(), configurationKey.getOptionsChecksum()));

      return new IdempotencyChecker();
    }

    /**
     * Checks the transition for idempotency before applying delegation.
     *
     * <p>If the transition is non-idempotent, marks {@link
     * ConfiguredTargetKey#shouldApplyRuleTransition} false in the delegate key.
     */
    private class IdempotencyChecker implements StateMachine, TransitionApplier.ResultSink {
      /* At first glance, it seems like setting `shouldApplyRuleTransition=false` should be benign
       * in both cases, but it would be an error in the idempotent case.
       *
       * Idempotent Case
       *
       * If we were to mark the idempotent case with `shouldApplyRuleTransition=false`, it would
       * lead to action conflicts. Let `//foo[123]` be a key that rule transitions to `//foo[abc]`
       * and suppose the outcome is marked `//foo[abc] shouldApplyRuleTransition=false`.
       *
       * A different parent might directly request `//foo[abc] shouldApplyRuleTransition=true`.
       * Since the rule transition is a idempotent, it would result in the same actions as
       * `//foo[abc] shouldApplyRuleTransition=false` with a different key, causing action
       * conflicts.
       *
       * Non-idempotent Case
       *
       * In the example of //foo[abc] shouldApplyRuleTransition=false and //foo[abc]
       * shouldApplyRuleTransition=true, there should be no action conflicts because the
       * `shouldApplyRuleTransition=false` is the result of a non-idempotent rule transition and
       * `shouldApplyRuleTransition=true` will produce a different configuration. */

      // -------------------- Internal State --------------------
      private BuildConfigurationKey configurationKey2;

      @Override
      public StateMachine step(Tasks tasks) {
        return new TransitionApplier(
            configurationKey,
            ruleTransition,
            transitionCache,
            (TransitionApplier.ResultSink) this,
            eventHandler,
            /* runAfter= */ this::checkIdempotencyAndDelegate);
      }

      @Override
      public void acceptTransitionedConfigurations(
          ImmutableMap<String, BuildConfigurationKey> transitionResult) {
        checkState(
            transitionResult.size() == 1, "Expected exactly one result: %s", transitionResult);
        this.configurationKey2 =
            checkNotNull(
                transitionResult.get(ConfigurationTransition.PATCH_TRANSITION_KEY),
                "Transition result missing patch transition entry: %s",
                transitionResult);
      }

      @Override
      public void acceptTransitionError(TransitionException e) {
        emitTransitionErrorMessage(e.getMessage());
      }

      @Override
      public void acceptTransitionError(OptionsParsingException e) {
        emitTransitionErrorMessage(e.getMessage());
      }

      private StateMachine checkIdempotencyAndDelegate(Tasks tasks) {
        if (configurationKey2 == null) {
          return DONE; // There was an error.
        }

        ConfiguredTargetKey.Builder keyBuilder =
            ConfiguredTargetKey.builder()
                .setLabel(preRuleTransitionKey.getLabel())
                .setExecutionPlatformLabel(preRuleTransitionKey.getExecutionPlatformLabel())
                .setConfigurationKey(configurationKey);

        if (!configurationKey.equals(configurationKey2)) {
          // The transition was not idempotent. Explicitly informs the delegate to avoid applying a
          // rule transition.
          keyBuilder.setShouldApplyRuleTransition(false);
        }
        delegateTo(tasks, keyBuilder.build());
        return DONE;
      }
    }

    private void emitTransitionErrorMessage(String message) {
      emitError(message, TargetUtils.getLocationMaybe(target), /* exitCode= */ null);
    }
  }

  private void emitError(
      String message, @Nullable Location location, @Nullable DetailedExitCode exitCode) {
    Cause cause =
        new AnalysisFailedCause(
            preRuleTransitionKey.getLabel(),
            configurationIdMessage(preRuleTransitionKey.getConfigurationKey().getOptionsChecksum()),
            exitCode != null ? exitCode : createDetailedExitCode(message));
    sink.acceptTargetAndConfigurationError(
        TargetAndConfigurationError.of(
            new ConfiguredValueCreationException(
                location,
                message,
                target.getLabel(),
                configurationId(preRuleTransitionKey.getConfigurationKey()),
                NestedSetBuilder.create(Order.STABLE_ORDER, cause),
                exitCode != null ? exitCode : createDetailedExitCode(message))));
  }

  public static ConfigurationId configurationIdMessage(@Nullable String optionsCheckSum) {
    if (optionsCheckSum == null) {
      return ConfigurationId.newBuilder().setId("none").build();
    }
    return ConfigurationId.newBuilder().setId(optionsCheckSum).build();
  }

  public static DetailedExitCode createDetailedExitCode(String message) {
    return DetailedExitCode.of(
        FailureDetail.newBuilder()
            .setMessage(message)
            .setAnalysis(
                Analysis.newBuilder().setCode(Analysis.Code.CONFIGURED_VALUE_CREATION_FAILED))
            .build());
  }

  // Public for Cquery.
  // TODO: @aranguyen keep cquery in sync with ConfiguredTargetFunction
  @Nullable
  public static ConfigurationTransition computeTransition(
      Rule rule, @Nullable TransitionFactory<RuleTransitionData> trimmingTransitionFactory) {
    var transitionData = RuleTransitionData.create(rule, /* configConditions= */ null, "");

    ConfigurationTransition transition = null;

    TransitionFactory<RuleTransitionData> transitionFactory =
        rule.getRuleClassObject().getTransitionFactory();
    if (transitionFactory != null) {
      transition = transitionFactory.create(transitionData);
    }
    boolean isAlias = rule.getAssociatedRule().getName().equals("alias");
    if (trimmingTransitionFactory != null && !isAlias) {
      var trimmingTransition = trimmingTransitionFactory.create(transitionData);
      if (transition != null) {
        transition = ComposingTransition.of(transition, trimmingTransition);
      } else {
        transition = trimmingTransition;
      }
    }

    return transition;
  }
}
