// Copyright 2021 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.skyframe;

import static com.google.devtools.build.lib.skyframe.BuildDriverKey.TestType.EXCLUSIVE;
import static com.google.devtools.build.lib.skyframe.BuildDriverKey.TestType.EXCLUSIVE_IF_LOCAL;
import static com.google.devtools.build.lib.skyframe.BuildDriverKey.TestType.NOT_TEST;
import static com.google.devtools.build.lib.skyframe.BuildDriverKey.TestType.PARALLEL;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AspectValue;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.ExtraActionArtifactsProvider;
import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.constraints.RuleContextConstraintSemantics;
import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics;
import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics.EnvironmentCompatibility;
import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics.PlatformCompatibility;
import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics.TargetCompatibilityCheckException;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.Sharder;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.server.FailureDetails.Analysis;
import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.ConflictException;
import com.google.devtools.build.lib.skyframe.AspectCompletionValue.AspectCompletionKey;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.AspectAnalyzedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.SomeExecutionStartedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TestAnalyzedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelEntityAnalysisConcludedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetAnalyzedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetPendingExecutionEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetSkippedEvent;
import com.google.devtools.build.lib.util.RegexFilter;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunction.Environment.SkyKeyComputeState;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.SkyframeIterableResult;
import com.google.devtools.build.skyframe.SkyframeLookupResult;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Drives the analysis & execution of an ActionLookupKey, which is wrapped inside a BuildDriverKey.
 */
public class BuildDriverFunction implements SkyFunction {
  private final TransitiveActionLookupValuesHelper transitiveActionLookupValuesHelper;
  private final Supplier<IncrementalArtifactConflictFinder> incrementalArtifactConflictFinder;
  private final Supplier<RuleContextConstraintSemantics> ruleContextConstraintSemantics;
  private final Supplier<RegexFilter> extraActionFilterSupplier;

  BuildDriverFunction(
      TransitiveActionLookupValuesHelper transitiveActionLookupValuesHelper,
      Supplier<IncrementalArtifactConflictFinder> incrementalArtifactConflictFinder,
      Supplier<RuleContextConstraintSemantics> ruleContextConstraintSemantics,
      Supplier<RegexFilter> extraActionFilterSupplier) {
    this.transitiveActionLookupValuesHelper = transitiveActionLookupValuesHelper;
    this.incrementalArtifactConflictFinder = incrementalArtifactConflictFinder;
    this.ruleContextConstraintSemantics = ruleContextConstraintSemantics;
    this.extraActionFilterSupplier = extraActionFilterSupplier;
  }

