// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.analysis;

import static com.google.common.base.Preconditions.checkState;
import static java.util.stream.Collectors.joining;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
import com.google.devtools.build.lib.actions.ArtifactFactory;
import com.google.devtools.build.lib.actions.FailAction;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.ExecGroupCollection.InvalidExecGroupException;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.ConfigConditions;
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.RequiredFragmentsUtil;
import com.google.devtools.build.lib.analysis.configuredtargets.EnvironmentGroupConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.InputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.OutputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.PackageGroupConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.starlark.StarlarkAttributeTransitionProvider;
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleConfiguredTargetUtil;
import com.google.devtools.build.lib.analysis.test.AnalysisFailure;
import com.google.devtools.build.lib.analysis.test.AnalysisFailureInfo;
import com.google.devtools.build.lib.analysis.test.AnalysisFailurePropagationException;
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.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.AdvertisedProviderSet;
import com.google.devtools.build.lib.packages.Aspect;
import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy;
import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
import com.google.devtools.build.lib.packages.EnvironmentGroup;
import com.google.devtools.build.lib.packages.InputFile;
import com.google.devtools.build.lib.packages.OutputFile;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.PackageGroup;
import com.google.devtools.build.lib.packages.PackageGroupsRuleVisibility;
import com.google.devtools.build.lib.packages.PackageSpecification;
import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.RuleVisibility;
import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.profiler.memory.CurrentRuleTracker;
import com.google.devtools.build.lib.server.FailureDetails.FailAction.Code;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.util.OrderedSetMultimap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import net.starlark.java.eval.Mutability;

/**
 * This class creates {@link ConfiguredTarget} instances using a given {@link
 * ConfiguredRuleClassProvider}.
 */
@ThreadSafe
public final class ConfiguredTargetFactory {

  private static final NestedSet<PackageGroupContents> PUBLIC_VISIBILITY =
      NestedSetBuilder.create(
          Order.STABLE_ORDER,
          PackageGroupContents.create(ImmutableList.of(PackageSpecification.everything())));

  private static final NestedSet<PackageGroupContents> PRIVATE_VISIBILITY =
      NestedSetBuilder.emptySet(Order.STABLE_ORDER);

  // This class is not meant to be outside of the analysis phase machinery and is only public
  // in order to be accessible from the .view.skyframe package.

  private final ConfiguredRuleClassProvider ruleClassProvider;

  public ConfiguredTargetFactory(ConfiguredRuleClassProvider ruleClassProvider) {
    this.ruleClassProvider = ruleClassProvider;
  }

  /**
   * Returns the visibility of the given target. Errors during package group resolution are reported
   * to the {@code AnalysisEnvironment}.
   */
  private static NestedSet<PackageGroupContents> convertVisibility(
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> prerequisiteMap,
      EventHandler reporter,
      Target target) {
    RuleVisibility ruleVisibility = target.getVisibility();
    if (ruleVisibility.equals(RuleVisibility.PUBLIC)) {
      return PUBLIC_VISIBILITY;
    }
    if (ruleVisibility.equals(RuleVisibility.PRIVATE)) {
      return PRIVATE_VISIBILITY;
    }
    checkState(ruleVisibility instanceof PackageGroupsRuleVisibility, ruleVisibility);
    PackageGroupsRuleVisibility packageGroupsVisibility =
        (PackageGroupsRuleVisibility) ruleVisibility;

    NestedSetBuilder<PackageGroupContents> result = NestedSetBuilder.stableOrder();
    for (Label groupLabel : packageGroupsVisibility.getPackageGroups()) {
      // PackageGroupsConfiguredTargets are always in the package-group configuration.
      TransitiveInfoCollection group = findVisibilityPrerequisite(prerequisiteMap, groupLabel);
      PackageSpecificationProvider provider = null;
      // group == null can only happen if the package group list comes from a default_visibility
      // attribute, because in every other case, this missing link is caught during transitive
      // closure visitation or if the RuleConfiguredTargetGraph threw out a visibility edge because
      // if would have caused a cycle. The filtering should be done in a single place,
      // ConfiguredTargetGraph, but for now, this is the minimally invasive way of providing a sane
      // error message in case a cycle is created by a visibility attribute.
      if (group != null) {
        provider = group.get(PackageSpecificationProvider.PROVIDER);
      }
      if (provider != null) {
        result.addTransitive(provider.getPackageSpecifications());
      } else {
        reporter.handle(
            Event.error(
                target.getLocation(),
                String.format("Label '%s' does not refer to a package group", groupLabel)));
      }
    }

    result.add(packageGroupsVisibility.getDirectPackages());
    return result.build();
  }

