summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2018-12-10 16:07:46 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2018-12-18 10:10:50 +0100
commita7301790446a48908da362a7fdc5e4079759e8f6 (patch)
tree5ca272ecbb3a2d31146013dcdafd41912c6b27bc
parent79fc0bb16b68eaec36104d9970fda4497add6918 (diff)
downloadvala-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.vala7
-rw-r--r--codegen/valaccodemethodcallmodule.vala2
-rw-r--r--codegen/valagasyncmodule.vala6
-rw-r--r--codegen/valagdbusclientmodule.vala2
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/asynchronous/result-pos.vala48
-rw-r--r--tests/gir/async-result-pos.test56
-rw-r--r--vala/valagirparser.vala13
-rw-r--r--vala/valamethod.vala3
-rw-r--r--vala/valausedattr.vala3
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", "",