From: Markus Armbruster <armbru@redhat.com>
To: John Snow <jsnow@redhat.com>
Cc: qemu-devel@nongnu.org, "Michael Roth" <michael.roth@amd.com>,
"Eric Blake" <eblake@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Richard Henderson" <richard.henderson@linaro.org>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Mauro Carvalho Chehab" <mchehab+huawei@kernel.org>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Pierrick Bouvier" <pierrick.bouvier@oss.qualcomm.com>,
"Igor Mammedov" <imammedo@redhat.com>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Ani Sinha" <anisinha@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Markus Armbruster" <armbru@redhat.com>
Subject: Re: [PATCH v2 07/13] qapi/docs: add "Intro" section parsing
Date: Mon, 04 May 2026 13:57:21 +0200 [thread overview]
Message-ID: <875x539yla.fsf@pond.sub.org> (raw)
In-Reply-To: <20260429192611.1581223-8-jsnow@redhat.com> (John Snow's message of "Wed, 29 Apr 2026 15:26:05 -0400")
John Snow <jsnow@redhat.com> writes:
> Add parsing for explicit Intro section syntax.
>
> A side effect of this patch is that we will always create an empty Intro
> section, similar to how we used to have an empty Plain section. The
> tests are adjusted accordingly, rendered document output does not change
> at all.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
> docs/devel/qapi-code-gen.rst | 17 +++++----
> scripts/qapi/parser.py | 47 ++++++++++++++++++-------
> tests/qapi-schema/doc-good.out | 18 ++++++++++
> tests/qapi-schema/doc-missing-colon.err | 2 +-
> 4 files changed, 64 insertions(+), 20 deletions(-)
>
> diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
> index 3a632b4a648..a8175934d52 100644
> --- a/docs/devel/qapi-code-gen.rst
> +++ b/docs/devel/qapi-code-gen.rst
> @@ -862,7 +862,7 @@ documentation comment.
> If the documentation comment starts like ::
>
> ##
> - # @SYMBOL:
> + # @SYMBOL: [...]
>
> it documents the definition of SYMBOL, else it's free-form
> documentation.
> @@ -984,11 +984,11 @@ definition it documents.
> When documentation is required (see pragma_ 'doc-required'), every
> definition must have documentation.
>
> -Definition documentation starts with a line naming the definition,
> -followed by an optional overview, a description of each argument (for
> -commands and events), member (for structs and unions), branch (for
> -alternates), or value (for enums), a description of each feature (if
> -any), and finally optional tagged sections.
> +Definition documentation starts with a description naming the definition
> +with an optional overview, a description of each argument (for commands
> +and events), member (for structs and unions), branch (for alternates),
> +or value (for enums), a description of each feature (if any), and
> +finally optional tagged sections.
>
> Descriptions start with '\@name:'. The description text must be
> indented like this::
> @@ -996,6 +996,11 @@ indented like this::
> # @name: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
> # do eiusmod tempor incididunt ut labore et dolore magna aliqua.
>
> +Definition descriptions are special: the optional introductory overview
> +describing the definition will not be inlined when referenced by other
> +definitions (such as when using 'base' to include members from another
> +definition), while other descriptions and tagged sections will be.
> +
Isn't this premature? We're not inlining anything just yet.
> .. FIXME The parser accepts these things in almost any order.
>
> .. FIXME union branches should be described, too.
> diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
> index 6612f471bb8..c23fd26aaa7 100644
> --- a/scripts/qapi/parser.py
> +++ b/scripts/qapi/parser.py
> @@ -24,6 +24,7 @@
> Match,
> Optional,
> Set,
> + Tuple,
> Union,
> )
>
> @@ -524,6 +525,30 @@ def get_doc_paragraph(self, doc: 'QAPIDoc') -> Optional[str]:
> return line
> doc.append_line(line)
>
> + def _get_doc_intro(
> + self,
> + line: str,
> + info: QAPISourceInfo
> + ) -> Tuple['QAPIDoc', Optional[str]]:
> + match = self._match_at_name_colon(line)
> + if not match:
> + raise QAPIParseError(self, "@name must end with ':'")
> +
> + # Invalid names are not checked here, but the name
> + # provided *must* match the following definition,
> + # which *is* validated in expr.py.
> + symbol = match.group(1)
> + if not symbol:
> + raise QAPIParseError(self, "name required after '@'")
> + doc = QAPIDoc(info, symbol)
> +
Drop the blank line. For what it's worth, you do it already in PATCH
13.
> + doc.ensure_untagged_section(info, QAPIDoc.Kind.INTRO)
Hmm.
.ensure_untagged_section() extends the current section if we have one
and it is of kind .INTRO, else creates a new one of kind .INTRO.
But there is no current section here! Why not simply create one?
> + text = line[match.end():]
> + if text:
> + doc.append_line(text)
> +
> + return doc, self.get_doc_indented(doc)
> +
> def get_doc(self) -> 'QAPIDoc':
> if self.val != '##':
> raise QAPIParseError(
> @@ -532,18 +557,9 @@ def get_doc(self) -> 'QAPIDoc':
> self.accept(False)
> line = self.get_doc_line()
> if line is not None and line.startswith('@'):
> +
Drop the blank line, please.
> # Definition documentation
> - if not line.endswith(':'):
> - raise QAPIParseError(self, "line should end with ':'")
> - # Invalid names are not checked here, but the name
> - # provided *must* match the following definition,
> - # which *is* validated in expr.py.
> - symbol = line[1:-1]
> - if not symbol:
> - raise QAPIParseError(self, "name required after '@'")
> - doc = QAPIDoc(info, symbol)
> - self.accept(False)
> - line = self.get_doc_line()
> + doc, line = self._get_doc_intro(line, info)
> no_more_args = False
>
> while line is not None:
> @@ -751,8 +767,13 @@ def end(self) -> None:
> raise QAPISemError(
> section.info, "text required after '%s:'" % section.kind)
>
> - def ensure_untagged_section(self, info: QAPISourceInfo) -> None:
> - kind = QAPIDoc.Kind.PLAIN
> + def ensure_untagged_section(
> + self,
> + info: QAPISourceInfo,
> + kind: Optional['QAPIDoc.Kind'] = None,
Why not = QAPIDoc.Kind.PLAIN here, so ...
> + ) -> None:
> + if kind is None:
> + kind = QAPIDoc.Kind.PLAIN
... you don't need this?
>
> if self.all_sections and self.all_sections[-1].kind == kind:
> # extend current section
Hmm.
QAPIDoc.ensure_untagged_section() extends the current section if we have
one and it's "untagged", else creates a new "untagged" section.
In the beginning, there was just one kind of "untagged" section. Its
encoding eventually became "Section.kind is QAPIDoc.Kind.PLAIN". So
what the function does was clear enough.
This patch adds a second kind: QAPIDoc.Kind.INTRO.
.ensure_untagged_section() now takes a kind argument. It ensures *that*
kind of section.
I think the function name becomes misleading. It can now ensure *any*
kind of section, not just "untagged".
Rename to ensure_section() and make the @kind argument mandatory?
> diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> index 6fcc8175cfe..bc89853765f 100644
> --- a/tests/qapi-schema/doc-good.out
> +++ b/tests/qapi-schema/doc-good.out
> @@ -106,6 +106,8 @@ Examples:
> - *verbatim*
> - {braces}
> doc symbol=Enum
> + section=Intro
> +
> arg=one
> The _one_ {and only}, description on the same line
> arg=two
> @@ -117,10 +119,14 @@ a member feature
> section=Plain
> @two is undocumented
> doc symbol=Base
> + section=Intro
> +
> arg=base1
> description starts on a new line,
> minimally indented
> doc symbol=Variant1
> + section=Intro
> +
> section=Plain
> A paragraph
>
> @@ -134,10 +140,16 @@ a feature
> feature=member-feat
> a member feature
> doc symbol=Variant2
> + section=Intro
> +
> doc symbol=Object
> + section=Intro
> +
> feature=union-feat1
> a feature
> doc symbol=Alternate
> + section=Intro
> +
> arg=i
> description starts on the same line
> remainder indented the same
> @@ -151,6 +163,8 @@ doc freeform
> Another subsection
> ==================
> doc symbol=cmd
> + section=Intro
> +
> arg=arg1
> description starts on a new line,
> indented
> @@ -198,6 +212,8 @@ Note::
> section=Since
> 2.10
> doc symbol=cmd-boxed
> + section=Intro
> +
> section=Plain
> If you're bored enough to read this, go see a video of boxed cats
> feature=cmd-feat1
> @@ -211,5 +227,7 @@ another feature
>
> <- ... has no title ...
> doc symbol=EVT_BOXED
> + section=Intro
> +
> feature=feat3
> a feature
> diff --git a/tests/qapi-schema/doc-missing-colon.err b/tests/qapi-schema/doc-missing-colon.err
> index cbcea007153..bd5862b30f3 100644
> --- a/tests/qapi-schema/doc-missing-colon.err
> +++ b/tests/qapi-schema/doc-missing-colon.err
> @@ -1 +1 @@
> -doc-missing-colon.json:4:1: line should end with ':'
> +doc-missing-colon.json:4:1: @name must end with ':'
Let's not change this error message in this patch. For what it's worth,
PATCH 13 changes it right back.
next prev parent reply other threads:[~2026-05-04 11:57 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-29 19:25 [PATCH v2 00/13] qapi: add formal "intro" section John Snow
2026-04-29 19:25 ` [PATCH v2 01/13] tests/qapi: generate output in source order John Snow
2026-05-04 9:50 ` Markus Armbruster
2026-05-04 17:55 ` John Snow
2026-04-29 19:26 ` [PATCH v2 02/13] qapi/docs: remove unused QAPIDoc subsection members John Snow
2026-05-04 9:51 ` Markus Armbruster
2026-04-29 19:26 ` [PATCH v2 03/13] qapi/docs: make remaining subsection members "private" John Snow
2026-05-04 9:54 ` Markus Armbruster
2026-05-04 18:07 ` John Snow
2026-04-29 19:26 ` [PATCH v2 04/13] qapi/docs: add "Intro" section John Snow
2026-04-29 19:26 ` [PATCH v2 05/13] qapi/docs: adjust stub member insertion algorithm John Snow
2026-05-04 11:20 ` Markus Armbruster
2026-05-04 18:30 ` John Snow
2026-05-05 13:54 ` Markus Armbruster
2026-05-04 18:33 ` John Snow
2026-04-29 19:26 ` [PATCH v2 06/13] qapi/docs: remove implicit Plain section John Snow
2026-04-29 19:26 ` [PATCH v2 07/13] qapi/docs: add "Intro" section parsing John Snow
2026-05-04 11:57 ` Markus Armbruster [this message]
2026-05-04 18:44 ` John Snow
2026-05-05 13:30 ` Markus Armbruster
2026-04-29 19:26 ` [PATCH v2 08/13] qapi/docs: Add rendering for INTRO sections John Snow
2026-05-04 12:05 ` Markus Armbruster
2026-05-12 21:13 ` John Snow
2026-05-13 6:25 ` Markus Armbruster
2026-04-29 19:26 ` [PATCH v2 09/13] qapi: convert intro sections for accelerator.json John Snow
2026-04-29 19:26 ` [PATCH v2 10/13] qapi: convert intro sections for acpi-hest.json John Snow
2026-04-29 19:26 ` [PATCH v2 11/13] qapi: convert intro sections for acpi.json John Snow
2026-04-29 19:26 ` [PATCH v2 12/13] qapi: convert intro sections for audio.json John Snow
2026-04-29 19:26 ` [PATCH v2 13/13] rfc: intro starts on next line John Snow
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=875x539yla.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=anisinha@redhat.com \
--cc=eblake@redhat.com \
--cc=imammedo@redhat.com \
--cc=jsnow@redhat.com \
--cc=kraxel@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=mchehab+huawei@kernel.org \
--cc=michael.roth@amd.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/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