// Copyright 2022 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.ActionArtifactCycleReporter.ACTION_OR_ARTIFACT_OR_TRANSITIVE_RDEP;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionExecutionException;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.BuildFailedException;
import com.google.devtools.build.lib.actions.InputFileErrorException;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.actions.TestExecException;
import com.google.devtools.build.lib.analysis.AnalysisFailureEvent;
import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics.TargetCompatibilityCheckException;
import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.bugreport.BugReporter;
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.causes.LabelCause;
import com.google.devtools.build.lib.causes.LoadingFailedCause;
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.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.pkgcache.LoadingFailureEvent;
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.Execution;
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.ArtifactNestedSetFunction.ArtifactNestedSetEvalException;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.TopLevelAspectsKey;
import com.google.devtools.build.lib.skyframe.TestCompletionValue.TestCompletionKey;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelEntityAnalysisConcludedEvent;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.DetailedExitCode.DetailedExitCodeComparator;
import com.google.devtools.build.skyframe.CycleInfo;
import com.google.devtools.build.skyframe.CyclesReporter;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.WalkableGraph;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Supplier;
import javax.annotation.Nullable;

/** A utility class that provides methods to parse errors from Skyframe EvaluationResults. */
public final class SkyframeErrorProcessor {

  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  private SkyframeErrorProcessor() {}

  /**
   * Indicates if there are errors with the various phases, and an exception to be thrown to halt
   * the build, in case of --nokeep_going.
   *
   * <p>The various attributes will be used later on to construct the FailureDetail in {@link
   * com.google.devtools.build.lib.analysis.BuildView#createAnalysisFailureDetail}.
   */
  @AutoValue
  abstract static class ErrorProcessingResult {
    abstract boolean hasLoadingError();

    abstract boolean hasAnalysisError();

    abstract ImmutableMap<ActionAnalysisMetadata, ConflictException> actionConflicts();

    @Nullable
    abstract DetailedExitCode executionDetailedExitCode();

    static AggregatingBuilder newBuilder() {
      return new AggregatingBuilder();
    }

    static class AggregatingBuilder {
      private boolean hasLoadingError = false;
      private boolean hasAnalysisError = false;
      private final Map<ActionAnalysisMetadata, ConflictException> actionConflicts =
          Maps.newHashMap();
      @Nullable private DetailedExitCode executionDetailedExitCode = null;

      void aggregateSingleResult(IndividualErrorProcessingResult individualErrorProcessingResult) {
        hasLoadingError = hasLoadingError || individualErrorProcessingResult.isLoadingError();
        hasAnalysisError = hasAnalysisError || individualErrorProcessingResult.isAnalysisError();
        actionConflicts.putAll(individualErrorProcessingResult.actionConflicts());
        executionDetailedExitCode =
            DetailedExitCodeComparator.chooseMoreImportantWithFirstIfTie(
                executionDetailedExitCode,
                individualErrorProcessingResult.executionDetailedExitCode());
      }

      ErrorProcessingResult build() {
        return new AutoValue_SkyframeErrorProcessor_ErrorProcessingResult(
            hasLoadingError,
            hasAnalysisError,
            ImmutableMap.copyOf(actionConflicts),
            executionDetailedExitCode);
      }
    }
  }

  /**
   * Represents the information around one single error in the build. These are the building blocks
   * for the final {@link ErrorProcessingResult}.
   */
  @AutoValue
  abstract static class IndividualErrorProcessingResult {

    abstract ImmutableMap<ActionAnalysisMetadata, ConflictException> actionConflicts();

    @Nullable
    abstract DetailedExitCode executionDetailedExitCode();

    abstract NestedSet<Cause> analysisRootCauses();

    abstract ImmutableSet<Label> loadingRootCauses();

    boolean isActionConflictError() {
      return !actionConflicts().isEmpty();
    }

    boolean isLoadingError() {
      return !loadingRootCauses().isEmpty();
    }

    /** This is true for all non-execution errors: including loading & action conflict errors. */
    boolean isAnalysisError() {
      return executionDetailedExitCode() == null;
    }

    static IndividualErrorProcessingResult create(
        ImmutableMap<ActionAnalysisMetadata, ConflictException> actionConflicts,
        @Nullable DetailedExitCode executionDetailedExitCode,
        NestedSet<Cause> analysisRootCauses,
        ImmutableSet<Label> loadingRootCauses) {
      return new AutoValue_SkyframeErrorProcessor_IndividualErrorProcessingResult(
          actionConflicts, executionDetailedExitCode, analysisRootCauses, loadingRootCauses);
    }
  }

