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

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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition;
import com.google.devtools.build.lib.analysis.config.TransitionFactories;
import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet;
import com.google.devtools.build.lib.packages.Attribute.ImmutableAttributeFactory;
import com.google.devtools.build.lib.packages.Attribute.StarlarkComputedDefaultTemplate;
import com.google.devtools.build.lib.packages.AttributeTransitionData;
import com.google.devtools.build.lib.packages.AttributeValueSource;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.BuiltinRestriction;
import com.google.devtools.build.lib.packages.BzlInitThreadContext;
import com.google.devtools.build.lib.packages.LabelConverter;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.StarlarkAspect;
import com.google.devtools.build.lib.packages.StarlarkCallbackHelper;
import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.ConversionException;
import com.google.devtools.build.lib.packages.Type.LabelClass;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.starlarkbuildapi.NativeComputedDefaultApi;
import com.google.devtools.build.lib.starlarkbuildapi.StarlarkAttrModuleApi;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Printer;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;

/**
 * A helper class to provide Attr module in Starlark.
 *
 * <p>It exposes functions (for example, 'attr.string', 'attr.label_list', etc.) to Starlark users.
 * The functions are executed through reflection. As everywhere in Starlark, arguments are
 * type-checked with the signature and cannot be null.
 */
public final class StarlarkAttrModule implements StarlarkAttrModuleApi {

  // Arguments

  // TODO(adonovan): opt: this class does a lot of redundant hashtable lookups.

  /**
   * Throws {@link EvalException} if we're not in a Starlark evaluation context suitable for
   * creating attribute descriptors.
   *
   * <p>Currently, we restrict attribute descriptor creation to the same environments as the ones in
   * which rule classes may be defined. Namely, these are threads that do 1) .bzl initialization,
   * and 2) BUILD evaluation. The latter is only needed for {@code analysis_test}.
   *
   * <p>In principle, we could probably relax this to be any Starlark environment where the caller's
   * innermost stack frame is a .bzl file. But there seems to be no use case for this.
   */
  private static void checkContext(StarlarkThread thread, String what) throws EvalException {
    if (thread.getThreadLocal(RuleDefinitionEnvironment.class) != null) {
      // BUILD initialization.
      return;
    }
    try {
      BzlInitThreadContext.fromOrFail(thread, /* what= */ "<UNUSED>");
    } catch (EvalException unused) {
      throw Starlark.errorf(
          "%s can only be used during .bzl initialization (top-level evaluation) or package"
              + " evaluation (a BUILD file or macro)",
          what);
    }
  }

  private static boolean containsNonNoneKey(Map<String, Object> arguments, String key) {
    return arguments.containsKey(key) && arguments.get(key) != Starlark.NONE;
  }

  private static void setAllowedFileTypes(
      String attr, Object fileTypesObj, Attribute.Builder<?> builder) throws EvalException {
    if (fileTypesObj == Boolean.TRUE) {
      builder.allowedFileTypes(FileTypeSet.ANY_FILE);
    } else if (fileTypesObj == Boolean.FALSE) {
      builder.allowedFileTypes(FileTypeSet.NO_FILE);
    } else if (fileTypesObj instanceof Sequence) {
      ImmutableList<String> arg =
          ImmutableList.copyOf(Sequence.cast(fileTypesObj, String.class, "allow_files argument"));
      builder.allowedFileTypes(FileType.of(arg));
    } else {
      throw Starlark.errorf("%s should be a boolean or a string list", attr);
    }
  }

  // TODO(brandjon): Our treatment of attribute names is very confusing.
  //
  //   - The `name` in the Descriptor is an attribute type, e.g. "attr.label_list", but the `name`
  //     in an Attribute.Builder or ImmutableAttributeFactory is the actual attribute name, e.g.
  //     "srcs". These should be better distinguished in the variable identifier.
  //
  //   - The practice of using an empty string for the attr name in createAttributeFactory and
  //     createNonconfigurableAttrDescriptor is a code smell and is confusing. (The comment also
  //     gives insufficient context.) It looks like the name is unimportant because we use
  //     Attribute.Builder#buildPartial, which ignores the name. But it's unclear whether the name
  //     is still used in the Builder for error messages in Precondition checks. If it truly is
  //     unused then we should make it @Nullable (and do checkNotNull() in the regular non-partial
  //     #build() method).
  //
  //   - In createAttributeFactory, we're currently inconsistent about whether we pass in an empty
  //     attribute name (as in the wrapping overload) or the descriptor type (e.g. "label_list" in
  //     labelListAttribute()).

  // TODO(b/236456122): Instead of passing a StarlarkThread around, unwrap its LabelConverter and
  // StarlarkSemantics and pass those directly. Validate that we're in the right Starlark evaluation
  // context (BzlInitThreadContext.fromOrFail()) at the time of the unwrapping.
  private static ImmutableAttributeFactory createAttributeFactory(
      Type<?> type, Optional<String> doc, Map<String, Object> arguments, StarlarkThread thread)
      throws EvalException {
    // We use an empty name now so that we can set it later.
    // This trick makes sense only in the context of Starlark (builtin rules should not use it).
    return createAttributeFactory(type, doc, arguments, thread, "");
  }

  // TODO(brandjon): Inline into its sole caller, createAttrDescriptor().
  private static ImmutableAttributeFactory createAttributeFactory(
      Type<?> type,
      Optional<String> doc,
      Map<String, Object> arguments,
      StarlarkThread thread,
      String name)
      throws EvalException {
    return createAttribute(type, doc, arguments, thread, name).buildPartial();
  }

  @SuppressWarnings("unchecked")
  private static Attribute.Builder<?> createAttribute(
      Type<?> type,
      Optional<String> doc,
      Map<String, Object> arguments,
      StarlarkThread thread,
      String name)
      throws EvalException {
    Attribute.Builder<?> builder = Attribute.attr(name, type).starlarkDefined();
    doc.map(Starlark::trimDocString).ifPresent(builder::setDoc);

    Object defaultValue = arguments.get(DEFAULT_ARG);
    if (!Starlark.isNullOrNone(defaultValue)) {
      if (defaultValue instanceof StarlarkFunction) {
        // Computed attribute. Non label type attributes already caused a type check error.
        StarlarkCallbackHelper callback =
            new StarlarkCallbackHelper((StarlarkFunction) defaultValue, thread.getSemantics());
        // StarlarkComputedDefaultTemplate needs to know the names of all attributes that it depends
        // on. However, this method does not know anything about other attributes.
        // We solve this problem by asking the StarlarkCallbackHelper for the parameter names used
        // in the function definition, which must be the names of attributes used by the callback.
        builder.value(
            new StarlarkComputedDefaultTemplate(type, callback.getParameterNames(), callback));
      } else if (defaultValue instanceof StarlarkLateBoundDefault) {
        builder.value((StarlarkLateBoundDefault) defaultValue); // unchecked cast
      } else if (defaultValue instanceof NativeComputedDefaultApi) {
        // TODO(b/200065655#comment3): This hack exists until default_copts and default_hdrs_check
        //  in package() is replaced by proper package defaults. We don't check the particular
        //  instance to avoid adding a dependency to the C++ package.
        builder.value((NativeComputedDefaultApi) defaultValue);
      } else {
        builder.defaultValue(
            defaultValue, LabelConverter.forBzlEvaluatingThread(thread), DEFAULT_ARG);
      }
    }

    Object flagsArg = arguments.get(FLAGS_ARG);
    if (flagsArg != null) {
      for (String flag : Sequence.noneableCast(flagsArg, String.class, FLAGS_ARG)) {
        builder.setPropertyFlag(flag);
      }
    }

    if (containsNonNoneKey(arguments, MANDATORY_ARG) && (Boolean) arguments.get(MANDATORY_ARG)) {
      builder.setPropertyFlag("MANDATORY");
    }

    if (containsNonNoneKey(arguments, ALLOW_EMPTY_ARG)
        && !(Boolean) arguments.get(ALLOW_EMPTY_ARG)) {
      builder.setPropertyFlag("NON_EMPTY");
    }

    if (containsNonNoneKey(arguments, EXECUTABLE_ARG) && (Boolean) arguments.get(EXECUTABLE_ARG)) {
      builder.setPropertyFlag("EXECUTABLE");
      if (!containsNonNoneKey(arguments, CONFIGURATION_ARG)) {
        throw Starlark.errorf(
            "cfg parameter is mandatory when executable=True is provided. Please see "
                + "https://bazel.build/extending/rules#configurations "
                + "for more details.");
      }
    }

    if (containsNonNoneKey(arguments, ALLOW_FILES_ARG)
        && containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
      throw Starlark.errorf("Cannot specify both allow_files and allow_single_file");
    }

    if (containsNonNoneKey(arguments, ALLOW_FILES_ARG)) {
      Object fileTypesObj = arguments.get(ALLOW_FILES_ARG);
      setAllowedFileTypes(ALLOW_FILES_ARG, fileTypesObj, builder);
    } else if (containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
      Object fileTypesObj = arguments.get(ALLOW_SINGLE_FILE_ARG);
      setAllowedFileTypes(ALLOW_SINGLE_FILE_ARG, fileTypesObj, builder);
      builder.setPropertyFlag("SINGLE_ARTIFACT");
    } else if (type.getLabelClass() == LabelClass.DEPENDENCY) {
      builder.allowedFileTypes(FileTypeSet.NO_FILE);
    }

    Object ruleClassesObj = arguments.get(ALLOW_RULES_ARG);
    if (ruleClassesObj != null && ruleClassesObj != Starlark.NONE) {
      builder.allowedRuleClasses(
          Sequence.cast(
              ruleClassesObj, String.class, "allowed rule classes for attribute definition"));
    }

    Object valuesArg = arguments.get(VALUES_ARG);
    if (valuesArg != null) {
      List<Object> values = Sequence.noneableCast(valuesArg, Object.class, VALUES_ARG);
      if (!values.isEmpty()) {
        builder.allowedValues(new AllowedValueSet(values));
      }
    }

    if (containsNonNoneKey(arguments, PROVIDERS_ARG)) {
      Object obj = arguments.get(PROVIDERS_ARG);
      ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> providersList =
          buildProviderPredicate(Sequence.cast(obj, Object.class, PROVIDERS_ARG), PROVIDERS_ARG);

      // If there is at least one empty set, there is no restriction.
      if (providersList.stream().noneMatch(ImmutableSet::isEmpty)) {
        builder.mandatoryProvidersList(providersList);
      }
    }

    if (containsNonNoneKey(arguments, CONFIGURATION_ARG)) {
      Object trans = arguments.get(CONFIGURATION_ARG);
      boolean isSplit = false;
      if (trans instanceof SplitTransition || trans instanceof StarlarkDefinedConfigTransition) {
        isSplit = true;
      } else if (trans instanceof TransitionFactory) {
        TransitionFactory<?> tf = (TransitionFactory<?>) trans;
        if (tf.isSplit()) {
          isSplit = true;
        }
      }
      if (isSplit && defaultValue instanceof StarlarkLateBoundDefault) {
        throw Starlark.errorf(
            "late-bound attributes must not have a split configuration transition");
      }
      // TODO(b/203203933): remove after removing --incompatible_disable_starlark_host_transitions.
      if (trans.equals("host")) {
        boolean disableStarlarkHostTransitions =
            thread
                .getSemantics()
                .getBool(BuildLanguageOptions.INCOMPATIBLE_DISABLE_STARLARK_HOST_TRANSITIONS);
        if (disableStarlarkHostTransitions) {
          throw new EvalException(
              "'cfg = \"host\"' is deprecated and should no longer be used. Please use "
                  + "'cfg = \"exec\"' instead.");
        }
        builder.cfg(ExecutionTransitionFactory.createFactory());
      } else if (trans.equals("exec")) {
        builder.cfg(ExecutionTransitionFactory.createFactory());
      } else if (trans instanceof ExecutionTransitionFactory) {
        builder.cfg((ExecutionTransitionFactory) trans);
      } else if (trans instanceof SplitTransition) {
        builder.cfg(TransitionFactories.of((SplitTransition) trans));
      } else if (trans instanceof TransitionFactory) {
        @SuppressWarnings("unchecked")
        TransitionFactory<AttributeTransitionData> transitionFactory =
            (TransitionFactory<AttributeTransitionData>) trans;
        builder.cfg(transitionFactory);
      } else if (trans instanceof StarlarkDefinedConfigTransition) {
        StarlarkDefinedConfigTransition starlarkDefinedTransition =
            (StarlarkDefinedConfigTransition) trans;
        if (starlarkDefinedTransition.isForAnalysisTesting()) {
          builder.hasAnalysisTestTransition();
        } else {
          builder.hasStarlarkDefinedTransition();
        }
        builder.cfg(new StarlarkAttributeTransitionProvider(starlarkDefinedTransition));
      } else if (!trans.equals("target")) {
        // We don't actively advertise the hard-coded but exposed transitions like
        // android_split_transition because users of those transitions should already know about
        // them.
        throw Starlark.errorf(
            "cfg must be either 'target', 'exec' or a starlark defined transition defined by the "
                + "exec() or transition() functions.");
      }
    }

    if (containsNonNoneKey(arguments, ASPECTS_ARG)) {
      Object obj = arguments.get(ASPECTS_ARG);
      for (StarlarkAspect aspect : Sequence.cast(obj, StarlarkAspect.class, "aspects")) {
        builder.aspect(aspect);
      }
    }

    return builder;
  }

