summary refs log tree commit diff stats
path: root/scripts/qapi.py
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2018-01-11 22:01:17 +0200
committerMichael S. Tsirkin <mst@redhat.com>2018-01-11 22:03:50 +0200
commitacc95bc85036c443da8bf7159a77edf9f00dcd80 (patch)
tree21965c6e60a2e29664b7685e52feacdb6a86e0bd /scripts/qapi.py
parent880b1ffe6ec2f0ae25cc4175716227ad275e8b8a (diff)
parent997eba28a3ed5400a80f754bf3a1c8044b75b9ff (diff)
downloadfocaccia-qemu-acc95bc85036c443da8bf7159a77edf9f00dcd80.tar.gz
focaccia-qemu-acc95bc85036c443da8bf7159a77edf9f00dcd80.zip
Merge remote-tracking branch 'origin/master' into HEAD
Resolve conflicts around apb.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'scripts/qapi.py')
-rw-r--r--scripts/qapi.py107
1 files changed, 49 insertions, 58 deletions
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 62dc52ed6e..43a54bf40f 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -106,13 +106,10 @@ class QAPIDoc(object):
             # optional section name (argument/member or section name)
             self.name = name
             # the list of lines for this section
-            self.content = []
+            self.text = ''
 
         def append(self, line):
-            self.content.append(line)
-
-        def __repr__(self):
-            return '\n'.join(self.content).strip()
+            self.text += line.rstrip() + '\n'
 
     class ArgSection(Section):
         def __init__(self, name):
@@ -123,11 +120,11 @@ class QAPIDoc(object):
             self.member = member
 
     def __init__(self, parser, info):
-        # self.parser is used to report errors with QAPIParseError.  The
+        # self._parser is used to report errors with QAPIParseError.  The
         # resulting error position depends on the state of the parser.
         # It happens to be the beginning of the comment.  More or less
         # servicable, but action at a distance.
-        self.parser = parser
+        self._parser = parser
         self.info = info
         self.symbol = None
         self.body = QAPIDoc.Section()
@@ -136,7 +133,7 @@ class QAPIDoc(object):
         # a list of Section
         self.sections = []
         # the current section
-        self.section = self.body
+        self._section = self.body
 
     def has_section(self, name):
         """Return True if we have a section with this name."""
@@ -153,20 +150,20 @@ class QAPIDoc(object):
             return
 
         if line[0] != ' ':
-            raise QAPIParseError(self.parser, "Missing space after #")
+            raise QAPIParseError(self._parser, "Missing space after #")
         line = line[1:]
 
         # FIXME not nice: things like '#  @foo:' and '# @foo: ' aren't
         # recognized, and get silently treated as ordinary text
         if self.symbol:
             self._append_symbol_line(line)
-        elif not self.body.content and line.startswith('@'):
+        elif not self.body.text and line.startswith('@'):
             if not line.endswith(':'):
-                raise QAPIParseError(self.parser, "Line should end with :")
+                raise QAPIParseError(self._parser, "Line should end with :")
             self.symbol = line[1:-1]
             # FIXME invalid names other than the empty string aren't flagged
             if not self.symbol:
-                raise QAPIParseError(self.parser, "Invalid name")
+                raise QAPIParseError(self._parser, "Invalid name")
         else:
             self._append_freeform(line)
 
@@ -192,53 +189,48 @@ class QAPIDoc(object):
     def _start_args_section(self, name):
         # FIXME invalid names other than the empty string aren't flagged
         if not name:
-            raise QAPIParseError(self.parser, "Invalid parameter name")
+            raise QAPIParseError(self._parser, "Invalid parameter name")
         if name in self.args:
-            raise QAPIParseError(self.parser,
+            raise QAPIParseError(self._parser,
                                  "'%s' parameter name duplicated" % name)
         if self.sections:
-            raise QAPIParseError(self.parser,
+            raise QAPIParseError(self._parser,
                                  "'@%s:' can't follow '%s' section"
                                  % (name, self.sections[0].name))
         self._end_section()
-        self.section = QAPIDoc.ArgSection(name)
-        self.args[name] = self.section
+        self._section = QAPIDoc.ArgSection(name)
+        self.args[name] = self._section
 
-    def _start_section(self, name=''):
+    def _start_section(self, name=None):
         if name in ('Returns', 'Since') and self.has_section(name):
-            raise QAPIParseError(self.parser,
+            raise QAPIParseError(self._parser,
                                  "Duplicated '%s' section" % name)
         self._end_section()
-        self.section = QAPIDoc.Section(name)
-        self.sections.append(self.section)
+        self._section = QAPIDoc.Section(name)
+        self.sections.append(self._section)
 
     def _end_section(self):
-        if self.section:
-            contents = str(self.section)
-            if self.section.name and (not contents or contents.isspace()):
-                raise QAPIParseError(self.parser, "Empty doc section '%s'"
-                                     % self.section.name)
-            self.section = None
+        if self._section:
+            text = self._section.text = self._section.text.strip()
+            if self._section.name and (not text or text.isspace()):
+                raise QAPIParseError(self._parser, "Empty doc section '%s'"
+                                     % self._section.name)
+            self._section = None
 
     def _append_freeform(self, line):
-        in_arg = isinstance(self.section, QAPIDoc.ArgSection)
-        if (in_arg and self.section.content
-                and not self.section.content[-1]
+        in_arg = isinstance(self._section, QAPIDoc.ArgSection)
+        if (in_arg and self._section.text.endswith('\n\n')
                 and line and not line[0].isspace()):
             self._start_section()
-        if (in_arg or not self.section.name
-                or not self.section.name.startswith('Example')):
+        if (in_arg or not self._section.name
+                or not self._section.name.startswith('Example')):
             line = line.strip()
         match = re.match(r'(@\S+:)', line)
         if match:
-            raise QAPIParseError(self.parser,
+            raise QAPIParseError(self._parser,
                                  "'%s' not allowed in free-form documentation"
                                  % match.group(1))
-        # TODO Drop this once the dust has settled
-        if (isinstance(self.section, QAPIDoc.ArgSection)
-                and '#optional' in line):
-            raise QAPISemError(self.info, "Please drop the #optional tag")
-        self.section.append(line)
+        self._section.append(line)
 
     def connect_member(self, member):
         if member.name not in self.args:
@@ -265,8 +257,7 @@ class QAPISchemaParser(object):
 
     def __init__(self, fp, previously_included=[], incl_info=None):
         abs_fname = os.path.abspath(fp.name)
-        fname = fp.name
-        self.fname = fname
+        self.fname = fp.name
         previously_included.append(abs_fname)
         self.incl_info = incl_info
         self.src = fp.read()
@@ -277,21 +268,21 @@ class QAPISchemaParser(object):
         self.line_pos = 0
         self.exprs = []
         self.docs = []
-        self.cur_doc = None
         self.accept()
+        cur_doc = None
 
         while self.tok is not None:
-            info = {'file': fname, 'line': self.line,
+            info = {'file': self.fname, 'line': self.line,
                     'parent': self.incl_info}
             if self.tok == '#':
-                self.reject_expr_doc()
-                self.cur_doc = self.get_doc(info)
-                self.docs.append(self.cur_doc)
+                self.reject_expr_doc(cur_doc)
+                cur_doc = self.get_doc(info)
+                self.docs.append(cur_doc)
                 continue
 
             expr = self.get_expr(False)
             if 'include' in expr:
-                self.reject_expr_doc()
+                self.reject_expr_doc(cur_doc)
                 if len(expr) != 1:
                     raise QAPISemError(info, "Invalid 'include' directive")
                 include = expr['include']
@@ -301,7 +292,7 @@ class QAPISchemaParser(object):
                 self._include(include, info, os.path.dirname(abs_fname),
                               previously_included)
             elif "pragma" in expr:
-                self.reject_expr_doc()
+                self.reject_expr_doc(cur_doc)
                 if len(expr) != 1:
                     raise QAPISemError(info, "Invalid 'pragma' directive")
                 pragma = expr['pragma']
@@ -313,22 +304,22 @@ class QAPISchemaParser(object):
             else:
                 expr_elem = {'expr': expr,
                              'info': info}
-                if self.cur_doc:
-                    if not self.cur_doc.symbol:
+                if cur_doc:
+                    if not cur_doc.symbol:
                         raise QAPISemError(
-                            self.cur_doc.info,
-                            "Expression documentation required")
-                    expr_elem['doc'] = self.cur_doc
+                            cur_doc.info, "Expression documentation required")
+                    expr_elem['doc'] = cur_doc
                 self.exprs.append(expr_elem)
-            self.cur_doc = None
-        self.reject_expr_doc()
+            cur_doc = None
+        self.reject_expr_doc(cur_doc)
 
-    def reject_expr_doc(self):
-        if self.cur_doc and self.cur_doc.symbol:
+    @staticmethod
+    def reject_expr_doc(doc):
+        if doc and doc.symbol:
             raise QAPISemError(
-                self.cur_doc.info,
+                doc.info,
                 "Documentation for '%s' is not followed by the definition"
-                % self.cur_doc.symbol)
+                % doc.symbol)
 
     def _include(self, include, info, base_dir, previously_included):
         incl_abs_fname = os.path.join(base_dir, include)