qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: mdroth@linux.vnet.ibm.com
Subject: [PATCH v3 20/34] qapi: Add feature flags to struct members
Date: Sun, 15 Mar 2020 15:46:39 +0100	[thread overview]
Message-ID: <20200315144653.22660-21-armbru@redhat.com> (raw)
In-Reply-To: <20200315144653.22660-1-armbru@redhat.com>

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/devel/qapi-code-gen.txt            |  4 +++-
 tests/qapi-schema/doc-good.texi         |  2 ++
 qapi/introspect.json                    |  6 +++++-
 scripts/qapi/expr.py                    |  3 ++-
 scripts/qapi/introspect.py              |  2 +-
 scripts/qapi/schema.py                  | 25 ++++++++++++++++++++-----
 tests/qapi-schema/doc-good.json         |  5 ++++-
 tests/qapi-schema/doc-good.out          |  3 +++
 tests/qapi-schema/qapi-schema-test.json |  2 +-
 tests/qapi-schema/qapi-schema-test.out  |  1 +
 tests/qapi-schema/test-qapi.py          |  7 ++++---
 11 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 9fce78dcad..a1ef1cfd61 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -234,7 +234,9 @@ Syntax:
                '*features': FEATURES }
     MEMBERS = { MEMBER, ... }
     MEMBER = STRING : TYPE-REF
-           | STRING : { 'type': TYPE-REF, '*if': COND }
+           | STRING : { 'type': TYPE-REF,
+                        '*if': COND,
+                        '*features': FEATURES }
 
 Member 'struct' names the struct type.
 
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index 76b396dae6..7f28fb7a0f 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -132,6 +132,8 @@ Not documented
 @table @asis
 @item @code{variant1-feat}
 a feature
+@item @code{member-feat}
+a member feature
 @end table
 
 @end deftp
diff --git a/qapi/introspect.json b/qapi/introspect.json
index da3e176899..b1aabd4cfd 100644
--- a/qapi/introspect.json
+++ b/qapi/introspect.json
@@ -206,11 +206,15 @@
 #           Future extension: if present and non-null, the parameter
 #           is optional, and defaults to this value.
 #
+# @features: names of features associated with the member, in no
+#            particular order.  (since 5.0)
+#
 # Since: 2.5
 ##
 { 'struct': 'SchemaInfoObjectMember',
-  'data': { 'name': 'str', 'type': 'str', '*default': 'any' } }
+  'data': { 'name': 'str', 'type': 'str', '*default': 'any',
 # @default's type must be null or match @type
+            '*features': [ 'str' ] } }
 
 ##
 # @SchemaInfoObjectVariant:
diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
index f9c4448980..2942520399 100644
--- a/scripts/qapi/expr.py
+++ b/scripts/qapi/expr.py
@@ -167,8 +167,9 @@ def check_type(value, info, source,
                        allow_optional=True, permit_upper=permit_upper)
         if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
             raise QAPISemError(info, "%s uses reserved name" % key_source)
-        check_keys(arg, info, key_source, ['type'], ['if'])
+        check_keys(arg, info, key_source, ['type'], ['if', 'features'])
         check_if(arg, info, key_source)
+        check_features(arg.get('features'), info)
         check_type(arg['type'], info, key_source, allow_array=True)
 
 
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index a3fa9865db..23652be810 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -173,7 +173,7 @@ const QLitObject %(c_name)s = %(c_string)s;
         obj = {'name': member.name, 'type': self._use_type(member.type)}
         if member.optional:
             obj['default'] = None
-        return _make_tree(obj, member.ifcond, None)
+        return _make_tree(obj, member.ifcond, member.features)
 
     def _gen_variants(self, tag_name, variants):
         return {'tag': tag_name,
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 59e1f5a395..6ee3677215 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -668,18 +668,31 @@ class QAPISchemaFeature(QAPISchemaMember):
 
 
 class QAPISchemaObjectTypeMember(QAPISchemaMember):
-    def __init__(self, name, info, typ, optional, ifcond=None):
+    def __init__(self, name, info, typ, optional, ifcond=None, features=None):
         super().__init__(name, info, ifcond)
         assert isinstance(typ, str)
         assert isinstance(optional, bool)
+        for f in features or []:
+            assert isinstance(f, QAPISchemaFeature)
+            f.set_defined_in(name)
         self._type_name = typ
         self.type = None
         self.optional = optional
+        self.features = features or []
 
     def check(self, schema):
         assert self.defined_in
         self.type = schema.resolve_type(self._type_name, self.info,
                                         self.describe)
+        seen = {}
+        for f in self.features:
+            f.check_clash(self.info, seen)
+
+    def connect_doc(self, doc):
+        super().connect_doc(doc)
+        if doc:
+            for f in self.features:
+                doc.connect_feature(f)
 
 
 class QAPISchemaVariant(QAPISchemaObjectTypeMember):
@@ -962,7 +975,7 @@ class QAPISchema:
             name, info, doc, ifcond, features,
             self._make_enum_members(data, info), prefix))
 
