diff mbox series

[38/42] docs/qapi: add branch support to inliner

Message ID 20250205231208.1480762-39-jsnow@redhat.com (mailing list archive)
State New
Headers show
Series docs: add sphinx-domain rST generator to qapidoc | expand

Commit Message

John Snow Feb. 5, 2025, 11:12 p.m. UTC
Well, kind of. Anything beyond simple member definitions aren't
included; including ifcond, details sections, features, etc. Definitely
the most "WIP" part of this entire patch series.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapidoc.py | 57 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 755eb0fa0ec..86c13520d94 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -44,6 +44,7 @@ 
 from qapi.schema import (
     QAPISchema,
     QAPISchemaArrayType,
+    QAPISchemaBranches,
     QAPISchemaCommand,
     QAPISchemaEntity,
     QAPISchemaEnumMember,
@@ -68,6 +69,20 @@ 
 logger = logging.getLogger(__name__)
 
 
+# These classes serve as pseudo-sections that this generator uses to
+# flatten and inline arg sections from multiple entities.
+class BranchStart(QAPIDoc.Section):
+    def __init__(self, key: str, value: str, info: QAPISourceInfo):
+        super().__init__(info, QAPIDoc.Kind.META)
+        self.key = key
+        self.value = value
+
+
+class BranchEnd(QAPIDoc.Section):
+    def __init__(self, info: QAPISourceInfo):
+        super().__init__(info, QAPIDoc.Kind.META)
+
+
 def dedent(text: str) -> str:
     # Adjust indentation to make description text parse as paragraph.
 
@@ -105,6 +120,7 @@  def categorize(section: QAPIDoc.Section) -> "Optional[DocRegion]":
     QAPIDoc.Kind.SINCE: None,
     QAPIDoc.Kind.TODO: None,
     QAPIDoc.Kind.DETAIL: DocRegion.DETAIL,
+    QAPIDoc.Kind.META: DocRegion.MEMBER,
 }
 
 
@@ -226,6 +242,15 @@  def _get_inline_target(
             return ent.base
         return None
 
+    def _variants(ent) -> Optional[QAPISchemaBranches]:
+        if isinstance(ent, QAPISchemaObjectType):
+            return ent.branches
+        return None
+
+    def _memb_filter(sec: QAPIDoc.Section) -> bool:
+        # meta grabs branch start/end markers, too.
+        return sec.kind in (QAPIDoc.Kind.MEMBER, QAPIDoc.Kind.META)
+
     # Let's do this thing!
 
     if ent is None:
@@ -241,7 +266,22 @@  def _get_inline_target(
     # Now, stitch the results together!
     sections.absorb(inlined)
 
-    # FIXME: Branches should be handled about here O:-)
+    # Now, pick up member sections from branches, if any.
+    # FIXME: Anything other than members are unhandled/ignored here...!
+    branch_sections = []
+    if variants := _variants(ent):
+        for variant in variants.variants:
+            branch_sections.append(
+                BranchStart(
+                    variants.tag_member.name, variant.name, variants.info
+                )
+            )
+            var_sections = inline(variant.type)
+            branch_sections.extend(filter(_memb_filter, var_sections))
+            branch_sections.append(BranchEnd(variants.info))
+
+    # Inject branches *after* the member section.
+    sections.partitions[DocRegion.MEMBER].extend(branch_sections)
 
     # Pseudo-feature: document the OOB property.
     if isinstance(ent, QAPISchemaCommand) and ent.allow_oob:
@@ -485,6 +525,21 @@  def visit_sections(self, ent: QAPISchemaEntity) -> None:
 
         # Add sections *in the order they are documented*:
         for section in sections:
+            if isinstance(section, BranchStart):
+                self.ensure_blank_line()
+                self.add_line(
+                    f".. qapi:branch:: {section.key} {section.value}",
+                    section.info,
+                )
+                self.ensure_blank_line()
+                self.indent += 1
+                continue
+
+            if isinstance(section, BranchEnd):
+                self.ensure_blank_line()
+                self.indent -= 1
+                continue
+
             if section.kind.name in ("INTRO", "DETAIL"):
                 self.visit_paragraph(section)
             elif section.kind == QAPIDoc.Kind.MEMBER: