This patch begins distinguishing "Plain" sections as being either "Intro" or "Details" sections for the purpose of knowing when/where/how to inline those sections.
The Intro section is always the first section of any doc block. It may be empty or any number of paragraphs. It is interrupted by any other non-plaintext section, i.e.; Members, Features, Errors, Returns, Since, and TODO. The details section, when present, is either the last section or the second-to-last section when a "Since:" section is present. It consists of any plain text in the doc block that follows any named sections if present. Signed-off-by: John Snow <[email protected]> --- docs/sphinx/qapidoc.py | 2 +- scripts/qapi/parser.py | 35 +++++++++++++++++++++++----------- tests/qapi-schema/doc-good.out | 8 ++++---- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index c2f09bac16c..e359836f110 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -368,7 +368,7 @@ def visit_sections(self, ent: QAPISchemaDefinition) -> None: for i, section in enumerate(sections): section.text = self.reformat_arobase(section.text) - if section.kind == QAPIDoc.Kind.PLAIN: + if section.kind.name in ("INTRO", "DETAILS"): self.visit_paragraph(section) elif section.kind == QAPIDoc.Kind.MEMBER: assert isinstance(section, QAPIDoc.ArgSection) diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index c3cf33904ef..da0ac32ad89 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -544,7 +544,7 @@ def get_doc(self) -> 'QAPIDoc': doc = QAPIDoc(info, symbol) self.accept(False) line = self.get_doc_line() - no_more_args = False + have_tagged = False while line is not None: # Blank lines @@ -573,10 +573,10 @@ def get_doc(self) -> 'QAPIDoc': if not doc.features: raise QAPIParseError( self, 'feature descriptions expected') - no_more_args = True + have_tagged = True elif match := self._match_at_name_colon(line): # description - if no_more_args: + if have_tagged: raise QAPIParseError( self, "description of '@%s:' follows a section" @@ -588,7 +588,7 @@ def get_doc(self) -> 'QAPIDoc': if text: doc.append_line(text) line = self.get_doc_indented(doc) - no_more_args = True + have_tagged = True elif match := re.match( r'(Returns|Errors|Since|Notes?|Examples?|TODO)' r'(?!::): *', @@ -629,10 +629,14 @@ def get_doc(self) -> 'QAPIDoc': if text: doc.append_line(text) line = self.get_doc_indented(doc) - no_more_args = True + have_tagged = True else: # plain paragraph - doc.ensure_untagged_section(self.info) + + # Paragraphs before tagged sections are "intro" paragraphs. + # Any appearing after are "detail" paragraphs. + intro = not have_tagged + doc.ensure_untagged_section(self.info, intro) doc.append_line(line) line = self.get_doc_paragraph(doc) else: @@ -674,13 +678,14 @@ class QAPIDoc: """ class Kind(enum.Enum): - PLAIN = 0 + INTRO = 0 MEMBER = 1 FEATURE = 2 RETURNS = 3 ERRORS = 4 SINCE = 5 TODO = 6 + DETAILS = 7 @staticmethod def from_string(kind: str) -> 'QAPIDoc.Kind': @@ -730,7 +735,7 @@ def __init__(self, info: QAPISourceInfo, symbol: Optional[str] = None): self.symbol: Optional[str] = symbol # the sections in textual order self.all_sections: List[QAPIDoc.Section] = [ - QAPIDoc.Section(info, QAPIDoc.Kind.PLAIN) + QAPIDoc.Section(info, QAPIDoc.Kind.INTRO) ] # the body section self.body: Optional[QAPIDoc.Section] = self.all_sections[0] @@ -748,12 +753,20 @@ def __init__(self, info: QAPISourceInfo, symbol: Optional[str] = None): def end(self) -> None: for section in self.all_sections: section.text = section.text.strip('\n') - if section.kind != QAPIDoc.Kind.PLAIN and section.text == '': + if ( + section.kind not in ( + QAPIDoc.Kind.INTRO, QAPIDoc.Kind.DETAILS + ) and section.text == '' + ): raise QAPISemError( section.info, "text required after '%s:'" % section.kind) - def ensure_untagged_section(self, info: QAPISourceInfo) -> None: - kind = QAPIDoc.Kind.PLAIN + def ensure_untagged_section( + self, + info: QAPISourceInfo, + intro: bool = True, + ) -> None: + kind = QAPIDoc.Kind.INTRO if intro else QAPIDoc.Kind.DETAILS if self.all_sections and self.all_sections[-1].kind == kind: # extend current section diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 04a55072646..04e29e8d50f 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -116,7 +116,7 @@ The _one_ {and only}, description on the same line Also _one_ {and only} feature=enum-member-feat a member feature - section=Plain + section=Details @two is undocumented doc symbol=Base body= @@ -175,7 +175,7 @@ description starts on the same line a feature feature=cmd-feat2 another feature - section=Plain + section=Details .. note:: @arg3 is undocumented section=Returns @Object @@ -183,7 +183,7 @@ another feature some section=Todo frobnicate - section=Plain + section=Details .. admonition:: Notes - Lorem ipsum dolor sit amet @@ -216,7 +216,7 @@ If you're bored enough to read this, go see a video of boxed cats a feature feature=cmd-feat2 another feature - section=Plain + section=Details .. qmp-example:: -> "this example" -- 2.53.0