  /**
   * Process only loading/analysis errors. Returns a {@link ErrorProcessingResult}.
   *
   * <p>In case of --nokeep_going: immediately throw the exception.
   */
  static ErrorProcessingResult processAnalysisErrors(
      EvaluationResult<? extends SkyValue> result,
      Supplier<Map<BuildConfigurationKey, BuildConfigurationValue>> configurationLookupSupplier,
      CyclesReporter cyclesReporter,
      ExtendedEventHandler eventHandler,
      boolean keepGoing,
      @Nullable EventBus eventBus,
      BugReporter bugReporter)
      throws InterruptedException, ViewCreationFailedException {
    try {
      return processErrors(
          result,
          configurationLookupSupplier,
          cyclesReporter,
          eventHandler,
          keepGoing,
          eventBus,
          bugReporter,
          /*includeExecutionPhase=*/ false);
    } catch (BuildFailedException | TestExecException unexpected) {
      throw new IllegalStateException("Unexpected execution phase exception: ", unexpected);
    }
  }

  /**
   * Process errors encountered during analysis/execution.
   *
   * <p>This method has different goals depending on --(no)keep_going:
   *
   * <ul>
   *   <li>In case of --keep_going: post the necessary events, then construct an {@link
   *       ErrorProcessingResult}.
   *   <li>In case of --nokeep_going: post the necessary events, then throw an appropriate exception
   *       ASAP, except when the error is caused by an action conflict: we need more downstream
   *       information.
   * </ul>
   *
   * <p>Visible only for use by tests via {@link
   * SkyframeExecutor#getConfiguredTargetMapForTesting(ExtendedEventHandler,
   * BuildConfigurationValue, Iterable)}. When called there, {@code eventBus} must be null to
   * indicate that this is a test, and so there may be additional {@link SkyKey}s in the {@code
   * result} that are not {@link AspectKeyCreator}s or {@link ConfiguredTargetKey}s. Those keys will
   * be ignored.
   *
   * @throws ViewCreationFailedException when the root cause is analysis-related.
   * @throws BuildFailedException when the root cause is execution-related.
   * @throws TestExecException when the root cause is test-related.
   * @return an ErrorProcessingResult (only in --keep_going mode, or action conflict).
   */
  static ErrorProcessingResult processErrors(
      EvaluationResult<? extends SkyValue> result,
      Supplier<Map<BuildConfigurationKey, BuildConfigurationValue>> configurationLookupSupplier,
      CyclesReporter cyclesReporter,
      ExtendedEventHandler eventHandler,
      boolean keepGoing,
      @Nullable EventBus eventBus,
      @Nullable BugReporter bugReporter,
      boolean includeExecutionPhase)
      throws InterruptedException, ViewCreationFailedException, BuildFailedException,
          TestExecException {
    boolean inBuildViewTest = eventBus == null;
    ViewCreationFailedException noKeepGoingAnalysisExceptionAspect = null;
    ErrorProcessingResult.AggregatingBuilder aggregatingResultBuilder =
        ErrorProcessingResult.newBuilder();

    for (Map.Entry<SkyKey, ErrorInfo> errorEntry : result.errorMap().entrySet()) {
      maybePostTopLevelEntryAnalysisConcludedEvent(
          errorEntry.getKey(), errorEntry.getValue(), eventBus, keepGoing);
      ErrorInfo errorInfo = errorEntry.getValue();

      // The cycle reporter requires that the path to the cycle starts at the top level key
      // (requested via SkyframeExecutor), hence we need to provide the original top level key here.
      //
      // Why is there a need for "original" vs "effective" error key?
      // 1) The non-skymeld code path deals with ActionLookupKeys as the top level key,
      // 2) We wanted to share the error handling code between skymeld and non skymeld.
      // To do so, we need to "normalize" the top level key in Skymeld mode by getting the effective
      // ActionLookupKey from a BuildDriverKey. The rest of the method can then be easily shared.
      cyclesReporter.reportCycles(
          errorInfo.getCycleInfo(), /*topLevelKey=*/ errorEntry.getKey(), eventHandler);

      SkyKey errorKey = getEffectiveErrorKey(errorEntry);
      if (includeExecutionPhase) {
        assertValidAnalysisOrExecutionException(errorInfo, errorKey, result.getWalkableGraph());
      } else {
        assertValidAnalysisException(errorInfo, errorKey, result.getWalkableGraph());
      }
      Exception cause = errorInfo.getException();
      Preconditions.checkState(cause != null || !errorInfo.getCycleInfo().isEmpty(), errorInfo);

      if (inBuildViewTest && !isValidErrorKeyType(errorKey.argument())) {
        // This means that we are in a BuildViewTestCase.
        //
        // Tests don't call target pattern parsing before requesting the analysis of a target.
        // Therefore if the package that contains them cannot be loaded, we get an error key that's
        // not a ConfiguredTargetKey, which cannot happen in production code.
        //
        // If it's an existing target in a nonexistent package, the error is signaled by posting an
        // AnalysisFailureEvent on the event bus, which is null in when running a BuildViewTestCase,
        // so we emit the root cause labels directly to the event handler below.
        eventHandler.handle(Event.error(errorInfo.toString()));
        continue;
      }

      Label label = getLabel(errorKey);
      IndividualErrorProcessingResult individualErrorProcessingResult =
          processIndividualError(
              result, eventHandler, bugReporter, configurationLookupSupplier, errorKey, errorInfo);

      // For action conflicts, more downstream operations are required to have all the
      // information. We intentionally don't send out any failure event, throw any exception (even
      // with --nokeep_going) or print a warning message at this point. These will be done elsewhere
      // at a later point.
      if (individualErrorProcessingResult.isActionConflictError()) {
        aggregatingResultBuilder.aggregateSingleResult(individualErrorProcessingResult);
        continue;
      }

      maybePostFailureEventsForNonConflictError(
          configurationLookupSupplier,
          eventHandler,
          eventBus,
          inBuildViewTest,
          errorKey,
          label,
          individualErrorProcessingResult);

      if (keepGoing) {
        aggregatingResultBuilder.aggregateSingleResult(individualErrorProcessingResult);
        printWarningMessage(includeExecutionPhase, label, eventHandler);
      } else {
        noKeepGoingAnalysisExceptionAspect =
            throwOrReturnAspectAnalysisException(
                result,
                cause,
                bugReporter,
                errorKey,
                includeExecutionPhase,
                /*hasExecutionCycle=*/ CYCLE_CODE.equals(
                    individualErrorProcessingResult.executionDetailedExitCode()));
      }
    }

    if (noKeepGoingAnalysisExceptionAspect != null) {
      throw noKeepGoingAnalysisExceptionAspect;
    }

    return aggregatingResultBuilder.build();
  }

