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

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.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.config.HostTransition;
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.events.Location;
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.SkylarkComputedDefaultTemplate;
import com.google.devtools.build.lib.packages.AttributeValueSource;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.SkylarkAspect;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkbuildapi.SkylarkAttrApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.StarlarkContext;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.SkylarkUtils;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.syntax.Type.ConversionException;
import com.google.devtools.build.lib.syntax.Type.LabelClass;
import com.google.devtools.build.lib.syntax.UserDefinedFunction;
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 javax.annotation.Nullable;

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

  // Arguments

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

  private static void setAllowedFileTypes(
      String attr, Object fileTypesObj, FuncallExpression ast, 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 SkylarkFileType) {
      // TODO(laurentlb): deprecated, to be removed
      builder.allowedFileTypes(((SkylarkFileType) fileTypesObj).getFileTypeSet());
    } else if (fileTypesObj instanceof SkylarkList) {
      List<String> arg =
          SkylarkList.castSkylarkListOrNoneToList(
              fileTypesObj, String.class, "allow_files argument");
      builder.allowedFileTypes(FileType.of(arg));
    } else {
      throw new EvalException(
          ast.getLocation(), attr + " should be a boolean or a string list");
    }
  }

  private static ImmutableAttributeFactory createAttributeFactory(
      Type<?> type,
      String doc,
      SkylarkDict<String, Object> arguments,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    // We use an empty name now so that we can set it later.
    // This trick makes sense only in the context of Skylark (builtin rules should not use it).
    return createAttributeFactory(type, doc, arguments, ast, env, context, "");
  }

  private static ImmutableAttributeFactory createAttributeFactory(
      Type<?> type,
      String doc,
      SkylarkDict<String, Object> arguments,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context,
      String name)
      throws EvalException {
    return createAttribute(type, doc, arguments, ast, env, context, name).buildPartial();
  }

  private static Attribute.Builder<?> createAttribute(
      Type<?> type,
      String doc,
      SkylarkDict<String, Object> arguments,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context,
      String name)
      throws EvalException {
    Attribute.Builder<?> builder = Attribute.attr(name, type).setDoc(doc);

    Object defaultValue = arguments.get(DEFAULT_ARG);
    if (!EvalUtils.isNullOrNone(defaultValue)) {
      if (defaultValue instanceof UserDefinedFunction) {
        // Computed attribute. Non label type attributes already caused a type check error.
        SkylarkCallbackFunction callback =
            new SkylarkCallbackFunction(
                (UserDefinedFunction) defaultValue, ast, env.getSemantics(), context);
        // SkylarkComputedDefaultTemplate 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 SkylarkCallbackFunction for the parameter names used
        // in the function definition, which must be the names of attributes used by the callback.
        builder.value(
            new SkylarkComputedDefaultTemplate(
                type, callback.getParameterNames(), callback, ast.getLocation()));
      } else if (defaultValue instanceof SkylarkLateBoundDefault) {
        builder.value((SkylarkLateBoundDefault) defaultValue);
      } else {
        builder.defaultValue(defaultValue, env.getGlobals().getLabel(), DEFAULT_ARG);
      }
    }

    for (String flag : SkylarkList.castSkylarkListOrNoneToList(
        arguments.get(FLAGS_ARG), String.class, FLAGS_ARG)) {
      builder.setPropertyFlag(flag);
    }

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

    if (containsNonNoneKey(arguments, NON_EMPTY_ARG)
        && (Boolean) arguments.get(NON_EMPTY_ARG)) {
      if (env.getSemantics().incompatibleDisableDeprecatedAttrParams()) {
        throw new EvalException(
            ast.getLocation(),
            "'non_empty' is no longer supported. use allow_empty instead. You can use "
                + "--incompatible_disable_deprecated_attr_params=false to temporarily disable this "
                + "check.");
      }

      builder.setPropertyFlag("NON_EMPTY");
    }

    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 new EvalException(
            ast.getLocation(),
            "cfg parameter is mandatory when executable=True is provided. Please see "
            + "https://www.bazel.build/versions/master/docs/skylark/rules.html#configurations "
            + "for more details.");
      }
    }

    if (containsNonNoneKey(arguments, SINGLE_FILE_ARG)
        && (Boolean) arguments.get(SINGLE_FILE_ARG)) {
      if (env.getSemantics().incompatibleDisableDeprecatedAttrParams()) {
        throw new EvalException(
            ast.getLocation(),
            "'single_file' is no longer supported. use allow_single_file instead. You can use "
                + "--incompatible_disable_deprecated_attr_params=false to temporarily disable this "
                + "check.");
      }
      if (containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
        throw new EvalException(
            ast.getLocation(),
            "Cannot specify both single_file (deprecated) and allow_single_file");
      }

      builder.setPropertyFlag("SINGLE_ARTIFACT");
    }

    if (containsNonNoneKey(arguments, ALLOW_FILES_ARG)
        && containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
      throw new EvalException(
          ast.getLocation(), "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, ast, builder);
    } else if (containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
      Object fileTypesObj = arguments.get(ALLOW_SINGLE_FILE_ARG);
      setAllowedFileTypes(ALLOW_SINGLE_FILE_ARG, fileTypesObj, ast, 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 != Runtime.NONE) {
      builder.allowedRuleClasses(
          SkylarkList.castSkylarkListOrNoneToList(
              ruleClassesObj, String.class, "allowed rule classes for attribute definition"));
    }

    List<Object> values = SkylarkList.castSkylarkListOrNoneToList(
        arguments.get(VALUES_ARG), Object.class, VALUES_ARG);
    if (!Iterables.isEmpty(values)) {
      builder.allowedValues(new AllowedValueSet(values));
    }

    if (containsNonNoneKey(arguments, PROVIDERS_ARG)) {
      Object obj = arguments.get(PROVIDERS_ARG);
      SkylarkType.checkType(obj, SkylarkList.class, PROVIDERS_ARG);
      ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> providersList = buildProviderPredicate(
          (SkylarkList<?>) obj, PROVIDERS_ARG, ast.getLocation());

      // 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 =
          trans instanceof SplitTransition
              || trans instanceof TransitionFactory
              || trans instanceof StarlarkDefinedConfigTransition;
      if (isSplit && defaultValue instanceof SkylarkLateBoundDefault) {
        throw new EvalException(
            ast.getLocation(),
            "late-bound attributes must not have a split configuration transition");
      }
      if (trans.equals("host")) {
        builder.cfg(HostTransition.createFactory());
      } else if (trans instanceof SplitTransition) {
        builder.cfg(TransitionFactories.of((SplitTransition) trans));
      } else if (trans instanceof TransitionFactory) {
        builder.cfg((TransitionFactory) trans);
      } else if (trans instanceof StarlarkDefinedConfigTransition) {
        StarlarkDefinedConfigTransition starlarkDefinedTransition =
            (StarlarkDefinedConfigTransition) trans;
        if (starlarkDefinedTransition.isForAnalysisTesting()) {
          builder.hasAnalysisTestTransition();
        } else {
          if (!env.getSemantics().experimentalStarlarkConfigTransitions()) {
            throw new EvalException(
                ast.getLocation(),
                "Starlark-defined transitions on rule attributes is experimental and disabled by "
                    + "default. This API is in development and subject to change at any time. Use "
                    + "--experimental_starlark_config_transitions to use this experimental API.");
          }
          builder.hasStarlarkDefinedTransition();
        }
        builder.cfg(new StarlarkAttributeTransitionProvider(starlarkDefinedTransition));
      } else if (!trans.equals("target")) {
        // TODO(b/121134880): update error message when starlark build configurations is ready.
        throw new EvalException(ast.getLocation(), "cfg must be either 'host' or 'target'.");
      }
    }

    if (containsNonNoneKey(arguments, ASPECTS_ARG)) {
      Object obj = arguments.get(ASPECTS_ARG);
      SkylarkType.checkType(obj, SkylarkList.class, ASPECTS_ARG);

      List<SkylarkAspect> aspects =
          ((SkylarkList<?>) obj).getContents(SkylarkAspect.class, "aspects");
      for (SkylarkAspect aspect : aspects) {
        aspect.attachToAttribute(builder, ast.getLocation());
      }
    }

    return builder;
  }

  /**
   * Builds a list of sets of accepted providers from Skylark 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.
   * @param location location for error messages.
   */
  static ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> buildProviderPredicate(
      SkylarkList<?> obj, String argumentName, Location location) 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(getSkylarkProviderIdentifiers(obj, location));
    } else {
      return getProvidersList(obj, argumentName, location);
    }
  }

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

  /**
   * Converts Skylark identifiers of providers (either a string or a provider value)
   * to their internal representations.
   */
  static ImmutableSet<SkylarkProviderIdentifier> getSkylarkProviderIdentifiers(
      SkylarkList<?> list, Location location) throws EvalException {
    ImmutableList.Builder<SkylarkProviderIdentifier> result = ImmutableList.builder();

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

  private static ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> getProvidersList(
      SkylarkList<?> skylarkList, String argumentName, Location location) throws EvalException {
    ImmutableList.Builder<ImmutableSet<SkylarkProviderIdentifier>> 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 : skylarkList) {
      if (!(o instanceof SkylarkList)) {
        throw new EvalException(location, String.format(errorMsg, PROVIDERS_ARG,
            "an element of type " + EvalUtils.getDataTypeName(o, true)));
      }
      for (Object value : (SkylarkList) o) {
        if (!isProvider(value)) {
          throw new EvalException(location, String.format(errorMsg, argumentName,
              "list with an element of type "
                  + EvalUtils.getDataTypeNameFromClass(value.getClass())));
        }
      }
      providersList.add(getSkylarkProviderIdentifiers((SkylarkList<?>) o, location));
    }
    return providersList.build();
  }

  private static Descriptor createAttrDescriptor(
      String name,
      SkylarkDict<String, Object> kwargs,
      Type<?> type,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    try {
      return new Descriptor(name, createAttributeFactory(type, null, kwargs, ast, env, context));
    } catch (ConversionException e) {
      throw new EvalException(ast.getLocation(), 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")
          .build();

  /**
   * 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,
      SkylarkDict<String, Object> kwargs,
      Type<?> type,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      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 Skylark (builtin rules should not use it).
      return new Descriptor(
          name,
          createAttribute(type, null, kwargs, ast, env, context, "")
              .nonconfigurable(whyNotConfigurableReason)
              .buildPartial());
    } catch (ConversionException e) {
      throw new EvalException(ast.getLocation(), e.getMessage());
    }
  }

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

  @Override
  public Descriptor intAttribute(
      Integer defaultInt,
      String doc,
      Boolean mandatory,
      SkylarkList<?> values,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    // TODO(bazel-team): Replace literal strings with constants.
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.int", ast.getLocation());
    return createAttrDescriptor(
        "int",
        EvalUtils.<String, Object>optionMap(
            env, DEFAULT_ARG, defaultInt, MANDATORY_ARG, mandatory, VALUES_ARG, values),
        Type.INTEGER,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor stringAttribute(
      String defaultString,
      String doc,
      Boolean mandatory,
      SkylarkList<?> values,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string", ast.getLocation());
    return createAttrDescriptor(
        "string",
        EvalUtils.<String, Object>optionMap(
            env, DEFAULT_ARG, defaultString, MANDATORY_ARG, mandatory, VALUES_ARG, values),
        Type.STRING,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor labelAttribute(
      Object defaultO,
      String doc,
      Boolean executable,
      Object allowFiles,
      Object allowSingleFile,
      Boolean mandatory,
      SkylarkList<?> providers,
      Object allowRules,
      Boolean singleFile,
      Object cfg,
      SkylarkList<?> aspects,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.label", ast.getLocation());
    try {
      ImmutableAttributeFactory attribute =
          createAttributeFactory(
              BuildType.LABEL,
              doc,
              EvalUtils.<String, Object>optionMap(
                  env,
                  DEFAULT_ARG,
                  defaultO,
                  EXECUTABLE_ARG,
                  executable,
                  ALLOW_FILES_ARG,
                  allowFiles,
                  ALLOW_SINGLE_FILE_ARG,
                  allowSingleFile,
                  MANDATORY_ARG,
                  mandatory,
                  PROVIDERS_ARG,
                  providers,
                  ALLOW_RULES_ARG,
                  allowRules,
                  SINGLE_FILE_ARG,
                  singleFile,
                  CONFIGURATION_ARG,
                  cfg,
                  ASPECTS_ARG,
                  aspects),
              ast,
              env,
              context,
              "label");
      return new Descriptor("label", attribute);
    } catch (EvalException e) {
      throw new EvalException(ast.getLocation(), e.getMessage(), e);
    }
  }

  @Override
  public Descriptor stringListAttribute(
      Boolean mandatory,
      Boolean nonEmpty,
      Boolean allowEmpty,
      SkylarkList<?> defaultList,
      String doc,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string_list", ast.getLocation());
    return createAttrDescriptor(
        "string_list",
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultList,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty),
        Type.STRING_LIST,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor intListAttribute(
      Boolean mandatory,
      Boolean nonEmpty,
      Boolean allowEmpty,
      SkylarkList<?> defaultList,
      String doc,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.int_list", ast.getLocation());
    return createAttrDescriptor(
        "int_list",
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultList,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty),
        Type.INTEGER_LIST,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor labelListAttribute(
      Boolean allowEmpty,
      Object defaultList,
      String doc,
      Object allowFiles,
      Object allowRules,
      SkylarkList<?> providers,
      SkylarkList<?> flags,
      Boolean mandatory,
      Boolean nonEmpty,
      Object cfg,
      SkylarkList<?> aspects,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.label_list", ast.getLocation());
    SkylarkDict<String, Object> kwargs =
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultList,
            ALLOW_FILES_ARG,
            allowFiles,
            ALLOW_RULES_ARG,
            allowRules,
            PROVIDERS_ARG,
            providers,
            FLAGS_ARG,
            flags,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty,
            CONFIGURATION_ARG,
            cfg,
            ASPECTS_ARG,
            aspects);
    try {
      ImmutableAttributeFactory attribute =
          createAttributeFactory(
              BuildType.LABEL_LIST, doc, kwargs, ast, env, context, "label_list");
      return new Descriptor("label_list", attribute);
    } catch (EvalException e) {
      throw new EvalException(ast.getLocation(), e.getMessage(), e);
    }
  }

  @Override
  public Descriptor labelKeyedStringDictAttribute(
      Boolean allowEmpty,
      Object defaultList,
      String doc,
      Object allowFiles,
      Object allowRules,
      SkylarkList<?> providers,
      SkylarkList<?> flags,
      Boolean mandatory,
      Boolean nonEmpty,
      Object cfg,
      SkylarkList<?> aspects,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(
        env, "attr.label_keyed_string_dict", ast.getLocation());
    SkylarkDict<String, Object> kwargs =
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultList,
            ALLOW_FILES_ARG,
            allowFiles,
            ALLOW_RULES_ARG,
            allowRules,
            PROVIDERS_ARG,
            providers,
            FLAGS_ARG,
            flags,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty,
            CONFIGURATION_ARG,
            cfg,
            ASPECTS_ARG,
            aspects);
    try {
      ImmutableAttributeFactory attribute =
          createAttributeFactory(
              BuildType.LABEL_KEYED_STRING_DICT,
              doc,
              kwargs,
              ast,
              env,
              context,
              "label_keyed_string_dict");
      return new Descriptor("label_keyed_string_dict", attribute);
    } catch (EvalException e) {
      throw new EvalException(ast.getLocation(), e.getMessage(), e);
    }
  }

  @Override
  public Descriptor boolAttribute(
      Boolean defaultO,
      String doc,
      Boolean mandatory,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.bool", ast.getLocation());
    return createAttrDescriptor(
        "bool",
        EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
        Type.BOOLEAN,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor outputAttribute(
      Object defaultO,
      String doc,
      Boolean mandatory,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.output", ast.getLocation());

    return createNonconfigurableAttrDescriptor(
        "output",
        EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
        BuildType.OUTPUT,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor outputListAttribute(
      Boolean allowEmpty,
      Object defaultList,
      String doc,
      Boolean mandatory,
      Boolean nonEmpty,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.output_list", ast.getLocation());

    return createAttrDescriptor(
        "output_list",
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultList,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty),
        BuildType.OUTPUT_LIST,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor stringDictAttribute(
      Boolean allowEmpty,
      SkylarkDict<?, ?> defaultO,
      String doc,
      Boolean mandatory,
      Boolean nonEmpty,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string_dict", ast.getLocation());
    return createAttrDescriptor(
        "string_dict",
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultO,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty),
        Type.STRING_DICT,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor stringListDictAttribute(
      Boolean allowEmpty,
      SkylarkDict<?, ?> defaultO,
      String doc,
      Boolean mandatory,
      Boolean nonEmpty,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.string_list_dict", ast.getLocation());
    return createAttrDescriptor(
        "string_list_dict",
        EvalUtils.<String, Object>optionMap(
            env,
            DEFAULT_ARG,
            defaultO,
            MANDATORY_ARG,
            mandatory,
            NON_EMPTY_ARG,
            nonEmpty,
            ALLOW_EMPTY_ARG,
            allowEmpty),
        Type.STRING_LIST_DICT,
        ast,
        env,
        context);
  }

  @Override
  public Descriptor licenseAttribute(
      Object defaultO,
      String doc,
      Boolean mandatory,
      FuncallExpression ast,
      Environment env,
      StarlarkContext context)
      throws EvalException {
    SkylarkUtils.checkLoadingOrWorkspacePhase(env, "attr.license", ast.getLocation());
    return createNonconfigurableAttrDescriptor(
        "license",
        EvalUtils.<String, Object>optionMap(env, DEFAULT_ARG, defaultO, MANDATORY_ARG, mandatory),
        BuildType.LICENSE,
        ast,
        env,
        context);
  }

  /** A descriptor of an attribute defined in Skylark. */
  @AutoCodec
  public static final class Descriptor implements SkylarkAttrApi.Descriptor {
    private final ImmutableAttributeFactory attributeFactory;
    private final String name;

    @AutoCodec.VisibleForSerialization
    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 Attribute build(String name) {
      return attributeFactory.build(name);
    }

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