  private static class State implements SkyKeyComputeState {
    private ImmutableMap<ActionAnalysisMetadata, ConflictException> actionConflicts;
    // It's only necessary to do this check once.
    private boolean checkedForCompatibility = false;
    private boolean checkedForPlatformCompatibility = false;
  }
  /**
   * From the ConfiguredTarget/Aspect keys, get the top-level artifacts. Then evaluate them together
   * with the appropriate CompletionFunctions. This is the bridge between the conceptual analysis &
   * execution phases.
   *
   * <p>TODO(b/240944910): implement coverage.
   */
  @Nullable
  @Override
  public SkyValue compute(SkyKey skyKey, Environment env)
      throws SkyFunctionException, InterruptedException {
    BuildDriverKey buildDriverKey = (BuildDriverKey) skyKey;
    ActionLookupKey actionLookupKey = buildDriverKey.getActionLookupKey();
    TopLevelArtifactContext topLevelArtifactContext = buildDriverKey.getTopLevelArtifactContext();
    State state = env.getState(State::new);

    // Register a dependency on the BUILD_ID. We do this to make sure BuildDriverFunction is
    // reevaluated every build.
    PrecomputedValue.BUILD_ID.get(env);

    // Why SkyValue and not ActionLookupValue? The evaluation of some ActionLookupKey can result in
    // classes that don't implement ActionLookupValue
    // (e.g. ConfiguredTargetKey -> NonRuleConfiguredTargetValue).
    SkyValue topLevelSkyValue = env.getValue(actionLookupKey);

    if (env.valuesMissing()) {
      return null;
    }

    // This code path should not be run during error bubbling for several reasons:
    // 1. Correctness: to check for action conflicts, we need access to the transitive
    //    ConfiguredTargets, which will be null after AnalysisPhaseCompleteEvent in
    //    --discard_analysis_cache mode.
    // 2. Performance: this method is CPU intensive, and it does not offer anything while error
    //    bubbling.
    if (!env.inErrorBubblingForSkyFunctionsThatCanFullyRecoverFromErrors()) {
      // Unconditionally check for action conflicts.
      // TODO(b/214371092): Only check when necessary.
      try (SilentCloseable c =
          Profiler.instance().profile("BuildDriverFunction.checkActionConflicts")) {
        if (state.actionConflicts == null) {
          state.actionConflicts =
              checkActionConflicts(actionLookupKey, buildDriverKey.strictActionConflictCheck());
        }
        if (!state.actionConflicts.isEmpty()) {
          throw new BuildDriverFunctionException(
              new TopLevelConflictException(
                  "Action conflict(s) detected while analyzing top-level target "
                      + actionLookupKey.getLabel(),
                  state.actionConflicts));
        }
      }
    }

    Preconditions.checkState(
        topLevelSkyValue instanceof ConfiguredTargetValue
            || topLevelSkyValue instanceof TopLevelAspectsValue);
    if (topLevelSkyValue instanceof ConfiguredTargetValue) {
      ConfiguredTargetValue configuredTargetValue = (ConfiguredTargetValue) topLevelSkyValue;
      ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
      // At this point, the target is considered "analyzed". It's important that this event is sent
      // before the TopLevelEntityAnalysisConcludedEvent: when the last of the analysis work is
      // concluded, we need to have the *complete* list of analyzed targets ready in
      // BuildResultListener.
      postTopLevelTargetAnalyzedEvent(env, configuredTargetValue, configuredTarget);

      BuildConfigurationValue buildConfigurationValue =
          configuredTarget.getConfigurationKey() == null
              ? null
              : (BuildConfigurationValue) env.getValue(configuredTarget.getConfigurationKey());
      if (env.valuesMissing()) {
        return null;
      }

      if (!state.checkedForCompatibility) {
        try {
          Boolean isConfiguredTargetCompatible =
              isConfiguredTargetCompatible(
                  env,
                  state,
                  configuredTarget,
                  buildConfigurationValue,
                  buildDriverKey.isExplicitlyRequested());
          if (isConfiguredTargetCompatible == null) {
            return null;
          }

          state.checkedForCompatibility = true;
          if (!isConfiguredTargetCompatible) {
            env.getListener().post(TopLevelTargetSkippedEvent.create(configuredTarget));
            // We still record analyzed but skipped tests, as this information is needed for the
            // result summary.
            if (!NOT_TEST.equals(buildDriverKey.getTestType())) {
              env.getListener()
                  .post(
                      TestAnalyzedEvent.create(
                          configuredTarget,
                          Preconditions.checkNotNull(buildConfigurationValue),
                          /*isSkipped=*/ true));
            }
            // Only send the event now to include the compatibility check in the measurement for
            // time spent on analysis work.
            env.getListener().post(TopLevelEntityAnalysisConcludedEvent.success(buildDriverKey));
            // We consider the evaluation of this BuildDriverKey successful at this point, even when
            // the target is skipped.
            return new BuildDriverValue(topLevelSkyValue, /*skipped=*/ true);
          }
        } catch (TargetCompatibilityCheckException e) {
          throw new BuildDriverFunctionException(e);
        }
      }

      env.getListener().post(TopLevelEntityAnalysisConcludedEvent.success(buildDriverKey));
      env.getListener()
          .post(
              TopLevelTargetPendingExecutionEvent.create(
                  configuredTarget, buildDriverKey.isTest()));
      requestConfiguredTargetExecution(
          configuredTarget,
          buildDriverKey,
          actionLookupKey,
          buildConfigurationValue,
          env,
          topLevelArtifactContext);
    } else {
      announceAspectAnalysisDoneAndRequestExecution(
          buildDriverKey, (TopLevelAspectsValue) topLevelSkyValue, env, topLevelArtifactContext);
    }

    if (env.valuesMissing()) {
      return null;
    }

    // If we get to this point, the execution of this target/aspect succeeded.

    if (EXCLUSIVE.equals(buildDriverKey.getTestType())
        || EXCLUSIVE_IF_LOCAL.equals(buildDriverKey.getTestType())) {
      Preconditions.checkState(topLevelSkyValue instanceof ConfiguredTargetValue);
      return new ExclusiveTestBuildDriverValue(
          topLevelSkyValue, ((ConfiguredTargetValue) topLevelSkyValue).getConfiguredTarget());
    }

    return new BuildDriverValue(topLevelSkyValue, /*skipped=*/ false);
  }