  /*
   * Post the relevant failure events if we're not in test.
   *
   * <p>There is 1 exception: for aspects, the failures should already have been reported to the
   * event handler, so we do nothing here.
   */
  private static void maybePostFailureEventsForNonConflictError(
      Supplier<Map<BuildConfigurationKey, BuildConfigurationValue>> configurationLookupSupplier,
      ExtendedEventHandler eventHandler,
      @Nullable EventBus eventBus,
      boolean inBuildViewTest,
      SkyKey errorKey,
      @Nullable Label label,
      IndividualErrorProcessingResult individualErrorProcessingResult) {
    Preconditions.checkState(!individualErrorProcessingResult.isActionConflictError());
    if (inBuildViewTest) {
      // eventBus is null, but tests can still assert on the expected root causes being found.
      eventHandler.handle(
          Event.error(individualErrorProcessingResult.analysisRootCauses().toList().toString()));
      return;
    }

    Preconditions.checkNotNull(eventBus);
    if (!(errorKey instanceof ConfiguredTargetKey)) {
      return;
    }

    ConfiguredTargetKey ctKey = (ConfiguredTargetKey) errorKey.argument();
    // For loading errors, we expect both LoadingFailureEvent and AnalysisFailureEvent.
    if (individualErrorProcessingResult.isLoadingError()) {
      for (Label loadingRootCause : individualErrorProcessingResult.loadingRootCauses()) {
        // This event is only for backwards compatibility with the old event protocol. Remove
        // once we've migrated to the build event protocol.
        eventBus.post(new LoadingFailureEvent(Preconditions.checkNotNull(label), loadingRootCause));
      }
    }

    if (individualErrorProcessingResult.isAnalysisError()) {
      BuildConfigurationValue configuration =
          configurationLookupSupplier.get().get(ctKey.getConfigurationKey());
      eventBus.post(
          new AnalysisFailureEvent(
              ctKey,
              configuration == null ? null : configuration.getEventId(),
              individualErrorProcessingResult.analysisRootCauses()));
    }
  }

