// Copyright 2017 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.constraints;

import static java.util.stream.Collectors.joining;

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.IncompatiblePlatformProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.configuredtargets.OutputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.constraints.SupportedEnvironmentsProvider.RemovedEnvironmentCulprit;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.EnvironmentGroup;
import com.google.devtools.build.lib.packages.EnvironmentLabels;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.PackageManager;
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.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.SaneAnalysisException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Function;
import javax.annotation.Nullable;

/**
 * Constraint semantics that apply to top-level targets.
 *
 * <p>Top-level targets are "special" because they have no parents that can assert expected
 * environment compatibility. So these expectations have to be declared by other means.
 *
 * <p>For all other targets see {@link ConstraintSemantics}.
 */
public class TopLevelConstraintSemantics {
  private final RuleContextConstraintSemantics constraintSemantics;
  private final PackageManager packageManager;
  private final Function<BuildConfigurationKey, BuildConfigurationValue> configurationProvider;
  private final ExtendedEventHandler eventHandler;
  private static final String TARGET_INCOMPATIBLE_ERROR_TEMPLATE =
      "Target %s is incompatible and cannot be built, but was explicitly requested.%s";

  /**
   * Constructor with helper classes for loading targets.
   *
   * @param constraintSemantics core constraints implementation logic
   * @param packageManager object for retrieving loaded targets
   * @param configurationProvider gets configurations from {@link ConfiguredTarget}s
   * @param eventHandler the build's event handler
   */
  public TopLevelConstraintSemantics(
      RuleContextConstraintSemantics constraintSemantics,
      PackageManager packageManager,
      Function<BuildConfigurationKey, BuildConfigurationValue> configurationProvider,
      ExtendedEventHandler eventHandler) {
    this.constraintSemantics = constraintSemantics;
    this.packageManager = packageManager;
    this.configurationProvider = configurationProvider;
    this.eventHandler = eventHandler;
  }

  static class MissingEnvironment {
    private final Label environment;
    @Nullable
    // If null, the top-level target just didn't declare a required environment. If not null, that
    // means the declaration got "refined" away due to some select() somewhere in its deps. See
    // ConstraintSemantics's documentation for an explanation of refinement.
    private final RemovedEnvironmentCulprit culprit;
    private MissingEnvironment(Label environment, RemovedEnvironmentCulprit culprit) {
      this.environment = environment;
      this.culprit = culprit;
    }
  }

  /**
   * Returns the compatibility of a ConfiguredTarget with the platform.
   *
   * <p>See {@link #checkPlatformRestrictions}.
   */
  public static PlatformCompatibility compatibilityWithPlatformRestrictions(
      ConfiguredTarget configuredTarget,
      ExtendedEventHandler eventHandler,
      boolean eagerlyThrowError,
      boolean explicitlyRequested,
      boolean skipIncompatibleExplicitTargets)
      throws TargetCompatibilityCheckException {

    RuleContextConstraintSemantics.IncompatibleCheckResult incompatibleCheckResult =
        RuleContextConstraintSemantics.checkForIncompatibility(configuredTarget);
    if (!incompatibleCheckResult.isIncompatible()) {
      return PlatformCompatibility.COMPATIBLE;
    }

    // We need the label in unambiguous form here. I.e. with the "@" prefix for targets in the
    // main repository. explicitTargetPatterns is also already in the unambiguous form to make
    // comparison succeed regardless of the provided form.
    if (!skipIncompatibleExplicitTargets && explicitlyRequested) {
      if (eagerlyThrowError) {
        // Use the slightly simpler form for printing error messages. I.e. no "@" prefix for
        // targets in the main repository.
        throw getExceptionForExplicitlyRequestedIncompatibleTarget(
            configuredTarget, incompatibleCheckResult.underlyingTarget());
      }
      eventHandler.handle(
          Event.warn(
              String.format(TARGET_INCOMPATIBLE_ERROR_TEMPLATE, configuredTarget.getLabel(), "")));
      return PlatformCompatibility.INCOMPATIBLE_EXPLICIT;
    }
    // We can safely skip this target if it wasn't explicitly requested or we've been instructed
    // to skip explicitly requested targets.
    return PlatformCompatibility.INCOMPATIBLE_IMPLICIT;
  }

