[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v5 08/20] scripts/qapi/parser.py: improve doc comment indent hand
From: |
Peter Maydell |
Subject: |
[PATCH v5 08/20] scripts/qapi/parser.py: improve doc comment indent handling |
Date: |
Mon, 10 Aug 2020 20:50:07 +0100 |
Make the handling of indentation in doc comments more sophisticated,
so that when we see a section like:
Notes: some text
some more text
indented line 3
we save it for the doc-comment processing code as:
some text
some more text
indented line 3
and when we see a section with the heading on its own line:
Notes:
some text
some more text
indented text
we also accept that and save it in the same form.
The exception is that we always retain indentation as-is for Examples
sections, because these are literal text.
If we detect that the comment document text is not indented as much
as we expect it to be, we throw a parse error. (We don't complain
about over-indented sections, because for rST this can be legitimate
markup.)
The golden reference for the doc comment text is updated to remove
the two 'wrong' indents; these now form a test case that we correctly
stripped leading whitespace from an indented multi-line argument
definition.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
v1->v2: Update doc-good.out as per final para.
---
scripts/qapi/parser.py | 81 +++++++++++++++++++++++++++-------
tests/qapi-schema/doc-good.out | 4 +-
2 files changed, 67 insertions(+), 18 deletions(-)
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 7fae4478d34..d9f11eadd96 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -308,18 +308,32 @@ class QAPIDoc:
"""
class Section:
- def __init__(self, name=None):
+ def __init__(self, parser, name=None, indent=0):
+ # parser, for error messages about indentation
+ self._parser = parser
# optional section name (argument/member or section name)
self.name = name
# the list of lines for this section
self.text = ''
+ # the expected indent level of the text of this section
+ self._indent = indent
def append(self, line):
+ # Strip leading spaces corresponding to the expected indent level
+ # Blank lines are always OK.
+ if line:
+ spacecount = len(line) - len(line.lstrip(" "))
+ if spacecount > self._indent:
+ spacecount = self._indent
+ if spacecount < self._indent:
+ raise QAPIParseError(self._parser, "unexpected de-indent")
+ line = line[spacecount:]
+
self.text += line.rstrip() + '\n'
class ArgSection(Section):
- def __init__(self, name):
- super().__init__(name)
+ def __init__(self, parser, name, indent=0):
+ super().__init__(parser, name, indent)
self.member = None
def connect(self, member):
@@ -333,7 +347,7 @@ class QAPIDoc:
self._parser = parser
self.info = info
self.symbol = None
- self.body = QAPIDoc.Section()
+ self.body = QAPIDoc.Section(parser)
# dict mapping parameter name to ArgSection
self.args = OrderedDict()
self.features = OrderedDict()
@@ -438,7 +452,18 @@ class QAPIDoc:
if name.startswith('@') and name.endswith(':'):
line = line[len(name)+1:]
- self._start_args_section(name[1:-1])
+ if not line or line.isspace():
+ # Line was just the "@arg:" header; following lines
+ # are not indented
+ indent = 0
+ line = ''
+ else:
+ # Line is "@arg: first line of description"; following
+ # lines should be indented by len(name) + 1, and we
+ # pad out this first line so it is handled the same way
+ indent = len(name) + 1
+ line = ' ' * indent + line
+ self._start_args_section(name[1:-1], indent)
elif self._is_section_tag(name):
self._append_line = self._append_various_line
self._append_various_line(line)
@@ -460,7 +485,17 @@ class QAPIDoc:
if name.startswith('@') and name.endswith(':'):
line = line[len(name)+1:]
- self._start_features_section(name[1:-1])
+ if not line or line.isspace():
+ # Line is just the "@name:" header, no ident for following
lines
+ indent = 0
+ line = ''
+ else:
+ # Line is "@arg: first line of description"; following
+ # lines should be indented by len(name) + 3, and we
+ # pad out this first line so it is handled the same way
+ indent = len(name) + 1
+ line = ' ' * indent + line
+ self._start_features_section(name[1:-1], indent)
elif self._is_section_tag(name):
self._append_line = self._append_various_line
self._append_various_line(line)
@@ -493,11 +528,23 @@ class QAPIDoc:
% (name, self.sections[0].name))
if self._is_section_tag(name):
line = line[len(name)+1:]
- self._start_section(name[:-1])
+ if not line or line.isspace():
+ # Line is just "SectionName:", no indent for following lines
+ indent = 0
+ line = ''
+ elif name.startswith("Example"):
+ # The "Examples" section is literal-text, so preserve
+ # all the indentation as-is
+ indent = 0
+ else:
+ # Line is "SectionName: some text", indent required
+ indent = len(name) + 1
+ line = ' ' * indent + line
+ self._start_section(name[:-1], indent)
self._append_freeform(line)
- def _start_symbol_section(self, symbols_dict, name):
+ def _start_symbol_section(self, symbols_dict, name, indent):
# FIXME invalid names other than the empty string aren't flagged
if not name:
raise QAPIParseError(self._parser, "invalid parameter name")
@@ -506,21 +553,21 @@ class QAPIDoc:
"'%s' parameter name duplicated" % name)
assert not self.sections
self._end_section()
- self._section = QAPIDoc.ArgSection(name)
+ self._section = QAPIDoc.ArgSection(self._parser, name, indent)
symbols_dict[name] = self._section
- def _start_args_section(self, name):
- self._start_symbol_section(self.args, name)
+ def _start_args_section(self, name, indent):
+ self._start_symbol_section(self.args, name, indent)
- def _start_features_section(self, name):
- self._start_symbol_section(self.features, name)
+ def _start_features_section(self, name, indent):
+ self._start_symbol_section(self.features, name, indent)
- def _start_section(self, name=None):
+ def _start_section(self, name=None, indent=0):
if name in ('Returns', 'Since') and self.has_section(name):
raise QAPIParseError(self._parser,
"duplicated '%s' section" % name)
self._end_section()
- self._section = QAPIDoc.Section(name)
+ self._section = QAPIDoc.Section(self._parser, name, indent)
self.sections.append(self._section)
def _end_section(self):
@@ -543,7 +590,7 @@ class QAPIDoc:
def connect_member(self, member):
if member.name not in self.args:
# Undocumented TODO outlaw
- self.args[member.name] = QAPIDoc.ArgSection(member.name)
+ self.args[member.name] = QAPIDoc.ArgSection(self._parser,
member.name)
self.args[member.name].connect(member)
def connect_feature(self, feature):
@@ -551,6 +598,8 @@ class QAPIDoc:
raise QAPISemError(feature.info,
"feature '%s' lacks documentation"
% feature.name)
+ self.features[feature.name] = QAPIDoc.ArgSection(self._parser,
+ feature.name)
self.features[feature.name].connect(feature)
def check_expr(self, expr):
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 0ef85d959ac..bbf77b08dc3 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -158,7 +158,7 @@ doc symbol=Alternate
arg=i
an integer
- @b is undocumented
+@b is undocumented
arg=b
feature=alt-feat
@@ -173,7 +173,7 @@ doc symbol=cmd
the first argument
arg=arg2
the second
- argument
+argument
arg=arg3
feature=cmd-feat1
--
2.20.1
- [PATCH v5 00/20] Convert QAPI doc comments to generate rST instead of texinfo, Peter Maydell, 2020/08/10
- [PATCH v5 01/20] qapi/migration.json: Fix indentation, Peter Maydell, 2020/08/10
- [PATCH v5 02/20] qapi: Fix indentation, again, Peter Maydell, 2020/08/10
- [PATCH v5 03/20] qapi/block-core.json: Fix nbd-server-start docs, Peter Maydell, 2020/08/10
- [PATCH v5 04/20] qapi/qapi-schema.json: Put headers in their own doc-comment blocks, Peter Maydell, 2020/08/10
- [PATCH v5 05/20] qapi/machine.json: Escape a literal '*' in doc comment, Peter Maydell, 2020/08/10
- [PATCH v5 06/20] tests/qapi/doc-good.json: Prepare for qapi-doc Sphinx extension, Peter Maydell, 2020/08/10
- [PATCH v5 07/20] scripts/qapi: Move doc-comment whitespace stripping to doc.py, Peter Maydell, 2020/08/10
- [PATCH v5 08/20] scripts/qapi/parser.py: improve doc comment indent handling,
Peter Maydell <=
- [PATCH v5 10/20] docs/interop: Convert qemu-ga-ref to rST, Peter Maydell, 2020/08/10
- [PATCH v5 09/20] docs/sphinx: Add new qapi-doc Sphinx extension, Peter Maydell, 2020/08/10
- [PATCH v5 11/20] docs/interop: Convert qemu-qmp-ref to rST, Peter Maydell, 2020/08/10
- [PATCH v5 12/20] qapi: Use rST markup for literal blocks, Peter Maydell, 2020/08/10
- [PATCH v5 13/20] qga/qapi-schema.json: Add some headings, Peter Maydell, 2020/08/10
- [PATCH v5 15/20] docs/devel/qapi-code-gen.txt: Update to new rST backend conventions, Peter Maydell, 2020/08/10
- [PATCH v5 14/20] scripts/qapi: Remove texinfo generation support, Peter Maydell, 2020/08/10
- [PATCH v5 16/20] Makefile: Remove redundant Texinfo related rules, Peter Maydell, 2020/08/10
- [PATCH v5 18/20] Remove Texinfo related files from .gitignore and git.orderfile, Peter Maydell, 2020/08/10