// Copyright 2019 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.
//
// Protos for Stardoc data.
//
// Stardoc collects information about Starlark functions, providers, and rules.
syntax = "proto3";

package stardoc_output;

// option java_api_version = 2;
option java_package = "com.google.devtools.build.lib.starlarkdocextract";
option java_outer_classname = "StardocOutputProtos";

// The root output proto of Stardoc. An invocation of Stardoc on a single file
// will output exactly one instance of this proto, representing all
// documentation for the input Starlark file.
message ModuleInfo {
  repeated RuleInfo rule_info = 1;

  repeated ProviderInfo provider_info = 2;

  repeated StarlarkFunctionInfo func_info = 3;

  repeated AspectInfo aspect_info = 4;

  // The docstring present at the top of the input Starlark file.
  string module_docstring = 5;

  // The display form of the label of the module file (as seen from the
  // starlark_doc_extract or Stardoc target's repo). Unset when there is no
  // module file (e.g. when the module is a REPL, or in Bazel's internal tests).
  string file = 6;

  repeated ModuleExtensionInfo module_extension_info = 7;

  repeated RepositoryRuleInfo repository_rule_info = 8;

  repeated MacroInfo macro_info = 9;
}

// Representation of a Starlark rule attribute type. These generally
// have a one-to-one correspondence with functions defined at
// https://bazel.build/rules/lib/attr.
enum AttributeType {
  UNKNOWN = 0;
  // A special case of STRING; all rules have exactly one implicit
  // attribute "name" of type NAME.
  NAME = 1;
  INT = 2;
  LABEL = 3;
  STRING = 4;
  STRING_LIST = 5;
  INT_LIST = 6;
  LABEL_LIST = 7;
  BOOLEAN = 8;
  LABEL_STRING_DICT = 9;
  STRING_DICT = 10;
  STRING_LIST_DICT = 11;
  OUTPUT = 12;
  OUTPUT_LIST = 13;
  LABEL_DICT_UNARY = 14;
}

// Representation of a Starlark rule definition.
message RuleInfo {
  // In Stardoc and starlark_doc_extract output, this is the name under which
  // the rule is made accessible to a user of this module, including any structs
  // it is nested in, for example "foo.foo_library".
  //
  // In query output, this is the name under which the rule was defined (which
  // might be a private symbol prefixed with "_").
  string rule_name = 1;

  // The documentation string of the rule.
  string doc_string = 2;

  // The attributes of the rule.
  repeated AttributeInfo attribute = 3;

  // Note: legacy Stardoc (0.5.x and earlier) does not set any fields below.

  // The module where and the name under which the rule was originally declared.
  OriginKey origin_key = 4;

  // The list of providers that the rule's implementation must return. Unset if
  // the rule lists no advertised providers.
  ProviderNameGroup advertised_providers = 5;

  // True if this is a test rule.
  bool test = 6;

  // True if this is an executable rule.
  //
  // Note: if test is true, executable is also true (test rules are implicitly
  // executable).
  bool executable = 7;
}

// Representation of a Starlark symbolic macro definition.
// Note: symbolic macros (and thus, their documentation format) are an
// experimental feature gated by the --experimental_enable_first_class_macros
// flag.
message MacroInfo {
  // The name under which the macro is made accessible to a user of this module,
  // including any structs it is nested in, for example "foo.foo_library".
  string macro_name = 1;

  // The documentation string of the macro.
  string doc_string = 2;

  // The attributes of the macro.
  repeated AttributeInfo attribute = 3;

  // The module where and the name under which the macro was originally
  // declared.
  OriginKey origin_key = 4;

  // True if this macro is a rule finalizer.
  bool finalizer = 5;
}