  private static TargetCompatibilityCheckException
      getExceptionForExplicitlyRequestedIncompatibleTarget(
          ConfiguredTarget configuredTarget, ConfiguredTarget underlyingTarget) {
    String targetIncompatibleMessage =
        String.format(
            TARGET_INCOMPATIBLE_ERROR_TEMPLATE,
            configuredTarget.getLabel(),
            // We need access to the provider so we pass in the underlying target here that is
            // responsible for the incompatibility.
            reportOnIncompatibility(underlyingTarget));
    return new TargetCompatibilityCheckException(
        targetIncompatibleMessage,
        FailureDetail.newBuilder()
            .setMessage(targetIncompatibleMessage)
            .setAnalysis(Analysis.newBuilder().setCode(Code.INCOMPATIBLE_TARGET_REQUESTED))
            .build());
  }

  /**
   * Returns the compatibility with the target environment.
   *
   * <p>See {@link #checkTargetEnvironmentRestrictions}.
   *
   * @return null if the {@code targetLookup} performs a Skyframe lookup and the value is missing.
   */
  @Nullable
  public static EnvironmentCompatibility compatibilityWithTargetEnvironment(
      ConfiguredTarget configuredTarget,
      @Nullable BuildConfigurationValue buildConfigurationValue,
      TargetLookup targetLookup,
      ExtendedEventHandler eventHandler)
      throws InterruptedException, TargetCompatibilityCheckException {
    Target target;
    try {
      target = Preconditions.checkNotNull(targetLookup.getTarget(configuredTarget.getLabel()));
    } catch (NoSuchPackageException | NoSuchTargetException e) {
      eventHandler.handle(
          Event.error(
              "Unable to get target from package when checking environment restrictions. " + e));
      return EnvironmentCompatibility.compatible();
    }
    // TODO(bazel-team): support file targets (they should apply package-default constraints.
    if (buildConfigurationValue == null
        || !buildConfigurationValue
            .enforceConstraints() // Constraint checking is disabled for all targets.
        || target.getAssociatedRule() == null
        || !target
            .getAssociatedRule()
            .getRuleClassObject()
            .supportsConstraintChecking() // This target doesn't participate in constraints.
    ) {
      return EnvironmentCompatibility.compatible();
    }

    // Check explicitly expected environments.
    ImmutableSet<MissingEnvironment> severeMissingEnvironments =
        getMissingEnvironments(
            configuredTarget, buildConfigurationValue.getTargetEnvironments(), targetLookup);
    // Missing value.
    if (severeMissingEnvironments == null) {
      return null;
    }

    if (!severeMissingEnvironments.isEmpty()) {
      return EnvironmentCompatibility.severeIncompatible(severeMissingEnvironments);
    }

    // Check auto-detected CPU environments.
    try {
      ImmutableSet<MissingEnvironment> nonSevereMissingEnvironment =
          getMissingEnvironments(
              configuredTarget,
              autoConfigureTargetEnvironments(
                  buildConfigurationValue,
                  buildConfigurationValue.getAutoCpuEnvironmentGroup(),
                  targetLookup),
              targetLookup);
      if (nonSevereMissingEnvironment == null) {
        return null;
      }
      if (!nonSevereMissingEnvironment.isEmpty()) {
        return EnvironmentCompatibility.nonSevereIncompatible();
      }
    } catch (NoSuchPackageException | NoSuchTargetException e) {
      throw new TargetCompatibilityCheckException(
          "invalid target environment", e.getDetailedExitCode().getFailureDetail(), e);
    }
    return EnvironmentCompatibility.compatible();
  }

  /**
   * Checks that the all top-level targets are compatible with the target platform.
   *
   * <p>If any target doesn't support the target platform it will be either marked as "to be
   * skipped" or marked as "errored".
   *
   * <p>Targets that are incompatible with the target platform and are not explicitly requested on
   * the command line should be skipped.
   *
   * <p>Targets that are incompatible with the target platform and *are* explicitly requested on the
   * command line are errored unless --skip_incompatible_explicit_targets is enabled. Having one or
   * more errored targets will cause the entire build to fail with an error message.
   *
   * @param topLevelTargets the build's top-level targets
   * @param explicitTargetPatterns the set of explicit target patterns specified by the user on the
   *     command line. Every target must be in the unambiguous canonical form (i.e., with the "@"
   *     prefix for all targets including in the main repository).
   * @return the set of to-be-skipped and errored top-level targets.
   * @throws ViewCreationFailedException if any top-level target was explicitly requested on the
   *     command line.
   */
  public PlatformRestrictionsResult checkPlatformRestrictions(
      ImmutableSet<ConfiguredTarget> topLevelTargets,
      ImmutableSet<Label> explicitTargetPatterns,
      boolean keepGoing,
      boolean skipIncompatibleExplicitTargets)
      throws ViewCreationFailedException {
    ImmutableSet.Builder<ConfiguredTarget> incompatibleTargets = ImmutableSet.builder();
    ImmutableSet.Builder<ConfiguredTarget> incompatibleButRequestedTargets = ImmutableSet.builder();

    try {
      for (ConfiguredTarget target : topLevelTargets) {
        PlatformCompatibility platformCompatibility =
            compatibilityWithPlatformRestrictions(
                target,
                eventHandler,
                /* eagerlyThrowError= */ !keepGoing,
                explicitTargetPatterns.contains(target.getLabel()),
                skipIncompatibleExplicitTargets);
        if (PlatformCompatibility.INCOMPATIBLE_EXPLICIT.equals(platformCompatibility)) {
          incompatibleButRequestedTargets.add(target);
        } else if (PlatformCompatibility.INCOMPATIBLE_IMPLICIT.equals(platformCompatibility)) {
          incompatibleTargets.add(target);
        }
      }
    } catch (TargetCompatibilityCheckException e) {
      throw new ViewCreationFailedException(e.getFailureDetail(), /*cause=*/ e);
    }

    return PlatformRestrictionsResult.builder()
        .targetsToSkip(ImmutableSet.copyOf(incompatibleTargets.build()))
        .targetsWithErrors(ImmutableSet.copyOf(incompatibleButRequestedTargets.build()))
        .build();
  }

  /**
   * Assembles the explanation for a platform incompatibility.
   *
   * <p>This is useful when trying to explain to the user why an explicitly requested target on the
   * command line is considered incompatible. The goal is to print out the dependency chain and the
   * constraint that wasn't satisfied so that the user can immediately figure out what happened.
   *
   * @param target the incompatible target that was explicitly requested on the command line.
   * @return the verbose error message to show to the user.
   */
  private static String reportOnIncompatibility(ConfiguredTarget target) {
    Preconditions.checkNotNull(target);

    String message = "\nDependency chain:";
    IncompatiblePlatformProvider provider = null;

    // TODO(austinschuh): While the first error is helpful, reporting all the errors at once would
    // save the user bazel round trips.
    while (target != null) {
      message +=
          String.format(
              "\n    %s (%s)",
              target.getLabel(), target.getConfigurationChecksum().substring(0, 6));
      provider = target.get(IncompatiblePlatformProvider.PROVIDER);
      ImmutableList<ConfiguredTarget> targetList = provider.targetsResponsibleForIncompatibility();
      if (targetList == null) {
        target = null;
      } else {
        target = targetList.get(0);
      }
    }

    message +=
        String.format(
            "   <-- target platform (%s) didn't satisfy constraint", provider.targetPlatform());
    if (provider.constraintsResponsibleForIncompatibility().size() == 1) {
      message += " " + provider.constraintsResponsibleForIncompatibility().get(0).label();
      return message;
    }

    message += "s [";

    boolean first = true;
    for (ConstraintValueInfo constraintValueInfo :
        provider.constraintsResponsibleForIncompatibility()) {
      if (first) {
        first = false;
      } else {
        message += ", ";
      }
      message += constraintValueInfo.label();
    }

    message += "]";

    return message;
  }