  @Nullable
  private static TransitiveInfoCollection findVisibilityPrerequisite(
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> prerequisiteMap, Label label) {
    for (ConfiguredTargetAndData prerequisite :
        prerequisiteMap.get(DependencyKind.VISIBILITY_DEPENDENCY)) {
      if (prerequisite.getTargetLabel().equals(label) && prerequisite.getConfiguration() == null) {
        return prerequisite.getConfiguredTarget();
      }
    }
    return null;
  }

  /**
   * Invokes the appropriate constructor to create a {@link ConfiguredTarget} instance.
   *
   * <p>For use in {@code ConfiguredTargetFunction}.
   *
   * <p>Returns null if Skyframe deps are missing or upon certain errors.
   */
  @Nullable
  public ConfiguredTarget createConfiguredTarget(
      AnalysisEnvironment analysisEnvironment,
      ArtifactFactory artifactFactory,
      Target target,
      BuildConfigurationValue config,
      ConfiguredTargetKey configuredTargetKey,
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> prerequisiteMap,
      ConfigConditions configConditions,
      @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
      @Nullable NestedSet<Package> transitivePackages,
      ExecGroupCollection.Builder execGroupCollectionBuilder,
      @Nullable StarlarkAttributeTransitionProvider starlarkExecTransition)
      throws InterruptedException,
          ActionConflictException,
          InvalidExecGroupException,
          AnalysisFailurePropagationException {
    if (target instanceof Rule) {
      try {
        CurrentRuleTracker.beginConfiguredTarget(((Rule) target).getRuleClassObject());
        return createRule(
            analysisEnvironment,
            (Rule) target,
            config,
            configuredTargetKey,
            prerequisiteMap,
            configConditions,
            toolchainContexts,
            transitivePackages,
            execGroupCollectionBuilder,
            starlarkExecTransition);
      } finally {
        CurrentRuleTracker.endConfiguredTarget();
      }
    }

    // Visibility, like all package groups, doesn't have a configuration
    NestedSet<PackageGroupContents> visibility =
        convertVisibility(prerequisiteMap, analysisEnvironment.getEventHandler(), target);
    if (target instanceof OutputFile) {
      OutputFile outputFile = (OutputFile) target;
      TargetContext targetContext =
          new TargetContext(
              analysisEnvironment,
              target,
              config,
              prerequisiteMap.get(DependencyKind.OUTPUT_FILE_RULE_DEPENDENCY),
              visibility);
      if (analysisEnvironment.getSkyframeEnv().valuesMissing()) {
        return null;
      }
      Label ruleLabel = outputFile.getGeneratingRule().getLabel();
      RuleConfiguredTarget rule =
          (RuleConfiguredTarget)
              targetContext.findDirectPrerequisite(
                  ruleLabel,
                  // Don't pass a specific configuration, as we don't care what configuration the
                  // generating rule is in. There can only be one actual dependency here, which is
                  // the target that generated the output file.
                  Optional.empty());
      Verify.verifyNotNull(
          rule, "While analyzing %s, missing generating rule %s", outputFile, ruleLabel);
      // If analysis failures are allowed and the generating rule has failure info, just propagate
      // it. The output artifact won't exist, so we can't create an OutputFileConfiguredTarget.
      if (config.allowAnalysisFailures()
          && rule.get(AnalysisFailureInfo.STARLARK_CONSTRUCTOR.getKey()) != null) {
        return rule;
      }
      Artifact artifact = rule.findArtifactByOutputLabel(outputFile.getLabel());
      return new OutputFileConfiguredTarget(targetContext, artifact, rule);
    } else if (target instanceof InputFile) {
      InputFile inputFile = (InputFile) target;
      TargetContext targetContext =
          new TargetContext(
              analysisEnvironment,
              target,
              config,
              prerequisiteMap.get(DependencyKind.OUTPUT_FILE_RULE_DEPENDENCY),
              visibility);
      SourceArtifact artifact =
          artifactFactory.getSourceArtifact(
              inputFile.getExecPath(
                  analysisEnvironment
                      .getStarlarkSemantics()
                      .getBool(BuildLanguageOptions.EXPERIMENTAL_SIBLING_REPOSITORY_LAYOUT)),
              inputFile.getPackage().getSourceRoot().get(),
              ConfiguredTargetKey.builder()
                  .setLabel(target.getLabel())
                  .setConfiguration(config)
                  .build());
      return new InputFileConfiguredTarget(targetContext, artifact);
    } else if (target instanceof PackageGroup) {
      PackageGroup packageGroup = (PackageGroup) target;
      TargetContext targetContext =
          new TargetContext(
              analysisEnvironment,
              target,
              config,
              prerequisiteMap.get(DependencyKind.VISIBILITY_DEPENDENCY),
              visibility);
      return new PackageGroupConfiguredTarget(configuredTargetKey, targetContext, packageGroup);
    } else if (target instanceof EnvironmentGroup) {
      return new EnvironmentGroupConfiguredTarget(configuredTargetKey);
    } else {
      throw new AssertionError("Unexpected target class: " + target.getClass().getName());
    }
  }

