From patchwork Mon Nov 2 22:41:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 539141 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 501E41402DD for ; Tue, 3 Nov 2015 09:42:48 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=comcast.net header.i=@comcast.net header.b=PuJ9Aenb; dkim-atps=neutral Received: from localhost ([::1]:44592 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtNoM-0004Av-5U for incoming@patchwork.ozlabs.org; Mon, 02 Nov 2015 17:42:46 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43672) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtNnl-0002zF-2s for qemu-devel@nongnu.org; Mon, 02 Nov 2015 17:42:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZtNnh-0003ex-Pt for qemu-devel@nongnu.org; Mon, 02 Nov 2015 17:42:09 -0500 Received: from resqmta-po-04v.sys.comcast.net ([96.114.154.163]:44334) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtNnh-0003en-L6 for qemu-devel@nongnu.org; Mon, 02 Nov 2015 17:42:05 -0500 Received: from resomta-po-18v.sys.comcast.net ([96.114.154.242]) by resqmta-po-04v.sys.comcast.net with comcast id cmhj1r0085E3ZMc01mi40d; Mon, 02 Nov 2015 22:42:04 +0000 Received: from red.redhat.com ([24.10.254.122]) by resomta-po-18v.sys.comcast.net with comcast id cmhZ1r00S2fD5rL01mi4me; Mon, 02 Nov 2015 22:42:04 +0000 From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 2 Nov 2015 15:41:32 -0700 Message-Id: <1446504092-29008-5-git-send-email-eblake@redhat.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <871tc8tnsl.fsf@blackfin.pond.sub.org> References: <871tc8tnsl.fsf@blackfin.pond.sub.org> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcast.net; s=q20140121; t=1446504124; bh=XkF7wkpJ98DnniiVWyZFIDZitDe72GTmZhNV/3dj/yw=; h=Received:Received:From:To:Subject:Date:Message-Id; b=PuJ9AenbKw7IhEfyTfb6ItYascE5v1dkM/rerD5k5bCSYjHn3zmxATEv8UmQRkxEx 1dmMYHEZSH/KnXbC/fmpf5oyQZTP8YSZNUhNjibMFqVxHN/7WMJt00BeQQpPdB32SW RJ1m4Q1pd2pHNHT0QHe/4IZ7qDeMnp5kT+t5HEHkK/G6UYH/PWdzHssn+9CSF2nY1G BCwNj2+cNFyKldKGdthfB3gY8QQAZEXm1hgXGY/GmQ68RN8Q29gBWg3khYlZkqzkgH EnxsYMoqAuykalFnPtb2WpCblwWCZTsHRQN03ObYGizTwOhKMTX/8K37BqgqYYivnF c8yjCJ05boMwg== X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 96.114.154.163 Cc: armbru@redhat.com, Michael Roth Subject: [Qemu-devel] [PATCH v8.5 4/4] qapi: Consolidate collision detection code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Rather than having three separate places populate the seen map, it is easier to just factor out a subset of Member.check() that does this as a new method check_collision(), and have the remaining places in ObjectType.check() and Variant.check() call into it. This likewise means a new helper method ObjectType.check_collision(). Later patches can then change the handling of the seen array in just one place, when moving away from ad hoc parser tests. Note that there was some discrepancy in the existing code on whether name or c_name(name) could not previously be in the seen map; a future patch will clean this up to consistently populate the map via c_name(). Signed-off-by: Eric Blake --- v9: new patch, split off from v8 7/17; name change from ObjectType.check_qmp() to check_collision(), and new method Member.check_collision(). I'm open to naming suggestions. --- scripts/qapi.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/scripts/qapi.py b/scripts/qapi.py index 10bf16f..b519d30 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -981,18 +981,21 @@ class QAPISchemaObjectType(QAPISchemaType): seen = OrderedDict() if self._base_name: self.base = schema.lookup_type(self._base_name) - assert isinstance(self.base, QAPISchemaObjectType) - assert not self.base.variants # not implemented - self.base.check(schema) - for m in self.base.members: - assert c_name(m.name) not in seen - seen[m.name] = m + self.base.check_collision(schema, seen) for m in self.local_members: m.check(schema, seen) if self.variants: self.variants.check(schema, seen) self.members = seen.values() + # Check that the members of this type do not cause duplicate JSON fields, + # and update seen to track the members seen so far + def check_collision(self, schema, seen): + assert not self.variants # not implemented + self.check(schema) + for m in self.members: + m.check_collision(seen) + def is_implicit(self): # See QAPISchema._make_implicit_object_type() return self.name[0] == ':' @@ -1026,9 +1029,16 @@ class QAPISchemaObjectTypeMember(object): self.optional = optional def check(self, schema, seen): - assert self.name not in seen self.type = schema.lookup_type(self._type_name) + self.check_collision(seen) + + # Check that this member does not collide with anything in seen (the + # set of non-variant members when called from QAPISchemaObjectType, + # or the set of tag values when called from QAPISchemaObjectTypeVariant), + # and update seen accordingly. + def check_collision(self, seen): assert self.type + assert self.name not in seen seen[self.name] = self @@ -1074,12 +1084,7 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember): # If this variant is used within a union, then each member # field must avoid collisions with the non-variant members # already present in the union. - assert isinstance(self.type, QAPISchemaObjectType) - assert not self.type.variants # not implemented - self.type.check(schema) - for m in self.type.members: - assert c_name(m.name) not in seen - seen[m.name] = m + self.type.check_collision(schema, seen) # This function exists to support ugly simple union special cases # TODO get rid of them, and drop the function