[PATCH 6/8] qapi: enforce doc block section ordering

John Snow posted 8 patches 3 weeks ago
Maintainers: "Philippe Mathieu-Daudé" <philmd@linaro.org>, "Daniel P. Berrangé" <berrange@redhat.com>, Kashyap Chamarthy <kchamart@redhat.com>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, "Michael S. Tsirkin" <mst@redhat.com>, Stefano Garzarella <sgarzare@redhat.com>, Markus Armbruster <armbru@redhat.com>, Michael Roth <michael.roth@amd.com>, John Snow <jsnow@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, Mauro Carvalho Chehab <mchehab+huawei@kernel.org>, Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, Eric Blake <eblake@redhat.com>, Igor Mammedov <imammedo@redhat.com>, Ani Sinha <anisinha@redhat.com>, Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>, Jason Wang <jasowang@redhat.com>, "Alex Bennée" <alex.bennee@linaro.org>, Jiri Pirko <jiri@resnulli.us>, Stefan Berger <stefanb@linux.vnet.ibm.com>, Stefan Hajnoczi <stefanha@redhat.com>, Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>, Lukas Straub <lukasstraub2@web.de>
[PATCH 6/8] qapi: enforce doc block section ordering
Posted by John Snow 3 weeks ago
Ugly hack, gets the job done. Likely many simplifications can be made as
a result, but I didn't make any of them. There are some inconsistencies
with human-readable vs ENUM_NAMES in error messages in this patch, but
it appears to work anyway.

Consider this patch more of a rough idea and not anything approximating
the kind of code you'd want to see from an Enterprise Linux Senior
Software Engineer.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 scripts/qapi/parser.py | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 9e8dfc67208..1a7856bf213 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -545,19 +545,25 @@ def get_doc(self) -> 'QAPIDoc':
             self.accept(False)
             line = self.get_doc_line()
             have_tagged = False
-            no_more_tags = False
+            last_section = QAPIDoc.Kind.INTRO
 
             def _tag_check(what: str) -> None:
+                nonlocal last_section
+
                 if what in ('TODO', 'Since'):
                     return
 
-                if no_more_tags:
+                this_section = QAPIDoc.Kind.from_string(what)
+                if this_section.value < last_section.value:
                     raise QAPIParseError(
                         self,
-                        f"'{what}' section cannot appear after plain "
-                        "paragraphs that follow other tagged sections\n"
-                        "Move this section up above the plain paragraph(s)."
+                        f"'{what}' section cannot appear after "
+                        f"'{last_section!s}' section, please re-order the "
+                        "sections and adjust phrasing as necessary to ensure "
+                        "consistent documentation flow between the source "
+                        "code and the rendered HTML manual"
                     )
+                last_section = this_section
 
             while line is not None:
                 # Blank lines
@@ -571,7 +577,7 @@ def _tag_check(what: str) -> None:
                     if doc.features:
                         raise QAPIParseError(
                             self, "duplicated 'Features:' line")
-                    _tag_check("Features")
+                    _tag_check("FEATURE")
                     self.accept(False)
                     line = self.get_doc_line()
                     while line == '':
@@ -589,7 +595,7 @@ def _tag_check(what: str) -> None:
                             self, 'feature descriptions expected')
                     have_tagged = True
                 elif line == 'Details:':
-                    _tag_check("Details")
+                    _tag_check("DETAILS")
                     self.accept(False)
                     line = self.get_doc_line()
                     while line == '':
@@ -598,6 +604,7 @@ def _tag_check(what: str) -> None:
                     have_tagged = True
                 elif match := self._match_at_name_colon(line):
                     # description
