[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 04/20] qapi/parser: preserve indentation in QAPIDoc sections
From: |
John Snow |
Subject: |
[PATCH 04/20] qapi/parser: preserve indentation in QAPIDoc sections |
Date: |
Tue, 14 May 2024 17:57:23 -0400 |
Prior to this patch, a section like this:
@name: lorem ipsum
dolor sit amet
consectetur adipiscing elit
would be parsed as:
"lorem ipsum\ndolor sit amet\n consectetur adipiscing elit"
We want to preserve the indentation for even the first body line so that
the entire block can be parsed directly as rST. This patch would now
parse that segment as:
"lorem ipsum\n dolor sit amet\n consectetur adipiscing elit"
This understandably breaks qapidoc.py; so a new function is added there
to re-dedent the text. Once the new generator is merged, this function
will not be needed any longer and can be dropped.
(I verified this patch changes absolutely nothing by comparing the
md5sums of the QMP ref html pages both before and after the change, so
it's certified inert. QAPI test output has been updated to reflect the
new strategy of preserving indents for rST.)
Signed-off-by: John Snow <jsnow@redhat.com>
---
docs/sphinx/qapidoc.py | 36 +++++++++++++++++++++++++++++-----
scripts/qapi/parser.py | 8 ++++++--
tests/qapi-schema/doc-good.out | 32 +++++++++++++++---------------
3 files changed, 53 insertions(+), 23 deletions(-)
diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 1655682d4c7..2e3ffcbafb7 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -26,6 +26,7 @@
import os
import re
+import textwrap
from docutils import nodes
from docutils.parsers.rst import Directive, directives
@@ -51,6 +52,28 @@
__version__ = "1.0"
+def dedent(text: str) -> str:
+ # Temporary: In service of the new QAPI domain, the QAPI doc parser
+ # now preserves indents in args/members/features text. QAPIDoc does
+ # not handle this well, so undo that change here.
+
+ # QAPIDoc is being rewritten and will be replaced soon,
+ # but this function is here in the interim as transition glue.
+
+ lines = text.splitlines(True)
+ if len(lines) > 1:
+ if re.match(r"\s+", lines[0]):
+ # First line is indented; description started on
+ # the line after the name. dedent the whole block.
+ return textwrap.dedent(text)
+ else:
+ # Descr started on same line. Dedent line 2+.
+ return lines[0] + textwrap.dedent("".join(lines[1:]))
+ else:
+ # Descr was a single line; dedent entire line.
+ return textwrap.dedent(text)
+
+
# fmt: off
# Function borrowed from pydash, which is under the MIT license
def intersperse(iterable, separator):
@@ -169,7 +192,7 @@ def _nodes_for_members(self, doc, what, base=None,
branches=None):
term = self._nodes_for_one_member(section.member)
# TODO drop fallbacks when undocumented members are outlawed
if section.text:
- defn = section.text
+ defn = dedent(section.text)
else:
defn = [nodes.Text('Not documented')]
@@ -207,7 +230,7 @@ def _nodes_for_enum_values(self, doc):
termtext.extend(self._nodes_for_ifcond(section.member.ifcond))
# TODO drop fallbacks when undocumented members are outlawed
if section.text:
- defn = section.text
+ defn = dedent(section.text)
else:
defn = [nodes.Text('Not documented')]
@@ -242,7 +265,7 @@ def _nodes_for_features(self, doc):
dlnode = nodes.definition_list()
for section in doc.features.values():
dlnode += self._make_dlitem(
- [nodes.literal('', section.member.name)], section.text)
+ [nodes.literal('', section.member.name)], dedent(section.text))
seen_item = True
if not seen_item:
@@ -265,9 +288,12 @@ def _nodes_for_sections(self, doc):
continue
snode = self._make_section(section.tag)
if section.tag and section.tag.startswith('Example'):
- snode += self._nodes_for_example(section.text)
+ snode += self._nodes_for_example(dedent(section.text))
else:
- self._parse_text_into_node(section.text, snode)
+ self._parse_text_into_node(
+ dedent(section.text) if section.tag else section.text,
+ snode,
+ )
nodelist.append(snode)
return nodelist
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 7b13a583ac1..8cdd5334ec6 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -448,7 +448,10 @@ def get_doc_indented(self, doc: 'QAPIDoc') ->
Optional[str]:
indent = must_match(r'\s*', line).end()
if not indent:
return line
- doc.append_line(line[indent:])
+
+ # Preserve the indent, it's needed for rST formatting.
+ doc.append_line(line)
+
prev_line_blank = False
while True:
self.accept(False)
@@ -465,7 +468,8 @@ def get_doc_indented(self, doc: 'QAPIDoc') -> Optional[str]:
self,
"unexpected de-indent (expected at least %d spaces)" %
indent)
- doc.append_line(line[indent:])
+ # Again, preserve the indent for ReST.
+ doc.append_line(line)
prev_line_blank = True
def get_doc_paragraph(self, doc: 'QAPIDoc') -> Optional[str]:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 716a9a41026..435f6e6d768 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -117,8 +117,8 @@ doc symbol=Base
body=
arg=base1
-description starts on a new line,
-minimally indented
+ description starts on a new line,
+ minimally indented
doc symbol=Variant1
body=
A paragraph
@@ -145,8 +145,8 @@ doc symbol=Alternate
arg=i
description starts on the same line
-remainder indented the same
-@b is undocumented
+ remainder indented the same
+ @b is undocumented
arg=b
feature=alt-feat
@@ -158,11 +158,11 @@ doc symbol=cmd
body=
arg=arg1
-description starts on a new line,
-indented
+ description starts on a new line,
+ indented
arg=arg2
description starts on the same line
-remainder indented differently
+ remainder indented differently
arg=arg3
feature=cmd-feat1
@@ -178,16 +178,16 @@ some
section=TODO
frobnicate
section=Notes
-- Lorem ipsum dolor sit amet
-- Ut enim ad minim veniam
+ - Lorem ipsum dolor sit amet
+ - Ut enim ad minim veniam
-Duis aute irure dolor
+ Duis aute irure dolor
section=Example
--> in
-<- out
+ -> in
+ <- out
section=Examples
-- *verbatim*
-- {braces}
+ - *verbatim*
+ - {braces}
section=Since
2.10
doc symbol=cmd-boxed
@@ -198,9 +198,9 @@ a feature
feature=cmd-feat2
another feature
section=Example
--> in
+ -> in
-<- out
+ <- out
doc symbol=EVT_BOXED
body=
--
2.44.0
[PATCH 04/20] qapi/parser: preserve indentation in QAPIDoc sections,
John Snow <=
[PATCH 01/20] [DO-NOT-MERGE]: Add some ad-hoc linting helpers., John Snow, 2024/05/14
[PATCH 06/20] qapi/parser: fix comment parsing immediately following a doc block, John Snow, 2024/05/14
[PATCH 07/20] qapi/parser: add semantic 'kind' parameter to QAPIDoc.Section, John Snow, 2024/05/14