  /**
   * Throw the necessary exceptions based on the error processing result.
   *
   * <p>This method should be called in --nokeep_going mode, unless the error is an action conflict.
   *
   * <p>Special case: if the analysis error belongs to a top-level Aspect, we don't throw the
   * ViewCreationFailedException immediately to make sure that a target analysis error is preferred
   * over an aspect one.
   *
   * @throws ViewCreationFailedException when the root cause is analysis-related.
   * @throws BuildFailedException when the root cause is execution-related.
   * @throws TestExecException when the root cause is test-related.
   * @return a ViewCreationFailedException if the error belongs to a top-level Aspect.
   */
  private static ViewCreationFailedException throwOrReturnAspectAnalysisException(
      EvaluationResult<? extends SkyValue> result,
      Exception cause,
      BugReporter bugReporter,
      SkyKey errorKey,
      boolean includeExecutionPhase,
      boolean hasExecutionCycle)
      throws BuildFailedException, TestExecException, ViewCreationFailedException {
    // If the error is execution-related: straightaway rethrow. No further steps required.
    if (isExecutionException(cause)) {
      rethrow(cause, bugReporter, result);
    }
    // If a --nokeep_going build found a cycle, that means there were no other errors thrown
    // during evaluation (otherwise, it wouldn't have bothered to find a cycle). So the best
    // we can do is throw a generic build failure exception, since we've already reported the
    // cycles above. Analysis cycles are handled below.
    if (hasExecutionCycle) {
      throw new BuildFailedException(null, CYCLE_CODE);
    }

    if (errorKey instanceof TopLevelAspectsKey) {
      TopLevelAspectsKey aspectKey = (TopLevelAspectsKey) errorKey.argument();
      String errorMsg =
          String.format(
              "Analysis of aspects '%s' failed; build aborted", aspectKey.getDescription());
      return createViewCreationFailedException(cause, errorMsg);
    }

    Label topLevelLabel = ((ConfiguredTargetKey) errorKey).getLabel();
    String errorMsg =
        includeExecutionPhase
            ? String.format("Build of target '%s' failed; build aborted", topLevelLabel)
            : String.format("Analysis of target '%s' failed; build aborted", topLevelLabel);
    throw createViewCreationFailedException(cause, errorMsg);
  }

  /**
   * Processes one individual error from the result.
   *
   * <p>No exception should ever be thrown here: this is just to gather the relevant information
   * around 1 single error. {@link #processErrors} will decide what to do with this information.
   */
  private static IndividualErrorProcessingResult processIndividualError(
      EvaluationResult<? extends SkyValue> result,
      ExtendedEventHandler eventHandler,
      BugReporter bugReporter,
      Supplier<Map<BuildConfigurationKey, BuildConfigurationValue>> configurationLookupSupplier,
      SkyKey errorKey,
      ErrorInfo errorInfo) {
    Exception exception = errorInfo.getException();
    Set<Label> loadingRootCauses = Sets.newHashSet();
    ImmutableMap<ActionAnalysisMetadata, ConflictException> actionConflicts = ImmutableMap.of();
    DetailedExitCode executionDetailedExitCode = null;

    // Legacy: analysis-related failure events for Aspects are sent somewhere else, so we don't have
    // to do any work related to constructing the analysis failure events here, only for the other
    // cases like action conflict or execution-related errors.
    // TODO(b/249690006): Can we simplify things by moving aspects events here?
    if (errorKey.argument() instanceof TopLevelAspectsKey) {
      if (exception instanceof TopLevelConflictException) {
        TopLevelConflictException tlce = (TopLevelConflictException) exception;
        actionConflicts = tlce.getTransitiveActionConflicts();
      } else if (isExecutionException(exception)) {
        executionDetailedExitCode =
            getExecutionDetailedExitCodeFromCause(result, exception, bugReporter);
      } else if (!errorInfo.getCycleInfo().isEmpty()
          && isExecutionCycle(errorInfo.getCycleInfo())) {
        executionDetailedExitCode = CYCLE_CODE;
      }
      return IndividualErrorProcessingResult.create(
          actionConflicts,
          executionDetailedExitCode,
          /*analysisRootCauses=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
          /*loadingRootCauses=*/ ImmutableSet.of());
    }

    // Only possible with actions generating build-info.txt and build-changelist.txt.
    if (errorKey.argument() instanceof ActionLookupData) {
      return IndividualErrorProcessingResult.create(
          /*actionConflicts=*/ ImmutableMap.of(),
          getExecutionDetailedExitCodeFromCause(result, exception, bugReporter),
          /*analysisRootCauses=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
          /*loadingRootCauses=*/ ImmutableSet.of());
    }

    Preconditions.checkState(
        errorKey.argument() instanceof ConfiguredTargetKey,
        "expected '%s' to be a TopLevelAspectsKey or ConfiguredTargetKey",
        errorKey.argument());
    ConfiguredTargetKey ctKey = (ConfiguredTargetKey) errorKey.argument();
    Label topLevelLabel = ctKey.getLabel();
    NestedSet<Cause> analysisRootCauses;

    if (exception instanceof TopLevelConflictException) {
      TopLevelConflictException tlce = (TopLevelConflictException) exception;
      actionConflicts = tlce.getTransitiveActionConflicts();
      analysisRootCauses = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    } else if (exception instanceof ConfiguredValueCreationException) {
      ConfiguredValueCreationException ctCause = (ConfiguredValueCreationException) exception;
      // Previously, the nested set was de-duplicating loading root cause labels. Now that we
      // track Cause instances including a message, we get one event per label and message. In
      // order to keep backwards compatibility, we de-duplicate root cause labels here.
      // TODO(ulfjack): Remove this code once we've migrated to the BEP.
      for (Cause rootCause : ctCause.getRootCauses().toList()) {
        if (rootCause instanceof LoadingFailedCause) {
          loadingRootCauses.add(rootCause.getLabel());
        }
      }
      analysisRootCauses = ctCause.getRootCauses();
    } else if (!errorInfo.getCycleInfo().isEmpty()) {
      if (isExecutionCycle(errorInfo.getCycleInfo())) {
        // If we have a cycle, cause would be null, so it's guaranteed that this
        // executionDetailedExitCode is final.
        executionDetailedExitCode = CYCLE_CODE;
        analysisRootCauses = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
      } else {
        Label analysisRootCause =
            maybeGetConfiguredTargetCycleCulprit(topLevelLabel, errorInfo.getCycleInfo());
        analysisRootCauses =
            analysisRootCause != null
                ? NestedSetBuilder.create(
                    Order.STABLE_ORDER,
                    new LabelCause(
                        analysisRootCause,
                        DetailedExitCode.of(createFailureDetail("Dependency cycle", Code.CYCLE))))
                // TODO(ulfjack): We need to report the dependency cycle here. How?
                : NestedSetBuilder.emptySet(Order.STABLE_ORDER);
      }
    } else if (exception instanceof ActionConflictException) {
      ((ActionConflictException) exception).reportTo(eventHandler);
      analysisRootCauses = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    } else if (exception instanceof NoSuchPackageException) {
      // This branch is only taken in --nokeep_going builds. In a --keep_going build, the
      // AnalysisFailedCause is properly reported through the ConfiguredValueCreationException.
      BuildConfigurationValue configuration =
          configurationLookupSupplier.get().get(ctKey.getConfigurationKey());
      ConfigurationId configId = configuration.getEventId().getConfiguration();
      AnalysisFailedCause analysisFailedCause =
          new AnalysisFailedCause(
              topLevelLabel, configId, ((NoSuchPackageException) exception).getDetailedExitCode());
      analysisRootCauses = NestedSetBuilder.create(Order.STABLE_ORDER, analysisFailedCause);
    } else if (exception instanceof TargetCompatibilityCheckException) {
      analysisRootCauses = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    } else if (isExecutionException(exception)) {
      executionDetailedExitCode =
          getExecutionDetailedExitCodeFromCause(result, exception, bugReporter);
      analysisRootCauses =
          exception instanceof ActionExecutionException
              ? ((ActionExecutionException) exception).getRootCauses()
              : NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    } else {
      BugReport.logUnexpected(
          exception, "Unexpected cause encountered while evaluating: %s", errorKey);
      analysisRootCauses = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }

    return IndividualErrorProcessingResult.create(
        actionConflicts,
        executionDetailedExitCode,
        analysisRootCauses,
        ImmutableSet.copyOf(loadingRootCauses));
  }

