// Copyright 2020 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.config;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.Collections2;
import com.google.devtools.build.lib.analysis.BuildSettingProvider;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.RequiredConfigFragmentsProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.config.CoreOptions.IncludeConfigFragmentsEnum;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.packages.Aspect;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.AttributeTransitionData;
import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy;
import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleTransitionData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import java.util.Objects;
import javax.annotation.Nullable;

/**
 * Utility methods for determining what {@link Fragment}s are required to analyze targets.
 *
 * <p>For example if a target reads <code>--copt</code> as part of its analysis logic, it requires
 * the {@link com.google.devtools.build.lib.rules.cpp.CppConfiguration} fragment.
 *
 * <p>Used by {@link
 * com.google.devtools.build.lib.query2.cquery.CqueryOptions#showRequiredConfigFragments}.
 */
public final class RequiredFragmentsUtil {

  /**
   * Returns a {@link RequiredConfigFragmentsProvider} identifying all pieces of configuration a
   * target requires, or {@code null} if required config fragments are not enabled (see {@link
   * CoreOptions#includeRequiredConfigFragmentsProvider}).
   *
   * <p>The returned config state includes things that are known to be required at the time when the
   * target's dependencies have already been analyzed but before it's been analyzed itself. See
   * {@link RuleConfiguredTargetBuilder#maybeAddRequiredConfigFragmentsProvider} for the remaining
   * pieces of config state.
   *
   * <p>If {@code configuration} is {@link CoreOptions.IncludeConfigFragmentsEnum#DIRECT}, the
   * result includes only the config state considered to be directly required by this target. If
   * it's {@link CoreOptions.IncludeConfigFragmentsEnum#TRANSITIVE}, it also includes config state
   * needed by transitive dependencies. If it's {@link CoreOptions.IncludeConfigFragmentsEnum#OFF},
   * this method returns {@code null}.
   *
   * <p>{@code select()}s and toolchain dependencies are considered when looking at what config
   * state is required.
   *
   * @param target the target
   * @param configuration the configuration for this target
   * @param universallyRequiredFragments fragments that are always required even if not explicitly
   *     specified for this target
   * @param configConditions <code>config_settings</code> required by this target's <code>select
   *     </code>s. Used for a) figuring out which options <code>select</code>s read and b) figuring
   *     out which transitions are attached to the target. {@link TransitionFactory}, which
   *     determines the transitions, may read the target's attributes.
   * @param prerequisites all prerequisites of {@code target}
   * @return {@link RequiredConfigFragmentsProvider} or {@code null} if not enabled
   */
  @Nullable
  public static RequiredConfigFragmentsProvider getRuleRequiredFragmentsIfEnabled(
      Rule target,
      BuildConfigurationValue configuration,
      FragmentClassSet universallyRequiredFragments,
      ConfigConditions configConditions,
      Iterable<ConfiguredTargetAndData> prerequisites) {
    IncludeConfigFragmentsEnum mode = getRequiredFragmentsMode(configuration);
    if (mode == IncludeConfigFragmentsEnum.OFF) {
      return null;
    }
    RuleClass ruleClass = target.getRuleClassObject();
    ConfiguredAttributeMapper attributes =
        ConfiguredAttributeMapper.of(target, configConditions.asProviders(), configuration);
    RequiredConfigFragmentsProvider.Builder requiredFragments =
        getRequiredFragments(
            mode,
            configuration,
            universallyRequiredFragments,
            ruleClass.getConfigurationFragmentPolicy(),
            configConditions,
            prerequisites);
    if (!ruleClass.isStarlark()) {
      ruleClass
          .getConfiguredTargetFactory(RuleConfiguredTargetFactory.class)
          .addRuleImplSpecificRequiredConfigFragments(requiredFragments, attributes, configuration);
    }
    addRequiredFragmentsFromRuleTransitions(
        requiredFragments, target, attributes, configuration.getBuildOptionDetails());

    // We consider build settings (which are both targets and configuration) to require themselves.
    if (target.isBuildSetting()) {
      requiredFragments.addStarlarkOption(target.getLabel());
    }

    return requiredFragments.build();
  }

