Browse Source

qapi: Add documentation format validation

Add explicit validation for QAPI documentation formatting rules:

1. Lines must not exceed 70 columns in width (including '# ' prefix)
2. Sentences must be separated by two spaces

Example sections and literal :: blocks (seldom case) are excluded, we
don't require them to be <= 70, that would be too restrictive. Anyway,
they share common 80-columns recommendations (not requirements).

Add two simple tests, illustrating the change.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Message-ID: <20251031183129.246814-1-vsementsov@yandex-team.ru>

The detection of example and literal blocks isn't quite correct, but
it works well enough, and we can improve on top.

Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Comments, error messages, and test file names tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
pull/307/head
Vladimir Sementsov-Ogievskiy 5 months ago
committed by Markus Armbruster
parent
commit
8107ba47fd
  1. 50
      scripts/qapi/parser.py
  2. 2
      tests/qapi-schema/doc-bad-space-between-sentences.err
  3. 6
      tests/qapi-schema/doc-bad-space-between-sentences.json
  4. 0
      tests/qapi-schema/doc-bad-space-between-sentences.out
  5. 1
      tests/qapi-schema/doc-long-line.err
  6. 6
      tests/qapi-schema/doc-long-line.json
  7. 0
      tests/qapi-schema/doc-long-line.out
  8. 2
      tests/qapi-schema/meson.build

50
scripts/qapi/parser.py

@ -108,6 +108,11 @@ class QAPISchemaParser:
self.exprs: List[QAPIExpression] = []
self.docs: List[QAPIDoc] = []
# State for tracking qmp-example blocks and simple
# :: literal blocks.
self._literal_mode = False
self._literal_mode_indent = 0
# Showtime!
self._parse()
@ -423,12 +428,55 @@ class QAPISchemaParser:
if self.val != '##':
raise QAPIParseError(
self, "junk after '##' at end of documentation comment")
self._literal_mode = False
return None
if self.val == '#':
return ''
if self.val[1] != ' ':
raise QAPIParseError(self, "missing space after #")
return self.val[2:].rstrip()
line = self.val[2:].rstrip()
if re.match(r'(\.\. +qmp-example)? *::$', line):
self._literal_mode = True
self._literal_mode_indent = 0
elif self._literal_mode and line:
indent = re.match(r'^ *', line).end()
if self._literal_mode_indent == 0:
self._literal_mode_indent = indent
elif indent < self._literal_mode_indent:
# ReST directives stop at decreasing indentation
self._literal_mode = False
if not self._literal_mode:
self._validate_doc_line_format(line)
return line
def _validate_doc_line_format(self, line: str) -> None:
"""
Validate documentation format rules for a single line:
1. Lines should not exceed 70 characters
2. Sentences should be separated by two spaces
"""
full_line_length = len(line) + 2 # "# " = 2 characters
if full_line_length > 70:
# Skip URL lines - they can't be broken
if re.match(r' *(https?|ftp)://[^ ]*$', line):
pass
else:
raise QAPIParseError(
self, "documentation line longer than 70 characters")
single_space_pattern = r'(\be\.g\.|^ *\d\.|([.!?])) [A-Z0-9(]'
for m in list(re.finditer(single_space_pattern, line)):
if not m.group(2):
continue
# HACK so the error message points to the offending spot
self.pos = self.line_pos + 2 + m.start(2) + 1
raise QAPIParseError(
self, "Use two spaces between sentences\n"
"If this not the end of a sentence, please report a bug.")
@staticmethod
def _match_at_name_colon(string: str) -> Optional[Match[str]]:

2
tests/qapi-schema/doc-bad-space-between-sentences.err

@ -0,0 +1,2 @@
doc-bad-space-between-sentences.json:4:47: Use two spaces between sentences
If this not the end of a sentence, please report a bug.

6
tests/qapi-schema/doc-bad-space-between-sentences.json

@ -0,0 +1,6 @@
##
# @foo:
#
# Sentences should be separated by two spaces. But here is only one.
##
{ 'command': 'foo' }

0
tests/qapi-schema/doc-bad-space-between-sentences.out

1
tests/qapi-schema/doc-long-line.err

@ -0,0 +1 @@
doc-long-line.json:4:1: documentation line longer than 70 characters

6
tests/qapi-schema/doc-long-line.json

@ -0,0 +1,6 @@
##
# @foo:
#
# This line has exactly 71 chars, including the leading hash and space.
##
{ 'command': 'foo' }

0
tests/qapi-schema/doc-long-line.out

2
tests/qapi-schema/meson.build

@ -61,6 +61,7 @@ schemas = [
'doc-bad-event-arg.json',
'doc-bad-feature.json',
'doc-bad-indent.json',
'doc-bad-space-between-sentences.json',
'doc-bad-symbol.json',
'doc-bad-union-member.json',
'doc-before-include.json',
@ -81,6 +82,7 @@ schemas = [
'doc-invalid-return2.json',
'doc-invalid-section.json',
'doc-invalid-start.json',
'doc-long-line.json',
'doc-missing-colon.json',
'doc-missing-expr.json',
'doc-missing-space.json',

Loading…
Cancel
Save