  /**
   * Builds a list of sets of accepted providers from Starlark list {@code obj}. The list can either
   * be a list of providers (in that case the result is a list with one set) or a list of lists of
   * providers (then the result is the list of sets).
   *
   * @param argumentName used in error messages.
   */
  static ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> buildProviderPredicate(
      Sequence<?> obj, String argumentName) throws EvalException {
    if (obj.isEmpty()) {
      return ImmutableList.of();
    }
    boolean isListOfProviders = true;
    for (Object o : obj) {
      if (!isProvider(o)) {
        isListOfProviders = false;
        break;
      }
    }
    if (isListOfProviders) {
      return ImmutableList.of(getStarlarkProviderIdentifiers(obj));
    } else {
      return getProvidersList(obj, argumentName);
    }
  }

  /**
   * Returns true if {@code o} is a Starlark provider (either a declared provider or a legacy
   * provider name.
   */
  static boolean isProvider(Object o) {
    return o instanceof String || o instanceof Provider;
  }

  /**
   * Converts Starlark identifiers of providers (either a string or a provider value) to their
   * internal representations.
   */
  static ImmutableSet<StarlarkProviderIdentifier> getStarlarkProviderIdentifiers(Sequence<?> list)
      throws EvalException {
    ImmutableList.Builder<StarlarkProviderIdentifier> result = ImmutableList.builder();

    for (Object obj : list) {
      if (obj instanceof String) {
        result.add(StarlarkProviderIdentifier.forLegacy((String) obj));
      } else if (obj instanceof Provider) {
        Provider constructor = (Provider) obj;
        if (!constructor.isExported()) {
          throw Starlark.errorf(
              "Providers should be top-level values in extension files that define them.");
        }
        result.add(StarlarkProviderIdentifier.forKey(constructor.getKey()));
      }
    }
    return ImmutableSet.copyOf(result.build());
  }