  /**
   * Variation of {@link #getRuleRequiredFragmentsIfEnabled} for aspects.
   *
   * @param aspect the aspect
   * @param aspectFactory the corresponding {@link ConfiguredAspectFactory}
   * @param associatedTarget the target this aspect is attached to
   * @param configuration the configuration for this aspect
   * @param universallyRequiredFragments fragments that are always required even if not explicitly
   *     specified for this aspect
   * @param configConditions <code>config_settings</code> required by <code>select</code>s on the
   *     associated target. Used for figuring out which transitions are attached to the target.
   * @param prerequisites all prerequisites of {@code aspect}
   * @return {@link RequiredConfigFragmentsProvider} or {@code null} if not enabled
   */
  @Nullable
  public static RequiredConfigFragmentsProvider getAspectRequiredFragmentsIfEnabled(
      Aspect aspect,
      ConfiguredAspectFactory aspectFactory,
      Rule associatedTarget,
      BuildConfigurationValue configuration,
      FragmentClassSet universallyRequiredFragments,
      ConfigConditions configConditions,
      Iterable<ConfiguredTargetAndData> prerequisites) {
    IncludeConfigFragmentsEnum mode = getRequiredFragmentsMode(configuration);
    if (mode == IncludeConfigFragmentsEnum.OFF) {
      return null;
    }
    RequiredConfigFragmentsProvider.Builder requiredFragments =
        getRequiredFragments(
            mode,
            configuration,
            universallyRequiredFragments,
            aspect.getDefinition().getConfigurationFragmentPolicy(),
            configConditions,
            prerequisites);
    aspectFactory.addAspectImplSpecificRequiredConfigFragments(requiredFragments);
    addRequiredFragmentsFromAspectTransitions(
        requiredFragments,
        aspect,
        ConfiguredAttributeMapper.of(
            associatedTarget, configConditions.asProviders(), configuration),
        configuration.getBuildOptionDetails());
    return requiredFragments.build();
  }

  /** Internal implementation that handles requirements common to both rules and aspects. */
  private static RequiredConfigFragmentsProvider.Builder getRequiredFragments(
      IncludeConfigFragmentsEnum mode,
      BuildConfigurationValue configuration,
      FragmentClassSet universallyRequiredFragments,
      ConfigurationFragmentPolicy configurationFragmentPolicy,
      ConfigConditions configConditions,
      Iterable<ConfiguredTargetAndData> prerequisites) {
    RequiredConfigFragmentsProvider.Builder requiredFragments =
        RequiredConfigFragmentsProvider.builder();

    if (mode == IncludeConfigFragmentsEnum.TRANSITIVE) {
      // Add transitive requirements first, which results in better performance. See explanation on
      // RequiredConfigFragmentsProvider.Builder.
      addTransitivelyRequiredFragments(requiredFragments, prerequisites);
    } else {
      addStarlarkBuildSettings(requiredFragments, prerequisites);
    }

    // Add directly required fragments:
    requiredFragments
        // Fragments explicitly required by the native target/aspect definition API:
        .addFragmentClasses(configurationFragmentPolicy.getRequiredConfigurationFragments())
        // Fragments explicitly required by the Starlark target/aspect definition API (nulls are
        // filtered because the rule definition may reference non-existent fragments):
        .addFragmentClasses(
            Collections2.filter(
                Collections2.transform(
                    configurationFragmentPolicy.getRequiredStarlarkFragments(),
                    configuration::getStarlarkFragmentByName),
                Objects::nonNull))
        // Fragments universally required by everything:
        .addFragmentClasses(universallyRequiredFragments);
    // Fragments required by attached select()s. Propagating fragments from the config conditions as
    // configured targets (rather than as providers) is necessary in case of a dependency on an
    // alias that resolves to a config setting. Providers only reflect the resolved settings, which
    // won't include fragments required to resolve a select within the alias rule (b/237534193).
    for (ConfiguredTargetAndData targetAndData : configConditions.asConfiguredTargets().values()) {
      requiredFragments.merge(
          targetAndData.getConfiguredTarget().getProvider(RequiredConfigFragmentsProvider.class));
    }
    return requiredFragments;
  }