// Representation of a Starlark rule, repository rule, or module extension tag
// attribute definition, comprised of an attribute name, and a schema defined by
// a call to one of the 'attr' module methods enumerated at
// https://bazel.build/rules/lib/attr
message AttributeInfo {
  // The name of the attribute.
  string name = 1;

  // The documentation string of the attribute, supplied via the 'doc'
  // parameter to the schema-creation call.
  string doc_string = 2;

  // The type of the attribute, defined generally by which function is invoked
  // in the attr module.
  AttributeType type = 3;

  // If true, all targets of the rule must specify a value for this attribute.
  bool mandatory = 4;

  // The target(s) in this attribute must define all the providers of at least
  // one of the ProviderNameGroups in this list. If the Attribute Type is not a
  // label, a label list, or a label-keyed string dictionary, the field will be
  // left empty. For attributes of a repository rule or a module extension tag,
  // this attribute is meaningless and may be ignored.
  // TODO(b/290788853): ensure this field is always empty for attributes of a
  // repository rule or a module extension tag.
  repeated ProviderNameGroup provider_name_group = 5;

  // The string representation of the default value of this attribute.
  string default_value = 6;

  // If true, the attribute is non-configurable.
  bool nonconfigurable = 7;

  // If true, the attribute is defined in Bazel's native code, not in Starlark.
  bool natively_defined = 8;
}

// Representation of a set of providers.
message ProviderNameGroup {
  // The names of the providers.
  //
  // This field is only intended for rendering human-readable output.
  // Please use origin_key (a list of the same length and in the same order as
  // this field) for cross-references and tooling.
  //
  // Note: legacy Stardoc (0.5.x and earlier) is unable to extract the name in
  // some circumstances (for example, if the provider is nested in a struct),
  // and in that case, the provider name will be "Unknown Provider".
  repeated string provider_name = 1;

  // A list of unambiguous references to providers, of the same length and in
  // the same order as the provider_name list.
  //
  // For provider symbols, this means modules where and the names under which
  // the providers were originally declared.
  //
  // For legacy struct providers, origin_key.file is unset.
  //
  // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
  repeated OriginKey origin_key = 2;
}

// Representation of Starlark function definition.
message StarlarkFunctionInfo {
  // The name under which the function is made accessible to a user of this
  // module, including any structs it is nested in, for example
  // "foo.frobnicate".
  string function_name = 1;

  // The parameters for the function, in the following order:
  // - positional parameters
  // - keyword-only parameters
  // - residual varargs parameter (`*args`)
  // - residual keyword arguments parameter (`**kwargs`)
  // This order differs from the order in which parameters are listed in the
  // function's declaration (where positional parameters and keyword-only
  // parameters are separated either by `*` or `*args`). The declaration order
  // can be recovered by looking for the transition from ordinary/positional to
  // keyword-only.
  repeated FunctionParamInfo parameter = 2;

  // The documented description of the function (if specified in the function's
  // docstring).
  string doc_string = 3;

  // The return value for the function.
  FunctionReturnInfo return = 4;

  // The deprecation for the function.
  FunctionDeprecationInfo deprecated = 5;

  // The module where and the name under which the function was originally
  // declared.
  //
  // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
  OriginKey origin_key = 6;
}

// Representation of the syntactic role of a given function parameter.
enum FunctionParamRole {
  PARAM_ROLE_UNSPECIFIED = 0;
  // An ordinary parameter which may be used as a positional or by keyword.
  PARAM_ROLE_ORDINARY = 1;
  // A positional-only parameter; such parameters cannot be defined in pure
  // Starlark code, but exist in some natively-defined functions.
  PARAM_ROLE_POSITIONAL_ONLY = 2;
  // A keyword-only parameter, i.e. a non-vararg/kwarg parameter that follows
  // `*` or `*args` in the function's declaration.
  PARAM_ROLE_KEYWORD_ONLY = 3;
  // Residual varargs, typically `*args` in the function's declaration.
  PARAM_ROLE_VARARGS = 4;
  // Residual keyword arguments, typically `**kwargs` in the function's
  // declaration.
  PARAM_ROLE_KWARGS = 5;
}

// Representation of a Starlark function parameter definition.
message FunctionParamInfo {
  // The name of the parameter. This does *not* include the `*` or `**` prefix
  // for varargs or residual keyword argument parameters.
  string name = 1;

  // The documented description of the parameter (if specified in the function's
  // docstring).
  string doc_string = 2;

  // If not an empty string, the default value of the parameter displayed
  // as a string.
  string default_value = 3;

  // If true, the default value is unset and a value is needed for this
  // parameter. This might be false even if defaultValue is empty in the case of
  // special parameter such as *args and **kwargs"
  bool mandatory = 4;

  // The parameter's syntactic role.
  FunctionParamRole role = 5;
}

