[Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions

Marc-André Lureau posted 54 patches 8 years, 5 months ago
There is a newer version of this series
[Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
Posted by Marc-André Lureau 8 years, 5 months ago
Accept 'if' key in top-level elements, accepted as string or list of
string type. The following patches will modify the test visitor to
check the value is correctly saved, and generate #if/#endif code (as a
single #if/endif line or a series for a list).

Example of 'if' key:
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },                                                                                                                                                               'if': 'defined(TEST_IF_STRUCT)' }

A following patch for qapi-code-gen.txt will provide more complete
documentation for 'if' usage.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py                         | 13 +++++++++++++
 tests/test-qmp-commands.c               |  6 ++++++
 tests/qapi-schema/qapi-schema-test.json | 20 ++++++++++++++++++++
 tests/qapi-schema/qapi-schema-test.out  | 22 ++++++++++++++++++++++
 4 files changed, 61 insertions(+)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 73adb90379..a94d93ada4 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -639,6 +639,16 @@ def add_name(name, info, meta, implicit=False):
     all_names[name] = meta
 
 
+def check_if(expr, info):
+    ifcond = expr.get('if')
+    if not ifcond or isinstance(ifcond, str):
+        return
+    if (not isinstance(ifcond, list) or
+            any([not isinstance(elt, str) for elt in ifcond])):
+        raise QAPISemError(info, "'if' condition requires a string or "
+                           "a list of string")
+
+
 def check_type(info, source, value, allow_array=False,
                allow_dict=False, allow_optional=False,
                allow_metas=[]):
@@ -865,6 +875,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
     expr = expr_elem['expr']
     info = expr_elem['info']
     name = expr[meta]
+    optional = optional + ['if']  # all top-level elem accept if
     if not isinstance(name, str):
         raise QAPISemError(info, "'%s' key must have a string value" % meta)
     required = required + [meta]
@@ -880,6 +891,8 @@ def check_keys(expr_elem, meta, required, optional=[]):
             raise QAPISemError(info,
                                "'%s' of %s '%s' should only use true value"
                                % (key, meta, name))
+        if key == 'if':
+            check_if(expr, info)
     for key in required:
         if key not in expr:
             raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 904c89d4d4..9b9a7ffee7 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -10,6 +10,12 @@
 
 static QmpCommandList qmp_commands;
 
+/* #if defined(TEST_IF_CMD) */
+void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
+{
+}
+/* #endif */
+
 void qmp_user_def_cmd(Error **errp)
 {
 }
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index c72dbd8050..dc2c444fc1 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -188,3 +188,23 @@
   'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
             'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
   'returns': '__org.qemu_x-Union1' }