  private static DetailedExitCode getExecutionDetailedExitCodeFromCause(
      EvaluationResult<? extends SkyValue> result, Exception cause, BugReporter bugReporter) {
    DetailedExitCode executionDetailedExitCode = DetailedException.getDetailedExitCode(cause);
    if (executionDetailedExitCode == null) {
      executionDetailedExitCode =
          sendBugReportAndCreateUnknownExecutionDetailedExitCode(result, cause, bugReporter);
    }
    return executionDetailedExitCode;
  }

  private static DetailedExitCode sendBugReportAndCreateUnknownExecutionDetailedExitCode(
      EvaluationResult<? extends SkyValue> result, Throwable cause, BugReporter bugReporter) {
    // An undetailed exception means we may incorrectly attribute responsibility for the failure:
    // we need to fix that.
    bugReporter.sendNonFatalBugReport(
        new IllegalStateException(
            "action terminated with unexpected exception with result " + result, cause));
    String message =
        "Unexpected exception, please file an issue with the Bazel team: " + cause.getMessage();
    return createDetailedExecutionExitCode(message, UNKNOWN_EXECUTION);
  }

  private static void printWarningMessage(
      boolean includeExecutionPhase,
      @Nullable Label topLevelLabel,
      ExtendedEventHandler eventHandler) {
    String warningMsg =
        includeExecutionPhase
            ? String.format("errors encountered while building target '%s'", topLevelLabel)
            : String.format(
                "errors encountered while analyzing target '%s': it will not be built",
                topLevelLabel);
    eventHandler.handle(Event.warn(warningMsg));
  }

  private static boolean isValidErrorKeyType(Object errorKey) {
    return errorKey instanceof ConfiguredTargetKey || errorKey instanceof TopLevelAspectsKey;
  }

  private static void maybePostTopLevelEntryAnalysisConcludedEvent(
      SkyKey skyKey, ErrorInfo errorInfo, EventBus eventBus, boolean keepGoing) {
    // In case of --nokeep_going and there's an analysis error, we don't consider the analysis phase
    // to be concluded.
    if (keepGoing
        && skyKey instanceof BuildDriverKey
        && !isExecutionException(errorInfo.getException())) {
      eventBus.post(TopLevelEntityAnalysisConcludedEvent.failure(skyKey));
    }
  }