message FunctionReturnInfo {
  // The documented return value of the function (if specified in the function's
  // docstring).
  string doc_string = 1;
}

message FunctionDeprecationInfo {
  // The documented deprecation of the function (if specified in the function's
  // docstring).
  string doc_string = 1;
}

// Representation of a Starlark provider field definition, comprised of
// the field name and provider description.
message ProviderFieldInfo {
  // The name of the field.
  string name = 1;

  // The description of the provider.
  string doc_string = 2;
}

// Representation of a Starlark provider definition.
message ProviderInfo {
  // The name under which the provider is made accessible to a user of this
  // module, including any structs it is nested in, for example "foo.FooInfo".
  string provider_name = 1;

  // The description of the provider.
  string doc_string = 2;

  // The fields of the provider.
  repeated ProviderFieldInfo field_info = 3;

  // Note: legacy Stardoc (0.5.x and earlier) does not set any fields below.

  // The module where and the name under which the provider was originally
  // declared.
  OriginKey origin_key = 4;

  // The provider's init callback.
  StarlarkFunctionInfo init = 5;
}

// Representation of a Starlark aspect definition.
message AspectInfo {
  // The name under which the aspect is made accessible to a user of this
  // module, including any structs it is nested in, for example
  // "foo.foo_aspect".
  string aspect_name = 1;

  // The documentation string of the aspect.
  string doc_string = 2;

  // The rule attributes along which the aspect propagates.
  repeated string aspect_attribute = 3;

  // The attributes of the aspect.
  repeated AttributeInfo attribute = 4;

  // The module where and the name under which the aspect was originally
  // declared.
  //
  // Note: legacy Stardoc (0.5.x and earlier) does not set this field.
  OriginKey origin_key = 5;
}

// Representation of a Bazel module extension, i.e. the object returned by
// calling `module_extension(...)`.
//
// Note: legacy Stardoc (0.5.x and earlier) does not emit this message.
message ModuleExtensionInfo {
  // The name under which the extension is made accessible to a user of this
  // Starlark module.
  string extension_name = 1;

  // The documentation string of the extension.
  string doc_string = 2;

  // The tag classes of the extension.
  repeated ModuleExtensionTagClassInfo tag_class = 3;

  // The Starlark module where the Bazel module extension was originally
  // declared; origin_key.name is currently never set.
  // TODO(arostovtsev): attempt to retrieve the name under which the module
  // extension was originally declared if it was declared as a global.
  OriginKey origin_key = 4;
}

// Representation of a Bazel module extension tag class.
message ModuleExtensionTagClassInfo {
  // The name of the tag for this tag class.
  string tag_name = 1;

  // The documentation string of the tag class.
  string doc_string = 2;

  // The tag class's attributes.
  repeated AttributeInfo attribute = 3;
}

// Representation of a Bazel repository rule, i.e. the object returned by
// calling `repository_rule(...)`.
//
// Note: legacy Stardoc (0.5.x and earlier) does not emit this message, instead
// using RuleInfo.
message RepositoryRuleInfo {
  // The name under which the repository rule is made accessible to a user of
  // this Starlark module.
  string rule_name = 1;

  // The documentation string of the repository rule.
  string doc_string = 2;

  // The attributes of the repository rule.
  repeated AttributeInfo attribute = 3;

  // Environment variables that this repository rule depends on.
  repeated string environ = 4;

  // The Starlark module where and the name under which the repository rule was
  // originally declared.
  OriginKey origin_key = 5;
}

// Representation of the origin of a rule, provider, aspect, or function.
// Intended to be used for building unambiguous cross-references: for example,
// between an element of a ProviderNameGroup required by a rule attribute and
// its corresponding ProviderInfo.
message OriginKey {
  // The name under which the entity was originally exported. Unset when the
  // entity was not exported in its module.
  string name = 1;

  // The display form of the label of the module file in which the entity was
  // originally declared (as seen from the starlark_doc_extract or Stardoc
  // target's repo), or "<native>" for Bazel's built-in entities implemented in
  // Java. Unset when there is no module file (such as for legacy struct
  // providers, when the module is a REPL, or in Bazel's internal tests).
  string file = 2;
}