-    def _make_member(self, name, typ, ifcond, info):
+    def _make_member(self, name, typ, ifcond, features, info):
         optional = False
         if name.startswith('*'):
             name = name[1:]
@@ -970,10 +983,12 @@ class QAPISchema:
         if isinstance(typ, list):
             assert len(typ) == 1
             typ = self._make_array_type(typ[0], info)
-        return QAPISchemaObjectTypeMember(name, info, typ, optional, ifcond)
+        return QAPISchemaObjectTypeMember(name, info, typ, optional, ifcond,
+                                          self._make_features(features, info))
 
     def _make_members(self, data, info):
-        return [self._make_member(key, value['type'], value.get('if'), info)
+        return [self._make_member(key, value['type'], value.get('if'),
+                                  value.get('features'), info)
                 for (key, value) in data.items()]
 
     def _def_struct_type(self, expr, info, doc):
@@ -996,7 +1011,7 @@ class QAPISchema:
             typ = self._make_array_type(typ[0], info)
         typ = self._make_implicit_object_type(
             typ, info, self.lookup_type(typ),
-            'wrapper', [self._make_member('data', typ, None, info)])
+            'wrapper', [self._make_member('data', typ, None, None, info)])
         return QAPISchemaVariant(case, info, typ, ifcond)
 
     def _def_union_type(self, expr, info, doc):
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 457b8b2cdf..ddd89d1233 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -78,10 +78,13 @@
 #
 # Features:
 # @variant1-feat: a feature
+# @member-feat: a member feature
 ##
 { 'struct': 'Variant1',
   'features': [ 'variant1-feat' ],
-  'data': { 'var1': { 'type': 'str', 'if': 'defined(IFSTR)' } } }
+  'data': { 'var1': { 'type': 'str',
+                      'features': [ 'member-feat' ],
+                      'if': 'defined(IFSTR)' } } }
 
 ##
 # @Variant2:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 9bcb2b3e91..6757dd26a2 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -21,6 +21,7 @@ object Base
 object Variant1
     member var1: str optional=False
         if ['defined(IFSTR)']
+        feature member-feat
     feature variant1-feat
 object Variant2
 object Object
@@ -135,6 +136,8 @@ Another paragraph (but no @var: line)
 
     feature=variant1-feat
 a feature
