The patch makes possible to avoid introducing dummy empty types
for the flat union branches that have no data.
Signed-off-by: Anton Nefedov <***@virtuozzo.com>
---
scripts/qapi/common.py | 18 ++++++++++++------
scripts/qapi/doc.py | 2 +-
scripts/qapi/types.py | 2 +-
scripts/qapi/visit.py | 12 +++++++-----
tests/qapi-schema/test-qapi.py | 2 +-
5 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index a032cec..ec5cf28 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -721,6 +721,7 @@ def check_union(expr, info):
name = expr['union']
base = expr.get('base')
discriminator = expr.get('discriminator')
+ partial = expr.get('data-partial', False)
members = expr['data']
# Two types of unions, determined by discriminator.
@@ -783,7 +784,7 @@ def check_union(expr, info):
% (key, enum_define['enum']))
# If discriminator is user-defined, ensure all values are covered
- if enum_define:
+ if enum_define and not partial:
for value in enum_define['data']:
if value not in members.keys():
raise QAPISemError(info, "Union '%s' data missing '%s' branch"
@@ -909,7 +910,7 @@ def check_exprs(exprs):
elif 'union' in expr:
meta = 'union'
check_keys(expr_elem, 'union', ['data'],
- ['base', 'discriminator'])
+ ['base', 'discriminator', 'data-partial'])
union_types[expr[meta]] = expr
elif 'alternate' in expr:
meta = 'alternate'
@@ -1035,7 +1036,7 @@ class QAPISchemaVisitor(object):
def visit_array_type(self, name, info, element_type):
pass
- def visit_object_type(self, name, info, base, members, variants):
+ def visit_object_type(self, name, info, base, members, variants, partial):
pass
def visit_object_type_flat(self, name, info, members, variants):
@@ -1192,7 +1193,8 @@ class QAPISchemaArrayType(QAPISchemaType):
class QAPISchemaObjectType(QAPISchemaType):
- def __init__(self, name, info, doc, base, local_members, variants):
+ def __init__(self, name, info, doc, base, local_members, variants,
+ partial = False):
# struct has local_members, optional base, and no variants
# flat union has base, variants, and no local_members
# simple union has local_members, variants, and no base
@@ -1209,6 +1211,7 @@ class QAPISchemaObjectType(QAPISchemaType):
self.local_members = local_members
self.variants = variants
self.members = None
+ self.partial = partial
def check(self, schema):
if self.members is False: # check for cycles
@@ -1269,7 +1272,8 @@ class QAPISchemaObjectType(QAPISchemaType):
def visit(self, visitor):
visitor.visit_object_type(self.name, self.info,
- self.base, self.local_members, self.variants)
+ self.base, self.local_members, self.variants,
+ self.partial)
visitor.visit_object_type_flat(self.name, self.info,
self.members, self.variants)
@@ -1636,6 +1640,7 @@ class QAPISchema(object):
name = expr['union']
data = expr['data']
base = expr.get('base')
+ partial = expr.get('data-partial', False)
tag_name = expr.get('discriminator')
tag_member = None
if isinstance(base, dict):
@@ -1656,7 +1661,8 @@ class QAPISchema(object):
QAPISchemaObjectType(name, info, doc, base, members,
QAPISchemaObjectTypeVariants(tag_name,
tag_member,
- variants)))
+ variants),
+ partial))
def _def_alternate_type(self, expr, info, doc):
name = expr['alternate']
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 9b312b2..40dffc4 100644
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -211,7 +211,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
body=texi_entity(doc, 'Values',
member_func=texi_enum_value)))
- def visit_object_type(self, name, info, base, members, variants):
+ def visit_object_type(self, name, info, base, members, variants, partial):
doc = self.cur_doc
if base and base.is_implicit():
base = None
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 64d9c0f..e805509 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -215,7 +215,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
self._genh.add(gen_array(name, element_type))
self._gen_type_cleanup(name)
- def visit_object_type(self, name, info, base, members, variants):
+ def visit_object_type(self, name, info, base, members, variants, partial):
# Nothing to do for the special empty builtin
if name == 'q_empty':
return
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 5d72d89..3ee64bb 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -34,7 +34,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp);
c_name=c_name(name))
-def gen_visit_object_members(name, base, members, variants):
+def gen_visit_object_members(name, base, members, variants, partial):
ret = mcgen('''
void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
@@ -93,9 +93,10 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
ret += mcgen('''
default:
- abort();
+ %(action)s
}
-''')
+''',
+ action="break;" if partial else "abort();")
# 'goto out' produced for base, for each member, and if variants were
# present
@@ -309,12 +310,13 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
self._genh.add(gen_visit_decl(name))
self._genc.add(gen_visit_list(name, element_type))
- def visit_object_type(self, name, info, base, members, variants):
+ def visit_object_type(self, name, info, base, members, variants, partial):
# Nothing to do for the special empty builtin
if name == 'q_empty':
return
self._genh.add(gen_visit_members_decl(name))
- self._genc.add(gen_visit_object_members(name, base, members, variants))
+ self._genc.add(gen_visit_object_members(name, base, members, variants,
+ partial))
# TODO Worth changing the visitor signature, so we could
# directly use rather than repeat type.is_implicit()?
if not name.startswith('q_'):
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index c1a144b..95cd575 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -28,7 +28,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
if prefix:
print(' prefix %s' % prefix)
- def visit_object_type(self, name, info, base, members, variants):
+ def visit_object_type(self, name, info, base, members, variants, partial):
print('object %s' % name)
if base:
print(' base %s' % base.name)
--
2.7.4