  /**
   * Checks that if this is an environment-restricted build, all top-level targets support expected
   * top-level environments. Expected top-level environments can be declared explicitly through
   * {@code --target_environment} or implicitly through {@code --auto_cpu_environment_group}. For
   * the latter, top-level targets must be compatible with the build's target configuration CPU.
   *
   * <p>If any target doesn't support an explicitly expected environment declared through {@link
   * CoreOptions#targetEnvironments}, the entire build fails with an error.
   *
   * <p>If any target doesn't support an implicitly expected environment declared through {@link
   * CoreOptions#autoCpuEnvironmentGroup}, the target is skipped during execution while remaining
   * targets execute as normal.
   *
   * @param topLevelTargets the build's top-level targets
   * @return the set of bad top-level targets.
   * @throws ViewCreationFailedException if any target doesn't support an explicitly expected
   *     environment declared through {@link CoreOptions#targetEnvironments}
   */
  public Set<ConfiguredTarget> checkTargetEnvironmentRestrictions(
      ImmutableSet<ConfiguredTarget> topLevelTargets)
      throws ViewCreationFailedException, InterruptedException {
    ImmutableSet.Builder<ConfiguredTarget> badTargets = ImmutableSet.builder();
    // Maps targets that are missing *explicitly* required environments to the set of environments
    // they're missing. These targets trigger a ViewCreationFailedException, which halts the build.
    // Targets with missing *implicitly* required environments don't belong here, since the build
    // continues while skipping them.
    Multimap<ConfiguredTarget, MissingEnvironment> exceptionInducingTargets =
        ArrayListMultimap.create();
    try {
      for (ConfiguredTarget topLevelTarget : topLevelTargets) {
        EnvironmentCompatibility compatibility =
            Preconditions.checkNotNull(
                compatibilityWithTargetEnvironment(
                    topLevelTarget,
                    configurationProvider.apply(topLevelTarget.getConfigurationKey()),
                    label -> packageManager.getTarget(eventHandler, label),
                    eventHandler));
        if (compatibility.isCompatible()) {
          continue;
        }
        if (compatibility.severeMissingEnvironments() != null) {
          exceptionInducingTargets.putAll(
              topLevelTarget, compatibility.severeMissingEnvironments());
        }
        badTargets.add(topLevelTarget);
      }
    } catch (TargetCompatibilityCheckException e) {
      throw new ViewCreationFailedException(e.getMessage(), e.getFailureDetail(), e);
    }

    if (!exceptionInducingTargets.isEmpty()) {
      String badTargetsUserMessage =
          getBadTargetsUserMessage(constraintSemantics, exceptionInducingTargets);
      throw new ViewCreationFailedException(
          badTargetsUserMessage,
          FailureDetail.newBuilder()
              .setMessage(badTargetsUserMessage)
              .setAnalysis(Analysis.newBuilder().setCode(Code.TARGETS_MISSING_ENVIRONMENTS))
              .build());
    }
    return badTargets.build();
  }

  /**
   * Helper method for {@link #checkTargetEnvironmentRestrictions} that populates inferred expected
   * environments.
   */
  @Nullable
  private static ImmutableList<Label> autoConfigureTargetEnvironments(
      BuildConfigurationValue config,
      @Nullable Label environmentGroupLabel,
      TargetLookup targetLookup)
      throws InterruptedException, NoSuchTargetException, NoSuchPackageException {
    if (environmentGroupLabel == null) {
      return ImmutableList.of();
    }

    EnvironmentGroup environmentGroup =
        (EnvironmentGroup) targetLookup.getTarget(environmentGroupLabel);
    // Missing value.
    if (environmentGroup == null) {
      return null;
    }

    ImmutableList.Builder<Label> targetEnvironments = new ImmutableList.Builder<>();
    for (Label environmentLabel : environmentGroup.getEnvironments()) {
      if (environmentLabel.getName().equals(config.getCpu())) {
        targetEnvironments.add(environmentLabel);
      }
    }

    return targetEnvironments.build();
  }

  /**
   * Returns the expected environments that the given top-level target doesn't support.
   *
   * @param topLevelTarget the top-level target to check
   * @param expectedEnvironmentLabels the environments this target is expected to support
   * @param targetLookup a function that is used to look up a Target given its Label.
   * @throws InterruptedException if environment target resolution fails
   * @throws TargetCompatibilityCheckException if an expected environment isn't a valid target
   */
  @Nullable
  private static ImmutableSet<MissingEnvironment> getMissingEnvironments(
      ConfiguredTarget topLevelTarget,
      @Nullable Collection<Label> expectedEnvironmentLabels,
      TargetLookup targetLookup)
      throws InterruptedException, TargetCompatibilityCheckException {
    // Missing value.
    if (expectedEnvironmentLabels == null) {
      return null;
    }
    if (expectedEnvironmentLabels.isEmpty()) {
      return ImmutableSet.of();
    }

    // Convert expected environment labels to actual environments.
    EnvironmentCollection.Builder expectedEnvironmentsBuilder = new EnvironmentCollection.Builder();
    for (Label envLabel : expectedEnvironmentLabels) {
      try {
        Target env = targetLookup.getTarget(envLabel);
        // Missing value.
        if (env == null) {
          return null;
        }
        expectedEnvironmentsBuilder.put(
            ConstraintSemantics.getEnvironmentGroup(env).getEnvironmentLabels(), envLabel);
      } catch (NoSuchPackageException
          | NoSuchTargetException
          | ConstraintSemantics.EnvironmentLookupException e) {
        throw new TargetCompatibilityCheckException(
            "invalid target environment: " + e.getMessage(),
            e.getDetailedExitCode().getFailureDetail(),
            e);
      }
    }
    EnvironmentCollection expectedEnvironments = expectedEnvironmentsBuilder.build();

    // Dereference any aliases that might be present.
    topLevelTarget = topLevelTarget.getActual();
    // Now check the target against expected environments.
    TransitiveInfoCollection asProvider;
    if (topLevelTarget instanceof OutputFileConfiguredTarget) {
      asProvider = ((OutputFileConfiguredTarget) topLevelTarget).getGeneratingRule();
    } else {
      asProvider = topLevelTarget;
    }
    SupportedEnvironmentsProvider provider =
        Verify.verifyNotNull(asProvider.getProvider(SupportedEnvironmentsProvider.class));
    ImmutableSet.Builder<MissingEnvironment> ans = ImmutableSet.builder();
    for (Label unsupportedEnv :
        RuleContextConstraintSemantics.getUnsupportedEnvironments(
            provider.getRefinedEnvironments(), expectedEnvironments)) {
      // We apply this filter because the target might also not support default environments in
      // other environment groups. We don't care about those. We only care about the environments
      // explicitly referenced.
      if (!expectedEnvironmentLabels.contains(unsupportedEnv)) {
        continue;
      }

      List<Label> envAndFulfillers = new ArrayList<>();
      envAndFulfillers.add(unsupportedEnv);
      for (EnvironmentLabels envGroup : provider.getStaticEnvironments().getGroups()) {
        envAndFulfillers.addAll(envGroup.getFulfillers(unsupportedEnv).toList());
      }
      RemovedEnvironmentCulprit culprit = null;
      for (int i = 0; i < envAndFulfillers.size() && culprit == null; i++) {
        culprit = provider.getRemovedEnvironmentCulprit(envAndFulfillers.get(i));
      }
      // culprit could still be null here. See MissingEnvironment class comments for implications.
      ans.add(new MissingEnvironment(unsupportedEnv, culprit));
    }
    return ans.build();
  }

  /**
   * Prepares a user-friendly error message for a list of targets missing support for required
   * environments.
   */
  private static String getBadTargetsUserMessage(
      RuleContextConstraintSemantics constraintSemantics,
      Multimap<ConfiguredTarget, MissingEnvironment> badTargets) {
    StringJoiner msg = new StringJoiner("\n");
    msg.add("This is a restricted-environment build.");
    for (Map.Entry<ConfiguredTarget, Collection<MissingEnvironment>> entry :
        badTargets.asMap().entrySet()) {
      msg.add(getErrorMessageForTarget(constraintSemantics, entry.getKey(), entry.getValue()));
    }
    return msg.add(" ").toString();
  }