+                    _tag_check("MEMBER")
                     if have_tagged:
                         raise QAPIParseError(
                             self,
@@ -654,13 +661,10 @@ def _tag_check(what: str) -> None:
                     line = self.get_doc_indented(doc)
                     have_tagged = True
                 else:
-                    # plain paragraph
-                    if have_tagged:
-                        no_more_tags = True
-
                     # Paragraphs before tagged sections are "intro" paragraphs.
                     # Any appearing after are "detail" paragraphs.
                     intro = not have_tagged
+                    _tag_check("INTRO" if intro else "DETAILS")
                     doc.ensure_untagged_section(self.info, intro)
                     doc.append_line(line)
                     line = self.get_doc_paragraph(doc)
@@ -703,14 +707,17 @@ class QAPIDoc:
     """
 
     class Kind(enum.Enum):
+        # The order here is the order in which sections must appear in
+        # source code; with the exception of 'TODO' which may appear
+        # anywhere but is treated as a comment.
         INTRO = 0
         MEMBER = 1
-        FEATURE = 2
-        RETURNS = 3
-        ERRORS = 4
-        SINCE = 5
+        RETURNS = 2
+        ERRORS = 3
+        FEATURE = 4
+        DETAILS = 5
         TODO = 6
-        DETAILS = 7
+        SINCE = 7
 
         @staticmethod
         def from_string(kind: str) -> 'QAPIDoc.Kind':
-- 
2.53.0
Re: [PATCH 6/8] qapi: enforce doc block section ordering
Posted by Markus Armbruster 2 weeks, 3 days ago
John Snow <jsnow@redhat.com> writes:

> Ugly hack, gets the job done. Likely many simplifications can be made as
> a result, but I didn't make any of them. There are some inconsistencies
> with human-readable vs ENUM_NAMES in error messages in this patch, but
> it appears to work anyway.
>
> Consider this patch more of a rough idea and not anything approximating
> the kind of code you'd want to see from an Enterprise Linux Senior
> Software Engineer.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  scripts/qapi/parser.py | 39 +++++++++++++++++++++++----------------
>  1 file changed, 23 insertions(+), 16 deletions(-)

Missing: update to docs/devel/qapi-code-gen.rst.  Suggest to put in a
FIXME, so we don't forget.

Missing: test coverage.
Re: [PATCH 6/8] qapi: enforce doc block section ordering
Posted by John Snow 2 weeks, 3 days ago
On Fri, Mar 20, 2026, 10:13 AM Markus Armbruster <armbru@redhat.com> wrote:

> John Snow <jsnow@redhat.com> writes:
>
> > Ugly hack, gets the job done. Likely many simplifications can be made as
> > a result, but I didn't make any of them. There are some inconsistencies
> > with human-readable vs ENUM_NAMES in error messages in this patch, but
> > it appears to work anyway.
> >
> > Consider this patch more of a rough idea and not anything approximating
> > the kind of code you'd want to see from an Enterprise Linux Senior
> > Software Engineer.
> >
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > ---
> >  scripts/qapi/parser.py | 39 +++++++++++++++++++++++----------------
> >  1 file changed, 23 insertions(+), 16 deletions(-)
>
> Missing: update to docs/devel/qapi-code-gen.rst.  Suggest to put in a
> FIXME, so we don't forget.
>

ACK


> Missing: test coverage.
>

Do we need to test every possible sequence, or just some characteristic
examples...?

>
Re: [PATCH 6/8] qapi: enforce doc block section ordering
Posted by Markus Armbruster 2 weeks ago
John Snow <jsnow@redhat.com> writes:

> On Fri, Mar 20, 2026, 10:13 AM Markus Armbruster <armbru@redhat.com> wrote:
>
>> John Snow <jsnow@redhat.com> writes:
>>
>> > Ugly hack, gets the job done. Likely many simplifications can be made as
>> > a result, but I didn't make any of them. There are some inconsistencies
>> > with human-readable vs ENUM_NAMES in error messages in this patch, but
>> > it appears to work anyway.
>> >
>> > Consider this patch more of a rough idea and not anything approximating
>> > the kind of code you'd want to see from an Enterprise Linux Senior
>> > Software Engineer.
>> >
>> > Signed-off-by: John Snow <jsnow@redhat.com>
>> > ---
>> >  scripts/qapi/parser.py | 39 +++++++++++++++++++++++----------------
>> >  1 file changed, 23 insertions(+), 16 deletions(-)
>>
>> Missing: update to docs/devel/qapi-code-gen.rst.  Suggest to put in a
>> FIXME, so we don't forget.
>>
>
> ACK
>
>
>> Missing: test coverage.
>>
>
> Do we need to test every possible sequence, or just some characteristic
> examples...?

Let's start with characteristic examples.