  private static void postTopLevelTargetAnalyzedEvent(
      Environment env,
      ConfiguredTargetValue configuredTargetValue,
      ConfiguredTarget configuredTarget) {
    // It's possible that this code path is triggered AFTER the analysis cache clean up and the
    // transitive packages for package root resolution is already cleared. In such a case, the
    // symlinks should have already been planted.
    TopLevelTargetAnalyzedEvent topLevelTargetAnalyzedEvent =
        configuredTargetValue.getTransitivePackages() == null
            ? TopLevelTargetAnalyzedEvent.createWithoutFurtherSymlinkPlanting(configuredTarget)
            : TopLevelTargetAnalyzedEvent.create(
                configuredTarget, configuredTargetValue.getTransitivePackages());

    env.getListener().post(topLevelTargetAnalyzedEvent);
  }

  /**
   * Checks if a ConfiguredTarget is compatible with the platform/environment. See {@link
   * TopLevelConstraintSemantics}.
   *
   * @return null if a value is missing in the environment.
   */
  @Nullable
  private Boolean isConfiguredTargetCompatible(
      Environment env,
      State state,
      ConfiguredTarget configuredTarget,
      BuildConfigurationValue buildConfigurationValue,
      boolean isExplicitlyRequested)
      throws InterruptedException, TargetCompatibilityCheckException {

    if (!state.checkedForPlatformCompatibility) {
      PlatformCompatibility platformCompatibility =
          TopLevelConstraintSemantics.compatibilityWithPlatformRestrictions(
              configuredTarget,
              env.getListener(),
              /*eagerlyThrowError=*/ true,
              isExplicitlyRequested);
      state.checkedForPlatformCompatibility = true;
      switch (platformCompatibility) {
        case INCOMPATIBLE_EXPLICIT:
        case INCOMPATIBLE_IMPLICIT:
          return false;
        case COMPATIBLE:
          break;
      }
    }

    EnvironmentCompatibility environmentCompatibility =
        TopLevelConstraintSemantics.compatibilityWithTargetEnvironment(
            configuredTarget,
            buildConfigurationValue,
            label -> getTarget(env, label),
            env.getListener());
    if (env.valuesMissing() || environmentCompatibility == null) {
      return null;
    }
    if (environmentCompatibility.isCompatible()) {
      return true;
    }
    if (environmentCompatibility.severeMissingEnvironments() == null) {
      return false;
    }
    String badTargetsUserMessage =
        TopLevelConstraintSemantics.getErrorMessageForTarget(
            ruleContextConstraintSemantics.get(),
            configuredTarget,
            environmentCompatibility.severeMissingEnvironments());
    throw new TargetCompatibilityCheckException(
        badTargetsUserMessage,
        FailureDetail.newBuilder()
            .setMessage(badTargetsUserMessage)
            .setAnalysis(Analysis.newBuilder().setCode(Code.TARGETS_MISSING_ENVIRONMENTS))
            .build());
  }

  @Nullable
  private static Target getTarget(Environment env, Label label)
      throws InterruptedException, NoSuchTargetException {
    PackageValue packageValue =
        (PackageValue) env.getValue(PackageValue.key(label.getPackageIdentifier()));
    if (env.valuesMissing() || packageValue == null) {
      return null;
    }
    Package pkg = packageValue.getPackage();
    return pkg.getTarget(label.getName());
  }

  private void requestConfiguredTargetExecution(
      ConfiguredTarget configuredTarget,
      BuildDriverKey buildDriverKey,
      ActionLookupKey actionLookupKey,
      BuildConfigurationValue buildConfigurationValue,
      Environment env,
      TopLevelArtifactContext topLevelArtifactContext)
      throws InterruptedException {
    ImmutableSet.Builder<Artifact> artifactsToBuild = ImmutableSet.builder();
    addExtraActionsIfRequested(
        configuredTarget.getProvider(ExtraActionArtifactsProvider.class), artifactsToBuild);
    env.getListener().post(SomeExecutionStartedEvent.create());
    if (NOT_TEST.equals(buildDriverKey.getTestType())) {
      declareDependenciesAndCheckValues(
          env,
          Iterables.concat(
              Artifact.keys(artifactsToBuild.build()),
              Collections.singletonList(
                  TargetCompletionValue.key(
                      (ConfiguredTargetKey) actionLookupKey, topLevelArtifactContext, false))));
      return;
    }

    env.getListener()
        .post(
            TestAnalyzedEvent.create(
                configuredTarget,
                Preconditions.checkNotNull(buildConfigurationValue),
                /*isSkipped=*/ false));

    if (PARALLEL.equals(buildDriverKey.getTestType())) {
      // Only run non-exclusive tests here. Exclusive tests need to be run sequentially later.
      declareDependenciesAndCheckValues(
          env,
          Iterables.concat(
              artifactsToBuild.build(),
              Collections.singletonList(
                  TestCompletionValue.key(
                      (ConfiguredTargetKey) actionLookupKey,
                      topLevelArtifactContext,
                      /*exclusiveTesting=*/ false))));
      return;
    }

    // Exclusive tests will be run with sequential Skyframe evaluations afterwards.
    declareDependenciesAndCheckValues(env, artifactsToBuild.build());
  }

  private void announceAspectAnalysisDoneAndRequestExecution(
      BuildDriverKey buildDriverKey,
      TopLevelAspectsValue topLevelAspectsValue,
      Environment env,
      TopLevelArtifactContext topLevelArtifactContext)
      throws InterruptedException {

    env.getListener().post(SomeExecutionStartedEvent.create());
    ImmutableSet.Builder<Artifact> artifactsToBuild = ImmutableSet.builder();
    List<SkyKey> aspectCompletionKeys = new ArrayList<>();
    for (SkyValue value : topLevelAspectsValue.getTopLevelAspectsValues()) {
      AspectValue aspectValue = (AspectValue) value;
      AspectKey aspectKey = aspectValue.getKey();
      ConfiguredAspect configuredAspect = aspectValue.getConfiguredAspect();
      addExtraActionsIfRequested(
          configuredAspect.getProvider(ExtraActionArtifactsProvider.class), artifactsToBuild);
      postAspectAnalyzedEvent(env, aspectValue, aspectKey, configuredAspect);
      aspectCompletionKeys.add(AspectCompletionKey.create(aspectKey, topLevelArtifactContext));
    }
    // Send the AspectAnalyzedEvents first to make sure the BuildResultListener is up-to-date before
    // signaling that the analysis of this top level aspect has concluded.
    env.getListener().post(TopLevelEntityAnalysisConcludedEvent.success(buildDriverKey));

    declareDependenciesAndCheckValues(
        env, Iterables.concat(Artifact.keys(artifactsToBuild.build()), aspectCompletionKeys));
  }