  public static String getErrorMessageForTarget(
      RuleContextConstraintSemantics constraintSemantics,
      ConfiguredTarget configuredTarget,
      Collection<MissingEnvironment> missingEnvironments) {
    StringJoiner msg = new StringJoiner("\n");
    ConfiguredTarget targetWithProvider = configuredTarget.getActual();
    if (targetWithProvider instanceof OutputFileConfiguredTarget) {
      targetWithProvider = ((OutputFileConfiguredTarget) targetWithProvider).getGeneratingRule();
    }
    SupportedEnvironmentsProvider supportedEnvironments =
        targetWithProvider.getProvider(SupportedEnvironmentsProvider.class);
    String declaredEnvs =
        supportedEnvironments.getStaticEnvironments().getEnvironments().stream()
            .map(Label::toString)
            .collect(joining(", "));
    ;
    msg.add(" ")
        .add(configuredTarget.getLabel() + " declares compatibility with:")
        .add("  [" + declaredEnvs + "]")
        .add("but does not support:");
    boolean isFirst = true;
    boolean lastEntryWasMultiline = false;
    for (MissingEnvironment missingEnvironment : missingEnvironments) {
      if (missingEnvironment.culprit == null) {
        // The target didn't declare support for this environment.
        if (lastEntryWasMultiline) {
          // Pretty-format: if the last environment message was multi-line, make it clear this
          // one is a different entry. But we don't want to do that if all entries are single-line
          // because that would be pointlessly long.
          msg.add(" ");
        }
        msg.add("  " + missingEnvironment.environment);
        lastEntryWasMultiline = false;
      } else {
        // The target declared support, but it was refined out by a select() somewhere in its
        // transitive deps.
        if (!isFirst) {
          msg.add(" "); // Pretty-format for clarity.
        }
        msg.add(
            constraintSemantics.getMissingEnvironmentCulpritMessage(
                configuredTarget.getLabel(),
                missingEnvironment.environment,
                missingEnvironment.culprit));
        lastEntryWasMultiline = true;
      }
      isFirst = false;
    }
    return msg.toString();
  }

  /** Tells the compatibility of a ConfiguredTarget with the target environment. */
  @AutoValue
  public abstract static class EnvironmentCompatibility {
    public abstract boolean isCompatible();

    @Nullable
    public abstract ImmutableSet<MissingEnvironment> severeMissingEnvironments();

    public static EnvironmentCompatibility compatible() {
      return new AutoValue_TopLevelConstraintSemantics_EnvironmentCompatibility(
          /*isCompatible=*/ true, /*severeMissingEnvironments=*/ null);
    }

    public static EnvironmentCompatibility nonSevereIncompatible() {
      return new AutoValue_TopLevelConstraintSemantics_EnvironmentCompatibility(
          /*isCompatible=*/ false, /*severeMissingEnvironments=*/ null);
    }

    public static EnvironmentCompatibility severeIncompatible(
        ImmutableSet<MissingEnvironment> severeMissingEnvironments) {
      return new AutoValue_TopLevelConstraintSemantics_EnvironmentCompatibility(
          /*isCompatible=*/ false, severeMissingEnvironments);
    }
  }

  /** Tells the compatibility of a ConfiguredTarget with the platform. */
  public enum PlatformCompatibility {
    COMPATIBLE,
    INCOMPATIBLE_IMPLICIT,
    INCOMPATIBLE_EXPLICIT
  }

  /** For Exceptions that arise during the compatibility checking of a target. */
  public static class TargetCompatibilityCheckException extends Exception
      implements SaneAnalysisException {
    private final FailureDetail failureDetail;

    public TargetCompatibilityCheckException(String message, FailureDetail failureDetail) {
      super(message);
      this.failureDetail = failureDetail;
    }

    public TargetCompatibilityCheckException(
        String message, FailureDetail failureDetail, Throwable cause) {
      super(message, cause);
      this.failureDetail = failureDetail;
    }

    public FailureDetail getFailureDetail() {
      return failureDetail;
    }

    @Override
    public DetailedExitCode getDetailedExitCode() {
      return DetailedExitCode.of(failureDetail);
    }
  }

  /** Provides a method to look up a Target, given its Label. */
  @FunctionalInterface
  public interface TargetLookup {
    // Returns null if the implementation involves a Skyframe lookup and the value is missing.
    @Nullable
    Target getTarget(Label label)
        throws NoSuchPackageException, NoSuchTargetException, InterruptedException;
  }
}
