Cajole the QAPI Doc parser into yelping if a QAPI Doc Block contains two
or more paragraphs of plaintext and has no instances of Members, Errors,
Returns, or Features that would naturally delineate an introduction from
additional details such as notes, examples, and additional details.
Such locations do not currently *guarantee* a difference to rendered
manual output, but later changes to the documentation generator that may
include additional auto-generated sections, and complexities from the
inliner, may increase the odds that these locations are suspect and will
need to be explicitly delineated.
Signed-off-by: John Snow <jsnow@redhat.com>
---
[Review notes: no changes to *.ir files. --js]
Signed-off-by: John Snow <jsnow@redhat.com>
---
scripts/qapi/parser.py | 49 ++++++++++++++++++++++
tests/qapi-schema/doc-missing-details.err | 0
tests/qapi-schema/doc-missing-details.json | 3 ++
tests/qapi-schema/doc-missing-details.out | 11 +++++
tests/qapi-schema/meson.build | 1 +
5 files changed, 64 insertions(+)
create mode 100644 tests/qapi-schema/doc-missing-details.err
create mode 100644 tests/qapi-schema/doc-missing-details.json
create mode 100644 tests/qapi-schema/doc-missing-details.out
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 1d52d80e672..ade26d124df 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -32,6 +32,8 @@
from .source import QAPISourceInfo
+# pylint: disable=too-many-lines
+
if TYPE_CHECKING:
# pylint: disable=cyclic-import
# TODO: Remove cycle. [schema -> expr -> parser -> schema]
@@ -962,3 +964,50 @@ def check_args_section(
check_args_section(self.args, 'member')
check_args_section(self.features, 'feature')
+
+ # Ignore free-form documentation sections
+ if self.symbol is None:
+ return
+
+ n_intro_para = 0
+ has_intro = False
+ has_other = False
+
+ for section in self.all_sections:
+ # Ignore Since: and TODO: sections
+ if section.kind in (QAPIDoc.Kind.SINCE, QAPIDoc.Kind.TODO):
+ continue
+
+ # Ignore empty plaintext sections
+ if section.kind in (QAPIDoc.Kind.INTRO, QAPIDoc.Kind.DETAILS):
+ if not section.text:
+ continue
+
+ if section.kind == QAPIDoc.Kind.INTRO:
+ has_intro = True
+ n_intro_para = len(section.text.split("\n\n"))
+ else:
+ if section.kind == QAPIDoc.Kind.MEMBER and not section.text:
+ pass
+ elif section.kind == QAPIDoc.Kind.RETURNS and not section.text:
+ pass
+ else:
+ # This section is something other than an Intro section;
+ # but we explicitly exclude stub entries for members
+ # (undocumented fields with no text) from consideration
+ # because they were auto-generated; they are not useful
+ # for identifying the case "There are multiple intro
+ # paragraphs and no other explicit source sections."
+ has_other = True
+
+ # If an intro section is only a single paragraph, we are
+ # confident it is well and truly just an introduction. If we
+ # have a single, multi-paragraph intro section and *no other*
+ # explicit sections in source code, it is potentially a semantic
+ # goof-em-up where the intro and details sections have bled
+ # together. Warn about this case.
+ if has_intro and n_intro_para > 1 and not has_other:
+ print(
+ f"Warning: paragraphs for {self.symbol} are ambiguous "
+ "and could be either intro or details paragraphs."
+ )
diff --git a/tests/qapi-schema/doc-missing-details.err b/tests/qapi-schema/doc-missing-details.err
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/qapi-schema/doc-missing-details.json b/tests/qapi-schema/doc-missing-details.json
new file mode 100644
index 00000000000..02c14ee768d
--- /dev/null
+++ b/tests/qapi-schema/doc-missing-details.json
@@ -0,0 +1,3 @@
+# TODO / FIXME
+# This test intentionally triggers the parser warning
+# suggesting we use the Details: marker.
diff --git a/tests/qapi-schema/doc-missing-details.out b/tests/qapi-schema/doc-missing-details.out
new file mode 100644
index 00000000000..52ca7cb8727
--- /dev/null
+++ b/tests/qapi-schema/doc-missing-details.out
@@ -0,0 +1,11 @@
+module ./builtin
+object q_empty
+enum QType
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
+module doc-missing-details.json
diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index c233d77ab78..01da8534f2e 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -85,6 +85,7 @@ schemas = [
'doc-long-line.json',
'doc-misplaced-details.json',
'doc-missing-colon.json',
+ 'doc-missing-details.json',
'doc-missing-expr.json',
'doc-missing-space.json',
'doc-missing.json',
--
2.53.0