[vala/0.42] codegen: Handle non-default AsyncResult parameter position



commit 901b52af0ef0319afb731fb36df922863f7b7f6e
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Mon Dec 10 16:07:46 2018 +0100

    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

 codegen/valaccode.vala                 |  5 +++
 codegen/valaccodebasemodule.vala       |  2 +-
 codegen/valaccodemethodcallmodule.vala |  2 +-
 codegen/valagasyncmodule.vala          |  6 ++--
 codegen/valagdbusclientmodule.vala     |  2 +-
 tests/Makefile.am                      |  2 ++
 tests/asynchronous/result-pos.vala     | 48 +++++++++++++++++++++++++++++
 tests/gir/async-result-pos.test        | 56 ++++++++++++++++++++++++++++++++++
 vala/valagirparser.vala                | 13 ++++++++
 vala/valamethod.vala                   |  3 +-
 vala/valausedattr.vala                 |  2 +-
 11 files changed, 133 insertions(+), 8 deletions(-)
---
diff --git a/codegen/valaccode.vala b/codegen/valaccode.vala
index 28f0c01a2..07e10133d 100644
--- a/codegen/valaccode.vala
+++ b/codegen/valaccode.vala
@@ -341,6 +341,11 @@ namespace Vala {
                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/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index b7a8e94d3..327da2726 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -4804,7 +4804,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) {
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 1bca80aee..b57f154cd 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -129,7 +129,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 9d63ab7ad..1c9809a2d 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -582,7 +582,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);
 
@@ -853,9 +853,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 32a45de21..c3f3d840b 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -933,7 +933,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 689ce3537..4c28d6815 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -394,6 +394,7 @@ TESTS = \
        asynchronous/bug793158.vala \
        asynchronous/closures.vala \
        asynchronous/generator.vala \
+       asynchronous/result-pos.vala \
        asynchronous/yield.vala \
        generics/bug640330.test \
        generics/bug640330.vala \
@@ -425,6 +426,7 @@ TESTS = \
        gir/bug788775.test \
        gir/bug792998.test \
        gir/array-fixed-length.test \
+       gir/async-result-pos.test \
        gir/class.test \
        gir/delegate-alias-without-target.test \
        gir/delegate-closure-destroy-index-conflict.test \
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 fdaa303d1..0bc1c52d2 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -3843,6 +3843,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) {
@@ -3874,6 +3875,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++;
                }
 
@@ -4113,6 +4124,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 f9c31e48a..166ed9d20 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -1014,6 +1014,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;
        }
@@ -1078,7 +1079,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 dab15a864..89d1f3fd0 100644
--- a/vala/valausedattr.vala
+++ b/vala/valausedattr.vala
@@ -40,7 +40,7 @@ public class Vala.UsedAttr : CodeVisitor {
                "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",
-               "use_inplace", "feature_test_macro", "default_value_on_error", "",
+               "use_inplace", "feature_test_macro", "default_value_on_error", "async_result_pos", "",
 
                "Immutable", "",
                "Compact", "",


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]