  /**
   * Factory method: constructs a RuleConfiguredTarget of the appropriate class, based on the rule
   * class. May return null if an error occurred.
   */
  @Nullable
  private ConfiguredTarget createRule(
      AnalysisEnvironment env,
      Rule rule,
      BuildConfigurationValue configuration,
      ConfiguredTargetKey configuredTargetKey,
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> prerequisiteMap,
      ConfigConditions configConditions,
      @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
      @Nullable NestedSet<Package> transitivePackages,
      ExecGroupCollection.Builder execGroupCollectionBuilder,
      @Nullable StarlarkAttributeTransitionProvider starlarkExecTransition)
      throws InterruptedException,
          ActionConflictException,
          InvalidExecGroupException,
          AnalysisFailurePropagationException {
    RuleClass ruleClass = rule.getRuleClassObject();
    ConfigurationFragmentPolicy configurationFragmentPolicy =
        ruleClass.getConfigurationFragmentPolicy();
    // Visibility computation and checking is done for every rule.
    RuleContext ruleContext =
        new RuleContext.Builder(env, rule, /* aspects= */ ImmutableList.of(), configuration)
            .setRuleClassProvider(ruleClassProvider)
            .setConfigurationFragmentPolicy(configurationFragmentPolicy)
            .setActionOwnerSymbol(configuredTargetKey)
            .setMutability(Mutability.create("configured target"))
            .setVisibility(convertVisibility(prerequisiteMap, env.getEventHandler(), rule))
            .setPrerequisites(removeToolchainDeps(prerequisiteMap))
            .setConfigConditions(configConditions)
            .setToolchainContexts(toolchainContexts)
            .setExecGroupCollectionBuilder(execGroupCollectionBuilder)
            .setRequiredConfigFragments(
                RequiredFragmentsUtil.getRuleRequiredFragmentsIfEnabled(
                    rule,
                    configuration,
                    ruleClassProvider.getFragmentRegistry().getUniversalFragments(),
                    configConditions,
                    Iterables.transform(
                        prerequisiteMap.values(), ConfiguredTargetAndData::getConfiguredTarget),
                    starlarkExecTransition))
            .setTransitivePackagesForRunfileRepoMappingManifest(transitivePackages)
            .build();

    ImmutableList<NestedSet<AnalysisFailure>> analysisFailures =
        depAnalysisFailures(ruleContext, ImmutableList.of());
    if (!analysisFailures.isEmpty()) {
      return erroredConfiguredTargetWithFailures(ruleContext, analysisFailures);
    }
    if (ruleContext.hasErrors()) {
      return erroredConfiguredTarget(ruleContext, null);
    }

    try {
      Class<?> missingFragmentClass = null;
      for (Class<? extends Fragment> fragmentClass :
          configurationFragmentPolicy.getRequiredConfigurationFragments()) {
        if (!configuration.hasFragment(fragmentClass)) {
          MissingFragmentPolicy missingFragmentPolicy =
              configurationFragmentPolicy.getMissingFragmentPolicy(fragmentClass);
          if (missingFragmentPolicy != MissingFragmentPolicy.IGNORE) {
            if (missingFragmentPolicy == MissingFragmentPolicy.FAIL_ANALYSIS) {
              ruleContext.ruleError(
                  missingFragmentError(
                      ruleContext, configurationFragmentPolicy, configuration.checksum()));
              return null;
            }
            // Otherwise missingFragmentPolicy == MissingFragmentPolicy.CREATE_FAIL_ACTIONS:
            missingFragmentClass = fragmentClass;
          }
        }
      }
      if (missingFragmentClass != null) {
        return createFailConfiguredTargetForMissingFragmentClass(ruleContext, missingFragmentClass);
      }

      final ConfiguredTarget target;

      if (ruleClass.isStarlark()) {
        if (ruleClass.getRuleClassType().equals(RuleClass.Builder.RuleClassType.WORKSPACE)) {
          ruleContext.ruleError(
              "Found reference to a workspace rule in a context where a build"
                  + " rule was expected; probably a reference to a target in that external"
                  + " repository, properly specified as @reponame//path/to/package:target,"
                  + " should have been specified by the requesting rule.");
          return erroredConfiguredTarget(ruleContext, null);
        }

        final Object rawProviders;
        final boolean isDefaultExecutableCreated;
        @Nullable final RequiredConfigFragmentsProvider requiredConfigFragmentsProvider;
        try {
          ruleContext.initStarlarkRuleContext();
          // TODO(bazel-team): maybe merge with RuleConfiguredTargetBuilder?
          rawProviders = StarlarkRuleConfiguredTargetUtil.evalRule(ruleContext, ruleClass);
        } finally {
          // TODO(b/268525292): isDefaultExecutableCreated is set to True when
          // ctx.outputs.executable
          // is accessed in the implementation. This fragile mechanism should be revised and removed
          isDefaultExecutableCreated =
              ruleContext.getStarlarkRuleContext().isDefaultExecutableCreated();
          requiredConfigFragmentsProvider = ruleContext.getRequiredConfigFragments();
          ruleContext.close();
        }
        if (rawProviders == null) {
          return erroredConfiguredTarget(ruleContext, requiredConfigFragmentsProvider);
        }
        // Because ruleContext was closed, rawProviders are now immutable
        // Postprocess providers to create the finished target.
        target =
            StarlarkRuleConfiguredTargetUtil.createTarget(
                ruleContext,
                rawProviders,
                ruleClass.getAdvertisedProviders(),
                isDefaultExecutableCreated,
                requiredConfigFragmentsProvider); // may be null
        return target != null
            ? target
            : erroredConfiguredTarget(ruleContext, requiredConfigFragmentsProvider);
      } else {
        try {
          target =
              Preconditions.checkNotNull(
                      ruleClass.getConfiguredTargetFactory(RuleConfiguredTargetFactory.class),
                      "No configured target factory for %s",
                      ruleClass)
                  .create(ruleContext);

        } finally {
          // close() is required if the native rule created StarlarkRuleContext to perform any
          // Starlark evaluation, i.e. using the @_builtins mechanism.
          ruleContext.close();
        }
        // TODO(https://github.com/bazelbuild/bazel/issues/17915): genquery and similar native rules
        // may return null without setting a ruleContext error to signal a skyframe restart.
        return target != null ? target : erroredConfiguredTarget(ruleContext, null);
      }
    } catch (RuleErrorException ruleErrorException) {
      return erroredConfiguredTarget(ruleContext, null);
    }
  }

