xref: /aosp_15_r20/external/bazelbuild-rules_python/sphinxdocs/docs/sphinx-bzl.md (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1# Bazel plugin for Sphinx
2
3The `sphinx_bzl` Python package is a Sphinx plugin that defines a custom domain
4("bzl") in the Sphinx system. This provides first-class integration with Sphinx
5and allows code comments to provide rich information and allows manually writing
6docs for objects that aren't directly representable in bzl source code. For
7example, the fields of a provider can use `:type:` to indicate the type of a
8field, or manually written docs can use the `{bzl:target}` directive to document
9a well known target.
10
11## Configuring Sphinx
12
13To enable the plugin in Sphinx, depend on
14`@rules_python//sphinxdocs/src/sphinx_bzl` and enable it in `conf.py`:
15
16```
17extensions = [
18    "sphinx_bzl.bzl",
19]
20```
21
22## Brief introduction to Sphinx terminology
23
24To aid understanding how to write docs, lets define a few common terms:
25
26* **Role**: A role is the "bzl:obj" part when writing ``{bzl:obj}`ref` ``.
27  Roles mark inline text as needing special processing. There's generally
28  two types of processing: creating cross references, or role-specific custom
29  rendering. For example `{bzl:obj}` will create a cross references, while
30  `{bzl:default-value}` indicates the default value of an argument.
31* **Directive**: A directive is indicated with `:::` and allows defining an
32  entire object and its parts. For example, to describe a function and its
33  arguments, the `:::{bzl:function}` directive is used.
34* **Directive Option**: A directive option is the "type" part when writing
35  `:type:` within a directive. Directive options are how directives are told
36  the meaning of certain values, such as the type of a provider field. Depending
37  on the object being documented, a directive option may be used instead of
38  special role to indicate semantic values.
39
40Most often, you'll be using roles to refer other objects or indicate special
41values in doc strings. For directives, you're likely to only use them when
42manually writing docs to document flags, targets, or other objects that
43`sphinx_stardoc` generates for you.
44
45## MyST vs RST
46
47By default, Sphinx uses ReStructured Text (RST) syntax for its documents.
48Unfortunately, RST syntax is very different than the popular Markdown syntax. To
49bridge the gap, MyST translates Markdown-style syntax into the RST equivalents.
50This allows easily using Markdown in bzl files.
51
52While MyST isn't required for the core `sphinx_bzl` plugin to work, this
53document uses MyST syntax because `sphinx_stardoc` bzl doc gen rule requires
54MyST.
55
56The main difference in syntax is:
57* MyST directives use `:::{name}` with closing `:::` instead of `.. name::` with
58  indented content.
59* MyST roles use `{role:name}` instead of `:role:name:`
60
61## Type expressions
62
63Several roles or fields accept type expressions. Type expressions use
64Python-style annotation syntax to describe data types. For example `None | list[str]`
65describes a type of "None or a list of strings". Each component of the
66expression is parsed and cross reference to its associated type definition.
67
68## Cross references
69
70In brief, to reference bzl objects, use the `bzl:obj` role and use the
71Bazel label string you would use to refer to the object in Bazel (using `%` to
72denote names within a file). For example, to unambiguously refer to `py_binary`:
73
74```
75{bzl:obj}`@rules_python//python:py_binary.bzl%py_binary`
76```
77
78The above is pretty long, so shorter names are also supported, and `sphinx_bzl`
79will try to find something that matches. Additionally, in `.bzl` code, the
80`bzl:` prefix is set as the default. The above can then be shortened to:
81
82```
83{obj}`py_binary`
84```
85
86The text that is displayed can be customized by putting the reference string in
87chevrons (`<>`):
88
89```
90{obj}`the binary rule <py_binary>`
91```
92
93Specific types of objects (rules, functions, providers, etc) can be
94specified to help disambiguate short names:
95
96```
97{function}`py_binary`  # Refers to the wrapping macro
98{rule}`py_binary`  # Refers to the underlying rule
99```
100
101Finally, objects built into Bazel can be explicitly referenced by forcing
102a lookup outside the local project using `{external}`. For example, the symbol
103`toolchain` is a builtin Bazel function, but it could also be the name of a tag
104class in the local project. To force looking up the builtin Bazel `toolchain` rule,
105`{external:bzl:rule}` can be used, e.g.:
106
107```
108{external:bzl:obj}`toolchain`
109```
110
111Those are the basics of cross referencing. Sphinx has several additional
112syntaxes for finding and referencing objects; see
113[the MyST docs for supported
114syntaxes](https://myst-parser.readthedocs.io/en/latest/syntax/cross-referencing.html#reference-roles)
115
116### Cross reference roles
117
118A cross reference role is the `obj` portion of `{bzl:obj}`. It affects what is
119searched and matched.
120
121:::{note}
122The documentation renders using RST notation (`:foo:role:`), not
123MyST notation (`{foo:role}`.
124:::
125
126:::{rst:role} bzl:arg
127Refer to a function argument.
128:::
129
130:::{rst:role} bzl:attr
131Refer to a rule attribute.
132:::
133
134:::{rst:role} bzl:flag
135Refer to a flag.
136:::
137
138:::{rst:role} bzl:obj
139Refer to any type of Bazel object
140:::
141
142:::{rst:role} bzl:rule
143Refer to a rule.
144:::
145
146:::{rst:role} bzl:target
147Refer to a target.
148:::
149
150:::{rst:role} bzl:type
151Refer to a type or type expression; can also be used in argument documentation.
152
153```
154def func(arg):
155    """Do stuff
156
157    Args:
158      arg: {type}`int | str` the arg
159    """
160    print(arg + 1)
161```
162:::
163
164## Special roles
165
166There are several special roles that can be used to annotate parts of objects,
167such as the type of arguments or their default values.
168
169:::{note}
170The documentation renders using RST notation (`:foo:role:`), not
171MyST notation (`{foo:role}`.
172:::
173
174:::{rst:role} bzl:default-value
175
176Indicate the default value for a function argument or rule attribute. Use it in
177the Args doc of a function or the doc text of an attribute.
178
179```
180def func(arg=1):
181   """Do stuff
182
183   Args:
184     foo: {default-value}`1` the arg
185
186my_rule = rule(attrs = {
187    "foo": attr.string(doc="{default-value}`bar`)
188})
189
190```
191:::
192
193:::{rst:role} bzl:return-type
194
195Indicates the return type for a function. Use it in the Returns doc of a
196function.
197
198```
199def func():
200    """Do stuff
201
202    Returns:
203      {return-type}`int`
204    """
205    return 1
206```
207:::
208
209## Directives
210
211Most directives are automatically generated by `sphinx_stardoc`. Here, we only
212document ones that must be manually written.
213
214To write a directive, a line starts with 3 to 6 colons (`:`), followed by the
215directive name in braces (`{}`), and eventually ended by the same number of
216colons on their own line. For example:
217
218```
219:::{bzl:target} //my:target
220
221Doc about target
222:::
223```
224
225:::{note}
226The documentation renders using RST notation (`.. directive::`), not
227MyST notation.
228:::
229
230:::{rst:directive} .. bzl:currentfile:: file
231
232This directive indicates the Bazel file that objects defined in the current
233documentation file are in. This is required for any page that defines Bazel
234objects. The format of `file` is Bazel label syntax, e.g. `//foo:bar.bzl` for bzl
235files, and `//foo:BUILD.bazel` for things in BUILD files.
236
237:::
238
239
240:::{rst:directive} .. bzl:target:: target
241
242Documents a target. It takes no directive options. The format of `target`
243can either be a fully qualified label (`//foo:bar`), or the base target name
244relative to `{bzl:currentfile}`.
245
246```
247:::{bzl:target} //foo:target
248
249My docs
250:::
251```
252
253:::{rst:directive} .. bzl:flag:: target
254
255Documents a flag. It has the same format as `{bzl:target}`
256:::
257
258