qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: stefanha@redhat.com, John Snow <jsnow@redhat.com>
Subject: [PULL 09/32] qapi: Fix undocumented return values by generating something
Date: Mon, 14 Jul 2025 15:44:35 +0200	[thread overview]
Message-ID: <20250714134458.2991097-10-armbru@redhat.com> (raw)
In-Reply-To: <20250714134458.2991097-1-armbru@redhat.com>

From: John Snow <jsnow@redhat.com>

Generated command documentation lacks information on return value in
several cases, e.g. query-tpm.

The obvious fix would be to require a Returns: section when a command
returns something.

However, note that many existing Returns: sections are pretty useless:
the description is basically the return type, which then gets rendered
like "Return: <Type> – <basically the return type>".  This suggests
that a description is often not really necessary, and requiring one
isn't useful.

Instead, generate the obvious minimal thing when Returns: is absent:
"Return: <Type>".

This auto-generated Return documentation is placed is as follows:

1. If we have arguments, return goes right after them.
2. Else if we have errors, return goes right before them.
3. Else if we have features, return goes right before them.
4. Else return goes right after the intro

To facilitate this algorithm, a "TODO:" hack line is used to separate
the intro from the remainder of the documentation block in cases where
there are no other sections to separate the intro from e.g. examples and
additional detail meant to appear below the key sections of interest.

Signed-off-by: John Snow <jsnow@redhat.com>
Message-ID: <20250711051045.51110-3-jsnow@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[_insert_near_kind() code replaced by something simpler, commit
message amended to explain why we're doing this]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/sphinx/qapidoc.py | 14 ++++++++------
 qapi/machine.json      |  2 ++
 scripts/qapi/parser.py | 37 +++++++++++++++++++++++++++++++++++++
 scripts/qapi/schema.py |  3 +++
 4 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index b794cde697..c2f09bac16 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -258,16 +258,18 @@ def visit_feature(self, section: QAPIDoc.ArgSection) -> None:
     def visit_returns(self, section: QAPIDoc.Section) -> None:
         assert isinstance(self.entity, QAPISchemaCommand)
         rtype = self.entity.ret_type
-        # q_empty can produce None, but we won't be documenting anything
-        # without an explicit return statement in the doc block, and we
-        # should not have any such explicit statements when there is no
-        # return value.
+        # return statements will not be present (and won't be
+        # autogenerated) for any command that doesn't return
+        # *something*, so rtype will always be defined here.
         assert rtype
 
         typ = self.format_type(rtype)
         assert typ
-        assert section.text
-        self.add_field("return", typ, section.text, section.info)
+
+        if section.text:
+            self.add_field("return", typ, section.text, section.info)
+        else:
+            self.add_lines(f":return-nodesc: {typ}", section.info)
 
     def visit_errors(self, section: QAPIDoc.Section) -> None:
         # If the section text does not start with a space, it means text
diff --git a/qapi/machine.json b/qapi/machine.json
index af00a20b1f..2d6a137f21 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1303,6 +1303,8 @@
 # Return the amount of initially allocated and present hotpluggable
 # (if enabled) memory in bytes.
 #
+# TODO: This line is a hack to separate the example from the body
+#
 # .. qmp-example::
 #
 #     -> { "execute": "query-memory-size-summary" }
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index d43a123cd7..2529edf81a 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -804,6 +804,43 @@ def connect_feature(self, feature: 'QAPISchemaFeature') -> None:
                                % feature.name)
         self.features[feature.name].connect(feature)
 
+    def ensure_returns(self, info: QAPISourceInfo) -> None:
+
+        def _insert_near_kind(
+            kind: QAPIDoc.Kind,
+            new_sect: QAPIDoc.Section,
+            after: bool = False,
+        ) -> bool:
+            for idx, sect in enumerate(reversed(self.all_sections)):
+                if sect.kind == kind:
+                    pos = len(self.all_sections) - idx - 1
+                    if after:
+                        pos += 1
+                    self.all_sections.insert(pos, new_sect)
+                    return True
+            return False
+
+        if any(s.kind == QAPIDoc.Kind.RETURNS for s in self.all_sections):
+            return
+
+        # Stub "Returns" section for undocumented returns value
+        stub = QAPIDoc.Section(info, QAPIDoc.Kind.RETURNS)
+
+        if any(_insert_near_kind(kind, stub, after) for kind, after in (
+                # 1. If arguments, right after those.
+                (QAPIDoc.Kind.MEMBER, True),
+                # 2. Elif errors, right *before* those.
+                (QAPIDoc.Kind.ERRORS, False),
+                # 3. Elif features, right *before* those.
+                (QAPIDoc.Kind.FEATURE, False),
+        )):
+            return
+
+        # Otherwise, it should go right after the intro. The intro
+        # is always the first section and is always present (even
+        # when empty), so we can insert directly at index=1 blindly.
+        self.all_sections.insert(1, stub)
+
     def check_expr(self, expr: QAPIExpression) -> None:
         if 'command' in expr:
             if self.returns and 'returns' not in expr:
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index cbe3b5aa91..3abddea352 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -1062,6 +1062,9 @@ def connect_doc(self, doc: Optional[QAPIDoc] = None) -> None:
             if self.arg_type and self.arg_type.is_implicit():
                 self.arg_type.connect_doc(doc)
 