  /** Peel away the wrapper layers to get to the ActionLookupKey of the top level target. */
  private static SkyKey getEffectiveErrorKey(Entry<SkyKey, ErrorInfo> errorEntry) {
    if (errorEntry.getKey().argument() instanceof BuildDriverKey) {
      return ((BuildDriverKey) errorEntry.getKey().argument()).getActionLookupKey();
    }
    // For exclusive tests.
    if (errorEntry.getKey().argument() instanceof TestCompletionKey) {
      return ((TestCompletionKey) errorEntry.getKey().argument()).configuredTargetKey();
    }
    return errorEntry.getKey();
  }

  @Nullable
  private static Label getLabel(SkyKey errorKey) {
    return errorKey instanceof ActionLookupKey ? ((ActionLookupKey) errorKey).getLabel() : null;
  }

  private static ViewCreationFailedException createViewCreationFailedException(
      @Nullable Exception e, String errorMsg) {
    if (e == null) {
      return new ViewCreationFailedException(
          errorMsg, createFailureDetail(errorMsg + " due to cycle", Code.CYCLE));
    }
    return new ViewCreationFailedException(
        errorMsg, maybeContextualizeFailureDetail(e, errorMsg), e);
  }

  /**
   * Returns a {@link FailureDetail} with message prefixed by {@code errorMsg} derived from the
   * failure detail in {@code e} if it's a {@link DetailedException}, and otherwise returns one with
   * {@code errorMsg} and {@link Code#UNEXPECTED_ANALYSIS_EXCEPTION}.
   */
  private static FailureDetail maybeContextualizeFailureDetail(
      @Nullable Exception e, String errorMsg) {
    DetailedException detailedException = convertToAnalysisException(e);
    if (detailedException == null) {
      return createFailureDetail(errorMsg, Code.UNEXPECTED_ANALYSIS_EXCEPTION);
    }
    FailureDetail originalFailureDetail =
        detailedException.getDetailedExitCode().getFailureDetail();
    return originalFailureDetail.toBuilder()
        .setMessage(errorMsg + ": " + originalFailureDetail.getMessage())
        .build();
  }

  private static FailureDetail createFailureDetail(String errorMessage, Code code) {
    return FailureDetail.newBuilder()
        .setMessage(errorMessage)
        .setAnalysis(Analysis.newBuilder().setCode(code))
        .build();
  }

  @Nullable
  private static Label maybeGetConfiguredTargetCycleCulprit(
      Label labelToLoad, Iterable<CycleInfo> cycleInfos) {
    for (CycleInfo cycleInfo : cycleInfos) {
      SkyKey culprit = Iterables.getFirst(cycleInfo.getCycle(), null);
      if (culprit == null) {
        continue;
      }
      if (culprit.functionName().equals(SkyFunctions.CONFIGURED_TARGET)) {
        return ((ConfiguredTargetKey) culprit.argument()).getLabel();
      } else if (culprit.functionName().equals(TransitiveTargetKey.NAME)) {
        return ((TransitiveTargetKey) culprit).getLabel();
      } else {
        return labelToLoad;
      }
    }
    return null;
  }

  private static void assertValidAnalysisException(
      ErrorInfo errorInfo, SkyKey key, WalkableGraph walkableGraph) throws InterruptedException {
    Throwable cause = errorInfo.getException();
    if (cause == null) {
      // Cycle.
      return;
    }

    if (convertToAnalysisException(cause) != null) {
      // Valid exception type.
      return;
    }

    logUnexpectedExceptionOrigin(errorInfo, key, walkableGraph, cause);
  }

  private static void assertValidAnalysisOrExecutionException(
      ErrorInfo errorInfo, SkyKey key, WalkableGraph walkableGraph) throws InterruptedException {
    Throwable cause = errorInfo.getException();
    if (cause == null) {
      // Cycle.
      return;
    }

    if (convertToAnalysisException(cause) != null
        || isExecutionException(cause)
        || cause instanceof TopLevelConflictException) {
      // Valid exception type.
      return;
    }

    logUnexpectedExceptionOrigin(errorInfo, key, walkableGraph, cause);
  }

  /**
   * Walk the graph to find a path to the lowest-level node that threw unexpected exception and log
   * it.
   */
  private static void logUnexpectedExceptionOrigin(
      ErrorInfo errorInfo, SkyKey key, WalkableGraph walkableGraph, Throwable cause)
      throws InterruptedException {
    List<SkyKey> path = new ArrayList<>();
    try {
      SkyKey currentKey = key;
      boolean foundDep;
      do {
        path.add(currentKey);
        foundDep = false;

        Map<SkyKey, Exception> missingMap =
            walkableGraph.getMissingAndExceptions(ImmutableList.of(currentKey));
        if (missingMap.containsKey(currentKey) && missingMap.get(currentKey) == null) {
          // This can happen in a no-keep-going build, where we don't write the bubbled-up error
          // nodes to the graph.
          break;
        }

        for (SkyKey dep : walkableGraph.getDirectDeps(currentKey)) {
          if (cause.equals(walkableGraph.getException(dep))) {
            currentKey = dep;
            foundDep = true;
            break;
          }
        }
      } while (foundDep);
    } finally {
      BugReport.logUnexpected("Unexpected analysis error: %s -> %s, (%s)", key, errorInfo, path);
    }
  }

  @Nullable
  private static DetailedException convertToAnalysisException(Throwable cause) {
    // The cause may be NoSuch{Target,Package}Exception if we run the reduced loading phase and then
    // analyze with --nokeep_going.
    if (cause instanceof SaneAnalysisException
        || cause instanceof NoSuchTargetException
        || cause instanceof NoSuchPackageException) {
      return (DetailedException) cause;
    }
    return null;
  }

  private static boolean isExecutionException(Throwable cause) {
    return cause instanceof ActionExecutionException
        || cause instanceof InputFileErrorException
        || cause instanceof TestExecException
        // Refer to UnusedInputsFailureIntegrationTest#incrementalFailureOnUnusedInput.
        || cause instanceof ArtifactNestedSetEvalException;
  }

  /**
   * Process an {@link EvaluationResult}, taking into account the keepGoing setting.
   *
   * <p>Returns a nullable {@link DetailedExitCode} value, as follows:
   *
   * <ol>
   *   <li>{@code null}, if {@code result} had no errors
   *   <li>{@code e} if result had errors and one of them specified a {@link DetailedExitCode} value
   *       {@code e}
   *   <li>a {@link DetailedExitCode} with {@link Execution.Code#NON_ACTION_EXECUTION_FAILURE} if
   *       result had errors but none specified a {@link DetailedExitCode} value
   * </ol>
   *
   * <p>Throws on catastrophic failures and, if !keepGoing, on any failure. TODO(leba): We should
   * ideally remove this method and incorporate its logic into #processAnalysisErrors.
   */
  @Nullable
  public static DetailedExitCode processResult(
      ExtendedEventHandler eventHandler,
      EvaluationResult<?> result,
      boolean keepGoing,
      CyclesReporter cyclesReporter,
      @Nullable BugReporter bugReporter)
      throws BuildFailedException, TestExecException {
    if (result.hasError()) {
      for (Map.Entry<SkyKey, ErrorInfo> entry : result.errorMap().entrySet()) {
        ImmutableList<CycleInfo> cycles = entry.getValue().getCycleInfo();
        cyclesReporter.reportCycles(cycles, entry.getKey(), eventHandler);
      }

      if (result.getCatastrophe() != null) {
        rethrow(result.getCatastrophe(), bugReporter, result);
      }
      if (keepGoing) {
        return getDetailedExitCodeKeepGoing(result);
      }
      ErrorInfo errorInfo = Preconditions.checkNotNull(result.getError(), result);
      Exception exception = errorInfo.getException();
      if (exception == null) {
        Preconditions.checkState(!errorInfo.getCycleInfo().isEmpty(), errorInfo);
        // If a keepGoing=false build found a cycle, that means there were no other errors thrown
        // during evaluation (otherwise, it wouldn't have bothered to find a cycle). So the best
        // we can do is throw a generic build failure exception, since we've already reported the
        // cycles above.
        throw new BuildFailedException(null, CYCLE_CODE);
      } else {
        rethrow(exception, bugReporter, result);
      }
    }

    return null;
  }

  private static DetailedExitCode getDetailedExitCodeKeepGoing(EvaluationResult<?> result) {
    // If build fails and keepGoing is true, an exit code is assigned using reported errors
    // in the following order:
    //   1. First infrastructure error with non-null exit code
    //   2. First non-infrastructure error with non-null exit code
    //   3. If the build fails but no interpretable error is specified, BUILD_FAILURE.
    DetailedExitCode detailedExitCode = null;
    Throwable undetailedCause = null;
    for (Map.Entry<SkyKey, ErrorInfo> error : result.errorMap().entrySet()) {
      Throwable cause = error.getValue().getException();
      if (cause instanceof DetailedException) {
        // Update global exit code when current exit code is not null and global exit code has
        // a lower 'reporting' priority.
        detailedExitCode =
            DetailedExitCodeComparator.chooseMoreImportantWithFirstIfTie(
                detailedExitCode, ((DetailedException) cause).getDetailedExitCode());
        if (!(cause instanceof ActionExecutionException)
            && !(cause instanceof InputFileErrorException)) {
          logger.atWarning().withCause(cause).log(
              "Non-action-execution/input-error exception for %s", error);
        }
      } else if (!error.getValue().getCycleInfo().isEmpty()) {
        detailedExitCode =
            DetailedExitCodeComparator.chooseMoreImportantWithFirstIfTie(
                detailedExitCode, CYCLE_CODE);
      } else {
        undetailedCause = cause;
      }
    }
    if (detailedExitCode != null) {
      return detailedExitCode;
    }
    return createDetailedExitCodeForUndetailedExecutionCauseKeepGoing(result, undetailedCause);
  }