  private static ImmutableList<ImmutableSet<StarlarkProviderIdentifier>> getProvidersList(
      Sequence<?> starlarkList, String argumentName) throws EvalException {
    ImmutableList.Builder<ImmutableSet<StarlarkProviderIdentifier>> providersList =
        ImmutableList.builder();
    String errorMsg =
        "Illegal argument: element in '%s' is of unexpected type. "
            + "Either all elements should be providers, "
            + "or all elements should be lists of providers, but got %s.";

    for (Object o : starlarkList) {
      if (!(o instanceof Sequence)) {
        throw Starlark.errorf(errorMsg, argumentName, "an element of type " + Starlark.type(o));
      }
      for (Object value : (Sequence) o) {
        if (!isProvider(value)) {
          throw Starlark.errorf(
              errorMsg, argumentName, "list with an element of type " + Starlark.type(value));
        }
      }
      providersList.add(getStarlarkProviderIdentifiers((Sequence<?>) o));
    }
    return providersList.build();
  }

  private static Descriptor createAttrDescriptor(
      String name,
      Optional<String> doc,
      Map<String, Object> kwargs,
      Type<?> type,
      StarlarkThread thread)
      throws EvalException {
    try {
      return new Descriptor(name, createAttributeFactory(type, doc, kwargs, thread));
    } catch (ConversionException e) {
      throw new EvalException(e.getMessage());
    }
  }

  private static final Map<Type<?>, String> whyNotConfigurable =
      ImmutableMap.<Type<?>, String>builder()
          .put(
              BuildType.LICENSE,
              "loading phase license checking logic assumes non-configurable values")
          .put(BuildType.OUTPUT, "output paths are part of the static graph structure")
          .buildOrThrow();

  /**
   * If the given attribute type is non-configurable, returns the reason why. Otherwise, returns
   * {@code null}.
   */
  @Nullable
  public static String maybeGetNonConfigurableReason(Type<?> type) {
    return whyNotConfigurable.get(type);
  }

  private static Descriptor createNonconfigurableAttrDescriptor(
      String name,
      Optional<String> doc,
      Map<String, Object> kwargs,
      Type<?> type,
      StarlarkThread thread)
      throws EvalException {
    String whyNotConfigurableReason =
        Preconditions.checkNotNull(maybeGetNonConfigurableReason(type), type);
    try {
      // We use an empty name now so that we can set it later.
      // This trick makes sense only in the context of Starlark (builtin rules should not use it).
      return new Descriptor(
          name,
          createAttribute(type, doc, kwargs, thread, "")
              .nonconfigurable(whyNotConfigurableReason)
              .buildPartial());
    } catch (ConversionException e) {
      throw new EvalException(e.getMessage());
    }
  }

  @Override
  public void repr(Printer printer) {
    printer.append("<attr>");
  }

  @Override
  public Descriptor intAttribute(
      StarlarkInt defaultValue,
      Object doc,
      Boolean mandatory,
      Sequence<?> values,
      StarlarkThread thread)
      throws EvalException {
    // TODO(bazel-team): Replace literal strings with constants.
    checkContext(thread, "attr.int()");
    return createAttrDescriptor(
        "int",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory, VALUES_ARG, values),
        Type.INTEGER,
        thread);
  }

  @Override
  public Descriptor stringAttribute(
      Object defaultValue, Object doc, Boolean mandatory, Sequence<?> values, StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.string()");
    return createAttrDescriptor(
        "string",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory, VALUES_ARG, values),
        Type.STRING,
        thread);
  }

  @Override
  public Descriptor labelAttribute(
      Object defaultValue, // Label | String | LateBoundDefaultApi | StarlarkFunction
      Object doc,
      Boolean executable,
      Object allowFiles,
      Object allowSingleFile,
      Boolean mandatory,
      Sequence<?> providers,
      Object allowRules,
      Object cfg,
      Sequence<?> aspects,
      Object flagsObject, // Sequence<String> expected
      StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.label()");

    if (flagsObject != Starlark.UNBOUND) {
      BuiltinRestriction.failIfCalledOutsideBuiltins(thread);
    }
    @SuppressWarnings("unchecked")
    Sequence<String> flags =
        flagsObject == Starlark.UNBOUND
            ? StarlarkList.immutableOf()
            : ((Sequence<String>) flagsObject);

    ImmutableAttributeFactory attribute =
        createAttributeFactory(
            BuildType.LABEL,
            Starlark.toJavaOptional(doc, String.class),
            optionMap(
                DEFAULT_ARG,
                defaultValue,
                EXECUTABLE_ARG,
                executable,
                ALLOW_FILES_ARG,
                allowFiles,
                ALLOW_SINGLE_FILE_ARG,
                allowSingleFile,
                MANDATORY_ARG,
                mandatory,
                PROVIDERS_ARG,
                providers,
                ALLOW_RULES_ARG,
                allowRules,
                CONFIGURATION_ARG,
                cfg,
                ASPECTS_ARG,
                aspects,
                FLAGS_ARG,
                flags),
            thread,
            "label");
    return new Descriptor("label", attribute);
  }

  @Override
  public Descriptor stringListAttribute(
      Boolean mandatory, Boolean allowEmpty, Object defaultValue, Object doc, StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.string_list()");
    return createAttrDescriptor(
        "string_list",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory, ALLOW_EMPTY_ARG, allowEmpty),
        Type.STRING_LIST,
        thread);
  }

  @Override
  public Descriptor intListAttribute(
      Boolean mandatory,
      Boolean allowEmpty,
      Sequence<?> defaultValue,
      Object doc,
      StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.int_list()");
    return createAttrDescriptor(
        "int_list",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory, ALLOW_EMPTY_ARG, allowEmpty),
        Type.INTEGER_LIST,
        thread);
  }

  @Override
  public Descriptor labelListAttribute(
      Boolean allowEmpty,
      Object defaultValue, // Sequence | StarlarkFunction
      Object doc,
      Object allowFiles,
      Object allowRules,
      Sequence<?> providers,
      Sequence<?> flags,
      Boolean mandatory,
      Object cfg,
      Sequence<?> aspects,
      StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.label_list()");
    Map<String, Object> kwargs =
        optionMap(
            DEFAULT_ARG,
            defaultValue,
            ALLOW_FILES_ARG,
            allowFiles,
            ALLOW_RULES_ARG,
            allowRules,
            PROVIDERS_ARG,
            providers,
            FLAGS_ARG,
            flags,
            MANDATORY_ARG,
            mandatory,
            ALLOW_EMPTY_ARG,
            allowEmpty,
            CONFIGURATION_ARG,
            cfg,
            ASPECTS_ARG,
            aspects);
    ImmutableAttributeFactory attribute =
        createAttributeFactory(
            BuildType.LABEL_LIST,
            Starlark.toJavaOptional(doc, String.class),
            kwargs,
            thread,
            "label_list");
    return new Descriptor("label_list", attribute);
  }

  @Override
  public Descriptor labelKeyedStringDictAttribute(
      Boolean allowEmpty,
      Object defaultValue, // Dict | StarlarkFunction
      Object doc,
      Object allowFiles,
      Object allowRules,
      Sequence<?> providers,
      Sequence<?> flags,
      Boolean mandatory,
      Object cfg,
      Sequence<?> aspects,
      StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.label_keyed_string_dict()");
    Map<String, Object> kwargs =
        optionMap(
            DEFAULT_ARG,
            defaultValue,
            ALLOW_FILES_ARG,
            allowFiles,
            ALLOW_RULES_ARG,
            allowRules,
            PROVIDERS_ARG,
            providers,
            FLAGS_ARG,
            flags,
            MANDATORY_ARG,
            mandatory,
            ALLOW_EMPTY_ARG,
            allowEmpty,
            CONFIGURATION_ARG,
            cfg,
            ASPECTS_ARG,
            aspects);
    ImmutableAttributeFactory attribute =
        createAttributeFactory(
            BuildType.LABEL_KEYED_STRING_DICT,
            Starlark.toJavaOptional(doc, String.class),
            kwargs,
            thread,
            "label_keyed_string_dict");
    return new Descriptor("label_keyed_string_dict", attribute);
  }

  @Override
  public Descriptor boolAttribute(
      Boolean defaultValue, Object doc, Boolean mandatory, StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.bool()");
    return createAttrDescriptor(
        "bool",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory),
        Type.BOOLEAN,
        thread);
  }

  @Override
  public Descriptor outputAttribute(Object doc, Boolean mandatory, StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.output()");

    return createNonconfigurableAttrDescriptor(
        "output",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(MANDATORY_ARG, mandatory),
        BuildType.OUTPUT,
        thread);
  }

  @Override
  public Descriptor outputListAttribute(
      Boolean allowEmpty, Object doc, Boolean mandatory, StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.output_list()");

    return createAttrDescriptor(
        "output_list",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(MANDATORY_ARG, mandatory, ALLOW_EMPTY_ARG, allowEmpty),
        BuildType.OUTPUT_LIST,
        thread);
  }

  @Override
  public Descriptor stringDictAttribute(
      Boolean allowEmpty,
      Dict<?, ?> defaultValue,
      Object doc,
      Boolean mandatory,
      StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.string_dict()");
    return createAttrDescriptor(
        "string_dict",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory, ALLOW_EMPTY_ARG, allowEmpty),
        Type.STRING_DICT,
        thread);
  }

  @Override
  public Descriptor stringListDictAttribute(
      Boolean allowEmpty,
      Dict<?, ?> defaultValue,
      Object doc,
      Boolean mandatory,
      StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.string_list_dict()");
    return createAttrDescriptor(
        "string_list_dict",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory, ALLOW_EMPTY_ARG, allowEmpty),
        Type.STRING_LIST_DICT,
        thread);
  }

  @Override
  public Descriptor licenseAttribute(
      Object defaultValue, Object doc, Boolean mandatory, StarlarkThread thread)
      throws EvalException {
    checkContext(thread, "attr.license()");
    return createNonconfigurableAttrDescriptor(
        "license",
        Starlark.toJavaOptional(doc, String.class),
        optionMap(DEFAULT_ARG, defaultValue, MANDATORY_ARG, mandatory),
        BuildType.LICENSE,
        thread);
  }

  /** A descriptor of an attribute defined in Starlark. */
  public static final class Descriptor implements StarlarkAttrModuleApi.Descriptor {
    private final ImmutableAttributeFactory attributeFactory;
    private final String name;

    private Descriptor(String name, ImmutableAttributeFactory attributeFactory) {
      this.attributeFactory = Preconditions.checkNotNull(attributeFactory);
      this.name = name;
    }

    public boolean hasDefault() {
      return attributeFactory.isValueSet();
    }

    public AttributeValueSource getValueSource() {
      return attributeFactory.getValueSource();
    }

    public Type<?> getType() {
      return attributeFactory.getType();
    }

    public Attribute build(String name) {
      return attributeFactory.build(name);
    }

    @Override
    public void repr(Printer printer) {
      printer.append("<attr." + name + ">");
    }

    // Value equality semantics - same as for native Attribute.
    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof Descriptor)) {
        return false;
      }
      Descriptor that = (Descriptor) o;
      return Objects.equals(name, that.name)
          && Objects.equals(attributeFactory, that.attributeFactory);
    }

    @Override
    public int hashCode() {
      return Objects.hash(name, attributeFactory);
    }

    TransitionFactory<AttributeTransitionData> getTransitionFactory() {
      return attributeFactory.getTransitionFactory();
    }
  }

  // Returns an immutable map from a list of alternating name/value pairs,
  // skipping values that are null or None. Keys must be unique.
  private static Map<String, Object> optionMap(Object... pairs) {
    Preconditions.checkArgument(pairs.length % 2 == 0);
    ImmutableMap.Builder<String, Object> b = new ImmutableMap.Builder<>();
    for (int i = 0; i < pairs.length; i += 2) {
      String key = (String) Preconditions.checkNotNull(pairs[i]);
      Object value = pairs[i + 1];
      if (value != null && value != Starlark.NONE) {
        b.put(key, value);
      }
    }
    return b.buildOrThrow();
  }
}