+            if self.ret_type and self.info:
+                doc.ensure_returns(self.info)
+
     def visit(self, visitor: QAPISchemaVisitor) -> None:
         super().visit(visitor)
         visitor.visit_command(
-- 
2.49.0



  parent reply	other threads:[~2025-07-14 15:22 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-14 13:44 [PULL 00/32] QAPI patches patches for 2025-07-14 Markus Armbruster
2025-07-14 13:44 ` [PULL 01/32] docs/sphinx: adjust qapidoc to cope with same-line error sections Markus Armbruster
2025-07-14 13:44 ` [PULL 02/32] docs/sphinx: parse @references in freeform text Markus Armbruster
2025-07-14 13:44 ` [PULL 03/32] docs/sphinx: remove legacy QAPI manual generator Markus Armbruster
2025-07-14 13:44 ` [PULL 04/32] docs/sphinx: remove special parsing for freeform sections Markus Armbruster
2025-07-14 13:44 ` [PULL 05/32] qapi: lift restriction on using '=' in doc blocks Markus Armbruster
2025-07-14 13:44 ` [PULL 06/32] qapi: Clean up "This command will do ..." command descriptions Markus Armbruster
2025-07-14 13:44 ` [PULL 07/32] qapi: Clean up a few Errors: sections Markus Armbruster
2025-07-14 13:44 ` [PULL 08/32] docs/qapi-domain: add return-nodesc Markus Armbruster
2025-07-14 13:44 ` Markus Armbruster [this message]
2025-07-14 13:44 ` [PULL 10/32] qapi: remove trivial "Returns:" sections Markus Armbruster
2025-07-14 13:44 ` [PULL 11/32] qapi: rephrase return docs to avoid type name Markus Armbruster
2025-07-14 13:44 ` [PULL 12/32] qapi: add cross-references to acpi.json Markus Armbruster
2025-07-14 13:44 ` [PULL 13/32] qapi: add cross-references to authz.json Markus Armbruster
2025-07-14 13:44 ` [PULL 14/32] qapi: add cross-references to block layer Markus Armbruster
2025-07-14 13:44 ` [PULL 15/32] qapi: add cross-references to crypto.json Markus Armbruster
2025-07-14 13:44 ` [PULL 16/32] qapi: add cross-references to dump.json Markus Armbruster
2025-07-14 13:44 ` [PULL 17/32] qapi: add cross-references to job.json Markus Armbruster
2025-07-14 13:44 ` [PULL 18/32] qapi: add cross-references to Machine core Markus Armbruster
2025-07-14 13:44 ` [PULL 19/32] qapi: add cross-references to migration.json Markus Armbruster
2025-07-14 13:44 ` [PULL 20/32] qapi: add cross-references to net.json Markus Armbruster
2025-07-14 13:44 ` [PULL 21/32] qapi: add cross-references to pci.json Markus Armbruster
2025-07-14 13:44 ` [PULL 22/32] qapi: add cross-references to QOM Markus Armbruster
2025-07-14 13:44 ` [PULL 23/32] qapi: add cross-references to replay.json Markus Armbruster
2025-07-14 13:44 ` [PULL 24/32] qapi: add cross-references to run-state.json Markus Armbruster
2025-07-14 13:44 ` [PULL 25/32] qapi: add cross-references to sockets.json Markus Armbruster
2025-07-14 13:44 ` [PULL 26/32] qapi: add cross-references to ui.json Markus Armbruster
2025-07-14 13:44 ` [PULL 27/32] qapi: add cross-references to virtio.json Markus Armbruster
2025-07-14 13:44 ` [PULL 28/32] qapi: add cross-references to yank.json Markus Armbruster
2025-07-14 13:44 ` [PULL 29/32] qapi: add cross-references to misc modules Markus Armbruster
2025-07-14 13:44 ` [PULL 30/32] qom: qom-list-get Markus Armbruster
2025-07-14 13:44 ` [PULL 31/32] python: use qom-list-get Markus Armbruster
2025-07-14 13:44 ` [PULL 32/32] tests/qtest/qom-test: unit test for qom-list-get Markus Armbruster
2025-07-15  4:26 ` [PULL 00/32] QAPI patches patches for 2025-07-14 Stefan Hajnoczi
2025-07-15  6:30   ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250714134458.2991097-10-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).