[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 20/34] qapi: Add feature flags to struct members
From: |
Marc-André Lureau |
Subject: |
Re: [PATCH v3 20/34] qapi: Add feature flags to struct members |
Date: |
Mon, 16 Mar 2020 18:10:42 +0100 |
On Sun, Mar 15, 2020 at 4:23 PM Markus Armbruster <address@hidden> wrote:
>
> Signed-off-by: Markus Armbruster <address@hidden>
Reviewed-by: Marc-André Lureau <address@hidden>
> ---
> 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
>
>
--
Marc-André Lureau
- [PATCH v3 34/34] qapi: New -compat deprecated-input=crash, (continued)
- [PATCH v3 34/34] qapi: New -compat deprecated-input=crash, Markus Armbruster, 2020/03/15
- [PATCH v3 18/34] qapi/schema: Rename QAPISchemaObjectType{Variant, Variants}, Markus Armbruster, 2020/03/15
- [PATCH v3 31/34] qapi: Implement deprecated-output=hide for QMP introspection, Markus Armbruster, 2020/03/15
- [PATCH v3 27/34] qemu-options: New -compat to set policy for deprecated interfaces, Markus Armbruster, 2020/03/15
- [PATCH v3 15/34] qapi/introspect: Factor out _make_tree(), Markus Armbruster, 2020/03/15
- [PATCH v3 14/34] qapi/introspect: Rename *qlit* to reduce confusion, Markus Armbruster, 2020/03/15
- [PATCH v3 20/34] qapi: Add feature flags to struct members, Markus Armbruster, 2020/03/15
- Re: [PATCH v3 20/34] qapi: Add feature flags to struct members,
Marc-André Lureau <=