// 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.packages;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.SetMultimap;
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.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.StarlarkImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.License.DistributionType;
import com.google.devtools.build.lib.packages.Package.ConfigSettingVisibilityPolicy;
import com.google.devtools.build.lib.packages.RuleClass.ToolchainResolutionMode;
import com.google.devtools.build.lib.server.FailureDetails.PackageLoading;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;
import net.starlark.java.syntax.Location;

/**
 * An instance of a build rule in the build language. A rule has a name, a package to which it
 * belongs, a class such as <code>cc_library</code>, and set of typed attributes. The set of
 * attribute names and types is a property of the rule's class. The use of the term "class" here has
 * nothing to do with Java classes. All rules are implemented by the same Java classes, Rule and
 * RuleClass.
 *
 * <p>Here is a typical rule as it appears in a BUILD file:
 *
 * <pre>
 * cc_library(name = 'foo',
 *            defines = ['-Dkey=value'],
 *            srcs = ['foo.cc'],
 *            deps = ['bar'])
 * </pre>
 */
// Non-final only for mocking in tests. Do not subclass!
public class Rule implements Target, DependencyFilter.AttributeInfoProvider {

  /** Label predicate that allows every label. */
  public static final Predicate<Label> ALL_LABELS = Predicates.alwaysTrue();

  private static final String NAME = RuleClass.NAME_ATTRIBUTE.getName();
  private static final String GENERATOR_FUNCTION = "generator_function";
  private static final String GENERATOR_LOCATION = "generator_location";

  private final Label label;

  private final Package pkg;

  private final RuleClass ruleClass;

  private AttributeContainer attributes;

  private RuleVisibility visibility;

  private boolean containsErrors;

  private final Location location;

  private final CallStack callstack;

  private final ImplicitOutputsFunction implicitOutputsFunction;

  /**
   * A compact representation of a multimap from "output keys" to output files.
   *
   * <p>An output key is an identifier used to access the output in {@code ctx.outputs}, or the
   * empty string in the case of an output that's not exposed there. For explicit outputs, the
   * output key is the name of the attribute under which that output appears. For Starlark-defined
   * implicit outputs, the output key is determined by the dict returned from the Starlark function.
   * Native-defined implicit outputs are not named in this manner, and so are invisible to {@code
   * ctx.outputs} and use the empty string key. (It'd be pathological for the empty string to be
   * used as a key in the other two cases, but this class makes no attempt to prohibit that.)
   *
   * <p>Rather than naively store an ImmutableListMultimap, we save space by compressing it as an
   * ImmutableList, where each key is followed by all the values having that key. We distinguish
   * keys (Strings) from values (OutputFiles) by the fact that they have different types. The
   * accessor methods traverse the list and create a more user-friendly view.
   *
   * <p>To distinguish implicit outputs from explicit outputs, we store all the implicit outputs in
   * the list first, and record how many implicit output keys there are in a separate field.
   *
   * <p>The order of the implicit outputs is the same as returned by the implicit output function.
   * This allows a native rule implementation and native implicit outputs function to agree on the
   * index of a given kind of output. The order of explicit outputs preserves the attribute
   * iteration order and the order of values in a list attribute; the latter is important so that
   * {@code ctx.outputs.some_list} has a well-defined order.
   */
  // Both of these fields are initialized by populateOutputFiles().
  private ImmutableList<Object> flattenedOutputFileMap;

  private int numImplicitOutputKeys;

  Rule(
      Package pkg,
      Label label,
      RuleClass ruleClass,
      Location location,
      CallStack callstack,
      AttributeContainer attributeContainer) {
    this(
        pkg,
        label,
        ruleClass,
        location,
        callstack,
        attributeContainer,
        ruleClass.getDefaultImplicitOutputsFunction());
  }

  Rule(
      Package pkg,
      Label label,
      RuleClass ruleClass,
      Location location,
      CallStack callstack,
      AttributeContainer attributeContainer,
      ImplicitOutputsFunction implicitOutputsFunction) {
    this.pkg = Preconditions.checkNotNull(pkg);
    this.label = label;
    this.ruleClass = Preconditions.checkNotNull(ruleClass);
    this.location = Preconditions.checkNotNull(location);
    this.callstack = Preconditions.checkNotNull(callstack);
    this.attributes = attributeContainer;
    this.implicitOutputsFunction = implicitOutputsFunction;
    this.containsErrors = false;
  }

  void setVisibility(RuleVisibility visibility) {
    this.visibility = visibility;
  }

  void setAttributeValue(Attribute attribute, Object value, boolean explicit) {
    String attrName = attribute.getName();
    if (attrName.equals(NAME)) {
      // Avoid unnecessarily storing the name in the attribute container - it's stored in the label.
      return;
    }
    Integer attrIndex = ruleClass.getAttributeIndex(attrName);
    Preconditions.checkArgument(
        attrIndex != null, "attribute %s is not valid for this rule", attrName);
    attributes.setAttributeValue(attrIndex, value, explicit);
  }

  void setContainsErrors() {
    this.containsErrors = true;
  }

  @Override
  public Label getLabel() {
    return label;
  }

  @Override
  public String getName() {
    return label.getName();
  }

  @Override
  public Package getPackage() {
    return pkg;
  }

  public RuleClass getRuleClassObject() {
    return ruleClass;
  }

  @Override
  public String getTargetKind() {
    return ruleClass.getTargetKind();
  }

  /** Returns the class of this rule. (e.g. "cc_library") */
  @Override
  public String getRuleClass() {
    return ruleClass.getName();
  }

  /**
   * Returns true iff the outputs of this rule should be created beneath the bin directory, false if
   * beneath genfiles. For most rule classes, this is constant, but for genrule, it is a property of
   * the individual target, derived from the 'output_to_bindir' attribute.
   */
  public boolean outputsToBindir() {
    return ruleClass.getName().equals("genrule") // this is unfortunate...
        ? NonconfigurableAttributeMapper.of(this).get("output_to_bindir", Type.BOOLEAN)
        : ruleClass.outputsToBindir();
  }

  /** Returns true if this rule is an analysis test (set by analysis_test = true). */
  public boolean isAnalysisTest() {
    return ruleClass.isAnalysisTest();
  }

  /**
   * Returns true if this rule has at least one attribute with an analysis test transition. (A
   * starlark-defined transition using analysis_test_transition()).
   */
  public boolean hasAnalysisTestTransition() {
    return ruleClass.hasAnalysisTestTransition();
  }

  public boolean isBuildSetting() {
    return ruleClass.getBuildSetting() != null;
  }

  /**
   * Returns true iff there were errors while constructing this rule, such as
   * attributes with missing values or values of the wrong type.
   */
  public boolean containsErrors() {
    return containsErrors;
  }

  public boolean hasAspects() {
    return ruleClass.hasAspects();
  }

  /**
   * Returns an (unmodifiable, unordered) collection containing all the
   * Attribute definitions for this kind of rule.  (Note, this doesn't include
   * the <i>values</i> of the attributes, merely the schema.  Call
   * get[Type]Attr() methods to access the actual values.)
   */
  public Collection<Attribute> getAttributes() {
    return ruleClass.getAttributes();
  }

  /**
   * Returns true if the given attribute is configurable.
   */
  public boolean isConfigurableAttribute(String attributeName) {
    Attribute attribute = ruleClass.getAttributeByNameMaybe(attributeName);
    // TODO(murali): This method should be property of ruleclass not rule instance.
    // Further, this call to AbstractAttributeMapper.isConfigurable is delegated right back
    // to this instance!
    return attribute != null
        && AbstractAttributeMapper.isConfigurable(this, attributeName, attribute.getType());
  }

  /**
   * Returns the attribute definition whose name is {@code attrName}, or null
   * if not found.  (Use get[X]Attr for the actual value.)
   *
   * @deprecated use {@link AbstractAttributeMapper#getAttributeDefinition} instead
   */
  @Deprecated
  public Attribute getAttributeDefinition(String attrName) {
    return ruleClass.getAttributeByNameMaybe(attrName);
  }

  /**
   * Constructs and returns an immutable list containing all the declared output files of this rule.
   *
   * <p>There are two kinds of outputs. Explicit outputs are declared in attributes of type OUTPUT
   * or OUTPUT_LABEL. Implicit outputs are determined by custom rule logic in an "implicit outputs
   * function" (either defined natively or in Starlark), and are named following a template pattern
   * based on the target's attributes.
   *
   * <p>All implicit output files (declared in the {@link RuleClass}) are listed first, followed by
   * any explicit files (declared via output attributes). Additionally, both implicit and explicit
   * outputs will retain the relative order in which they were declared.
   */
  public ImmutableList<OutputFile> getOutputFiles() {
    // Discard the String keys, taking only the OutputFile values.
    ImmutableList.Builder<OutputFile> result = ImmutableList.builder();
    for (Object o : flattenedOutputFileMap) {
      if (o instanceof OutputFile) {
        result.add((OutputFile) o);
      }
    }
    return result.build();
  }

  /**
   * Constructs and returns an immutable list of all the implicit output files of this rule, in the
   * order they were declared.
   */
  public ImmutableList<OutputFile> getImplicitOutputFiles() {
    ImmutableList.Builder<OutputFile> result = ImmutableList.builder();
    int seenKeys = 0;
    for (Object o : flattenedOutputFileMap) {
      if (o instanceof String) {
        if (++seenKeys > numImplicitOutputKeys) {
          break;
        }
      } else {
        result.add((OutputFile) o);
      }
    }
    return result.build();
  }

  /**
   * Constructs and returns an immutable multimap of the explicit outputs, from attribute name to
   * associated value.
   *
   * <p>Keys are listed in the same order as attributes. Order of attribute values (outputs in an
   * output list) is preserved.
   *
   * <p>Since this is a multimap, attributes that have no associated outputs are omitted from the
   * result.
   */
  public ImmutableListMultimap<String, OutputFile> getExplicitOutputFileMap() {
    ImmutableListMultimap.Builder<String, OutputFile> result = ImmutableListMultimap.builder();
    int seenKeys = 0;
    String key = null;
    for (Object o : flattenedOutputFileMap) {
      if (o instanceof String) {
        seenKeys++;
        key = (String) o;
      } else if (seenKeys > numImplicitOutputKeys) {
        result.put(key, (OutputFile) o);
      }
    }
    return result.build();
  }

  /**
   * Returns a map of the Starlark-defined implicit outputs, from dict key to output file.
   *
   * <p>If there is no implicit outputs function, or it is a native one, an empty map is returned.
   *
   * <p>This is not a multimap because Starlark-defined implicit output functions return exactly one
   * output per key.
   */
  public ImmutableMap<String, OutputFile> getStarlarkImplicitOutputFileMap() {
    if (!(implicitOutputsFunction instanceof StarlarkImplicitOutputsFunction)) {
      return ImmutableMap.of();
    }
    ImmutableMap.Builder<String, OutputFile> result = ImmutableMap.builder();
    int seenKeys = 0;
    String key = null;
    for (Object o : flattenedOutputFileMap) {
      if (o instanceof String) {
        if (++seenKeys > numImplicitOutputKeys) {
          break;
        }
        key = (String) o;
      } else {
        result.put(key, (OutputFile) o);
      }
    }
    return result.buildOrThrow();
  }

  @Override
  public Location getLocation() {
    return location;
  }

  /** Returns the stack of function calls active when this rule was instantiated. */
  public CallStack getCallStack() {
    return callstack;
  }

  public ImplicitOutputsFunction getImplicitOutputsFunction() {
    return implicitOutputsFunction;
  }

  @Override
  public Rule getAssociatedRule() {
    return this;
  }

  /**
   * Returns this rule's raw attribute info, suitable for being fed into an {@link AttributeMap} for
   * user-level attribute access. Don't use this method for direct attribute access.
   */
  AttributeContainer getAttributeContainer() {
    return attributes;
  }

  /*
   *******************************************************************
   * Attribute accessor functions.
   *
   * The below provide access to attribute definitions and other generic
   * metadata.
   *
   * For access to attribute *values* (e.g. "What's the value of attribute
   * X for Rule Y?"), go through {@link RuleContext#attributes}. If no
   * RuleContext is available, create a localized {@link AbstractAttributeMapper}
   * instance instead.
   *******************************************************************
   */

  /**
   * Returns the default value for the attribute {@code attrName}, which may be of any type, but
   * must exist (an exception is thrown otherwise).
   */
  public Object getAttrDefaultValue(String attrName) {
    Object defaultValue = ruleClass.getAttributeByName(attrName).getDefaultValue(this);
    // Computed defaults not expected here.
    Preconditions.checkState(!(defaultValue instanceof Attribute.ComputedDefault));
    return defaultValue;
  }

  /**
   * Returns true iff the rule class has an attribute with the given name and type.
   *
   * <p>Note: RuleContext also has isAttrDefined(), which takes Aspects into account. Whenever
   * possible, use RuleContext.isAttrDefined() instead of this method.
   */
  public boolean isAttrDefined(String attrName, Type<?> type) {
    return ruleClass.hasAttr(attrName, type);
  }

  /**
   * Returns the value of the attribute with the given index. Returns null, if no such attribute
   * exists OR no value was set.
   */
  @Nullable
  private Object getAttrWithIndex(int attrIndex) {
    Object value = attributes.getAttributeValue(attrIndex);
    if (value != null) {
      return value;
    }
    Attribute attr = ruleClass.getAttribute(attrIndex);
    if (attr.hasComputedDefault()) {
      // Frozen attribute containers don't store computed defaults, so get it from the attribute.
      // Mutable attribute containers do store computed defaults if they've been populated. If a
      // mutable container returns null, return null here since resolving the default could trigger
      // reads of other attributes which have not yet been populated. Note that in this situation
      // returning null does not result in a correctness issue, since the value for the attribute is
      // actually a function to compute the value.
      return attributes.isFrozen() ? attr.getDefaultValue(this) : null;
    }
    switch (attr.getName()) {
      case GENERATOR_FUNCTION:
        return callstack.size() > 1 ? callstack.getFrame(1).name : "";
      case GENERATOR_LOCATION:
        return callstack.size() > 1 ? relativeLocation(callstack.getFrame(0).location) : "";
      default:
        return attr.getDefaultValue(null);
    }
  }

  @Nullable
  private String relativeLocation(Location location) {
    // Determining the workspace root only works reliably if both location and label point to files
    // in the same package.
    // It would be preferable to construct the path from the label itself, but this doesn't work for
    // rules created from function calls in a subincluded file, even if both files share a path
    // prefix (for example, when //a/package:BUILD subincludes //a/package/with/a/subpackage:BUILD).
    // We can revert to that approach once subincludes aren't supported anymore.
    //
    // TODO(b/151165647): this logic has always been wrong:
    // it spuriously matches occurrences of the package name earlier in the path.
    String absolutePath = location.toString();
    int pos = absolutePath.indexOf(label.getPackageName());
    return (pos < 0) ? null : absolutePath.substring(pos);
  }

  /**
   * Returns the value of the given attribute for this rule. Returns null for invalid attributes and
   * default value if attribute was not set.
   *
   * @param attrName the name of the attribute to lookup.
   */
  @Nullable
  public Object getAttr(String attrName) {
    if (attrName.equals(NAME)) {
      return getName();
    }
    Integer attrIndex = ruleClass.getAttributeIndex(attrName);
    return attrIndex == null ? null : getAttrWithIndex(attrIndex);
  }

  /**
   * Returns the value of the given attribute if it has the right type.
   *
   * @throws IllegalArgumentException if the attribute does not have the expected type.
   */
  @Nullable
  public <T> Object getAttr(String attrName, Type<T> type) {
    if (attrName.equals(NAME)) {
      checkAttrType(attrName, type, RuleClass.NAME_ATTRIBUTE);
      return getName();
    }

    Integer index = ruleClass.getAttributeIndex(attrName);
    if (index == null) {
      throw new IllegalArgumentException(
          "No such attribute " + attrName + " in " + ruleClass + " rule " + label);
    }
    checkAttrType(attrName, type, ruleClass.getAttribute(index));
    return getAttrWithIndex(index);
  }

  private void checkAttrType(String attrName, Type<?> requestedType, Attribute attr) {
    if (requestedType != attr.getType()) {
      throw new IllegalArgumentException(
          "Attribute "
              + attrName
              + " is of type "
              + attr.getType()
              + " and not of type "
              + requestedType
              + " in "
              + ruleClass
              + " rule "
              + label);
    }
  }