  private static void postAspectAnalyzedEvent(
      Environment env,
      AspectValue aspectValue,
      AspectKey aspectKey,
      ConfiguredAspect configuredAspect) {
    // It's possible that this code path is triggered AFTER the analysis cache clean up and the
    // transitive packages for package root resolution is already cleared. In such a case, the
    // symlinks should have already been planted.
    AspectAnalyzedEvent aspectAnalyzedEvent =
        aspectValue.getTransitivePackages() == null
            ? AspectAnalyzedEvent.createWithoutFurtherSymlinkPlanting(aspectKey, configuredAspect)
            : AspectAnalyzedEvent.create(
                aspectKey, configuredAspect, aspectValue.getTransitivePackages());

    env.getListener().post(aspectAnalyzedEvent);
  }

  /**
   * Declares dependencies and checks values for requested nodes in the graph.
   *
   * <p>Calls {@link SkyframeIterableResult} and iterates over the result. If any node is not done,
   * or during iteration any value has exception, {@link SkyFunction.Environment#valuesMissing} will
   * return true.
   */
  private static void declareDependenciesAndCheckValues(
      Environment env, Iterable<? extends SkyKey> skyKeys) throws InterruptedException {
    SkyframeLookupResult result = env.getValuesAndExceptions(skyKeys);
    for (SkyKey key : skyKeys) {
      if (result.get(key) == null) {
        return;
      }
    }
  }

  @VisibleForTesting
  ImmutableMap<ActionAnalysisMetadata, ConflictException> checkActionConflicts(
      ActionLookupKey actionLookupKey, boolean strictConflictCheck) throws InterruptedException {
    ActionLookupValuesCollectionResult transitiveValueCollectionResult =
        transitiveActionLookupValuesHelper.collect(actionLookupKey);

    ImmutableMap<ActionAnalysisMetadata, ConflictException> conflicts =
        incrementalArtifactConflictFinder
            .get()
            .findArtifactConflicts(
                transitiveValueCollectionResult.collectedValues(), strictConflictCheck)
            .getConflicts();
    if (conflicts.isEmpty()) {
      transitiveActionLookupValuesHelper.registerConflictFreeKeys(
          transitiveValueCollectionResult.visitedKeys());
    }
    return conflicts;
  }

  private void addExtraActionsIfRequested(
      ExtraActionArtifactsProvider provider, ImmutableSet.Builder<Artifact> artifactsToBuild) {
    if (provider != null) {
      addArtifactsToBuilder(
          provider.getTransitiveExtraActionArtifacts().toList(),
          artifactsToBuild,
          extraActionFilterSupplier.get());
    }
  }

  private static void addArtifactsToBuilder(
      List<? extends Artifact> artifacts,
      ImmutableSet.Builder<Artifact> builder,
      RegexFilter filter) {
    for (Artifact artifact : artifacts) {
      if (filter.isIncluded(artifact.getOwnerLabel().toString())) {
        builder.add(artifact);
      }
    }
  }

  /** A SkyFunctionException wrapper for the actual TopLevelConflictException. */
  private static final class BuildDriverFunctionException extends SkyFunctionException {
    // The exception is transient here since it could be caused by external factors (conflict with
    // another target).
    BuildDriverFunctionException(TopLevelConflictException cause) {
      super(cause, Transience.TRANSIENT);
    }

    BuildDriverFunctionException(TargetCompatibilityCheckException cause) {
      super(cause, Transience.TRANSIENT);
    }
  }

  interface TransitiveActionLookupValuesHelper {

    /**
     * Perform the traversal of the transitive closure of the {@code key} and collect the
     * corresponding ActionLookupValues.
     */
    ActionLookupValuesCollectionResult collect(ActionLookupKey key) throws InterruptedException;

    /** Register with the helper that the {@code keys} are conflict-free. */
    void registerConflictFreeKeys(ImmutableSet<ActionLookupKey> keys);
  }

  @AutoValue
  abstract static class ActionLookupValuesCollectionResult {
    abstract Sharder<ActionLookupValue> collectedValues();

    abstract ImmutableSet<ActionLookupKey> visitedKeys();

    static ActionLookupValuesCollectionResult create(
        Sharder<ActionLookupValue> collectedValues, ImmutableSet<ActionLookupKey> visitedKeys) {
      return new AutoValue_BuildDriverFunction_ActionLookupValuesCollectionResult(
          collectedValues, visitedKeys);
    }
  }
}
