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

import static com.google.devtools.build.lib.analysis.config.CoreOptionConverters.BUILD_SETTING_CONVERTERS;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.AliasProvider;
import com.google.devtools.build.lib.analysis.BuildSettingProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.LicensesProviderImpl;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitionMode;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationOptionDetails;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
import com.google.devtools.build.lib.analysis.config.CoreOptions.IncludeConfigFragmentsEnum;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.FragmentOptions.SelectRestriction;
import com.google.devtools.build.lib.analysis.config.TransitiveOptionDetails;
import com.google.devtools.build.lib.analysis.platform.ConstraintCollection;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.RuleErrorConsumer;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.config.ConfigRuleClasses.ConfigSettingRule;
import com.google.devtools.build.lib.util.ClassName;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Implementation for the config_setting rule.
 *
 * <p>This is a "pseudo-rule" in that its purpose isn't to generate output artifacts
 * from input artifacts. Rather, it provides configuration context to rules that
 * depend on it.
 */
public class ConfigSetting implements RuleConfiguredTargetFactory {

  @Override
  public ConfiguredTarget create(RuleContext ruleContext)
      throws InterruptedException, ActionConflictException {
    AttributeMap attributes = NonconfigurableAttributeMapper.of(ruleContext.getRule());

    // Get the built-in Blaze flag settings that match this rule.
    ImmutableMultimap<String, String> nativeFlagSettings =
        ImmutableMultimap.<String, String>builder()
            .putAll(attributes.get(ConfigSettingRule.SETTINGS_ATTRIBUTE, Type.STRING_DICT)
                .entrySet())
            .putAll(attributes.get(ConfigSettingRule.DEFINE_SETTINGS_ATTRIBUTE, Type.STRING_DICT)
                .entrySet()
                .stream()
                .map(in -> Maps.immutableEntry("define", in.getKey() + "=" + in.getValue()))
                .collect(ImmutableList.toImmutableList()))
            .build();

    // Get the user-defined flag settings that match this rule.
    Map<Label, String> userDefinedFlagSettings =
        attributes.get(
            ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE, BuildType.LABEL_KEYED_STRING_DICT);

    // Get the platform constraint settings that match this rule.
    List<Label> constraintValueSettings =
        attributes.get(ConfigSettingRule.CONSTRAINT_VALUES_ATTRIBUTE, BuildType.LABEL_LIST);

    // Check that this config_setting contains at least one of {values, define_values,
    // constraint_values}
    if (!valuesAreSet(
        nativeFlagSettings, userDefinedFlagSettings, constraintValueSettings, ruleContext)) {
      return null;
    }

    TransitiveOptionDetails optionDetails =
        BuildConfigurationOptionDetails.get(ruleContext.getConfiguration());
    ImmutableSet.Builder<String> requiredFragmentOptions = ImmutableSet.builder();

    boolean nativeFlagsMatch =
        matchesConfig(
            nativeFlagSettings.entries(), optionDetails, requiredFragmentOptions, ruleContext);

    UserDefinedFlagMatch userDefinedFlags =
        UserDefinedFlagMatch.fromAttributeValueAndPrerequisites(
            userDefinedFlagSettings, optionDetails, requiredFragmentOptions, ruleContext);

    boolean constraintValuesMatch = constraintValuesMatch(ruleContext);

    if (ruleContext.hasErrors()) {
      return null;
    }

    // For config_setting, transitive and direct are the same (it has no transitive deps).
    boolean includeRequiredFragments =
        ruleContext
                .getConfiguration()
                .getOptions()
                .get(CoreOptions.class)
                .includeRequiredConfigFragmentsProvider
            != IncludeConfigFragmentsEnum.OFF;

    ConfigMatchingProvider configMatcher =
        new ConfigMatchingProvider(
            ruleContext.getLabel(),
            nativeFlagSettings,
            userDefinedFlags.getSpecifiedFlagValues(),
            includeRequiredFragments ? requiredFragmentOptions.build() : ImmutableSet.<String>of(),
            nativeFlagsMatch && userDefinedFlags.matches() && constraintValuesMatch);

    return new RuleConfiguredTargetBuilder(ruleContext)
        .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY)
        .addProvider(FileProvider.class, FileProvider.EMPTY)
        .addProvider(FilesToRunProvider.class, FilesToRunProvider.EMPTY)
        .addProvider(LicensesProviderImpl.EMPTY)
        .addProvider(ConfigMatchingProvider.class, configMatcher)
        .addRequiredConfigFragments(configMatcher.getRequiredFragmentOptions())
        .build();
  }

  /**
   * Returns true if all <code>constraint_values</code> settings are valid and match this
   * configuration, false otherwise.
   *
   * <p>May generate rule errors on bad settings (e.g. wrong target types).
   */
  boolean constraintValuesMatch(RuleContext ruleContext) {
    List<ConstraintValueInfo> constraintValues = new ArrayList<>();
    for (TransitiveInfoCollection dep :
        ruleContext.getPrerequisites(
            ConfigSettingRule.CONSTRAINT_VALUES_ATTRIBUTE, TransitionMode.DONT_CHECK)) {
      if (!PlatformProviderUtils.hasConstraintValue(dep)) {
        ruleContext.attributeError(
            ConfigSettingRule.CONSTRAINT_VALUES_ATTRIBUTE,
            String.format(dep.getLabel() + " is not a constraint_value"));
      } else {
        constraintValues.add(PlatformProviderUtils.constraintValue(dep));
      }
    }
    if (ruleContext.hasErrors()) {
      return false;
    }

    // The set of constraint_values in a config_setting should never contain multiple
    // constraint_values that map to the same constraint_setting. This method checks if there are
    // duplicates and records an error if so.
    try {
      ConstraintCollection.validateConstraints(constraintValues);
    } catch (ConstraintCollection.DuplicateConstraintException e) {
      ruleContext.ruleError(
          ConstraintCollection.DuplicateConstraintException.formatError(e.duplicateConstraints()));
        return false;
    }

    return ruleContext
        .getToolchainContext()
        .targetPlatform()
        .constraints()
        .containsAll(constraintValues);
  }

  private static RepositoryName getToolsRepository(RuleContext ruleContext) {
    try {
      return RepositoryName.create(
          ruleContext.attributes().get(ConfigSettingRule.TOOLS_REPOSITORY_ATTRIBUTE, Type.STRING));
    } catch (LabelSyntaxException ex) {
      throw new IllegalStateException(ex);
    }
  }

  /**
   * Returns whether the given label falls under the {@code //tools} package (including subpackages)
   * of the tools repository.
   */
  @VisibleForTesting
  static boolean isUnderToolsPackage(Label label, RepositoryName toolsRepository) {
    PackageIdentifier packageId = label.getPackageIdentifier();
    if (!packageId.getRepository().equals(toolsRepository)) {
      return false;
    }
    try {
      return packageId.getPackageFragment().subFragment(0, 1).equals(PathFragment.create("tools"));
    } catch (IndexOutOfBoundsException e) {
      // Top-level package (//).
      return false;
    }
  }

  /**
   * User error when value settings can't be properly parsed.
   */
  private static final String PARSE_ERROR_MESSAGE = "error while parsing configuration settings: ";

  /**
   * Check to make sure this config_setting contains and sets least one of {values, define_values,
   * flag_value or constraint_values}.
   */
  private boolean valuesAreSet(
      ImmutableMultimap<String, String> nativeFlagSettings,
      Map<Label, String> userDefinedFlagSettings,
      Iterable<Label> constraintValues,
      RuleErrorConsumer errors) {
    if (nativeFlagSettings.isEmpty()
        && userDefinedFlagSettings.isEmpty()
        && Iterables.isEmpty(constraintValues)) {
      errors.ruleError(
          String.format(
              "Either %s, %s or %s must be specified and non-empty",
              ConfigSettingRule.SETTINGS_ATTRIBUTE,
              ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
              ConfigSettingRule.CONSTRAINT_VALUES_ATTRIBUTE));
      return false;
    }
    return true;
  }

  /**
   * Given a list of [flagName, flagValue] pairs for native Blaze flags, returns true if flagName ==
   * flagValue for every item in the list under this configuration, false otherwise.
   *
   * <p>This also sets {@code requiredFragmentOptions} to the {@link FragmentOptions} that options
   * read by this {@code config_setting} belong to.
   */
  private static boolean matchesConfig(
      Collection<Map.Entry<String, String>> expectedSettings,
      TransitiveOptionDetails options,
      ImmutableSet.Builder<String> requiredFragmentOptions,
      RuleContext ruleContext) {
    // Rather than returning fast when we find a mismatch, continue looking at the other flags
    // to check they're indeed valid flag specifications.
    boolean foundMismatch = false;

    for (Map.Entry<String, String> setting : expectedSettings) {
      String optionName = setting.getKey();
      String expectedRawValue = setting.getValue();

      Class<? extends FragmentOptions> optionClass = options.getOptionClass(optionName);
      if (optionClass == null) {
        ruleContext.attributeError(
            ConfigSettingRule.SETTINGS_ATTRIBUTE,
            String.format(PARSE_ERROR_MESSAGE + "unknown option: '%s'", optionName));
        foundMismatch = true;
        continue;
      }

      if (optionName.equals("define")) {
        // --define is more like user-defined build flags than traditional native flags. Report it
        // like user-defined flags: the dependency is directly on the flag vs. the fragment that
        // contains the flag. This frees a rule that depends on "--define a=1" from preserving
        // another rule's dependency on "--define b=2". In other words, if both rules simply said
        // "I require CoreOptions" (which is the FragmentOptions --define belongs to), that would
        // hide the reality that they really have orthogonal dependencies: removing
        // "--define b=2" is perfectly safe for the rule that needs "--define a=1".
        int equalsIndex = expectedRawValue.indexOf('=');
        requiredFragmentOptions.add(
            "--define:"
                + (equalsIndex > 0
                    ? expectedRawValue.substring(0, equalsIndex)
                    : expectedRawValue));
      } else {
        // For other native flags, it's reasonable to report the fragment they belong to.
        requiredFragmentOptions.add(ClassName.getSimpleNameWithOuter(optionClass));
      }

      SelectRestriction selectRestriction = options.getSelectRestriction(optionName);
      if (selectRestriction != null) {
        boolean underToolsPackage =
            isUnderToolsPackage(ruleContext.getRule().getLabel(), getToolsRepository(ruleContext));
        if (!(selectRestriction.isVisibleWithinToolsPackage() && underToolsPackage)) {
          String errorMessage =
              String.format("option '%s' cannot be used in a config_setting", optionName);
          if (selectRestriction.isVisibleWithinToolsPackage()) {
            errorMessage +=
                String.format(
                    " (it is whitelisted to %s//tools/... only)",
                    getToolsRepository(ruleContext).getDefaultCanonicalForm());
          }
          if (selectRestriction.getErrorMessage() != null) {
            errorMessage += ". " + selectRestriction.getErrorMessage();
          }
          ruleContext.attributeError(ConfigSettingRule.SETTINGS_ATTRIBUTE, errorMessage);
          foundMismatch = true;
          continue;
        }
      }

      OptionsParser parser;
      try {
        parser = OptionsParser.builder().optionsClasses(optionClass).build();
        parser.parse("--" + optionName + "=" + expectedRawValue);
      } catch (OptionsParsingException ex) {
        ruleContext.attributeError(
            ConfigSettingRule.SETTINGS_ATTRIBUTE, PARSE_ERROR_MESSAGE + ex.getMessage());
        foundMismatch = true;
        continue;
      }

      Object expectedParsedValue = parser.getOptions(optionClass).asMap().get(optionName);
      if (!optionMatches(options, optionName, expectedParsedValue)) {
        foundMismatch = true;
      }
    }
    return !foundMismatch;
  }

  /**
   * For single-value options, returns true iff the option's value matches the expected value.
   *
   * <p>For multi-value List options returns true iff any of the option's values matches the
   * expected value(s). This means "--ios_multi_cpus=a --ios_multi_cpus=b --ios_multi_cpus=c"
   * matches the expected conditions {'ios_multi_cpus': 'a' } and { 'ios_multi_cpus': 'b,c' } but
   * not { 'ios_multi_cpus': 'd' }.
   *
   * <p>For multi-value Map options, returns true iff the last instance with the same key as the
   * expected key has the same value. This means "--define foo=1 --define bar=2" matches { 'define':
   * 'foo=1' }, but "--define foo=1 --define bar=2 --define foo=3" doesn't match. Note that the
   * definition of --define states that the last instance takes precedence. Also note that there's
   * no options-parsing support for multiple values in a single clause, e.g. { 'define':
   * 'foo=1,bar=2' } expands to { "foo": "1,bar=2" }, not {"foo": 1, "bar": "2"}.
   */
  private static boolean optionMatches(
      TransitiveOptionDetails options, String optionName, Object expectedValue) {
    Object actualValue = options.getOptionValue(optionName);
    if (actualValue == null) {
      return expectedValue == null;

      // Single-value case:
    } else if (!options.allowsMultipleValues(optionName)) {
      return actualValue.equals(expectedValue);
    }

    // Multi-value case:
    Preconditions.checkState(actualValue instanceof List);
    Preconditions.checkState(expectedValue instanceof List);
    List<?> actualList = (List<?>) actualValue;
    List<?> expectedList = (List<?>) expectedValue;

    if (actualList.isEmpty() || expectedList.isEmpty()) {
      return actualList.isEmpty() && expectedList.isEmpty();
    }

    // Multi-value map:
    if (actualList.get(0) instanceof Map.Entry) {
      // The config_setting's expected value *must* be a single map entry (see method comments).
      Object expectedListValue = Iterables.getOnlyElement(expectedList);
      Map.Entry<?, ?> expectedEntry = (Map.Entry<?, ?>) expectedListValue;
      for (Object elem : Lists.reverse(actualList)) {
        Map.Entry<?, ?> actualEntry = (Map.Entry<?, ?>) elem;
        if (actualEntry.getKey().equals(expectedEntry.getKey())) {
          // Found a key match!
          return actualEntry.getValue().equals(expectedEntry.getValue());
        }
      }
      return false;
    }

    // Multi-value list:
    return actualList.containsAll(expectedList);
  }

  private static final class UserDefinedFlagMatch {
    private final boolean matches;
    private final ImmutableMap<Label, String> specifiedFlagValues;

    private static final Joiner QUOTED_COMMA_JOINER = Joiner.on("', '");

    private UserDefinedFlagMatch(boolean matches, ImmutableMap<Label, String> specifiedFlagValues) {
      this.matches = matches;
      this.specifiedFlagValues = specifiedFlagValues;
    }

    /** Returns whether the specified flag values matched the actual flag values. */
    public boolean matches() {
      return matches;
    }

    /** Gets the specified flag values, with aliases converted to their original targets' labels. */
    ImmutableMap<Label, String> getSpecifiedFlagValues() {
      return specifiedFlagValues;
    }

    /** Groups aliases in the list of prerequisites by the target they point to. */
    private static ListMultimap<Label, Label> collectAliases(
        Iterable<? extends TransitiveInfoCollection> prerequisites) {
      ImmutableListMultimap.Builder<Label, Label> targetsToAliases =
          new ImmutableListMultimap.Builder<>();
      for (TransitiveInfoCollection target : prerequisites) {
        targetsToAliases.put(target.getLabel(), AliasProvider.getDependencyLabel(target));
      }
      return targetsToAliases.build();
    }

    /**
     * The 'flag_values' attribute takes a label->string dictionary of feature flags and
     * starlark-defined settings to their values in string form.
     *
     * @param attributeValue map of user-defined flag labels to their values as set in the
     *     'flag_values' attribute
     * @param optionDetails information about the configuration to match against
     * @param requiredFragmentOptions set of config fragments this config_setting requires. This
     *     method adds feature flag and Starlark-defined setting requirements to this set.
     * @param ruleContext this rule's RuleContext
     */
    static UserDefinedFlagMatch fromAttributeValueAndPrerequisites(
        Map<Label, String> attributeValue,
        TransitiveOptionDetails optionDetails,
        ImmutableSet.Builder<String> requiredFragmentOptions,
        RuleContext ruleContext) {
      Map<Label, String> specifiedFlagValues = new LinkedHashMap<>();
      boolean matches = true;
      boolean foundDuplicate = false;

      // Get the actual targets the 'flag_values' keys reference.
      Iterable<? extends TransitiveInfoCollection> prerequisites =
          ruleContext.getPrerequisites(
              ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE, TransitionMode.TARGET);

      for (TransitiveInfoCollection target : prerequisites) {
        Label actualLabel = target.getLabel();
        Label specifiedLabel = AliasProvider.getDependencyLabel(target);
        String specifiedValue =
            maybeCanonicalizeLabel(attributeValue.get(specifiedLabel), target, ruleContext);
        if (specifiedFlagValues.containsKey(actualLabel)) {
          foundDuplicate = true;
        }
        specifiedFlagValues.put(actualLabel, specifiedValue);

        if (target.satisfies(ConfigFeatureFlagProvider.REQUIRE_CONFIG_FEATURE_FLAG_PROVIDER)) {
          // config_feature_flag
          requiredFragmentOptions.add(target.getLabel().toString());
          ConfigFeatureFlagProvider provider = ConfigFeatureFlagProvider.fromTarget(target);
          if (!provider.isValidValue(specifiedValue)) {
            ruleContext.attributeError(
                ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
                String.format(
                    "error while parsing user-defined configuration values: "
                        + "'%s' is not a valid value for '%s'",
                    specifiedValue, specifiedLabel));
            matches = false;
            continue;
          }
          if (!provider.getFlagValue().equals(specifiedValue)) {
            matches = false;
          }
        } else if (target.satisfies(BuildSettingProvider.REQUIRE_BUILD_SETTING_PROVIDER)) {
          // build setting
          requiredFragmentOptions.add(target.getLabel().toString());
          BuildSettingProvider provider = target.getProvider(BuildSettingProvider.class);
          Object configurationValue =
              optionDetails.getOptionValue(specifiedLabel) != null
                  ? optionDetails.getOptionValue(specifiedLabel)
                  : provider.getDefaultValue();
          Object convertedSpecifiedValue;
          try {
            convertedSpecifiedValue =
                BUILD_SETTING_CONVERTERS.get(provider.getType()).convert(specifiedValue);
          } catch (OptionsParsingException e) {
            ruleContext.attributeError(
                ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
                String.format(
                    "error while parsing user-defined configuration values: "
                        + "'%s' cannot be converted to %s type %s",
                    specifiedValue, specifiedLabel, provider.getType()));
            matches = false;
            continue;
          }

          if (configurationValue instanceof List) {
            // If the build_setting is a list, we use the same semantics as for multi-value native
            // flags: if *any* entry in the list matches the config_setting's expected entry, it's
            // a match. In other words, config_setting(flag_values {"//foo": "bar"} matches
            // //foo=["bar", "baz"].

            // If the config_setting expects "foo", convertedSpecifiedValue converts it to the
            // flag's native type, which produces ["foo"]. So unpack that again.
            Iterable<?> specifiedValueAsIterable = (Iterable<?>) convertedSpecifiedValue;
            if (Iterables.size(specifiedValueAsIterable) != 1) {
              ruleContext.attributeError(
                  ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
                  String.format(
                      "\"%s\" not a valid value for flag %s. Only single, exact values are allowed."
                          + " If you want to match multiple values, consider Skylib's "
                          + "selects.config_setting_group",
                      specifiedValue, specifiedLabel));
              matches = false;
            } else if (!((List<?>) configurationValue)
                .contains(Iterables.getOnlyElement(specifiedValueAsIterable))) {
              matches = false;
            }
          } else if (!configurationValue.equals(convertedSpecifiedValue)) {
            matches = false;
          }
        } else {
          ruleContext.attributeError(
              ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
              String.format(
                  "error while parsing user-defined configuration values: "
                      + "%s keys must be build settings or feature flags and %s is not",
                  ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE, specifiedLabel));
          matches = false;
        }
      }

      // attributeValue is the source of the prerequisites in prerequisites, so the final map built
      // from iterating over prerequisites should always be the same size, barring duplicates.
      assert foundDuplicate || attributeValue.size() == specifiedFlagValues.size();

      if (foundDuplicate) {
        ListMultimap<Label, Label> aliases = collectAliases(prerequisites);
        for (Label actualLabel : aliases.keySet()) {
          List<Label> aliasList = aliases.get(actualLabel);
          if (aliasList.size() > 1) {
            ruleContext.attributeError(
                ConfigSettingRule.FLAG_SETTINGS_ATTRIBUTE,
                String.format(
                    "flag '%s' referenced multiple times as ['%s']",
                    actualLabel, QUOTED_COMMA_JOINER.join(aliasList)));
          }
        }
        matches = false;
      }

      return new UserDefinedFlagMatch(matches, ImmutableMap.copyOf(specifiedFlagValues));
    }
  }

  /**
   * Given a 'flag_values = {"//ref:to:flagTarget": "expectedValue"}' pair, if expectedValue is a
   * relative label (e.g. ":sometarget") and flagTarget's value(s) are label-typed, returns an
   * absolute form of the label under the config_setting's package. Else returns the original value
   * unchanged.
   *
   * <p>This lets config_setting use relative labels to match against the actual values, which are
   * already represented in absolute form.
   *
   * <p>The value is returned as a string because it's subsequently fed through the flag's type
   * converter (which maps a string to the final type). Invalid labels are treated no differently
   * (they don't trigger special errors here) because the type converter will also handle that.
   *
   * @param expectedValue the raw value the config_setting expects
   * @param flagTarget the target of the flag whose value is being checked
   * @param @param ruleContext this rule's RuleContext
   */
  private static String maybeCanonicalizeLabel(
      String expectedValue, TransitiveInfoCollection flagTarget, RuleContext ruleContext) {
    if (!flagTarget.satisfies(BuildSettingProvider.REQUIRE_BUILD_SETTING_PROVIDER)) {
      return expectedValue;
    }
    if (!BuildType.isLabelType(flagTarget.getProvider(BuildSettingProvider.class).getType())) {
      return expectedValue;
    }
    if (!expectedValue.startsWith(":")) {
      return expectedValue;
    }
    try {
      return Label.create(
              ruleContext.getRule().getPackage().getPackageIdentifier(), expectedValue.substring(1))
          .getCanonicalForm();
    } catch (LabelSyntaxException e) {
      // Swallow this: the subsequent type conversion already checks for this.
      return expectedValue;
    }
  }
}