  /**
   * Returns a {@link BuildType.SelectorList} for the given attribute if the attribute is
   * configurable for this rule, null otherwise.
   */
  @Nullable
  @SuppressWarnings("unchecked")
  public <T> BuildType.SelectorList<T> getSelectorList(String attributeName, Type<T> type) {
    Integer index = ruleClass.getAttributeIndex(attributeName);
    if (index == null) {
      return null;
    }
    Object attrValue = attributes.getAttributeValue(index);
    if (!(attrValue instanceof BuildType.SelectorList)) {
      return null;
    }
    if (((BuildType.SelectorList<?>) attrValue).getOriginalType() != type) {
      throw new IllegalArgumentException(
          "Attribute "
              + attributeName
              + " is not of type "
              + type
              + " in "
              + ruleClass
              + " rule "
              + label);
    }
    return (BuildType.SelectorList<T>) attrValue;
  }
  /**
   * See {@link #isAttributeValueExplicitlySpecified(String)}
   */
  @Override
  public boolean isAttributeValueExplicitlySpecified(Attribute attribute) {
    return isAttributeValueExplicitlySpecified(attribute.getName());
  }

  /**
   * Returns true iff the value of the specified attribute is explicitly set in the BUILD file. This
   * returns true also if the value explicitly specified in the BUILD file is the same as the
   * attribute's default value. In addition, this method return false if the rule has no attribute
   * with the given name.
   */
  public boolean isAttributeValueExplicitlySpecified(String attrName) {
    if (attrName.equals(NAME)) {
      return true;
    }
    if (attrName.equals(GENERATOR_FUNCTION) || attrName.equals(GENERATOR_LOCATION)) {
      return wasCreatedByMacro();
    }
    Integer attrIndex = ruleClass.getAttributeIndex(attrName);
    if (attrIndex == null) {
      return false;
    }
    return attributes.isAttributeValueExplicitlySpecified(attrIndex);
  }

  /**
   * Returns whether this rule was created by a macro.
   */
  public boolean wasCreatedByMacro() {
    return hasStringAttribute("generator_name") || hasStringAttribute(GENERATOR_FUNCTION);
  }

  /** Returns the macro that generated this rule, or an empty string. */
  public String getGeneratorFunction() {
    Object value = getAttr(GENERATOR_FUNCTION);
    if (value instanceof String) {
      return (String) value;
    }
    return "";
  }

  private boolean hasStringAttribute(String attrName) {
    Object value = getAttr(attrName);
    if (value instanceof String) {
      return !((String) value).isEmpty();
    }
    return false;
  }

  /** Returns a new list containing all direct dependencies (all types). */
  public List<Label> getLabels() {
    List<Label> labels = new ArrayList<>();
    AggregatingAttributeMapper.of(this).visitAllLabels((attribute, label) -> labels.add(label));
    return labels;
  }

  /**
   * Returns a sorted set containing all labels that match a given {@link DependencyFilter}, not
   * including outputs.
   *
   * @param filter A dependency filter that determines whether a label should be included in the
   *     result. {@link DependencyFilter#test} is called with this rule and the attribute that
   *     contains the label. The label will be contained in the result iff the predicate returns
   *     {@code true} <em>and</em> the label is not an output.
   */
  public ImmutableSortedSet<Label> getSortedLabels(DependencyFilter filter) {
    ImmutableSortedSet.Builder<Label> labels = ImmutableSortedSet.naturalOrder();
    AggregatingAttributeMapper.of(this)
        .visitLabels(filter, (Attribute attribute, Label label) -> labels.add(label));
    return labels.build();
  }

  /**
   * Returns a {@link SetMultimap} containing all non-output labels matching a given {@link
   * DependencyFilter}, keyed by the corresponding attribute.
   *
   * <p>Labels that appear in multiple attributes will be mapped from each of their corresponding
   * attributes, provided they pass the {@link DependencyFilter}.
   *
   * @param filter A dependency filter that determines whether a label should be included in the
   *     result. {@link DependencyFilter#test} is called with this rule and the attribute that
   *     contains the label. The label will be contained in the result iff the predicate returns
   *     {@code true} <em>and</em> the label is not an output.
   */
  public SetMultimap<Attribute, Label> getTransitions(DependencyFilter filter) {
    SetMultimap<Attribute, Label> transitions = HashMultimap.create();
    AggregatingAttributeMapper.of(this).visitLabels(filter, transitions::put);
    return transitions;
  }

  void freeze() {
    attributes = attributes.freeze(this);
  }