  /**
   * If {@code --allow_analysis_failures} is true, returns a collection of propagated analysis
   * failures from the target's dependencies and {@code extraDeps} -- one NestedSet per dep with
   * failures to propagate. Otherwise if {@code --allow_analysis_failures} is false, returns the
   * empty set.
   */
  private static ImmutableList<NestedSet<AnalysisFailure>> depAnalysisFailures(
      RuleContext ruleContext, Iterable<? extends TransitiveInfoCollection> extraDeps) {
    if (ruleContext.getConfiguration().allowAnalysisFailures()) {
      ImmutableList.Builder<NestedSet<AnalysisFailure>> analysisFailures = ImmutableList.builder();
      Iterable<? extends TransitiveInfoCollection> infoCollections =
          Iterables.concat(ruleContext.getAllPrerequisites(), extraDeps);
      for (TransitiveInfoCollection infoCollection : infoCollections) {
        AnalysisFailureInfo failureInfo =
            infoCollection.get(AnalysisFailureInfo.STARLARK_CONSTRUCTOR);
        if (failureInfo != null) {
          analysisFailures.add(failureInfo.getCausesNestedSet());
        }
      }
      return analysisFailures.build();
    }
    // Analysis failures are only created and propagated if --allow_analysis_failures is
    // enabled, otherwise these result in actual rule errors which are not caught.
    return ImmutableList.of();
  }