  /**
   * Adds required fragments from transitions "attached" to a target.
   *
   * <p>"Attached" means the transition is attached to the target itself or one of its attributes.
   *
   * <p>These are the transitions required for a target to successfully analyze. Technically,
   * transitions attached to the target are evaluated during its parent's analysis, which is where
   * the configuration for the child is determined. We still consider these the child's requirements
   * because the child's properties determine that dependency.
   */
  private static void addRequiredFragmentsFromRuleTransitions(
      RequiredConfigFragmentsProvider.Builder requiredFragments,
      Rule target,
      ConfiguredAttributeMapper attributeMap,
      BuildOptionDetails optionDetails) {
    if (target.getRuleClassObject().getTransitionFactory() != null) {
      target
          .getRuleClassObject()
          .getTransitionFactory()
          .create(RuleTransitionData.create(target))
          .addRequiredFragments(requiredFragments, optionDetails);
    }
    // We don't set the execution platform in this data because a) that doesn't affect which
    // fragments are required and b) it's one less parameter we have to pass to
    // RequiredFragmenstUtil's public interface.
    AttributeTransitionData attributeTransitionData =
        AttributeTransitionData.builder().attributes(attributeMap).build();
    for (Attribute attribute : target.getRuleClassObject().getAttributes()) {
      if (attribute.getTransitionFactory() != null) {
        attribute
            .getTransitionFactory()
            .create(attributeTransitionData)
            .addRequiredFragments(requiredFragments, optionDetails);
      }
    }
  }

  /**
   * Adds required fragments from transitions "attached" to an aspect.
   *
   * <p>"Attached" means the transition is attached to one of the aspect's attributes. Transitions
   * can't be attached directly to aspects themselves.
   */
  private static void addRequiredFragmentsFromAspectTransitions(
      RequiredConfigFragmentsProvider.Builder requiredFragments,
      Aspect aspect,
      ConfiguredAttributeMapper attributeMap,
      BuildOptionDetails optionDetails) {
    AttributeTransitionData attributeTransitionData =
        AttributeTransitionData.builder().attributes(attributeMap).build();
    for (Attribute attribute : aspect.getDefinition().getAttributes().values()) {
      if (attribute.getTransitionFactory() != null) {
        attribute
            .getTransitionFactory()
            .create(attributeTransitionData)
            .addRequiredFragments(requiredFragments, optionDetails);
      }
    }
  }

  private static void addTransitivelyRequiredFragments(
      RequiredConfigFragmentsProvider.Builder requiredFragments,
      Iterable<ConfiguredTargetAndData> prerequisites) {
    for (ConfiguredTargetAndData prereq : prerequisites) {
      RequiredConfigFragmentsProvider depProvider =
          prereq.getConfiguredTarget().getProvider(RequiredConfigFragmentsProvider.class);
      if (depProvider != null) {
        requiredFragments.merge(depProvider);
      }
    }
  }

  /**
   * Adds dependencies on Starlark build settings.
   *
   * <p>Starlark build settings are considered direct requirements on the rule even though they are
   * technically dependencies. Note that this method only needs to be called in {@link
   * IncludeConfigFragmentsEnum#DIRECT} mode, since {@link IncludeConfigFragmentsEnum#TRANSITIVE}
   * mode will already pick up these requirements from dependencies.
   */
  private static void addStarlarkBuildSettings(
      RequiredConfigFragmentsProvider.Builder requiredFragments,
      Iterable<ConfiguredTargetAndData> prerequisites) {
    for (ConfiguredTargetAndData prereq : prerequisites) {
      BuildSettingProvider buildSettingProvider =
          prereq.getConfiguredTarget().getProvider(BuildSettingProvider.class);
      if (buildSettingProvider != null) {
        requiredFragments.addStarlarkOption(buildSettingProvider.getLabel());
      }
    }
  }

  private static IncludeConfigFragmentsEnum getRequiredFragmentsMode(
      BuildConfigurationValue config) {
    return checkNotNull(
        config.getOptions().get(CoreOptions.class).includeRequiredConfigFragmentsProvider);
  }

  private RequiredFragmentsUtil() {}
}
