]> www.infradead.org Git - users/dwmw2/qemu.git/commitdiff
qapi: Recognize section tags and 'Features:' only after blank line
authorMarkus Armbruster <armbru@redhat.com>
Fri, 16 Feb 2024 14:58:35 +0000 (15:58 +0100)
committerMarkus Armbruster <armbru@redhat.com>
Mon, 26 Feb 2024 09:43:56 +0000 (10:43 +0100)
Putting a blank line before section tags and 'Features:' is good,
existing practice.  Enforce it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-ID: <20240216145841.2099240-12-armbru@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
docs/devel/qapi-code-gen.rst
scripts/qapi/parser.py
tests/qapi-schema/doc-duplicated-return.err
tests/qapi-schema/doc-duplicated-return.json
tests/qapi-schema/doc-duplicated-since.err
tests/qapi-schema/doc-duplicated-since.json
tests/qapi-schema/doc-good.json
tests/qapi-schema/doc-invalid-return.err
tests/qapi-schema/doc-invalid-return.json

index 77a40f3bdc1b9dd9982b11b86d5ad7388fa14fbb..6804a4b5963a36e409ca520da73859c9c2a8ace1 100644 (file)
@@ -986,16 +986,17 @@ indented like this::
 Extensions added after the definition was first released carry a
 "(since x.y.z)" comment.
 
-The feature descriptions must be preceded by a line "Features:", like
-this::
+The feature descriptions must be preceded by a blank line and then a
+line "Features:", like this::
 
+  #
   # Features:
   #
   # @feature: Description text
 
-A tagged section starts with one of the following words:
-"Note:"/"Notes:", "Since:", "Example:"/"Examples:", "Returns:",
-"TODO:".  The section ends with the start of a new section.
+A tagged section begins with a paragraph that starts with one of the
+following words: "Note:"/"Notes:", "Since:", "Example:"/"Examples:",
+"Returns:", "TODO:".  It ends with the start of a new section.
 
 The second and subsequent lines of tagged sections must be indented
 like this::
@@ -1086,8 +1087,10 @@ need to line up with each other, like this::
  #     or cache associativity unknown)
  #     (since 5.0)
 
-Section tags are case-sensitive and end with a colon.  Good example::
+Section tags are case-sensitive and end with a colon.  They are only
+recognized after a blank line.  Good example::
 
+ #
  # Since: 7.1
 
 Bad examples (all ordinary paragraphs)::
index f8da315332ad5fab060c0480ca9a45f4cc98e15e..de2ce3ec2cf4468ef9e512a594e570bd217bc368 100644 (file)
@@ -538,6 +538,7 @@ class QAPIDoc:
         # the current section
         self._section = self.body
         self._append_line = self._append_body_line
+        self._first_line_in_paragraph = False
 
     def has_section(self, tag: str) -> bool:
         """Return True if we have a section with this tag."""
@@ -560,12 +561,14 @@ class QAPIDoc:
         line = line[1:]
         if not line:
             self._append_freeform(line)
+            self._first_line_in_paragraph = True
             return
 
         if line[0] != ' ':
             raise QAPIParseError(self._parser, "missing space after #")
         line = line[1:]
         self._append_line(line)
+        self._first_line_in_paragraph = False
 
     def end_comment(self) -> None:
         self._switch_section(QAPIDoc.NullSection(self._parser))
@@ -574,9 +577,11 @@ class QAPIDoc:
     def _match_at_name_colon(string: str) -> Optional[Match[str]]:
         return re.match(r'@([^:]*): *', string)
 
-    @staticmethod
-    def _match_section_tag(string: str) -> Optional[Match[str]]:
-        return re.match(r'(Returns|Since|Notes?|Examples?|TODO): *', string)
+    def _match_section_tag(self, string: str) -> Optional[Match[str]]:
+        if not self._first_line_in_paragraph:
+            return None
+        return re.match(r'(Returns|Since|Notes?|Examples?|TODO): *',
+                        string)
 
     def _append_body_line(self, line: str) -> None:
         """
index fe97e3db8dcc04877077a8fa704088b72e30f309..f19a2b8ec47fd7438ff5d8d4e0c5c633a2131f7b 100644 (file)
@@ -1 +1 @@
-doc-duplicated-return.json:7:1: duplicated 'Returns' section
+doc-duplicated-return.json:8:1: duplicated 'Returns' section
index b44b5ae979bb4d3db05288e0d76e86587a3ee2a5..4e1ec2ef42f8475a66e8fed310361261c379a213 100644 (file)
@@ -4,5 +4,6 @@
 # @foo:
 #
 # Returns: 0
+#
 # Returns: 1
 ##
index abca141a2c6c19dbc2f47aa98f638312937fe32f..565b753b6a0d5ae83031c65ea861fdae79cb97d2 100644 (file)
@@ -1 +1 @@
-doc-duplicated-since.json:7:1: duplicated 'Since' section
+doc-duplicated-since.json:8:1: duplicated 'Since' section
index 343cd872cb5860e6c876e9b84bbf3d3db6da955b..2755f95719b58cf00ad971783402830428de397d 100644 (file)
@@ -4,5 +4,6 @@
 # @foo:
 #
 # Since: 0
+#
 # Since: 1
 ##
index 977bb38b6e7c6f178e9c0c806b4502a03d317f0f..5bb2b69071fc3bf89458cb5b0adc9ac8541af211 100644 (file)
 # Features:
 # @cmd-feat1: a feature
 # @cmd-feat2: another feature
+#
 # Note: @arg3 is undocumented
+#
 # Returns: @Object
+#
 # TODO: frobnicate
+#
 # Notes:
 #
 #  - Lorem ipsum dolor sit amet
 #  - Ut enim ad minim veniam
 #
 #  Duis aute irure dolor
+#
 # Example:
 #
 #  -> in
 #  <- out
+#
 # Examples:
 #  - *verbatim*
 #  - {braces}
+#
 # Since: 2.10
 ##
 { 'command': 'cmd',
 ##
 # @cmd-boxed:
 # If you're bored enough to read this, go see a video of boxed cats
+#
 # Features:
 # @cmd-feat1: a feature
 # @cmd-feat2: another feature
+#
 # Example:
 #
 #  -> in
index bc5826de20b1b2c2738c7617ebe39652a1132f36..3d9e71c2b3a52dad4be42233789884dd3c076931 100644 (file)
@@ -1 +1 @@
-doc-invalid-return.json:5: 'Returns:' is only valid for commands
+doc-invalid-return.json:6: 'Returns:' is only valid for commands
index 95e75839307276678b4c48b885c9d73f72ecf271..1aabef3482babd6c233806a6205a6763bda2af0f 100644 (file)
@@ -2,6 +2,7 @@
 
 ##
 # @FOO:
+#
 # Returns: blah
 ##
 { 'event': 'FOO' }