  private static ConfiguredTarget erroredConfiguredTargetWithFailures(
      RuleContext ruleContext, List<NestedSet<AnalysisFailure>> analysisFailures)
      throws ActionConflictException, InterruptedException, AnalysisFailurePropagationException {
    RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
    builder.addNativeDeclaredProvider(AnalysisFailureInfo.forAnalysisFailureSets(analysisFailures));
    builder.addProvider(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
    ConfiguredTarget configuredTarget = builder.build();
    if (configuredTarget == null) {
      // A failure here is a failure in analysis failure testing machinery, not a "normal" analysis
      // failure that some outer analysis failure test may want to capture. Instead, this failure
      // means that the outer test would be unusable. So we throw an exception rather than returning
      // null and allowing it to propagate up in the usual way.
      throw new AnalysisFailurePropagationException(
          ruleContext.getLabel(), ruleContext.getSuppressedErrorMessages());
    }
    return configuredTarget;
  }

  /**
   * Returns a {@link ConfiguredTarget} which indicates that an analysis error occurred in
   * processing the target. In most cases, this returns null, which signals to callers that the
   * target failed to build and thus the build should fail. However, if analysis failures are
   * allowed in this build, this returns a stub {@link ConfiguredTarget} which contains information
   * about the failure.
   */
  // TODO(blaze-team): requiredConfigFragmentsProvider is used for Android feature flags and should
  // be removed together with them.
  @Nullable
  private static ConfiguredTarget erroredConfiguredTarget(
      RuleContext ruleContext, RequiredConfigFragmentsProvider requiredConfigFragmentsProvider)
      throws ActionConflictException, InterruptedException, AnalysisFailurePropagationException {
    if (ruleContext.getConfiguration().allowAnalysisFailures()) {
      ImmutableList.Builder<AnalysisFailure> analysisFailures = ImmutableList.builder();

      for (String errorMessage : ruleContext.getSuppressedErrorMessages()) {
        analysisFailures.add(AnalysisFailure.create(ruleContext.getLabel(), errorMessage));
      }
      RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
      builder.addNativeDeclaredProvider(
          AnalysisFailureInfo.forAnalysisFailures(analysisFailures.build()));
      builder.addProvider(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
      if (requiredConfigFragmentsProvider != null) {
        builder.addProvider(requiredConfigFragmentsProvider);
      }
      ConfiguredTarget configuredTarget = builder.build();
      if (configuredTarget == null) {
        // See comment in erroredConfiguredTargetWithFailures.
        throw new AnalysisFailurePropagationException(
            ruleContext.getLabel(), ruleContext.getSuppressedErrorMessages());
      }
      return configuredTarget;
    } else {
      // Returning a null ConfiguredTarget is an indication a rule error occurred. Exceptions are
      // not propagated, as this would show a nasty stack trace to users, and only provide info
      // on one specific failure with poor messaging. By returning null, the caller can
      // inspect ruleContext for multiple errors and output thorough messaging on each.
      return null;
    }
  }

  private static String missingFragmentError(
      RuleContext ruleContext,
      ConfigurationFragmentPolicy configurationFragmentPolicy,
      String configurationId) {
    RuleClass ruleClass = ruleContext.getRule().getRuleClassObject();
    Set<Class<?>> missingFragments = new LinkedHashSet<>();
    for (Class<? extends Fragment> fragment :
        configurationFragmentPolicy.getRequiredConfigurationFragments()) {
      if (!ruleContext.getConfiguration().hasFragment(fragment)) {
        missingFragments.add(fragment);
      }
    }
    checkState(!missingFragments.isEmpty());
    return "all rules of type "
        + ruleClass.getName()
        + " require the presence of all of ["
        + missingFragments.stream().map(Class::getSimpleName).collect(joining(","))
        + "], but these were all disabled in configuration "
        + configurationId;
  }

  @VisibleForTesting
  public static OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> removeToolchainDeps(
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> map) {
    OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> result =
        OrderedSetMultimap.create();

    for (Map.Entry<DependencyKind, ConfiguredTargetAndData> entry : map.entries()) {
      if (DependencyKind.isToolchain(entry.getKey())) {
        continue;
      }
      result.put(entry.getKey(), entry.getValue());
    }

    return result;
  }

  /**
   * Constructs a {@link ConfiguredAspect}. Returns null if an error occurs; in that case, {@code
   * aspectFactory} should call one of the error reporting methods of {@link RuleContext}.
   */
  public ConfiguredAspect createAspect(
      AnalysisEnvironment env,
      Target associatedTarget,
      ConfiguredTarget configuredTarget,
      ImmutableList<Aspect> aspectPath,
      ConfiguredAspectFactory aspectFactory,
      Aspect aspect,
      OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> prerequisiteMap,
      ConfigConditions configConditions,
      @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
      @Nullable ExecGroupCollection.Builder execGroupCollectionBuilder,
      BuildConfigurationValue aspectConfiguration,
      @Nullable NestedSet<Package> transitivePackages,
      AspectKeyCreator.AspectKey aspectKey,
      StarlarkAttributeTransitionProvider starlarkExecTransition)
      throws InterruptedException,
          ActionConflictException,
          InvalidExecGroupException,
          RuleErrorException {
    RuleContext ruleContext =
        new RuleContext.Builder(env, associatedTarget, aspectPath, aspectConfiguration)
            .setRuleClassProvider(ruleClassProvider)
            .setConfigurationFragmentPolicy(aspect.getDefinition().getConfigurationFragmentPolicy())
            .setActionOwnerSymbol(aspectKey)
            .setMutability(Mutability.create("aspect"))
            .setVisibility(
                convertVisibility(prerequisiteMap, env.getEventHandler(), associatedTarget))
            .setPrerequisites(removeToolchainDeps(prerequisiteMap))
            .setConfigConditions(configConditions)
            .setToolchainContexts(toolchainContexts)
            .setExecGroupCollectionBuilder(execGroupCollectionBuilder)
            .setExecProperties(ImmutableMap.of())
            .setRequiredConfigFragments(
                RequiredFragmentsUtil.getAspectRequiredFragmentsIfEnabled(
                    aspect,
                    aspectFactory,
                    associatedTarget.getAssociatedRule(),
                    aspectConfiguration,
                    ruleClassProvider.getFragmentRegistry().getUniversalFragments(),
                    configConditions,
                    Iterables.concat(
                        Iterables.transform(
                            prerequisiteMap.values(), ConfiguredTargetAndData::getConfiguredTarget),
                        ImmutableList.of(configuredTarget)),
                    starlarkExecTransition))
            .setTransitivePackagesForRunfileRepoMappingManifest(transitivePackages)
            .build();

    // If allowing analysis failures, targets should be created as normal as possible, and errors
    // will be propagated via a hook elsewhere as AnalysisFailureInfo.
    boolean allowAnalysisFailures = ruleContext.getConfiguration().allowAnalysisFailures();

    ImmutableList<NestedSet<AnalysisFailure>> analysisFailures =
        depAnalysisFailures(ruleContext, ImmutableList.of(configuredTarget));
    if (!analysisFailures.isEmpty()) {
      return erroredConfiguredAspectWithFailures(ruleContext, analysisFailures);
    }
    if (ruleContext.hasErrors() && !allowAnalysisFailures) {
      return erroredConfiguredAspect(ruleContext, null);
    }

    ConfiguredAspect configuredAspect =
        aspectFactory.create(
            associatedTarget.getLabel(),
            configuredTarget,
            ruleContext,
            aspect.getParameters(),
            ruleClassProvider.getToolsRepository());
    if (configuredAspect == null) {
      return erroredConfiguredAspect(ruleContext, null);
    } else if (configuredAspect.get(AnalysisFailureInfo.STARLARK_CONSTRUCTOR) != null) {
      // this was created by #erroredConfiguredAspect, return early to skip validating advertised
      // providers
      return configuredAspect;
    }

    validateAdvertisedProviders(
        configuredAspect,
        aspectKey,
        aspect.getDefinition().getAdvertisedProviders(),
        associatedTarget,
        env.getEventHandler());
    return configuredAspect;
  }

  private static ConfiguredAspect erroredConfiguredAspectWithFailures(
      RuleContext ruleContext, List<NestedSet<AnalysisFailure>> analysisFailures)
      throws ActionConflictException, InterruptedException {
    ConfiguredAspect.Builder builder = new ConfiguredAspect.Builder(ruleContext);
    builder.addNativeDeclaredProvider(AnalysisFailureInfo.forAnalysisFailureSets(analysisFailures));
    // Unlike erroredConfiguredTargetAspectWithFailures, we do not add a RunfilesProvider; that
    // would result in a RunfilesProvider being provided twice in the merged configured target.

    // TODO(b/242887801): builder.build() could potentially return null; in that case, should we
    // throw an exception, as erroredConfiguredTarget does, to avoid propagating the error to an
    // outer analysis failure test?
    return builder.build();
  }

  /**
   * Returns a {@link ConfiguredAspect} which indicates that an analysis error occurred in
   * processing the aspect. In most cases, this returns null, which signals to callers that the
   * target failed to build and thus the build should fail. However, if analysis failures are
   * allowed in this build, this returns a stub {@link ConfiguredAspect} which contains information
   * about the failure.
   */
  @Nullable
  public static ConfiguredAspect erroredConfiguredAspect(
      RuleContext ruleContext,
      @Nullable RequiredConfigFragmentsProvider requiredConfigFragmentsProvider)
      throws ActionConflictException, InterruptedException {
    if (ruleContext.getConfiguration().allowAnalysisFailures()) {
      ImmutableList.Builder<AnalysisFailure> analysisFailures = ImmutableList.builder();

      for (String errorMessage : ruleContext.getSuppressedErrorMessages()) {
        analysisFailures.add(AnalysisFailure.create(ruleContext.getLabel(), errorMessage));
      }
      ConfiguredAspect.Builder builder = new ConfiguredAspect.Builder(ruleContext);
      builder.addNativeDeclaredProvider(
          AnalysisFailureInfo.forAnalysisFailures(analysisFailures.build()));

      if (requiredConfigFragmentsProvider != null) {
        builder.addProvider(requiredConfigFragmentsProvider);
      }

      // Unlike erroredConfiguredTarget, we do not add a RunfilesProvider; that would result in a
      // RunfilesProvider being provided twice in the merged configured target.

      // TODO(b/242887801): builder.build() could potentially return null; in that case, should we
      // throw an exception, as erroredConfiguredTarget does, to avoid propagating the error to an
      // outer analysis failure test?
      return builder.build();
    } else {
      // Returning a null ConfiguredAspect is an indication a rule error occurred. Exceptions are
      // not propagated, as this would show a nasty stack trace to users, and only provide info
      // on one specific failure with poor messaging. By returning null, the caller can
      // inspect ruleContext for multiple errors and output thorough messaging on each.
      return null;
    }
  }

  private static void validateAdvertisedProviders(
      ConfiguredAspect configuredAspect,
      AspectKeyCreator.AspectKey aspectKey,
      AdvertisedProviderSet advertisedProviders,
      Target target,
      EventHandler eventHandler) {
    if (advertisedProviders.canHaveAnyProvider()) {
      return;
    }
    for (Class<?> aClass : advertisedProviders.getBuiltinProviders()) {
      if (configuredAspect.getProvider(aClass.asSubclass(TransitiveInfoProvider.class)) == null) {
        eventHandler.handle(
            Event.error(
                target.getLocation(),
                String.format(
                    "Aspect '%s', applied to '%s', does not provide advertised provider '%s'",
                    aspectKey.getAspectClass().getName(),
                    target.getLabel(),
                    aClass.getSimpleName())));
      }
    }

    for (StarlarkProviderIdentifier providerId : advertisedProviders.getStarlarkProviders()) {
      if (configuredAspect.get(providerId) == null) {
        eventHandler.handle(
            Event.error(
                target.getLocation(),
                String.format(
                    "Aspect '%s', applied to '%s', does not provide advertised provider '%s'",
                    aspectKey.getAspectClass().getName(), target.getLabel(), providerId)));
      }
    }
  }

  /**
   * A pseudo-implementation for configured targets that creates fail actions for all declared
   * outputs, both implicit and explicit, due to a missing fragment class.
   */
  private static ConfiguredTarget createFailConfiguredTargetForMissingFragmentClass(
      RuleContext ruleContext, Class<?> missingFragmentClass) throws InterruptedException {
    RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
    if (!ruleContext.getOutputArtifacts().isEmpty()) {
      ruleContext.registerAction(
          new FailAction(
              ruleContext.getActionOwner(),
              ruleContext.getOutputArtifacts(),
              "Missing fragment class: " + missingFragmentClass.getName(),
              Code.FRAGMENT_CLASS_MISSING));
    }
    builder.addProvider(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
    try {
      return builder.build();
    } catch (ActionConflictException e) {
      throw new IllegalStateException(
          "Can't have an action conflict with one action: " + ruleContext.getLabel(), e);
    }
  }
}
