[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' ke
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members |
Date: |
Wed, 21 Mar 2018 12:51:46 +0100 |
Wherever a struct/union/alternate/command/event member with NAME: TYPE
form is accepted, desugar it to a NAME: { 'type': TYPE } form.
This will allow to add new member details, such as 'if' in the
following patch to introduce conditionals, or 'default' for default
values etc.
Signed-off-by: Marc-André Lureau <address@hidden>
---
scripts/qapi/common.py | 57 ++++++++++++-------
tests/Makefile.include | 3 +
tests/qapi-schema/alternate-invalid-dict.err | 1 +
tests/qapi-schema/alternate-invalid-dict.exit | 1 +
tests/qapi-schema/alternate-invalid-dict.json | 4 ++
tests/qapi-schema/alternate-invalid-dict.out | 0
tests/qapi-schema/event-nest-struct.err | 2 +-
tests/qapi-schema/flat-union-inline.err | 2 +-
tests/qapi-schema/nested-struct-data.err | 2 +-
tests/qapi-schema/qapi-schema-test.json | 10 ++--
.../struct-member-invalid-dict.err | 1 +
.../struct-member-invalid-dict.exit | 1 +
.../struct-member-invalid-dict.json | 3 +
.../struct-member-invalid-dict.out | 0
.../qapi-schema/union-branch-invalid-dict.err | 1 +
.../union-branch-invalid-dict.exit | 1 +
.../union-branch-invalid-dict.json | 4 ++
.../qapi-schema/union-branch-invalid-dict.out | 0
18 files changed, 66 insertions(+), 27 deletions(-)
create mode 100644 tests/qapi-schema/alternate-invalid-dict.err
create mode 100644 tests/qapi-schema/alternate-invalid-dict.exit
create mode 100644 tests/qapi-schema/alternate-invalid-dict.json
create mode 100644 tests/qapi-schema/alternate-invalid-dict.out
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.err
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.exit
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.json
create mode 100644 tests/qapi-schema/struct-member-invalid-dict.out
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.err
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.exit
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.json
create mode 100644 tests/qapi-schema/union-branch-invalid-dict.out
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 9eb2b0cc37..3f46ed5530 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -587,11 +587,11 @@ def discriminator_find_enum_define(expr):
if not base_members:
return None
- discriminator_type = base_members.get(discriminator)
- if not discriminator_type:
+ discriminator_member = base_members.get(discriminator)
+ if not discriminator_member:
return None
- return enum_types.get(discriminator_type)
+ return enum_types.get(discriminator_member['type'])
# Names must be letters, numbers, -, and _. They must start with letter,
@@ -659,6 +659,15 @@ def check_if(expr, info):
check_if_str(ifcond, info)
+def normalize_members(expr, field):
+ members = expr.get(field)
+ if isinstance(members, OrderedDict):
+ for key, arg in members.items():
+ if isinstance(arg, dict):
+ continue
+ members[key] = {'type': arg}
+
+
def check_type(info, source, value, allow_array=False,
allow_implicit=False, allow_optional=False,
allow_metas=[]):
@@ -703,8 +712,9 @@ def check_type(info, source, value, allow_array=False,
% (source, key))
# Todo: allow dictionaries to represent default values of
# an optional argument.
- check_type(info, "Member '%s' of %s" % (key, source), arg,
- allow_array=True,
+ member_source = "Member '%s' of %s" % (key, source)
+ check_known_keys(info, member_source, arg, ['type'], [])
+ check_type(info, member_source, arg['type'], allow_array=True,
allow_metas=['built-in', 'union', 'alternate', 'struct',
'enum'])
@@ -775,13 +785,13 @@ def check_union(expr, info):
# member of the base struct.
check_name(info, "Discriminator of flat union '%s'" % name,
discriminator)
- discriminator_type = base_members.get(discriminator)
- if not discriminator_type:
+ discriminator_member = base_members.get(discriminator)
+ if not discriminator_member:
raise QAPISemError(info,
"Discriminator '%s' is not a member of base "
"struct '%s'"
% (discriminator, base))
- enum_define = enum_types.get(discriminator_type)
+ enum_define = enum_types.get(discriminator_member['type'])
allow_metas = ['struct']
# Do not allow string discriminator
if not enum_define:
@@ -793,11 +803,14 @@ def check_union(expr, info):
if len(members) == 0:
raise QAPISemError(info, "Union '%s' cannot have empty 'data'" % name)
for (key, value) in members.items():
- check_name(info, "Member of union '%s'" % name, key)
+ source = "Member of union '%s'" % name
+ check_name(info, source, key)
+ check_known_keys(info, source, value, ['type'], [])
+ typ = value['type']
# Each value must name a known type
check_type(info, "Member '%s' of union '%s'" % (key, name),
- value, allow_array=not base, allow_metas=allow_metas)
+ typ, allow_array=not base, allow_metas=allow_metas)
# If the discriminator names an enum type, then all members
# of 'data' must also be members of the enum type.
@@ -828,18 +841,20 @@ def check_alternate(expr, info):
"in 'data'" % name)
for (key, value) in members.items():
check_name(info, "Member of alternate '%s'" % name, key)
+ source = "Member '%s' of alternate '%s'" % (key, name)
+ check_known_keys(info, source, value, ['type'], [])
+ typ = value['type']
# Ensure alternates have no type conflicts.
- check_type(info, "Member '%s' of alternate '%s'" % (key, name),
- value,
+ check_type(info, source, typ,
allow_metas=['built-in', 'union', 'struct', 'enum'])
- qtype = find_alternate_member_qtype(value)
+ qtype = find_alternate_member_qtype(typ)
if not qtype:
raise QAPISemError(info, "Alternate '%s' member '%s' cannot use "
- "type '%s'" % (name, key, value))
+ "type '%s'" % (name, key, typ))
conflicting = set([qtype])
if qtype == 'QTYPE_QSTRING':
- enum_expr = enum_types.get(value)
+ enum_expr = enum_types.get(typ)
if enum_expr:
for v in enum_get_names(enum_expr):
if v in ['on', 'off']:
@@ -952,6 +967,10 @@ def check_exprs(exprs):
info = expr_elem['info']
if 'enum' in expr:
normalize_enum(expr, info)
+ elif 'union' in expr:
+ normalize_members(expr, 'base')
+ if {'union', 'alternate', 'struct', 'command', 'event'} & set(expr):
+ normalize_members(expr, 'data')
# Learn the types and check for valid expression keys
for expr_elem in exprs:
@@ -1726,7 +1745,7 @@ class QAPISchema(object):
return QAPISchemaObjectTypeMember(name, typ, optional)
def _make_members(self, data, info):
- return [self._make_member(key, value, info)
+ return [self._make_member(key, value['type'], info)
for (key, value) in data.items()]
def _def_struct_type(self, expr, info, doc):
@@ -1762,11 +1781,11 @@ class QAPISchema(object):
name, info, doc, ifcond,
'base', self._make_members(base, info))
if tag_name:
- variants = [self._make_variant(key, value)
+ variants = [self._make_variant(key, value['type'])
for (key, value) in data.items()]
members = []
else:
- variants = [self._make_simple_variant(key, value, info)
+ variants = [self._make_simple_variant(key, value['type'], info)
for (key, value) in data.items()]
typ = self._make_implicit_enum_type(name, info, ifcond,
[v.name for v in variants])
@@ -1782,7 +1801,7 @@ class QAPISchema(object):
name = expr['alternate']
data = expr['data']
ifcond = expr.get('if')
- variants = [self._make_variant(key, value)
+ variants = [self._make_variant(key, value['type'])
for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
self._def_entity(
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 19873ea887..7a46c1620d 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -415,6 +415,7 @@ qapi-schema += alternate-conflict-string.json
qapi-schema += alternate-conflict-bool-string.json
qapi-schema += alternate-conflict-num-string.json
qapi-schema += alternate-empty.json
+qapi-schema += alternate-invalid-dict.json
qapi-schema += alternate-nested.json
qapi-schema += alternate-unknown.json
qapi-schema += args-alternate.json
@@ -556,6 +557,7 @@ qapi-schema += returns-whitelist.json
qapi-schema += struct-base-clash-deep.json
qapi-schema += struct-base-clash.json
qapi-schema += struct-data-invalid.json
+qapi-schema += struct-member-invalid-dict.json
qapi-schema += struct-member-invalid.json
qapi-schema += trailing-comma-list.json
qapi-schema += trailing-comma-object.json
@@ -567,6 +569,7 @@ qapi-schema += unicode-str.json
qapi-schema += union-base-empty.json
qapi-schema += union-base-no-discriminator.json
qapi-schema += union-branch-case.json
+qapi-schema += union-branch-invalid-dict.json
qapi-schema += union-clash-branches.json
qapi-schema += union-empty.json
qapi-schema += union-invalid-base.json
diff --git a/tests/qapi-schema/alternate-invalid-dict.err
b/tests/qapi-schema/alternate-invalid-dict.err
new file mode 100644
index 0000000000..39d3b6bca5
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-invalid-dict.json:2: Member 'two' of alternate
'Alt' must have 'type' key
diff --git a/tests/qapi-schema/alternate-invalid-dict.exit
b/tests/qapi-schema/alternate-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/alternate-invalid-dict.json
b/tests/qapi-schema/alternate-invalid-dict.json
new file mode 100644
index 0000000000..45f2c8ebef
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.json
@@ -0,0 +1,4 @@
+# invalid field dictionnary, missing type
+{ 'alternate': 'Alt',
+ 'data': { 'one': 'str',
+ 'two': { 'if': 'foo' } } }
diff --git a/tests/qapi-schema/alternate-invalid-dict.out
b/tests/qapi-schema/alternate-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/event-nest-struct.err
b/tests/qapi-schema/event-nest-struct.err
index 5a42701b8f..66cd141112 100644
--- a/tests/qapi-schema/event-nest-struct.err
+++ b/tests/qapi-schema/event-nest-struct.err
@@ -1 +1 @@
-tests/qapi-schema/event-nest-struct.json:1: Member 'a' of 'data' for event
'EVENT_A' should be a type name
+tests/qapi-schema/event-nest-struct.json:1: Member 'a' of 'data' for event
'EVENT_A' must have 'type' key
diff --git a/tests/qapi-schema/flat-union-inline.err
b/tests/qapi-schema/flat-union-inline.err
index 2333358d28..82d511c7ef 100644
--- a/tests/qapi-schema/flat-union-inline.err
+++ b/tests/qapi-schema/flat-union-inline.err
@@ -1 +1 @@
-tests/qapi-schema/flat-union-inline.json:7: Member 'value1' of union
'TestUnion' should be a type name
+tests/qapi-schema/flat-union-inline.json:7: Member of union 'TestUnion' must
have 'type' key
diff --git a/tests/qapi-schema/nested-struct-data.err
b/tests/qapi-schema/nested-struct-data.err
index da767bade2..728591fde3 100644
--- a/tests/qapi-schema/nested-struct-data.err
+++ b/tests/qapi-schema/nested-struct-data.err
@@ -1 +1 @@
-tests/qapi-schema/nested-struct-data.json:2: Member 'a' of 'data' for command
'foo' should be a type name
+tests/qapi-schema/nested-struct-data.json:2: Member 'a' of 'data' for command
'foo' must have 'type' key
diff --git a/tests/qapi-schema/qapi-schema-test.json
b/tests/qapi-schema/qapi-schema-test.json
index 6a1d3b6337..71023fb277 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -11,7 +11,7 @@
'guest-sync' ] } }
{ 'struct': 'TestStruct',
- 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
+ 'data': { 'integer': {'type': 'int'}, 'boolean': 'bool', 'string': 'str' } }
# for testing enums
{ 'struct': 'NestedEnumsOne',
@@ -74,7 +74,7 @@
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase', # intentional forward reference
'discriminator': 'enum1',
- 'data': { 'value1' : 'UserDefA',
+ 'data': { 'value1' : {'type': 'UserDefA'},
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
@@ -93,7 +93,7 @@
{ 'struct': 'WrapAlternate',
'data': { 'alt': 'UserDefAlternate' } }
{ 'alternate': 'UserDefAlternate',
- 'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int',
+ 'data': { 'udfu': {'type': 'UserDefFlatUnion'}, 'e': 'EnumOne', 'i': 'int',
'n': 'null' } }
{ 'struct': 'UserDefC',
@@ -129,7 +129,7 @@
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
{ 'command': 'user_def_cmd2',
- 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
+ 'data': {'ud1a': {'type': 'UserDefOne'}, '*ud1b': 'UserDefOne'},
'returns': 'UserDefTwo' }
# Returning a non-dictionary requires a name from the whitelist
@@ -156,7 +156,7 @@
# testing event
{ 'struct': 'EventStructOne',
- 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
+ 'data': { 'struct1': {'type': 'UserDefOne'}, 'string': 'str', '*enum2':
'EnumOne' } }
{ 'event': 'EVENT_A' }
{ 'event': 'EVENT_B',
diff --git a/tests/qapi-schema/struct-member-invalid-dict.err
b/tests/qapi-schema/struct-member-invalid-dict.err
new file mode 100644
index 0000000000..8435a78cb4
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-member-invalid-dict.json:2: Member '*a' of 'data' for
struct 'foo' must have 'type' key
diff --git a/tests/qapi-schema/struct-member-invalid-dict.exit
b/tests/qapi-schema/struct-member-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/struct-member-invalid-dict.json
b/tests/qapi-schema/struct-member-invalid-dict.json
new file mode 100644
index 0000000000..ebd9733b49
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.json
@@ -0,0 +1,3 @@
+# exploded member form must have a 'type'
+{ 'struct': 'foo',
+ 'data': { '*a': { 'case': 'foo' } } }
diff --git a/tests/qapi-schema/struct-member-invalid-dict.out
b/tests/qapi-schema/struct-member-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/union-branch-invalid-dict.err
b/tests/qapi-schema/union-branch-invalid-dict.err
new file mode 100644
index 0000000000..65f9999fc0
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-branch-invalid-dict.json:2: Member of union
'UnionInvalidBranch' must have 'type' key
diff --git a/tests/qapi-schema/union-branch-invalid-dict.exit
b/tests/qapi-schema/union-branch-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/union-branch-invalid-dict.json
b/tests/qapi-schema/union-branch-invalid-dict.json
new file mode 100644
index 0000000000..19c5d9cacd
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.json
@@ -0,0 +1,4 @@
+# exploded member form must have a 'type'
+{ 'union': 'UnionInvalidBranch',
+ 'data': { 'integer': { 'if': 'foo'},
+ 's8': 'int8' } }
diff --git a/tests/qapi-schema/union-branch-invalid-dict.out
b/tests/qapi-schema/union-branch-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--
2.16.2.521.g9aa15f885a
- [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely, (continued)
- [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys(), Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 20/49] qapi: add a dictionnary form with 'name' key for enum members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 21/49] qapi: add 'if' to enum members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 22/49] qapi-event: add 'if' condition to implicit event enum, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 23/49] qapi: rename allow_dict to allow_implicit, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 25/49] qapi: add 'if' to implicit struct members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members,
Marc-André Lureau <=
- [Qemu-devel] [PATCH v3 26/49] qapi: add an error in case a discriminator is conditionnal, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 27/49] qapi: add 'if' on union members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 28/49] qapi: add 'if' to alternate members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 29/49] qapi: add #if conditions to generated code members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 32/49] qapi2texi: add 'If:' condition to enum values, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 33/49] qapi2texi: add 'If:' condition to struct members, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 35/49] qapi: add conditions to VNC type/commands/events on the schema, Marc-André Lureau, 2018/03/21
- [Qemu-devel] [PATCH v3 34/49] qapi2texi: add condition to variants, Marc-André Lureau, 2018/03/21