  /**
   * Check if this rule is valid according to the validityPredicate of its RuleClass.
   */
  void checkValidityPredicate(EventHandler eventHandler) {
    PredicateWithMessage<Rule> predicate = ruleClass.getValidityPredicate();
    if (!predicate.apply(this)) {
      reportError(predicate.getErrorReason(this), eventHandler);
    }
  }

  /**
   * Collects the output files (both implicit and explicit). Must be called before the output
   * accessors methods can be used, and must be called only once.
   */
  void populateOutputFiles(EventHandler eventHandler, Package.Builder pkgBuilder)
      throws LabelSyntaxException, InterruptedException {
    populateOutputFilesInternal(
        eventHandler, pkgBuilder.getPackageIdentifier(), /*checkLabels=*/ true);
  }

  void populateOutputFilesUnchecked(Package.Builder pkgBuilder) throws InterruptedException {
    try {
      populateOutputFilesInternal(
          NullEventHandler.INSTANCE, pkgBuilder.getPackageIdentifier(), /*checkLabels=*/ false);
    } catch (LabelSyntaxException e) {
      throw new IllegalStateException(e);
    }
  }

  @FunctionalInterface
  private interface ExplicitOutputHandler {
    void accept(Attribute attribute, Label outputLabel) throws LabelSyntaxException;
  }

  @FunctionalInterface
  private interface ImplicitOutputHandler {
    void accept(String outputKey, String outputName);
  }

  private void populateOutputFilesInternal(
      EventHandler eventHandler, PackageIdentifier pkgId, boolean checkLabels)
      throws LabelSyntaxException, InterruptedException {
    Preconditions.checkState(flattenedOutputFileMap == null);

    // We associate each output with its String key (or empty string if there's no key) as we go,
    // and compress it down to a flat list afterwards. We use ImmutableListMultimap because it's
    // more efficient than LinkedListMultimap and provides ordering guarantees among keys (whereas
    // ArrayListMultimap doesn't).
    ImmutableListMultimap.Builder<String, OutputFile> outputFileMap =
        ImmutableListMultimap.builder();
    // Detects collisions where the same output key is used for both an explicit and implicit entry.
    HashSet<String> implicitOutputKeys = new HashSet<>();

    // We need the implicits to appear before the explicits in the final data structure, so we
    // process them first. We check for duplicates while handling the explicits.
    //
    // Each of these cases has two subcases, so we factor their bodies out into lambdas.

    ImplicitOutputHandler implicitOutputHandler =
        // outputKey: associated dict key if Starlark-defined, empty string otherwise
        // outputName: package-relative path fragment
        (outputKey, outputName) -> {
          Label label;
          if (checkLabels) { // controls label syntax validation only
            try {
              label = Label.create(pkgId, outputName);
            } catch (LabelSyntaxException e) {
              reportError(
                  String.format(
                      "illegal output file name '%s' in rule %s due to: %s",
                      outputName, this.label, e.getMessage()),
                  eventHandler);
              return;
            }
          } else {
            label = Label.createUnvalidated(pkgId, outputName);
          }
          validateOutputLabel(label, eventHandler);

          OutputFile file = new OutputFile(label, this);
          outputFileMap.put(outputKey, file);
          implicitOutputKeys.add(outputKey);
        };

    // Populate the implicit outputs.
    try {
      RawAttributeMapper attributeMap = RawAttributeMapper.of(this);
      // TODO(bazel-team): Reconsider the ImplicitOutputsFunction abstraction. It doesn't seem to be
      // a good fit if it forces us to downcast in situations like this. It also causes
      // getImplicitOutputs() to declare that it throws EvalException (which then has to be
      // explicitly disclaimed by the subclass SafeImplicitOutputsFunction).
      if (implicitOutputsFunction instanceof StarlarkImplicitOutputsFunction) {
        for (Map.Entry<String, String> e :
            ((StarlarkImplicitOutputsFunction) implicitOutputsFunction)
                .calculateOutputs(eventHandler, attributeMap)
                .entrySet()) {
          implicitOutputHandler.accept(e.getKey(), e.getValue());
        }
      } else {
        for (String out : implicitOutputsFunction.getImplicitOutputs(eventHandler, attributeMap)) {
          implicitOutputHandler.accept(/*outputKey=*/ "", out);
        }
      }
    } catch (EvalException e) {
      reportError(String.format("In rule %s: %s", label, e.getMessageWithStack()), eventHandler);
    }

    ExplicitOutputHandler explicitOutputHandler =
        (attribute, outputLabel) -> {
          String attrName = attribute.getName();
          if (implicitOutputKeys.contains(attrName)) {
            reportError(
                String.format(
                    "Implicit output key '%s' collides with output attribute name", attrName),
                eventHandler);
          }
          if (checkLabels) {
            if (!outputLabel.getPackageIdentifier().equals(pkg.getPackageIdentifier())) {
              throw new IllegalStateException(
                  String.format(
                      "Label for attribute %s should refer to '%s' but instead refers to '%s'"
                          + " (label '%s')",
                      attribute,
                      pkg.getName(),
                      outputLabel.getPackageFragment(),
                      outputLabel.getName()));
            }
            if (outputLabel.getName().equals(".")) {
              throw new LabelSyntaxException("output file name can't be equal '.'");
            }
          }
          validateOutputLabel(outputLabel, eventHandler);

          OutputFile outputFile = new OutputFile(outputLabel, this);
          outputFileMap.put(attrName, outputFile);
        };

    // Populate the explicit outputs.
    NonconfigurableAttributeMapper nonConfigurableAttributes =
        NonconfigurableAttributeMapper.of(this);
    for (Attribute attribute : ruleClass.getAttributes()) {
      String name = attribute.getName();
      Type<?> type = attribute.getType();
      if (type == BuildType.OUTPUT) {
        Label label = nonConfigurableAttributes.get(name, BuildType.OUTPUT);
        if (label != null) {
          explicitOutputHandler.accept(attribute, label);
        }
      } else if (type == BuildType.OUTPUT_LIST) {
        for (Label label : nonConfigurableAttributes.get(name, BuildType.OUTPUT_LIST)) {
          explicitOutputHandler.accept(attribute, label);
        }
      }
    }

    // Flatten the result into the final list.
    ImmutableList.Builder<Object> builder = ImmutableList.builder();
    for (Map.Entry<String, Collection<OutputFile>> e : outputFileMap.build().asMap().entrySet()) {
      builder.add(e.getKey());
      for (OutputFile out : e.getValue()) {
        builder.add(out);
      }
    }
    flattenedOutputFileMap = builder.build();
    numImplicitOutputKeys = implicitOutputKeys.size();
  }

