sphinxdocs: fix rendering of args in directives with empty doc (#2313)
This fixes a bug where tag-classes/functions that didn't have a doc
string, but did
have arguments/attributes, would render the args/attrs immediately after
the directive
line, which made them get interpreter as direction options (settings
that apply to
the overall directive) instead of doc fields nested within the directive
(separate
block-level elements that get rendered).
To fix, update the code to ensure there's a newline between the
directive line and
subsequent arg/attr lines. Also adds tests for this.
diff --git a/sphinxdocs/private/proto_to_markdown.py b/sphinxdocs/private/proto_to_markdown.py
index 1f0fe31..18fbd12 100644
--- a/sphinxdocs/private/proto_to_markdown.py
+++ b/sphinxdocs/private/proto_to_markdown.py
@@ -182,7 +182,7 @@
for tag in mod_ext.tag_class:
tag_name = f"{mod_ext.extension_name}.{tag.tag_name}"
tag_name = f"{tag.tag_name}"
- self._write(":::::{bzl:tag-class} ", tag_name, "\n\n")
+ self._write(":::::{bzl:tag-class} ")
_sort_attributes_inplace(tag.attribute)
self._render_signature(
@@ -192,7 +192,12 @@
get_default=lambda a: a.default_value,
)
- self._write(tag.doc_string.strip(), "\n\n")
+ if doc_string := tag.doc_string.strip():
+ self._write(doc_string, "\n\n")
+ # Ensure a newline between the directive and the doc fields,
+ # otherwise they get parsed as directive options instead.
+ if not doc_string and tag.attribute:
+ self.write("\n")
self._render_attributes(tag.attribute)
self._write(":::::\n")
self._write("::::::\n")
@@ -292,10 +297,15 @@
parameters = self._render_func_signature(func)
- if doc_string := func.doc_string.strip():
+ doc_string = func.doc_string.strip()
+ if doc_string:
self._write(doc_string, "\n\n")
if parameters:
+ # Ensure a newline between the directive and the doc fields,
+ # otherwise they get parsed as directive options instead.
+ if not doc_string:
+ self._write("\n")
for param in parameters:
self._write(f":arg {param.name}:\n")
if param.default_value:
diff --git a/sphinxdocs/tests/proto_to_markdown/proto_to_markdown_test.py b/sphinxdocs/tests/proto_to_markdown/proto_to_markdown_test.py
index 7835d64..66e3224 100644
--- a/sphinxdocs/tests/proto_to_markdown/proto_to_markdown_test.py
+++ b/sphinxdocs/tests/proto_to_markdown/proto_to_markdown_test.py
@@ -209,6 +209,62 @@
self.assertIn("\n::::::::::::{bzl:typedef} Carl.ns.Alpha\n", actual)
self.assertIn("\n:::::::::::::{bzl:typedef} Zeta\n", actual)
+ def test_render_func_no_doc_with_args(self):
+ proto_text = """
+file: "@repo//pkg:foo.bzl"
+func_info: {
+ function_name: "func"
+ parameter: {
+ name: "param"
+ doc_string: "param_doc"
+ }
+}
+"""
+ actual = self._render(proto_text)
+ expected = """
+:::::::::::::{bzl:function} func(*param)
+
+:arg param:
+ param_doc
+
+:::::::::::::
+"""
+ self.assertIn(expected, actual)
+
+ def test_render_module_extension(self):
+ proto_text = """
+file: "@repo//pkg:foo.bzl"
+module_extension_info: {
+ extension_name: "bzlmod_ext"
+ tag_class: {
+ tag_name: "bzlmod_ext_tag_a"
+ doc_string: "BZLMOD_EXT_TAG_A_DOC_STRING"
+ attribute: {
+ name: "attr1",
+ doc_string: "attr1doc"
+ type: STRING_LIST
+ }
+ }
+}
+"""
+ actual = self._render(proto_text)
+ expected = """
+:::::{bzl:tag-class} bzlmod_ext_tag_a(attr1)
+
+BZLMOD_EXT_TAG_A_DOC_STRING
+
+:attr attr1:
+ {type}`list[str]`
+ attr1doc
+ :::{bzl:attr-info} Info
+ :::
+
+
+:::::
+::::::
+"""
+ self.assertIn(expected, actual)
+
if __name__ == "__main__":
absltest.main()