diff options
Diffstat (limited to 'scripts/qapi/parser.py')
| -rw-r--r-- | scripts/qapi/parser.py | 97 | 
1 files changed, 70 insertions, 27 deletions
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py index 97def9f..94d5322 100644 --- a/scripts/qapi/parser.py +++ b/scripts/qapi/parser.py @@ -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:  | 