+
+# test 'if' condition handling
+
+{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+  'if': 'defined(TEST_IF_STRUCT)' }
+
+{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
+  'if': 'defined(TEST_IF_ENUM)' }
+
+{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
+  'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
+
+{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
+  'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
+
+{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
+  'if': 'defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)' }
+
+{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
+  'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 3b1e9082d3..7fbaea19bc 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
     prefix QENUM_TWO
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+alternate TestIfAlternate
+    tag type
+    case foo: int
+    case bar: TestStruct
+command TestIfCmd q_obj_TestIfCmd-arg -> None
+   gen=True success_response=True boxed=False
+enum TestIfEnum ['foo', 'bar']
+event TestIfEvent q_obj_TestIfEvent-arg
+   boxed=False
+object TestIfStruct
+    member foo: int optional=False
+object TestIfUnion
+    member type: TestIfUnionKind optional=False
+    tag type
+    case foo: q_obj_TestStruct-wrapper
+enum TestIfUnionKind ['foo']
 object TestStruct
     member integer: int optional=False
     member boolean: bool optional=False
@@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
     member b: str optional=False
     member c: str optional=True
     member enum3: EnumOne optional=True
+object q_obj_TestIfCmd-arg
+    member foo: TestIfStruct optional=False
+object q_obj_TestIfEvent-arg
+    member foo: TestIfStruct optional=False
+object q_obj_TestStruct-wrapper
+    member data: TestStruct optional=False
 object q_obj_UserDefFlatUnion2-base
     member integer: int optional=True
     member string: str optional=False
-- 
2.14.1.146.gd35faa819


Re: [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
Posted by Markus Armbruster 8 years, 5 months ago
Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Accept 'if' key in top-level elements, accepted as string or list of
> string type. The following patches will modify the test visitor to
> check the value is correctly saved, and generate #if/#endif code (as a
> single #if/endif line or a series for a list).
>
> Example of 'if' key:
> { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },                                                                                                                                                               'if': 'defined(TEST_IF_STRUCT)' }

Lost line break?

> A following patch for qapi-code-gen.txt will provide more complete
> documentation for 'if' usage.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py                         | 13 +++++++++++++
>  tests/test-qmp-commands.c               |  6 ++++++
>  tests/qapi-schema/qapi-schema-test.json | 20 ++++++++++++++++++++
>  tests/qapi-schema/qapi-schema-test.out  | 22 ++++++++++++++++++++++
>  4 files changed, 61 insertions(+)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 73adb90379..a94d93ada4 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -639,6 +639,16 @@ def add_name(name, info, meta, implicit=False):
>      all_names[name] = meta
>  
>  
> +def check_if(expr, info):
> +    ifcond = expr.get('if')
> +    if not ifcond or isinstance(ifcond, str):
> +        return
> +    if (not isinstance(ifcond, list) or
> +            any([not isinstance(elt, str) for elt in ifcond])):
> +        raise QAPISemError(info, "'if' condition requires a string or "
> +                           "a list of string")

The error also triggers on inputs 'if': '' and 'if': [].

The first one doesn't make sense (the C compiler will surely barf).  We
could leave rejecting it to the C compiler.  If we choose to reject it
here, we need a better error message, because the one above is
misleading.

The second one is a roundabout way to say "unconditional".  If we choose
to reject that, we also need a non-misleading error message.

The error can't trigger on absent 'if', because we don't get called
then.  To make that locally obvious, please say

       ifcond = expr['if']

Moreover, I'd prefer to avoid mixing conditionals with opposite sense,
i.e. if good: return; if bad: raise.

Taken together:

   def check_if(expr, info):
       ifcond = expr['if']
       if isinstance(ifcond, str):
           if ifcond == '':
               raise QAPISemError(info, "'if' condition '' makes no sense")
           return
       if isinstance(ifcond, list):
           if ifcond == []:
               raise QAPISemError(info, "'if' condition [] is useless")
           for elt in ifcond:
               if not isinstance(elt, str):
                   raise QAPISemError(
                           info, "'if' condition %s makes no sense" % elt)
           return
       raise QAPISemError(
               info, "'if' condition must be a string or a list of strings")

Written this way (one case after the other), each error has to report
just one narrow problem.  Makes crafting precise error messages easier.

> +
> +
>  def check_type(info, source, value, allow_array=False,
>                 allow_dict=False, allow_optional=False,
>                 allow_metas=[]):
> @@ -865,6 +875,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
>      expr = expr_elem['expr']
>      info = expr_elem['info']
>      name = expr[meta]
> +    optional = optional + ['if']  # all top-level elem accept if
>      if not isinstance(name, str):
>          raise QAPISemError(info, "'%s' key must have a string value" % meta)
>      required = required + [meta]

All top-level expressions require 'data'.  Done the obvious way: all
callers pass 'data' in @required.  Let's do 'if' the same way for
consistency.

> @@ -880,6 +891,8 @@ def check_keys(expr_elem, meta, required, optional=[]):
>              raise QAPISemError(info,
>                                 "'%s' of %s '%s' should only use true value"
>                                 % (key, meta, name))
> +        if key == 'if':
> +            check_if(expr, info)
>      for key in required:
>          if key not in expr:
>              raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
> index 904c89d4d4..9b9a7ffee7 100644
> --- a/tests/test-qmp-commands.c
> +++ b/tests/test-qmp-commands.c
> @@ -10,6 +10,12 @@
>  
>  static QmpCommandList qmp_commands;
>  
> +/* #if defined(TEST_IF_CMD) */
> +void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
> +{
> +}
> +/* #endif */
> +
>  void qmp_user_def_cmd(Error **errp)
>  {
>  }
> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> index c72dbd8050..dc2c444fc1 100644
> --- a/tests/qapi-schema/qapi-schema-test.json
> +++ b/tests/qapi-schema/qapi-schema-test.json
> @@ -188,3 +188,23 @@
>    'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
>              'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
>    'returns': '__org.qemu_x-Union1' }
> +
> +# test 'if' condition handling
> +
> +{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
> +  'if': 'defined(TEST_IF_STRUCT)' }
> +
> +{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
> +  'if': 'defined(TEST_IF_ENUM)' }
> +
> +{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
> +  'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
> +
> +{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
> +  'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
> +
> +{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
> +  'if': 'defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)' }
> +
> +{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
> +  'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
> index 3b1e9082d3..7fbaea19bc 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
>      prefix QENUM_TWO
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
> +alternate TestIfAlternate
> +    tag type
> +    case foo: int
> +    case bar: TestStruct
> +command TestIfCmd q_obj_TestIfCmd-arg -> None
> +   gen=True success_response=True boxed=False
> +enum TestIfEnum ['foo', 'bar']
> +event TestIfEvent q_obj_TestIfEvent-arg
> +   boxed=False
> +object TestIfStruct
> +    member foo: int optional=False
> +object TestIfUnion
> +    member type: TestIfUnionKind optional=False
> +    tag type
> +    case foo: q_obj_TestStruct-wrapper
> +enum TestIfUnionKind ['foo']
>  object TestStruct
>      member integer: int optional=False
>      member boolean: bool optional=False
> @@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
>      member b: str optional=False
>      member c: str optional=True
>      member enum3: EnumOne optional=True
> +object q_obj_TestIfCmd-arg
> +    member foo: TestIfStruct optional=False
> +object q_obj_TestIfEvent-arg
> +    member foo: TestIfStruct optional=False
> +object q_obj_TestStruct-wrapper
> +    member data: TestStruct optional=False
>  object q_obj_UserDefFlatUnion2-base
>      member integer: int optional=True
>      member string: str optional=False

The conditionals aren't visible in qapi-schema-test.out.  They should
be.

*Much* easier to review than its predecessor PATCH 07/26.  Appreciated!

Re: [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
Posted by Marc-André Lureau 8 years, 5 months ago
Hi

On Mon, Sep 4, 2017 at 3:27 PM, Markus Armbruster <armbru@redhat.com> wrote:
> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>
>> Accept 'if' key in top-level elements, accepted as string or list of
>> string type. The following patches will modify the test visitor to
>> check the value is correctly saved, and generate #if/#endif code (as a
>> single #if/endif line or a series for a list).
>>
>> Example of 'if' key:
>> { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },                                                                                                                                                               'if': 'defined(TEST_IF_STRUCT)' }
>
> Lost line break?

yes

>
>> A following patch for qapi-code-gen.txt will provide more complete
>> documentation for 'if' usage.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi.py                         | 13 +++++++++++++
>>  tests/test-qmp-commands.c               |  6 ++++++
>>  tests/qapi-schema/qapi-schema-test.json | 20 ++++++++++++++++++++
>>  tests/qapi-schema/qapi-schema-test.out  | 22 ++++++++++++++++++++++
>>  4 files changed, 61 insertions(+)
>>
>> diff --git a/scripts/qapi.py b/scripts/qapi.py
>> index 73adb90379..a94d93ada4 100644
>> --- a/scripts/qapi.py
>> +++ b/scripts/qapi.py
>> @@ -639,6 +639,16 @@ def add_name(name, info, meta, implicit=False):
>>      all_names[name] = meta
>>
>>
>> +def check_if(expr, info):
>> +    ifcond = expr.get('if')
>> +    if not ifcond or isinstance(ifcond, str):
>> +        return
>> +    if (not isinstance(ifcond, list) or
>> +            any([not isinstance(elt, str) for elt in ifcond])):
>> +        raise QAPISemError(info, "'if' condition requires a string or "
>> +                           "a list of string")
>
> The error also triggers on inputs 'if': '' and 'if': [].
>
> The first one doesn't make sense (the C compiler will surely barf).  We
> could leave rejecting it to the C compiler.  If we choose to reject it
> here, we need a better error message, because the one above is
> misleading.
>
> The second one is a roundabout way to say "unconditional".  If we choose
> to reject that, we also need a non-misleading error message.
>
> The error can't trigger on absent 'if', because we don't get called
> then.  To make that locally obvious, please say
>
>        ifcond = expr['if']
>
> Moreover, I'd prefer to avoid mixing conditionals with opposite sense,
> i.e. if good: return; if bad: raise.
>
> Taken together:
>
>    def check_if(expr, info):
>        ifcond = expr['if']
>        if isinstance(ifcond, str):
>            if ifcond == '':
>                raise QAPISemError(info, "'if' condition '' makes no sense")
>            return
>        if isinstance(ifcond, list):
>            if ifcond == []:
>                raise QAPISemError(info, "'if' condition [] is useless")
>            for elt in ifcond:
>                if not isinstance(elt, str):
>                    raise QAPISemError(
>                            info, "'if' condition %s makes no sense" % elt)
>            return
>        raise QAPISemError(
>                info, "'if' condition must be a string or a list of strings")
>
> Written this way (one case after the other), each error has to report
> just one narrow problem.  Makes crafting precise error messages easier.
>

ok, thanks

>> +
>> +
>>  def check_type(info, source, value, allow_array=False,
>>                 allow_dict=False, allow_optional=False,
>>                 allow_metas=[]):
>> @@ -865,6 +875,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
>>      expr = expr_elem['expr']
>>      info = expr_elem['info']
>>      name = expr[meta]
>> +    optional = optional + ['if']  # all top-level elem accept if
>>      if not isinstance(name, str):
>>          raise QAPISemError(info, "'%s' key must have a string value" % meta)
>>      required = required + [meta]
>
> All top-level expressions require 'data'.  Done the obvious way: all
> callers pass 'data' in @required.  Let's do 'if' the same way for
> consistency.

Not all, 'data' is not required for commands & events.

And 'if' is always optional.

But anyway, I modified it now to pass it as argument...

>
>> @@ -880,6 +891,8 @@ def check_keys(expr_elem, meta, required, optional=[]):
>>              raise QAPISemError(info,
>>                                 "'%s' of %s '%s' should only use true value"
>>                                 % (key, meta, name))
>> +        if key == 'if':
>> +            check_if(expr, info)
>>      for key in required:
>>          if key not in expr:
>>              raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
>> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
>> index 904c89d4d4..9b9a7ffee7 100644
>> --- a/tests/test-qmp-commands.c
>> +++ b/tests/test-qmp-commands.c
>> @@ -10,6 +10,12 @@
>>
>>  static QmpCommandList qmp_commands;
>>
>> +/* #if defined(TEST_IF_CMD) */
>> +void qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
>> +{
>> +}
>> +/* #endif */
>> +
>>  void qmp_user_def_cmd(Error **errp)
>>  {
>>  }
>> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
>> index c72dbd8050..dc2c444fc1 100644
>> --- a/tests/qapi-schema/qapi-schema-test.json
>> +++ b/tests/qapi-schema/qapi-schema-test.json
>> @@ -188,3 +188,23 @@
>>    'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
>>              'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
>>    'returns': '__org.qemu_x-Union1' }
>> +
>> +# test 'if' condition handling
>> +
>> +{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
>> +  'if': 'defined(TEST_IF_STRUCT)' }
>> +
>> +{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
>> +  'if': 'defined(TEST_IF_ENUM)' }
>> +
>> +{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
>> +  'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
>> +
>> +{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
>> +  'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
>> +
>> +{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
>> +  'if': 'defined(TEST_IF_CMD) && defined(TEST_IF_STRUCT)' }
>> +
>> +{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
>> +  'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
>> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
>> index 3b1e9082d3..7fbaea19bc 100644
>> --- a/tests/qapi-schema/qapi-schema-test.out
>> +++ b/tests/qapi-schema/qapi-schema-test.out
>> @@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
>>      prefix QENUM_TWO
>>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>>      prefix QTYPE
>> +alternate TestIfAlternate
>> +    tag type
>> +    case foo: int
>> +    case bar: TestStruct
>> +command TestIfCmd q_obj_TestIfCmd-arg -> None
>> +   gen=True success_response=True boxed=False
>> +enum TestIfEnum ['foo', 'bar']
>> +event TestIfEvent q_obj_TestIfEvent-arg
>> +   boxed=False
>> +object TestIfStruct
>> +    member foo: int optional=False
>> +object TestIfUnion
>> +    member type: TestIfUnionKind optional=False
>> +    tag type
>> +    case foo: q_obj_TestStruct-wrapper
>> +enum TestIfUnionKind ['foo']
>>  object TestStruct
>>      member integer: int optional=False
>>      member boolean: bool optional=False
>> @@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
>>      member b: str optional=False
>>      member c: str optional=True
>>      member enum3: EnumOne optional=True
>> +object q_obj_TestIfCmd-arg
>> +    member foo: TestIfStruct optional=False
>> +object q_obj_TestIfEvent-arg
>> +    member foo: TestIfStruct optional=False
>> +object q_obj_TestStruct-wrapper
>> +    member data: TestStruct optional=False
>>  object q_obj_UserDefFlatUnion2-base
>>      member integer: int optional=True
>>      member string: str optional=False
>
> The conditionals aren't visible in qapi-schema-test.out.  They should
> be.
>

That's a follow-up patch "qapi: add 'ifcond' to visitor methods"

> *Much* easier to review than its predecessor PATCH 07/26.  Appreciated!



-- 
Marc-André Lureau

Re: [Qemu-devel] [PATCH v2 15/54] qapi: add 'if' to top-level expressions
Posted by Markus Armbruster 8 years, 5 months ago
Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Mon, Sep 4, 2017 at 3:27 PM, Markus Armbruster <armbru@redhat.com> wrote:
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> Accept 'if' key in top-level elements, accepted as string or list of
>>> string type. The following patches will modify the test visitor to
>>> check the value is correctly saved, and generate #if/#endif code (as a
>>> single #if/endif line or a series for a list).
>>>
>>> Example of 'if' key:
>>> { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },                                                                                                                                                               'if': 'defined(TEST_IF_STRUCT)' }
>>
>> Lost line break?
>
> yes
>
>>
>>> A following patch for qapi-code-gen.txt will provide more complete
>>> documentation for 'if' usage.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[...]
>>> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
>>> index 3b1e9082d3..7fbaea19bc 100644
>>> --- a/tests/qapi-schema/qapi-schema-test.out
>>> +++ b/tests/qapi-schema/qapi-schema-test.out
>>> @@ -52,6 +52,22 @@ enum QEnumTwo ['value1', 'value2']
>>>      prefix QENUM_TWO
>>>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>>>      prefix QTYPE
>>> +alternate TestIfAlternate
>>> +    tag type
>>> +    case foo: int
>>> +    case bar: TestStruct
>>> +command TestIfCmd q_obj_TestIfCmd-arg -> None
>>> +   gen=True success_response=True boxed=False
>>> +enum TestIfEnum ['foo', 'bar']
>>> +event TestIfEvent q_obj_TestIfEvent-arg
>>> +   boxed=False
>>> +object TestIfStruct
>>> +    member foo: int optional=False
>>> +object TestIfUnion
>>> +    member type: TestIfUnionKind optional=False
>>> +    tag type
>>> +    case foo: q_obj_TestStruct-wrapper
>>> +enum TestIfUnionKind ['foo']
>>>  object TestStruct
>>>      member integer: int optional=False
>>>      member boolean: bool optional=False
>>> @@ -172,6 +188,12 @@ object q_obj_EVENT_D-arg
>>>      member b: str optional=False
>>>      member c: str optional=True
>>>      member enum3: EnumOne optional=True
>>> +object q_obj_TestIfCmd-arg
>>> +    member foo: TestIfStruct optional=False
>>> +object q_obj_TestIfEvent-arg
>>> +    member foo: TestIfStruct optional=False
>>> +object q_obj_TestStruct-wrapper
>>> +    member data: TestStruct optional=False
>>>  object q_obj_UserDefFlatUnion2-base
>>>      member integer: int optional=True
>>>      member string: str optional=False
>>
>> The conditionals aren't visible in qapi-schema-test.out.  They should
>> be.
>>
>
> That's a follow-up patch "qapi: add 'ifcond' to visitor methods"

Which I've since found %-}

Similarly, the generated code is for now *unconditional*.  Later patches
generate the conditionals.

Let's point this out in the commit message.

Remember, your poor, ignorant reviewer squints at your patches through a
toiler paper tube, and may need your help to see the bigger picture.

>> *Much* easier to review than its predecessor PATCH 07/26.  Appreciated!