  private void validateOutputLabel(Label label, EventHandler eventHandler) {
    if (label.getName().equals(getName())) {
      // TODO(bazel-team): for now (23 Apr 2008) this is just a warning.  After
      // June 1st we should make it an error.
      reportWarning("target '" + getName() + "' is both a rule and a file; please choose "
                    + "another name for the rule", eventHandler);
    }
  }

  void reportError(String message, EventHandler eventHandler) {
    eventHandler.handle(Package.error(location, message, PackageLoading.Code.STARLARK_EVAL_ERROR));
    this.containsErrors = true;
  }

  private void reportWarning(String message, EventHandler eventHandler) {
    eventHandler.handle(Event.warn(location, message));
  }

  /** Returns a string of the form "cc_binary rule //foo:foo" */
  @Override
  public String toString() {
    return getRuleClass() + " rule " + label;
  }

 /**
   * Returns the effective visibility of this Rule. Visibility is computed from
   * these sources in this order of preference:
   *   - 'visibility' attribute
   *   - 'default_visibility;' attribute of package() declaration
   *   - public.
   */
  @Override
  public RuleVisibility getVisibility() {
    // Temporary logic to relax config_setting's visibility enforcement while depot migrations set
    // visibility settings properly (legacy code may have visibility settings that would break if
    // enforced). See https://github.com/bazelbuild/bazel/issues/12669. Ultimately this entire
    // conditional should be removed.
    if (ruleClass.getName().equals("config_setting")) {
      ConfigSettingVisibilityPolicy policy = pkg.getConfigSettingVisibilityPolicy();
      if (visibility != null) {
        return visibility; // Use explicitly set visibility
      } else if (policy == ConfigSettingVisibilityPolicy.DEFAULT_PUBLIC) {
        return ConstantRuleVisibility.PUBLIC; // Default: //visibility:public.
      } else {
        return pkg.getDefaultVisibility(); // Default: same as all other rules.
      }
    }

    // All other rules.
    if (visibility != null) {
      return visibility;
    }
    return pkg.getDefaultVisibility();
  }

  public boolean isVisibilitySpecified() {
    return visibility != null;
  }

  @Override
  public boolean isConfigurable() {
    return true;
  }

  @Override
  public Set<DistributionType> getDistributions() {
    if (isAttrDefined("distribs", BuildType.DISTRIBUTIONS)
        && isAttributeValueExplicitlySpecified("distribs")) {
      return NonconfigurableAttributeMapper.of(this).get("distribs", BuildType.DISTRIBUTIONS);
    } else {
      return pkg.getDefaultDistribs();
    }
  }

  @Override
  public License getLicense() {
    // New style licenses defined by Starlark rules don't
    // have old-style licenses. This is hardcoding the representation
    // of new-style rules, but it's in the old-style licensing code path
    // and will ultimately be removed.
    if (ruleClass.isPackageMetadataRule()) {
      return License.NO_LICENSE;
    } else if (isAttrDefined("licenses", BuildType.LICENSE)
        && isAttributeValueExplicitlySpecified("licenses")) {
      return NonconfigurableAttributeMapper.of(this).get("licenses", BuildType.LICENSE);
    } else if (ruleClass.ignoreLicenses()) {
      return License.NO_LICENSE;
    } else {
      return pkg.getDefaultLicense();
    }
  }

  /**
   * Returns the license of the output of the binary created by this rule, or null if it is not
   * specified.
   */
  @Nullable
  public License getToolOutputLicense(AttributeMap attributes) {
    if (isAttrDefined("output_licenses", BuildType.LICENSE)
        && attributes.isAttributeValueExplicitlySpecified("output_licenses")) {
      return attributes.get("output_licenses", BuildType.LICENSE);
    } else {
      return null;
    }
  }

  /** Returns the Set of all tags exhibited by this target. May be empty. */
  @Override
  public Set<String> getRuleTags() {
    Set<String> ruleTags = new LinkedHashSet<>();
    for (Attribute attribute : ruleClass.getAttributes()) {
      if (attribute.isTaggable()) {
        Type<?> attrType = attribute.getType();
        String name = attribute.getName();
        // This enforces the expectation that taggable attributes are non-configurable.
        Object value = NonconfigurableAttributeMapper.of(this).get(name, attrType);
        Set<String> tags = attrType.toTagSet(value, name);
        ruleTags.addAll(tags);
      }
    }
    return ruleTags;
  }

  /**
   * Computes labels of additional dependencies that can be provided by aspects that this rule can
   * require from its direct dependencies.
   */
  public Collection<Label> getAspectLabelsSuperset(DependencyFilter predicate) {
    if (!hasAspects()) {
      return ImmutableList.of();
    }
    SetMultimap<Attribute, Label> labels = LinkedHashMultimap.create();
    for (Attribute attribute : this.getAttributes()) {
      for (Aspect candidateClass : attribute.getAspects(this)) {
        AspectDefinition.addAllAttributesOfAspect(Rule.this, labels, candidateClass, predicate);
      }
    }
    return labels.values();
  }

  /**
   * Should this rule instance resolve toolchains?
   *
   * <p>This may happen for two reasons:
   *
   * <ol>
   *   <li>The rule uses toolchains by definition ({@link
   *       RuleClass.Builder#useToolchainResolution(ToolchainResolutionMode)}
   *   <li>The rule instance has a select(), which means it may depend on target platform properties
   *       that are only provided when toolchain resolution is enabled.
   * </ol>
   */
  public boolean useToolchainResolution() {
    ToolchainResolutionMode mode = ruleClass.useToolchainResolution();
    if (mode.isActive()) {
      return true;
    } else if (mode == ToolchainResolutionMode.HAS_SELECT) {
      RawAttributeMapper attr = RawAttributeMapper.of(this);
      return (attr.has(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE)
          && !attr.get(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE, BuildType.LABEL_LIST).isEmpty());
    } else {
      return false;
    }
  }

  public RepositoryName getRepository() {
    return label.getPackageIdentifier().getRepository();
  }

  /** Returns the suffix of target kind for all rules. */
  public static String targetKindSuffix() {
    return " rule";
  }
}
