mirror of
https://github.com/qemu/qemu.git
synced 2026-02-15 13:46:35 +00:00
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>
This commit is contained in:
committed by
Markus Armbruster
parent
201a38d12b
commit
8107ba47fd
@@ -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
Normal file
2
tests/qapi-schema/doc-bad-space-between-sentences.err
Normal file
@@ -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
Normal file
6
tests/qapi-schema/doc-bad-space-between-sentences.json
Normal file
@@ -0,0 +1,6 @@
|
||||
##
|
||||
# @foo:
|
||||
#
|
||||
# Sentences should be separated by two spaces. But here is only one.
|
||||
##
|
||||
{ 'command': 'foo' }
|
||||
1
tests/qapi-schema/doc-long-line.err
Normal file
1
tests/qapi-schema/doc-long-line.err
Normal file
@@ -0,0 +1 @@
|
||||
doc-long-line.json:4:1: documentation line longer than 70 characters
|
||||
6
tests/qapi-schema/doc-long-line.json
Normal file
6
tests/qapi-schema/doc-long-line.json
Normal file
@@ -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
Normal file
0
tests/qapi-schema/doc-long-line.out
Normal file
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user