qemu-devel
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]