  /**
   * Figure out why an action's analysis/execution failed and rethrow the right kind of exception.
   */
  @VisibleForTesting
  static void rethrow(
      Throwable cause, BugReporter bugReporter, EvaluationResult<?> resultForDebugging)
      throws BuildFailedException, TestExecException {
    Throwables.throwIfUnchecked(cause);
    Throwable innerCause = cause.getCause();
    if (innerCause instanceof TestExecException) {
      throw (TestExecException) innerCause;
    }
    if (cause instanceof ActionExecutionException) {
      ActionExecutionException actionExecutionCause = (ActionExecutionException) cause;
      String message = cause.getMessage();
      if (actionExecutionCause.getAction() != null) {
        message = actionExecutionCause.getAction().describe() + " failed: " + message;
      }
      // Sometimes ActionExecutionExceptions are caused by Actions with no owner.
      if (actionExecutionCause.getLocation() != null) {
        message = actionExecutionCause.getLocation() + " " + message;
      }
      throw new BuildFailedException(
          message,
          actionExecutionCause.isCatastrophe(),
          /*errorAlreadyShown=*/ !actionExecutionCause.showError(),
          actionExecutionCause.getDetailedExitCode());
    }
    if (cause instanceof InputFileErrorException) {
      throw (InputFileErrorException) cause;
    }

    // We encountered an exception we don't think we should have encountered. This can indicate
    // an exception-processing bug in our code, such as lower level exceptions not being properly
    // handled, or in our expectations in this method.

    if (cause instanceof DetailedException) {
      // The exception escaped Skyframe error bubbling, but its failure detail can still be used.
      bugReporter.logUnexpected(
          (Exception) cause,
          "action terminated with unexpected exception with result %s",
          resultForDebugging);
      throw new BuildFailedException(
          cause.getMessage(), ((DetailedException) cause).getDetailedExitCode());
    }

    DetailedExitCode unknownExitCode =
        sendBugReportAndCreateUnknownExecutionDetailedExitCode(
            resultForDebugging, cause, bugReporter);
    throw new BuildFailedException(
        Preconditions.checkNotNull(unknownExitCode.getFailureDetail()).getMessage(),
        unknownExitCode);
  }

  private static DetailedExitCode createDetailedExitCodeForUndetailedExecutionCauseKeepGoing(
      EvaluationResult<?> result, Throwable undetailedCause) {
    if (undetailedCause == null) {
      BugReport.sendBugReport("No exceptions found despite error in %s", result);
      return createDetailedExecutionExitCode(
          "keep_going execution failed without an action failure",
          Execution.Code.NON_ACTION_EXECUTION_FAILURE);
    }
    BugReport.sendBugReport(
        new IllegalStateException("No detailed exception found in " + result, undetailedCause));
    return createDetailedExecutionExitCode(
        "keep_going execution failed without an action failure: "
            + undetailedCause.getMessage()
            + " ("
            + undetailedCause.getClass().getSimpleName()
            + ")",
        Execution.Code.NON_ACTION_EXECUTION_FAILURE);
  }

  private static final DetailedExitCode CYCLE_CODE =
      createDetailedExecutionExitCode("cycle found during execution", Execution.Code.CYCLE);
  private static final Execution UNKNOWN_EXECUTION =
      Execution.newBuilder().setCode(Execution.Code.UNEXPECTED_EXCEPTION).build();

  private static DetailedExitCode createDetailedExecutionExitCode(
      String message, Execution.Code detailedCode) {
    return createDetailedExecutionExitCode(
        message, Execution.newBuilder().setCode(detailedCode).build());
  }

  private static DetailedExitCode createDetailedExecutionExitCode(
      String message, Execution execution) {
    return DetailedExitCode.of(
        FailureDetail.newBuilder().setMessage(message).setExecution(execution).build());
  }

  private static boolean isExecutionCycle(Iterable<CycleInfo> cycleInfoCollection) {
    for (CycleInfo cycleInfo : cycleInfoCollection) {
      if (cycleInfo.getCycle().stream().allMatch(ACTION_OR_ARTIFACT_OR_TRANSITIVE_RDEP)) {
        // All these cycle info belong to the same top level key. If one of them is
        // execution-related, we consider the error to be execution-related.
        return true;
      }
    }
    return false;
  }
}
