[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 15/40] qapi: Track owner of each object member
From: |
Markus Armbruster |
Subject: |
[Qemu-devel] [PULL 15/40] qapi: Track owner of each object member |
Date: |
Thu, 17 Dec 2015 09:33:20 +0100 |
From: Eric Blake <address@hidden>
Future commits will migrate semantic checking away from parsing
and over to the various QAPISchema*.check() methods. But to
report an error message about an incorrect semantic use of a
member of an object type, it helps to know which type, command,
or event owns the member. In particular, when a member is
inherited from a base type, it is desirable to associate the
member name with the base type (and not the type calling
member.check()).
Rather than packing additional information into the seen array
passed to each member.check() (as in seen[m.name] = {'member':m,
'owner':type}), it is easier to have each member track the name
of the owner type in the first place (keeping things simpler
with the existing seen[m.name] = m). The new member.owner field
is set via a new set_owner() method, called when registering
the members and variants arrays with an object or variant type.
Track only a name, and not the actual type object, to avoid
creating a circular python reference chain.
Note that Variants.set_owner() method does not set the owner
for the tag_member field; this field is set earlier either as
part of an object's non-variant members, or explicitly by
alternates.
The source information is intended for human consumption in
error messages, and a new describe() method is added to access
the resulting information. For example, given the qapi:
{ 'command': 'foo', 'data': { 'string': 'str' } }
an implementation of visit_command() that calls
arg_type.members[0].describe()
will see "'string' (parameter of foo)".
To make the human-readable name of implicit types work without
duplicating efforts, the describe() method has to reverse the
name of implicit types, via the helper _pretty_owner().
No change to generated code.
Signed-off-by: Eric Blake <address@hidden>
Message-Id: <address@hidden>
[Incorrect & unused -wrapper case in _pretty_owner() dropped]
Signed-off-by: Markus Armbruster <address@hidden>
---
scripts/qapi.py | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 6fc14be..77d3e0a 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -957,8 +957,10 @@ class QAPISchemaObjectType(QAPISchemaType):
assert base is None or isinstance(base, str)
for m in local_members:
assert isinstance(m, QAPISchemaObjectTypeMember)
- assert (variants is None or
- isinstance(variants, QAPISchemaObjectTypeVariants))
+ m.set_owner(name)
+ if variants is not None:
+ assert isinstance(variants, QAPISchemaObjectTypeVariants)
+ variants.set_owner(name)
self._base_name = base
self.base = None
self.local_members = local_members
@@ -1013,6 +1015,8 @@ class QAPISchemaObjectType(QAPISchemaType):
class QAPISchemaObjectTypeMember(object):
+ role = 'member'
+
def __init__(self, name, typ, optional):
assert isinstance(name, str)
assert isinstance(typ, str)
@@ -1021,8 +1025,14 @@ class QAPISchemaObjectTypeMember(object):
self._type_name = typ
self.type = None
self.optional = optional
+ self.owner = None
+
+ def set_owner(self, name):
+ assert not self.owner
+ self.owner = name
def check(self, schema):
+ assert self.owner
self.type = schema.lookup_type(self._type_name)
assert self.type
@@ -1031,6 +1041,23 @@ class QAPISchemaObjectTypeMember(object):
assert self.name not in seen
seen[self.name] = self
+ def _pretty_owner(self):
+ owner = self.owner
+ if owner.startswith(':obj-'):
+ # See QAPISchema._make_implicit_object_type() - reverse the
+ # mapping there to create a nice human-readable description
+ owner = owner[5:]
+ if owner.endswith('-arg'):
+ return '(parameter of %s)' % owner[:-4]
+ else:
+ assert owner.endswith('-wrapper')
+ # Unreachable and not implemented
+ assert False
+ return '(%s of %s)' % (self.role, owner)
+
+ def describe(self):
+ return "'%s' %s" % (self.name, self._pretty_owner())
+
class QAPISchemaObjectTypeVariants(object):
def __init__(self, tag_name, tag_member, variants):
@@ -1047,6 +1074,10 @@ class QAPISchemaObjectTypeVariants(object):
self.tag_member = tag_member
self.variants = variants
+ def set_owner(self, name):
+ for v in self.variants:
+ v.set_owner(name)
+
def check(self, schema, seen):
if not self.tag_member: # flat union
self.tag_member = seen[self.tag_name]
@@ -1066,6 +1097,8 @@ class QAPISchemaObjectTypeVariants(object):
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
+ role = 'branch'
+
def __init__(self, name, typ):
QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
@@ -1085,6 +1118,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
QAPISchemaType.__init__(self, name, info)
assert isinstance(variants, QAPISchemaObjectTypeVariants)
assert not variants.tag_name
+ variants.set_owner(name)
+ variants.tag_member.set_owner(self.name)
self.variants = variants
def check(self, schema):
@@ -1217,6 +1252,7 @@ class QAPISchema(object):
def _make_implicit_object_type(self, name, info, role, members):
if not members:
return None
+ # See also QAPISchemaObjectTypeMember._pretty_owner()
name = ':obj-%s-%s' % (name, role)
if not self.lookup_entity(name, QAPISchemaObjectType):
self._def_entity(QAPISchemaObjectType(name, info, None,
--
2.4.3
- [Qemu-devel] [PULL 32/40] qapi: Inline _make_implicit_tag(), (continued)
- [Qemu-devel] [PULL 32/40] qapi: Inline _make_implicit_tag(), Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 14/40] qapi: Remove outdated tests related to QMP/branch collisions, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 08/40] qapi: Eliminate QAPISchemaObjectType.check() variable members, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 13/40] qapi: Hoist tag collision check to Variants.check(), Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 21/40] qapi: Tighten the regex on valid names, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 23/40] qapi: Remove obsolete tests for MAX collision, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 31/40] qapi-types: Drop unnedeed ._fwdefn, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 11/40] qapi: Check for QAPI collisions involving variant members, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 20/40] blkdebug: Avoid '.' in enum values, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 16/40] qapi: Detect collisions in C member names, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 15/40] qapi: Track owner of each object member,
Markus Armbruster <=
- [Qemu-devel] [PULL 28/40] qobject: Rename qtype_code to QType, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 35/40] qapi: Shorter visits of optional fields, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 34/40] qapi: Simplify visits of optional fields, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 27/40] qobject: Simplify QObject, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 39/40] qapi: Move duplicate collision checks to schema check(), Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 29/40] qapi: Convert QType into QAPI built-in enum type, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 37/40] qapi: Track enum values by QAPISchemaMember, not string, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 40/40] qapi: Detect base class loops, Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 33/40] qapi: Fix alternates that accept 'number' but not 'int', Markus Armbruster, 2015/12/17
- [Qemu-devel] [PULL 38/40] qapi: Enforce (or whitelist) case conventions on qapi members, Markus Armbruster, 2015/12/17