From nobody Sat Nov 15 12:16:47 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1752506545; cv=none; d=zohomail.com; s=zohoarc; b=WUyX7xpWZrhaZwkeCQ6nwDMGyRvgLmiSCIlzM1mmRUf2smspc2aJ/xDwxCP8BLNWUgwo/WNalYHYQLiYaLRSpFL8mGswZ9qw8nzjHThhywu9jxLfp8Kzcnc12mqWmGgN+IJK2jP5v1pl1FvP+/qGHkQr3Wg4WIzpq/+LPlAKecI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752506545; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=RqyqnGFyQnvq7sX2524kZSsjnQQSwOQe+Q3tvKbYFEQ=; b=CFSUjjPV0VY4OKWhOLgfUrQ8ZMgGA3dDKWFAhBKMs5Hoqtri86H5cYoMkVkm+7619mtJ6YYntor552WJgEY402Etz9tkP5rkrfns7zar3N43vq8MkxoqxFmpFDIuPO+8rPmrASR0e/ASFjNrDOBPZNRGIOETVn84EUyRTSIOHwU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1752506545141881.4191837410024; Mon, 14 Jul 2025 08:22:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubKqo-0007Sr-RS; Mon, 14 Jul 2025 11:12:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubJUa-0000IX-Rv for qemu-devel@nongnu.org; Mon, 14 Jul 2025 09:45:27 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubJUU-0003bc-4O for qemu-devel@nongnu.org; Mon, 14 Jul 2025 09:45:15 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-648-wPHNHk-zPUqH-Q9tTDojFw-1; Mon, 14 Jul 2025 09:45:06 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CE7D21809C8A for ; Mon, 14 Jul 2025 13:45:05 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.45.242.6]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 356381800264 for ; Mon, 14 Jul 2025 13:45:05 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DB23A21E6779; Mon, 14 Jul 2025 15:44:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752500708; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RqyqnGFyQnvq7sX2524kZSsjnQQSwOQe+Q3tvKbYFEQ=; b=IolPY4nNTKY5Nr2PKgKKAHdEY9QXCpToSPSFUmdp8r0dtWNrq4P1AVNOksnfmkcMgrpB+f 47/5DGLDy6yD8+xdQI94O5kB2cLUyrO7MEz7nBEuzotY/IDBjIgzppWp1OK9hjkFS9tqOi eZ1VBijLjw1RPo0tIBNgt3bmEfrsNP0= X-MC-Unique: wPHNHk-zPUqH-Q9tTDojFw-1 X-Mimecast-MFC-AGG-ID: wPHNHk-zPUqH-Q9tTDojFw_1752500705 From: Markus Armbruster To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, John Snow Subject: [PULL 09/32] qapi: Fix undocumented return values by generating something Date: Mon, 14 Jul 2025 15:44:35 +0200 Message-ID: <20250714134458.2991097-10-armbru@redhat.com> In-Reply-To: <20250714134458.2991097-1-armbru@redhat.com> References: <20250714134458.2991097-1-armbru@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752506546699116600 From: John Snow 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: =E2=80=93 ". 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: ". 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 Message-ID: <20250711051045.51110-3-jsnow@redhat.com> Reviewed-by: Markus Armbruster [_insert_near_kind() code replaced by something simpler, commit message amended to explain why we're doing this] Signed-off-by: Markus Armbruster --- 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 =3D 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 =20 typ =3D 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) =20 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) =20 + def ensure_returns(self, info: QAPISourceInfo) -> None: + + def _insert_near_kind( + kind: QAPIDoc.Kind, + new_sect: QAPIDoc.Section, + after: bool =3D False, + ) -> bool: + for idx, sect in enumerate(reversed(self.all_sections)): + if sect.kind =3D=3D kind: + pos =3D len(self.all_sections) - idx - 1 + if after: + pos +=3D 1 + self.all_sections.insert(pos, new_sect) + return True + return False + + if any(s.kind =3D=3D QAPIDoc.Kind.RETURNS for s in self.all_sectio= ns): + return + + # Stub "Returns" section for undocumented returns value + stub =3D 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=3D1 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] =3D None= ) -> None: if self.arg_type and self.arg_type.is_implicit(): self.arg_type.connect_doc(doc) =20 + if self.ret_type and self.info: + doc.ensure_returns(self.info) + def visit(self, visitor: QAPISchemaVisitor) -> None: super().visit(visitor) visitor.visit_command( --=20 2.49.0