+    feature=member-feat
+a member feature
 doc symbol=Variant2
     body=
 
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index fa4f3a15da..f576c337af 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -258,7 +258,7 @@
   'data': { 'foo': 'int' },
   'features': [] }
 { 'struct': 'FeatureStruct1',
-  'data': { 'foo': 'int' },
+  'data': { 'foo': { 'type': 'int', 'features': [ 'member-feature1' ] } },
   'features': [ 'feature1' ] }
 { 'struct': 'FeatureStruct2',
   'data': { 'foo': 'int' },
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 1cbd0802b3..cd863ae966 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -359,6 +359,7 @@ object FeatureStruct0
     member foo: int optional=False
 object FeatureStruct1
     member foo: int optional=False
+        feature member-feature1
     feature feature1
 object FeatureStruct2
     member foo: int optional=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 8e09e54edb..f396b471eb 100755
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -55,6 +55,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             print('    member %s: %s optional=%s'
                   % (m.name, m.type.name, m.optional))
             self._print_if(m.ifcond, 8)
+            self._print_features(m.features, indent=8)
         self._print_variants(variants)
         self._print_if(ifcond)
         self._print_features(features)
@@ -96,11 +97,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             print('%sif %s' % (' ' * indent, ifcond))
 
     @classmethod
-    def _print_features(cls, features):
+    def _print_features(cls, features, indent=4):
         if features:
             for f in features:
-                print('    feature %s' % f.name)
-                cls._print_if(f.ifcond, 8)
+                print('%sfeature %s' % (' ' * indent, f.name))
+                cls._print_if(f.ifcond, indent + 4)
 
 
 def test_frontend(fname):
-- 
2.21.1



  parent reply	other threads:[~2020-03-15 15:25 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-15 14:46 [PATCH v3 00/34] Configurable policy for handling deprecated interfaces Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 01/34] qemu-doc: Belatedly document QMP command arg & result deprecation Markus Armbruster
2020-03-16 15:10   ` Eric Blake
2020-03-16 18:34     ` Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 02/34] qapi: Belatedly update doc comment for @wait deprecation Markus Armbruster
2020-03-16 14:51   ` Marc-André Lureau
2020-03-16 15:10   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 03/34] docs/devel/qapi-code-gen: Clarify allow-oob introspection Markus Armbruster
2020-03-16 15:12   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 04/34] docs/devel/qapi-code-gen: Document 'features' introspection Markus Armbruster
2020-03-16 15:15   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 05/34] tests/test-qmp-cmds: Factor out qmp_dispatch() test helpers Markus Armbruster
2020-03-16 15:06   ` Marc-André Lureau
2020-03-16 19:46     ` Markus Armbruster
2020-03-16 17:16   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 06/34] tests/test-qmp-cmds: Check responses more thoroughly Markus Armbruster
2020-03-16 15:08   ` Marc-André Lureau
2020-03-16 17:18   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 07/34] tests/test-qmp-cmds: Simplify test data setup Markus Armbruster
2020-03-16 15:10   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 08/34] tests/test-qmp-event: " Markus Armbruster
2020-03-16 15:11   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 09/34] tests/test-qmp-event: Use qobject_is_equal() Markus Armbruster
2020-03-16 15:13   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 10/34] tests/test-qmp-event: Check event is actually emitted Markus Armbruster
2020-03-16 15:14   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 11/34] qapi/schema: Clean up around QAPISchemaEntity.connect_doc() Markus Armbruster
2020-03-16 16:47   ` Marc-André Lureau
2020-03-16 17:23   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 12/34] qapi: Add feature flags to remaining definitions Markus Armbruster
2020-03-16 17:55   ` Eric Blake
2020-03-17  5:46     ` Markus Armbruster
2020-03-17 11:29       ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 13/34] qapi: Consistently put @features parameter right after @ifcond Markus Armbruster
2020-03-16 16:52   ` Marc-André Lureau
2020-03-16 17:57   ` Eric Blake
2020-03-15 14:46 ` [PATCH v3 14/34] qapi/introspect: Rename *qlit* to reduce confusion Markus Armbruster
2020-03-16 16:54   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 15/34] qapi/introspect: Factor out _make_tree() Markus Armbruster
2020-03-16 16:58   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 16/34] qapi/schema: Change _make_features() to a take feature list Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 17/34] qapi/schema: Reorder classes so related ones are together Markus Armbruster
2020-03-16 17:03   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 18/34] qapi/schema: Rename QAPISchemaObjectType{Variant, Variants} Markus Armbruster
2020-03-16 17:06   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 19/34] qapi/schema: Call QAPIDoc.connect_member() in just one place Markus Armbruster
2020-03-16 17:08   ` Marc-André Lureau
2020-03-16 17:08   ` Marc-André Lureau
2020-03-15 14:46 ` Markus Armbruster [this message]
2020-03-16 17:10   ` [PATCH v3 20/34] qapi: Add feature flags to struct members Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 21/34] qapi: Inline do_qmp_dispatch() into qmp_dispatch() Markus Armbruster
2020-03-16 17:25   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 22/34] qapi: Simplify how qmp_dispatch() deals with QCO_NO_SUCCESS_RESP Markus Armbruster
2020-03-16 17:28   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 23/34] qapi: Simplify how qmp_dispatch() gets the request ID Markus Armbruster
2020-03-16 17:33   ` Marc-André Lureau
2020-03-17  6:39     ` Markus Armbruster
2020-03-17  7:37       ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 24/34] qapi: Replace qmp_dispatch()'s TODO comment by an explanation Markus Armbruster
2020-03-16 17:36   ` Marc-André Lureau
2020-03-17  6:52     ` Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 25/34] qapi: New special feature flag "deprecated" Markus Armbruster
2020-03-15 15:49   ` Philippe Mathieu-Daudé
2020-03-15 16:53     ` Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 26/34] qapi: Mark deprecated QMP parts with feature 'deprecated' Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 27/34] qemu-options: New -compat to set policy for deprecated interfaces Markus Armbruster
2020-03-16 17:43   ` Marc-André Lureau
2020-03-15 14:46 ` [PATCH v3 28/34] qapi: Implement deprecated-output=hide for QMP command results Markus Armbruster
2020-03-16 17:53   ` Marc-André Lureau
2020-03-16 19:46     ` Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 29/34] qapi: Implement deprecated-output=hide for QMP events Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 30/34] qapi: Implement deprecated-output=hide for QMP event data Markus Armbruster
2020-03-16 19:48   ` Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 31/34] qapi: Implement deprecated-output=hide for QMP introspection Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 32/34] qapi: Implement deprecated-input=reject for QMP commands Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 33/34] qapi: Implement deprecated-input=reject for QMP command arguments Markus Armbruster
2020-03-15 14:46 ` [PATCH v3 34/34] qapi: New -compat deprecated-input=crash Markus Armbruster

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=20200315144653.22660-21-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=mdroth@linux.vnet.ibm.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).