qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 15/40] qapi: Track owner of each object member
Date: Thu, 17 Dec 2015 09:33:20 +0100	[thread overview]
Message-ID: <1450341225-2735-16-git-send-email-armbru@redhat.com> (raw)
In-Reply-To: <1450341225-2735-1-git-send-email-armbru@redhat.com>

From: Eric Blake <eblake@redhat.com>

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 <eblake@redhat.com>
Message-Id: <1447836791-369-16-git-send-email-eblake@redhat.com>
[Incorrect & unused -wrapper case in _pretty_owner() dropped]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 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

  parent reply	other threads:[~2015-12-17  8:34 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-17  8:33 [Qemu-devel] [PULL 00/40] QAPI patches for 2015-12-17 Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 01/40] qapi: Track simple union tag in object.local_members Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 02/40] qapi-types: Consolidate gen_struct() and gen_union() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 03/40] qapi-types: Simplify gen_struct_field[s] Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 04/40] qapi: Drop obsolete tag value collision assertions Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 05/40] qapi: Simplify QAPISchemaObjectTypeMember.check() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 06/40] qapi: Clean up after previous commit Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 07/40] qapi: Fix up commit 7618b91's clash sanity checking change Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 08/40] qapi: Eliminate QAPISchemaObjectType.check() variable members Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 09/40] qapi: Factor out QAPISchemaObjectTypeMember.check_clash() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 10/40] qapi: Simplify QAPISchemaObjectTypeVariants.check() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 11/40] qapi: Check for QAPI collisions involving variant members Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 12/40] qapi: Factor out QAPISchemaObjectType.check_clash() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 13/40] qapi: Hoist tag collision check to Variants.check() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 14/40] qapi: Remove outdated tests related to QMP/branch collisions Markus Armbruster
2015-12-17  8:33 ` Markus Armbruster [this message]
2015-12-17  8:33 ` [Qemu-devel] [PULL 16/40] qapi: Detect collisions in C member names Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 17/40] qapi: Fix c_name() munging Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 18/40] qapi: Remove dead visitor code Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 19/40] blkdebug: Merge hand-rolled and qapi BlkdebugEvent enum Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 20/40] blkdebug: Avoid '.' in enum values Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 21/40] qapi: Tighten the regex on valid names Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 22/40] qapi: Don't let implicit enum MAX member collide Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 23/40] qapi: Remove obsolete tests for MAX collision Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 24/40] cpu: Convert CpuInfo into flat union Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 25/40] qapi: Add alias for ErrorClass Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 26/40] qapi: Change munging of CamelCase enum values Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 27/40] qobject: Simplify QObject Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 28/40] qobject: Rename qtype_code to QType Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 29/40] qapi: Convert QType into QAPI built-in enum type Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 30/40] qapi: Simplify visiting of alternate types Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 31/40] qapi-types: Drop unnedeed ._fwdefn Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 32/40] qapi: Inline _make_implicit_tag() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 33/40] qapi: Fix alternates that accept 'number' but not 'int' Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 34/40] qapi: Simplify visits of optional fields Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 35/40] qapi: Shorter " Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 36/40] qapi: Prepare new QAPISchemaMember base class Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 37/40] qapi: Track enum values by QAPISchemaMember, not string Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 38/40] qapi: Enforce (or whitelist) case conventions on qapi members Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 39/40] qapi: Move duplicate collision checks to schema check() Markus Armbruster
2015-12-17  8:33 ` [Qemu-devel] [PULL 40/40] qapi: Detect base class loops Markus Armbruster
2015-12-17 12:39 ` [Qemu-devel] [PULL 00/40] QAPI patches for 2015-12-17 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1450341225-2735-16-git-send-email-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).