// 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 static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.base.Preconditions.checkState;

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.Iterables;
import com.google.common.collect.Iterators;
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.Arrays;
import java.util.BitSet;
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.eval.StarlarkThread;
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 static final String GENERATOR_NAME = "generator_name";

  private static final int ATTR_SIZE_THRESHOLD = 126;

  private static final OutputFile[] NO_OUTPUTS = new OutputFile[0];

  private final Package pkg;
  private final Label label;
  private final RuleClass ruleClass;
  private final Location location;
  @Nullable private final CallStack.Node interiorCallStack;

  /**
   * The length of this rule's generator name if it is a prefix of its name, otherwise zero.
   *
   * <p>The generator name of a rule is the {@code name} parameter passed to a macro that
   * instantiates the rule. Most rules instantiated via macro follow this pattern:
   *
   * <pre>{@code
   * def some_macro(name):
   *   some_rule(name = name + '_some_suffix')
   * }</pre>
   *
   * thus resulting in a generator name which is a prefix of the rule name. In such a case, we save
   * memory by storing the length of the generator name instead of the string. Note that this saves
   * memory from both the storage in {@link #attrValues} and the string itself (if it is not
   * otherwise retained). This optimization works because this field does not push the shallow heap
   * cost of {@link Rule} beyond an 8-byte threshold. If it did, this optimization would be a net
   * loss.
   */
  private int generatorNamePrefixLength = 0;

  /**
   * Stores attribute values, taking on one of two shapes:
   *
   * <ol>
   *   <li>While the rule is mutable, the array length is equal to the number of attributes. Each
   *       array slot holds the attribute value for the corresponding index or null if not set.
   *   <li>After {@link #freeze}, the array is compacted to store only necessary values. Nulls and
   *       values that match {@link Attribute#getDefaultValue} are omitted to save space. Ordering
   *       of attributes by their index is preserved.
   * </ol>
   */
  private Object[] attrValues;

  /**
   * Holds bits of metadata about attributes, taking on one of three shapes:
   *
   * <ol>
   *   <li>While the rule is mutable, contains one bit for each attribute indicating whether it was
   *       explicitly set.
   *   <li>After {@link #freeze} for rules with fewer than 126 attributes (extremely common case),
   *       contains one byte dedicated to each value in the compact representation of {@link
   *       #attrValues}, at corresponding array indices. The first bit indicates whether the
   *       attribute was explicitly set. The remaining 7 bits represent the attribute's index (as
   *       per {@link RuleClass#getAttributeIndex}). See {@link #freezeSmall}.
   *   <li>After {@link #freeze} for rules with 126 or more attributes (rare case), contains the
   *       full set of bytes from the mutable representation, followed by the index of each
   *       attribute stored in the compact representation of {@link #attrValues}. Because attribute
   *       indices may require a full byte, there is no room to pack the explicit bit as we do for
   *       the small case. See {@link #freezeLarge}.
   * </ol>
   */
  private byte[] attrBytes;

  /**
   * Output files generated by this rule.
   *
   * <p>To save memory, this field is either {@link #NO_OUTPUTS} for zero outputs, an {@link
   * OutputFile} for a single output, or an {@code OutputFile[]} for multiple outputs.
   *
   * <p>In the case of multiple outputs, all implicit outputs come before any explicit outputs in
   * the array.
   *
   * <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.
   */
  // Initialized by populateOutputFilesInternal().
  private Object outputFiles;

  Rule(
      Package pkg,
      Label label,
      RuleClass ruleClass,
      Location location,
      @Nullable CallStack.Node interiorCallStack) {
    this.pkg = checkNotNull(pkg);
    this.label = checkNotNull(label);
    this.ruleClass = checkNotNull(ruleClass);
    this.location = checkNotNull(location);
    this.interiorCallStack = interiorCallStack;
    this.attrValues = new Object[ruleClass.getAttributeCount()];
    this.attrBytes = new byte[bitSetSize()];
  }

  void setContainsErrors() {
    pkg.setContainsErrors();
  }

  @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 if this rule is in error.
   *
   * <p>Examples of rule errors include attributes with missing values or values of the wrong type.
   *
   * <p>Any error in a package means that all rules in the package are considered to be in error
   * (even if they were evaluated prior to the error). This policy is arguably stricter than need
   * be, but stopping a build only for some errors but not others creates user confusion.
   */
  public boolean containsErrors() {
    return pkg.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() {
    return ImmutableList.copyOf(outputFilesArray());
  }

  /**
   * Constructs and returns an immutable list of all the implicit output files of this rule, in the
   * order they were declared.
   */
  ImmutableList<OutputFile> getImplicitOutputFiles() {
    ImmutableList.Builder<OutputFile> result = ImmutableList.builder();
    for (OutputFile output : outputFilesArray()) {
      if (!output.isImplicit()) {
        break;
      }
      result.add(output);
    }
    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();
    for (OutputFile output : outputFilesArray()) {
      if (!output.isImplicit()) {
        result.put(output.getOutputKey(), output);
      }
    }
    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 (!(ruleClass.getDefaultImplicitOutputsFunction()
        instanceof StarlarkImplicitOutputsFunction)) {
      return ImmutableMap.of();
    }
    ImmutableMap.Builder<String, OutputFile> result = ImmutableMap.builder();
    for (OutputFile output : outputFilesArray()) {
      if (!output.isImplicit()) {
        break;
      }
      result.put(output.getOutputKey(), output);
    }
    return result.buildOrThrow();
  }

  private OutputFile[] outputFilesArray() {
    return outputFiles instanceof OutputFile
        ? new OutputFile[] {(OutputFile) outputFiles}
        : (OutputFile[]) outputFiles;
  }

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

  /**
   * Returns the stack of function calls active when this rule was instantiated.
   *
   * <p>Requires reconstructing the call stack from a compact representation, so should only be
   * called when the full call stack is needed.
   */
  public ImmutableList<StarlarkThread.CallStackEntry> reconstructCallStack() {
    ImmutableList.Builder<StarlarkThread.CallStackEntry> stack = ImmutableList.builder();
    stack.add(StarlarkThread.callStackEntry(StarlarkThread.TOP_LEVEL, location));
    for (CallStack.Node node = interiorCallStack; node != null; node = node.next()) {
      stack.add(node.toCallStackEntry());
    }
    return stack.build();
  }

  @Nullable
  CallStack.Node getInteriorCallStack() {
    return interiorCallStack;
  }

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

  /*
   *******************************************************************
   * 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();
    // 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);
  }

  @Nullable
  private String getRelativeLocation() {
    // 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);
  }

  /** Copies attribute values from the given rule to this rule. */
  void copyAttributesFrom(Rule rule) {
    checkArgument(
        ruleClass.equals(rule.ruleClass),
        "Rule class mismatch: (this=%s, given=%s)",
        ruleClass,
        rule.ruleClass);
    checkArgument(rule.isFrozen(), "Not frozen: %s", rule);
    checkState(!isFrozen(), "Already frozen: %s", this);
    this.attrValues = rule.attrValues;
    this.attrBytes = rule.attrBytes;
  }

  void setAttributeValue(Attribute attribute, Object value, boolean explicit) {
    checkState(!isFrozen(), "Already frozen: %s", this);
    String attrName = attribute.getName();
    if (attrName.equals(NAME)) {
      // Avoid unnecessarily storing the name in attrValues - it's stored in the label.
      return;
    }
    if (attrName.equals(GENERATOR_NAME)) {
      String generatorName = (String) value;
      if (getName().startsWith(generatorName)) {
        generatorNamePrefixLength = generatorName.length();
        return;
      }
    }
    Integer attrIndex = ruleClass.getAttributeIndex(attrName);
    checkArgument(attrIndex != null, "Attribute %s is not valid for this rule", attrName);
    if (explicit) {
      checkState(!getExplicitBit(attrIndex), "Attribute %s already explicitly set", attrName);
      setExplicitBit(attrIndex);
    }
    attrValues[attrIndex] = value;
  }

  /**
   * 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);
  }

  /**
   * 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 = getAttrIfStored(attrIndex);
    if (value != null) {
      return value;
    }
    Attribute attr = ruleClass.getAttribute(attrIndex);
    if (attr.hasComputedDefault()) {
      // Frozen rules don't store computed defaults, so get it from the attribute. Mutable rules do
      // store computed defaults if they've been populated. If no value is stored for a mutable
      // rule, 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 isFrozen() ? attr.getDefaultValue() : null;
    }
    if (attr.isLateBound()) {
      // Frozen rules don't store late bound defaults.
      checkState(isFrozen(), "Mutable rule missing LateBoundDefault");
      return attr.getLateBoundDefault();
    }
    switch (attr.getName()) {
      case GENERATOR_FUNCTION:
        return interiorCallStack != null ? interiorCallStack.functionName() : "";
      case GENERATOR_LOCATION:
        return interiorCallStack != null ? getRelativeLocation() : "";
      case GENERATOR_NAME:
        return generatorNamePrefixLength > 0
            ? getName().substring(0, generatorNamePrefixLength)
            : "";
      default:
        return attr.getDefaultValue();
    }
  }

  /**
   * Returns the attribute value at the specified index if stored in this rule, otherwise {@code
   * null}.
   *
   * <p>Unlike {@link #getAttr}, does not fall back to the default value.
   */
  @Nullable
  Object getAttrIfStored(int attrIndex) {
    checkPositionIndex(attrIndex, attrCount() - 1);
    switch (getAttrState()) {
      case MUTABLE:
        return attrValues[attrIndex];
      case FROZEN_SMALL:
        int index = binarySearchAttrBytes(0, attrIndex, 0x7f);
        return index < 0 ? null : attrValues[index];
      case FROZEN_LARGE:
        if (attrBytes.length == 0) {
          return null;
        }
        int bitSetSize = bitSetSize();
        index = binarySearchAttrBytes(bitSetSize, attrIndex, 0xff);
        return index < 0 ? null : attrValues[index - bitSetSize];
    }
    throw new AssertionError();
  }

  /**
   * Returns raw attribute values stored by this rule.
   *
   * <p>The indices of attribute values in the returned list are not guaranteed to be consistent
   * with the other methods of this class. If this is important, which is generally the case, avoid
   * this method.
   *
   * <p>The returned iterable may contain null values. Its {@link Iterable#iterator} is
   * unmodifiable.
   */
  Iterable<Object> getRawAttrValues() {
    return () -> Iterators.forArray(attrValues);
  }

  /** 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)
        || attrName.equals(GENERATOR_NAME)) {
      return wasCreatedByMacro();
    }
    Integer attrIndex = ruleClass.getAttributeIndex(attrName);
    if (attrIndex == null) {
      return false;
    }
    switch (getAttrState()) {
      case MUTABLE:
      case FROZEN_LARGE:
        return getExplicitBit(attrIndex);
      case FROZEN_SMALL:
        int index = binarySearchAttrBytes(0, attrIndex, 0x7f);
        return index >= 0 && (attrBytes[index] & 0x80) != 0;
    }
    throw new AssertionError();
  }

  /** Returns index into {@link #attrBytes} for {@code attrIndex}, or -1 if not found */
  private int binarySearchAttrBytes(int start, int attrIndex, int mask) {
    // Binary search, treating values as unsigned bytes.
    int lo = start;
    int hi = attrBytes.length - 1;
    while (hi >= lo) {
      int mid = (lo + hi) / 2;
      int midAttrIndex = attrBytes[mid] & mask;
      if (midAttrIndex == attrIndex) {
        return mid;
      } else if (midAttrIndex < attrIndex) {
        lo = mid + 1;
      } else {
        hi = mid - 1;
      }
    }
    return -1;
  }

  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 {@code true} if this rule's attributes are immutable.
   *
   * <p>Frozen rules optimize for space by omitting storage for non-explicit attribute values that
   * match the {@link Attribute} default. If {@link #getAttrIfStored} returns {@code null}, the
   * value should be taken from either {@link Attribute#getLateBoundDefault} for late-bound defaults
   * or {@link Attribute#getDefaultValue} for all other attributes (including computed defaults).
   *
   * <p>Mutable rules have no such optimization. During rule creation, this allows for
   * distinguishing whether a computed default (which may depend on other unset attributes) is
   * available.
   */
  boolean isFrozen() {
    return getAttrState() != AttrState.MUTABLE;
  }

  /** Makes this rule's attributes immutable and compacts their representation. */
  void freeze() {
    if (isFrozen()) {
      return;
    }

    BitSet indicesToStore = new BitSet();
    for (int i = 0; i < attrValues.length; i++) {
      Object value = attrValues[i];
      if (value == null) {
        continue;
      }
      if (!getExplicitBit(i)) {
        Attribute attr = ruleClass.getAttribute(i);
        if (value.equals(attr.getDefaultValueUnchecked())) {
          // Non-explicit value matches the attribute's default. Save space by omitting storage.
          continue;
        }
      }
      indicesToStore.set(i);
    }

    if (attrCount() < ATTR_SIZE_THRESHOLD) {
      freezeSmall(indicesToStore);
    } else {
      freezeLarge(indicesToStore);
    }
    // Sanity check to ensure mutable vs frozen is distinguishable.
    checkState(isFrozen(), "Freeze unsuccessful");
  }

  private void freezeSmall(BitSet indicesToStore) {
    int numToStore = indicesToStore.cardinality();
    Object[] compactValues = new Object[numToStore];
    byte[] compactBytes = new byte[numToStore];

    int attrIndex = 0;
    for (int i = 0; i < numToStore; i++) {
      attrIndex = indicesToStore.nextSetBit(attrIndex);
      byte byteValue = (byte) (0x7f & attrIndex);
      if (getExplicitBit(attrIndex)) {
        byteValue = (byte) (byteValue | 0x80);
      }
      compactBytes[i] = byteValue;
      compactValues[i] = attrValues[attrIndex];
      attrIndex++;
    }

    this.attrValues = compactValues;
    this.attrBytes = compactBytes;
  }

  private void freezeLarge(BitSet indicesToStore) {
    int numToStore = indicesToStore.cardinality();
    int bitSetSize = attrBytes.length;
    Object[] compactValues = new Object[numToStore];
    byte[] compactBytes = Arrays.copyOf(attrBytes, bitSetSize + numToStore);

    int attrIndex = 0;
    for (int i = 0; i < numToStore; i++) {
      attrIndex = indicesToStore.nextSetBit(attrIndex);
      compactBytes[i + bitSetSize] = (byte) attrIndex;
      compactValues[i] = attrValues[attrIndex];
      attrIndex++;
    }

    this.attrValues = compactValues;
    this.attrBytes = compactBytes;
  }

  private int attrCount() {
    return ruleClass.getAttributeCount();
  }

  private enum AttrState {
    MUTABLE,
    FROZEN_SMALL,
    FROZEN_LARGE
  }

  private AttrState getAttrState() {
    int attrCount = attrCount();
    // This check works because the name attribute is never stored, so the compact representation
    // of attrValues will always have length < attrCount.
    if (attrValues.length == attrCount) {
      return AttrState.MUTABLE;
    }
    return attrCount < ATTR_SIZE_THRESHOLD ? AttrState.FROZEN_SMALL : AttrState.FROZEN_LARGE;
  }

  /** Calculates the number of bytes necessary to have an explicit bit for each attribute. */
  private int bitSetSize() {
    // ceil(attrCount() / 8)
    return (attrCount() + 7) / 8;
  }

  private boolean getExplicitBit(int attrIndex) {
    int byteIndex = attrIndex / 8;
    int bitIndex = attrIndex % 8;
    byte byteValue = attrBytes[byteIndex];
    return (byteValue & (1 << bitIndex)) != 0;
  }

  private void setExplicitBit(int attrIndex) {
    int byteIndex = attrIndex / 8;
    int bitIndex = attrIndex % 8;
    byte byteValue = attrBytes[byteIndex];
    attrBytes[byteIndex] = (byte) (byteValue | (1 << bitIndex));
  }

  /**
   * 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 = getAttrIfStored(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;
  }

  /**
   * Returns whether this rule was created by a macro.
   */
  public boolean wasCreatedByMacro() {
    return interiorCallStack != null || hasStringAttribute(GENERATOR_NAME);
  }

  /** 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;
  }

  /**
   * 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(),
        ruleClass.getDefaultImplicitOutputsFunction(),
        /* checkLabels= */ true);
  }

  void populateOutputFilesUnchecked(
      Package.Builder pkgBuilder, ImplicitOutputsFunction implicitOutputsFunction)
      throws InterruptedException {
    try {
      populateOutputFilesInternal(
          NullEventHandler.INSTANCE,
          pkgBuilder.getPackageIdentifier(),
          implicitOutputsFunction,
          /* 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,
      ImplicitOutputsFunction implicitOutputsFunction,
      boolean checkLabels)
      throws LabelSyntaxException, InterruptedException {
    Preconditions.checkState(outputFiles == null);

    List<OutputFile> outputs = new ArrayList<>();
    // 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);

          outputs.add(OutputFile.createImplicit(label, this, outputKey));
          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);

          outputs.add(OutputFile.createExplicit(outputLabel, this, attrName));
        };

    // 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);
        }
      }
    }

    if (outputs.isEmpty()) {
      outputFiles = NO_OUTPUTS;
    } else if (outputs.size() == 1) {
      outputFiles = outputs.get(0);
    } else {
      outputFiles = outputs.toArray(OutputFile[]::new);
    }
  }

  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));
    setContainsErrors();
  }

  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. For most rules, visibility is computed from
   * these sources in this order of preference:
   *
   * <ol>
   *   <li>'visibility' attribute
   *   <li>Package default visibility ('default_visibility' attribute of package() declaration)
   * </ol>
   */
  @Override
  public RuleVisibility getVisibility() {
    List<Label> rawLabels = getRawVisibilityLabels();
    return rawLabels == null
        ? getDefaultVisibility()
        // The attribute value was already validated when it was set, so call the unchecked method.
        : RuleVisibility.parseUnchecked(rawLabels);
  }

  @Override
  public Iterable<Label> getVisibilityDependencyLabels() {
    List<Label> rawLabels = getRawVisibilityLabels();
    if (rawLabels == null) {
      return getDefaultVisibility().getDependencyLabels();
    }
    RuleVisibility constantVisibility = RuleVisibility.parseIfConstant(rawLabels);
    if (constantVisibility != null) {
      return constantVisibility.getDependencyLabels();
    }
    // Filter out labels like :__pkg__ and :__subpackages__.
    return Iterables.filter(rawLabels, label -> PackageSpecification.fromLabel(label) == null);
  }

  @Override
  public List<Label> getVisibilityDeclaredLabels() {
    List<Label> rawLabels = getRawVisibilityLabels();
    return rawLabels == null ? getDefaultVisibility().getDeclaredLabels() : rawLabels;
  }

  public boolean isVisibilitySpecified() {
    return ruleClass.getName().equals("bind") || isAttributeValueExplicitlySpecified("visibility");
  }

  @Nullable
  @SuppressWarnings("unchecked")
  private List<Label> getRawVisibilityLabels() {
    Integer visibilityIndex = ruleClass.getAttributeIndex("visibility");
    if (visibilityIndex == null) {
      return null;
    }
    return (List<Label>) getAttrIfStored(visibilityIndex);
  }

  private RuleVisibility getDefaultVisibility() {
    if (ruleClass.getName().equals("bind")) {
      return RuleVisibility.PUBLIC; // bind rules are always public.
    }
    // 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")
        && pkg.getConfigSettingVisibilityPolicy() == ConfigSettingVisibilityPolicy.DEFAULT_PUBLIC) {
      return RuleVisibility.PUBLIC; // Default: //visibility:public.
    }
    return pkg.getDefaultVisibility();
  }

  @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(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() or target_compatible_with attribute, 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.ENABLED_ONLY_FOR_COMMON_LOGIC) {
      RawAttributeMapper attr = RawAttributeMapper.of(this);
      return ((attr.has(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE)
              && !attr.get(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE, BuildType.LABEL_LIST).isEmpty())
          || (attr.has(RuleClass.TARGET_COMPATIBLE_WITH_ATTR)
              && !attr.get(RuleClass.TARGET_COMPATIBLE_WITH_ATTR, 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";
  }
}
