diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2018-12-10 16:07:46 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2018-12-18 10:10:50 +0100 |
commit | a7301790446a48908da362a7fdc5e4079759e8f6 (patch) | |
tree | 5ca272ecbb3a2d31146013dcdafd41912c6b27bc | |
parent | 79fc0bb16b68eaec36104d9970fda4497add6918 (diff) | |
download | vala-a7301790446a48908da362a7fdc5e4079759e8f6.tar.gz |
codegen: Handle non-default AsyncResult parameter position
Unfortunately gdbus-codegen puts the AsyncResult parameter after possible
out-parameters therefore there is an "async_result_pos" attribute required
to handle this correctly.
Vala supposely follows the common practice to put the AsyncResult before
out-parameters by default.
Fixes https://gitlab.gnome.org/GNOME/vala/issues/709
-rw-r--r-- | codegen/valaccodebasemodule.vala | 7 | ||||
-rw-r--r-- | codegen/valaccodemethodcallmodule.vala | 2 | ||||
-rw-r--r-- | codegen/valagasyncmodule.vala | 6 | ||||
-rw-r--r-- | codegen/valagdbusclientmodule.vala | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/asynchronous/result-pos.vala | 48 | ||||
-rw-r--r-- | tests/gir/async-result-pos.test | 56 | ||||
-rw-r--r-- | vala/valagirparser.vala | 13 | ||||
-rw-r--r-- | vala/valamethod.vala | 3 | ||||
-rw-r--r-- | vala/valausedattr.vala | 3 |
10 files changed, 134 insertions, 8 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index d4c443124..9ea2e2c1b 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -4711,7 +4711,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { // output arguments used separately out_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal); // pass GAsyncResult stored in closure to finish function - out_arg_map.set (get_param_pos (0.1), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_")); + out_arg_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_")); } if (cl != null && !cl.is_compact) { @@ -6504,6 +6504,11 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { return get_ccode_attribute(m).vfunc_name; } + public static double get_ccode_async_result_pos (Method m) { + assert (m.coroutine); + return m.get_attribute_double ("CCode", "async_result_pos", 0.1); + } + public static string get_ccode_finish_name (Method m) { return get_ccode_attribute(m).finish_name; } diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index 187e1b01f..c188fb0ce 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -127,7 +127,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { // output arguments used separately out_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal); // pass GAsyncResult stored in closure to finish function - out_arg_map.set (get_param_pos (0.1), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_")); + out_arg_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_")); } } diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index 37ea7de08..6c706e8cf 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -603,7 +603,7 @@ public class Vala.GAsyncModule : GtkModule { var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal); - cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*")); + cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*")); generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2); @@ -902,9 +902,9 @@ public class Vala.GAsyncModule : GtkModule { carg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_user_data_")); } } else if (direction == 2) { - cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*")); + cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*")); if (carg_map != null) { - carg_map.set (get_param_pos (0.1), new CCodeIdentifier ("_res_")); + carg_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeIdentifier ("_res_")); } } } diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala index f2b199392..9939c501b 100644 --- a/codegen/valagdbusclientmodule.vala +++ b/codegen/valagdbusclientmodule.vala @@ -951,7 +951,7 @@ public class Vala.GDBusClientModule : GDBusModule { var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal); - cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*")); + cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*")); generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2); diff --git a/tests/Makefile.am b/tests/Makefile.am index 00bb4a45b..a63e38dfe 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -344,6 +344,7 @@ TESTS = \ asynchronous/bug793158.vala \ asynchronous/closures.vala \ asynchronous/generator.vala \ + asynchronous/result-pos.vala \ asynchronous/yield.vala \ generics/bug694765-1.vala \ generics/bug694765-2.vala \ @@ -370,6 +371,7 @@ TESTS = \ gir/bug742012.test \ gir/bug788775.test \ gir/array-fixed-length.test \ + gir/async-result-pos.test \ gir/delegate-alias-without-target.test \ annotations/deprecated.vala \ annotations/description.vala \ diff --git a/tests/asynchronous/result-pos.vala b/tests/asynchronous/result-pos.vala new file mode 100644 index 000000000..3c86f75b5 --- /dev/null +++ b/tests/asynchronous/result-pos.vala @@ -0,0 +1,48 @@ +[CCode (async_result_pos = 2.1)] +async void foo (int in_i, out int out_i) { + out_i = in_i; +} + +[CCode (async_result_pos = 2.1)] +async void bar (int in_i, out int out_i) throws Error { + out_i = in_i; +} + +async void run () { + int i; + yield foo (323, out i); + assert (i == 323); + try { + yield bar (742, out i); + assert (i == 742); + } catch { + assert_not_reached (); + } + loop.quit (); +} + +MainLoop loop; + +void main () { + loop = new MainLoop (); + + foo.begin (23, (o,r) => { + int i; + foo.end (r, out i); + assert (i == 23); + }); + + bar.begin (42, (o,r) => { + try { + int i; + bar.end (r, out i); + assert (i == 42); + } catch { + assert_not_reached (); + } + }); + + run.begin (); + + loop.run (); +} diff --git a/tests/gir/async-result-pos.test b/tests/gir/async-result-pos.test new file mode 100644 index 000000000..2a17f53dc --- /dev/null +++ b/tests/gir/async-result-pos.test @@ -0,0 +1,56 @@ +GIR + +Input: + +<class name="Foo" c:type="TestFoo" glib:type-name="TestFoo" glib:get-type="test_foo_get_type" glib:type-struct="FooClass" parent="GObject.Object"> + <method name="method_async" c:identifier="test_foo_method_async"> + <return-value transfer-ownership="none"> + <type name="none"/> + </return-value> + <parameters> + <instance-parameter name="self" transfer-ownership="none"> + <type name="Foo" c:type="TestFoo*"/> + </instance-parameter> + <parameter name="input" transfer-ownership="none"> + <type name="utf8" c:type="const gchar*"/> + </parameter> + <parameter name="_callback_" transfer-ownership="none" allow-none="1" closure="2" scope="async"> + <type name="Gio.AsyncReadyCallback" c:type="GAsyncReadyCallback"/> + </parameter> + <parameter name="_callback__target" transfer-ownership="none" allow-none="1"> + <type name="gpointer" c:type="void*"/> + </parameter> + </parameters> + </method> + <method name="method_finish" c:identifier="test_foo_method_finish" throws="1"> + <return-value transfer-ownership="full"> + <type name="none"/> + </return-value> + <parameters> + <instance-parameter name="self" transfer-ownership="none"> + <type name="Foo" c:type="TestFoo*"/> + </instance-parameter> + <parameter name="output" direction="out" transfer-ownership="full"> + <type name="utf8" c:type="gchar**"/> + </parameter> + <parameter name="_res_" transfer-ownership="none"> + <type name="Gio.AsyncResult" c:type="GAsyncResult*"/> + </parameter> + </parameters> + </method> + <constructor name="new" c:identifier="test_foo_new"> + <return-value transfer-ownership="full"> + <type name="Test.Foo" c:type="TestFoo*"/> + </return-value> + </constructor> +</class> + +Output: + +[CCode (cheader_filename = "test.h", type_id = "test_foo_get_type ()")] +public class Foo : GLib.Object { + [CCode (has_construct_function = false)] + public Foo (); + [CCode (async_result_pos = 2.1)] + public async void method_async (string input, out string output) throws GLib.Error; +} diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala index 948e9d13b..c9a9a576d 100644 --- a/vala/valagirparser.vala +++ b/vala/valagirparser.vala @@ -3823,6 +3823,7 @@ public class Vala.GirParser : CodeVisitor { int i = 0, j=1; + int first_out = -1; int last = -1; foreach (ParameterInfo info in parameters) { if (s is Delegate && info.closure_idx == i) { @@ -3854,6 +3855,16 @@ public class Vala.GirParser : CodeVisitor { // hidden parameters at the end of the parameter list info.vala_idx = (j - 1) + (i - last) * 0.1F; } + if (first_out < 0 && info.param.direction == ParameterDirection.OUT) { + first_out = i; + } + if (s is Method && first_out >= 0 && info.param.variable_type != null) { + var type_name = info.param.variable_type.to_string (); + if (type_name == "GLib.AsyncResult" || type_name == "Gio.AsyncResult") { + var shift = ((Method) s).binding == MemberBinding.INSTANCE ? 1.1 : 0.1; + s.set_attribute_double ("CCode", "async_result_pos", i + shift); + } + } i++; } @@ -4093,6 +4104,8 @@ public class Vala.GirParser : CodeVisitor { } } + method.copy_attribute_double (finish_method, "CCode", "async_result_pos"); + foreach (var param in finish_method.get_parameters ()) { if (param.direction == ParameterDirection.OUT) { var async_param = param.copy (); diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 0190702cd..81ca7bb0d 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -978,6 +978,7 @@ public class Vala.Method : Subroutine, Callable { foreach (var param in get_type_parameters ()) { end_method.add_type_parameter (param); } + end_method.copy_attribute_double (this, "CCode", "async_result_pos"); } return end_method; } @@ -1042,7 +1043,7 @@ public class Vala.Method : Subroutine, Callable { var result_type = new ObjectType ((ObjectTypeSymbol) glib_ns.scope.lookup ("AsyncResult")); var result_param = new Parameter ("_res_", result_type); - result_param.set_attribute_double ("CCode", "pos", 0.1); + result_param.set_attribute_double ("CCode", "pos", get_attribute_double ("CCode", "async_result_pos", 0.1)); params.add (result_param); foreach (var param in parameters) { diff --git a/vala/valausedattr.vala b/vala/valausedattr.vala index 5b6dcca5f..060594628 100644 --- a/vala/valausedattr.vala +++ b/vala/valausedattr.vala @@ -39,7 +39,8 @@ public class Vala.UsedAttr : CodeVisitor { "has_copy_function", "lower_case_csuffix", "ref_sink_function", "dup_function", "finish_function", "generic_type_pos", "array_length_type", "array_length", "array_length_cname", "array_length_cexpr", "array_null_terminated", "vfunc_name", "finish_vfunc_name", "finish_name", "free_function_address_of", "pos", "delegate_target", "delegate_target_cname", - "array_length_pos", "delegate_target_pos", "destroy_notify_pos", "ctype", "has_new_function", "notify", "finish_instance", "", + "array_length_pos", "delegate_target_pos", "destroy_notify_pos", "ctype", "has_new_function", "notify", "finish_instance", + "async_result_pos", "", "Immutable", "", "Compact", "", |