mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 04:13:53 -06:00
qapi: clean up encoding of section kinds
We have several kinds of sections, and to tell them apart, we use Section attribute @tag and also the section object's Python type: type @tag untagged Section None @foo: ArgSection 'foo' Returns: Section 'Returns' Errors: Section 'Errors' Since: Section 'Since' TODO: Section 'TODO' Note: * @foo can be a member or a feature description, depending on context. * tag == 'Since' can be a Since: section or a member or feature description. If it's a Section, it's the former, and if it's an ArgSection, it's the latter. Clean this up as follows. Move the member or feature name to new ArgSection attribute @name, and replace @tag by enum @kind like this: type kind name untagged Section PLAIN @foo: ArgSection MEMBER 'foo' if member or argument ArgSection FEATURE 'foo' if feature Returns: Section RETURNS Errors: Section ERRORS Since: Section SINCE TODO: Section TODO The qapi-schema tests are updated to account for the new section names; "TODO" becomes "Todo" and `None` becomes "Plain" there. Signed-off-by: John Snow <jsnow@redhat.com> Message-ID: <20250311034303.75779-34-jsnow@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
parent
faeacf858b
commit
323c668934
4 changed files with 80 additions and 36 deletions
|
@ -14,6 +14,7 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2.
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import enum
|
||||
import os
|
||||
import re
|
||||
from typing import (
|
||||
|
@ -574,7 +575,10 @@ class QAPISchemaParser:
|
|||
)
|
||||
raise QAPIParseError(self, emsg)
|
||||
|
||||
doc.new_tagged_section(self.info, match.group(1))
|
||||
doc.new_tagged_section(
|
||||
self.info,
|
||||
QAPIDoc.Kind.from_string(match.group(1))
|
||||
)
|
||||
text = line[match.end():]
|
||||
if text:
|
||||
doc.append_line(text)
|
||||
|
@ -585,7 +589,7 @@ class QAPISchemaParser:
|
|||
self,
|
||||
"unexpected '=' markup in definition documentation")
|
||||
else:
|
||||
# tag-less paragraph
|
||||
# plain paragraph
|
||||
doc.ensure_untagged_section(self.info)
|
||||
doc.append_line(line)
|
||||
line = self.get_doc_paragraph(doc)
|
||||
|
@ -634,14 +638,33 @@ class QAPIDoc:
|
|||
Free-form documentation blocks consist only of a body section.
|
||||
"""
|
||||
|
||||
class Kind(enum.Enum):
|
||||
PLAIN = 0
|
||||
MEMBER = 1
|
||||
FEATURE = 2
|
||||
RETURNS = 3
|
||||
ERRORS = 4
|
||||
SINCE = 5
|
||||
TODO = 6
|
||||
|
||||
@staticmethod
|
||||
def from_string(kind: str) -> 'QAPIDoc.Kind':
|
||||
return QAPIDoc.Kind[kind.upper()]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name.title()
|
||||
|
||||
class Section:
|
||||
# pylint: disable=too-few-public-methods
|
||||
def __init__(self, info: QAPISourceInfo,
|
||||
tag: Optional[str] = None):
|
||||
def __init__(
|
||||
self,
|
||||
info: QAPISourceInfo,
|
||||
kind: 'QAPIDoc.Kind',
|
||||
):
|
||||
# section source info, i.e. where it begins
|
||||
self.info = info
|
||||
# section tag, if any ('Returns', '@name', ...)
|
||||
self.tag = tag
|
||||
# section kind
|
||||
self.kind = kind
|
||||
# section text without tag
|
||||
self.text = ''
|
||||
|
||||
|
@ -649,8 +672,14 @@ class QAPIDoc:
|
|||
self.text += line + '\n'
|
||||
|
||||
class ArgSection(Section):
|
||||
def __init__(self, info: QAPISourceInfo, tag: str):
|
||||
super().__init__(info, tag)
|
||||
def __init__(
|
||||
self,
|
||||
info: QAPISourceInfo,
|
||||
kind: 'QAPIDoc.Kind',
|
||||
name: str
|
||||
):
|
||||
super().__init__(info, kind)
|
||||
self.name = name
|
||||
self.member: Optional['QAPISchemaMember'] = None
|
||||
|
||||
def connect(self, member: 'QAPISchemaMember') -> None:
|
||||
|
@ -662,7 +691,9 @@ class QAPIDoc:
|
|||
# definition doc's symbol, None for free-form doc
|
||||
self.symbol: Optional[str] = symbol
|
||||
# the sections in textual order
|
||||
self.all_sections: List[QAPIDoc.Section] = [QAPIDoc.Section(info)]
|
||||
self.all_sections: List[QAPIDoc.Section] = [
|
||||
QAPIDoc.Section(info, QAPIDoc.Kind.PLAIN)
|
||||
]
|
||||
# the body section
|
||||
self.body: Optional[QAPIDoc.Section] = self.all_sections[0]
|
||||
# dicts mapping parameter/feature names to their description
|
||||
|
@ -679,12 +710,14 @@ class QAPIDoc:
|
|||
def end(self) -> None:
|
||||
for section in self.all_sections:
|
||||
section.text = section.text.strip('\n')
|
||||
if section.tag is not None and section.text == '':
|
||||
if section.kind != QAPIDoc.Kind.PLAIN and section.text == '':
|
||||
raise QAPISemError(
|
||||
section.info, "text required after '%s:'" % section.tag)
|
||||
section.info, "text required after '%s:'" % section.kind)
|
||||
|
||||
def ensure_untagged_section(self, info: QAPISourceInfo) -> None:
|
||||
if self.all_sections and not self.all_sections[-1].tag:
|
||||
kind = QAPIDoc.Kind.PLAIN
|
||||
|
||||
if self.all_sections and self.all_sections[-1].kind == kind:
|
||||
# extend current section
|
||||
section = self.all_sections[-1]
|
||||
if not section.text:
|
||||
|
@ -692,46 +725,56 @@ class QAPIDoc:
|
|||
section.info = info
|
||||
section.text += '\n'
|
||||
return
|
||||
|
||||
# start new section
|
||||
section = self.Section(info)
|
||||
section = self.Section(info, kind)
|
||||
self.sections.append(section)
|
||||
self.all_sections.append(section)
|
||||
|
||||
def new_tagged_section(self, info: QAPISourceInfo, tag: str) -> None:
|
||||
section = self.Section(info, tag)
|
||||
if tag == 'Returns':
|
||||
def new_tagged_section(
|
||||
self,
|
||||
info: QAPISourceInfo,
|
||||
kind: 'QAPIDoc.Kind',
|
||||
) -> None:
|
||||
section = self.Section(info, kind)
|
||||
if kind == QAPIDoc.Kind.RETURNS:
|
||||
if self.returns:
|
||||
raise QAPISemError(
|
||||
info, "duplicated '%s' section" % tag)
|
||||
info, "duplicated '%s' section" % kind)
|
||||
self.returns = section
|
||||
elif tag == 'Errors':
|
||||
elif kind == QAPIDoc.Kind.ERRORS:
|
||||
if self.errors:
|
||||
raise QAPISemError(
|
||||
info, "duplicated '%s' section" % tag)
|
||||
info, "duplicated '%s' section" % kind)
|
||||
self.errors = section
|
||||
elif tag == 'Since':
|
||||
elif kind == QAPIDoc.Kind.SINCE:
|
||||
if self.since:
|
||||
raise QAPISemError(
|
||||
info, "duplicated '%s' section" % tag)
|
||||
info, "duplicated '%s' section" % kind)
|
||||
self.since = section
|
||||
self.sections.append(section)
|
||||
self.all_sections.append(section)
|
||||
|
||||
def _new_description(self, info: QAPISourceInfo, name: str,
|
||||
desc: Dict[str, ArgSection]) -> None:
|
||||
def _new_description(
|
||||
self,
|
||||
info: QAPISourceInfo,
|
||||
name: str,
|
||||
kind: 'QAPIDoc.Kind',
|
||||
desc: Dict[str, ArgSection]
|
||||
) -> None:
|
||||
if not name:
|
||||
raise QAPISemError(info, "invalid parameter name")
|
||||
if name in desc:
|
||||
raise QAPISemError(info, "'%s' parameter name duplicated" % name)
|
||||
section = self.ArgSection(info, '@' + name)
|
||||
section = self.ArgSection(info, kind, name)
|
||||
self.all_sections.append(section)
|
||||
desc[name] = section
|
||||
|
||||
def new_argument(self, info: QAPISourceInfo, name: str) -> None:
|
||||
self._new_description(info, name, self.args)
|
||||
self._new_description(info, name, QAPIDoc.Kind.MEMBER, self.args)
|
||||
|
||||
def new_feature(self, info: QAPISourceInfo, name: str) -> None:
|
||||
self._new_description(info, name, self.features)
|
||||
self._new_description(info, name, QAPIDoc.Kind.FEATURE, self.features)
|
||||
|
||||
def append_line(self, line: str) -> None:
|
||||
self.all_sections[-1].append_line(line)
|
||||
|
@ -744,7 +787,7 @@ class QAPIDoc:
|
|||
"%s '%s' lacks documentation"
|
||||
% (member.role, member.name))
|
||||
self.args[member.name] = QAPIDoc.ArgSection(
|
||||
self.info, '@' + member.name)
|
||||
self.info, QAPIDoc.Kind.MEMBER, member.name)
|
||||
self.args[member.name].connect(member)
|
||||
|
||||
def connect_feature(self, feature: 'QAPISchemaFeature') -> None:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue