diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2018-10-21 10:34:28 +0200 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2019-01-08 18:14:04 +0100 |
commit | dd304f4d8ace88491a7c93e6939bc577fd2f7eaf (patch) | |
tree | 38b319213c96182235f2ff7c851b400379b138be | |
parent | afb9ea9687db1ca95ff169016e605f04e650cdfb (diff) | |
download | vala-dd304f4d8ace88491a7c93e6939bc577fd2f7eaf.tar.gz |
vala: Async methods don't allow out-parameters before in-parameters
out-parameters are always handled in the *_finish implementation and
therefore are asynchronous. Report an error for occurances in source
and a warning for GIR sources where convert them to pointer-types to
create a usuable signature for bindings.
Fixes https://gitlab.gnome.org/GNOME/vala/issues/636
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/asynchronous/out-parameter-invalid.test | 7 | ||||
-rw-r--r-- | tests/gir/async-sync-out.test | 58 | ||||
-rw-r--r-- | vala/valagirparser.vala | 14 | ||||
-rw-r--r-- | vala/valamethod.vala | 14 |
5 files changed, 95 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index b3d16c732..87afd9070 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -410,6 +410,7 @@ TESTS = \ asynchronous/bug793158.vala \ asynchronous/closures.vala \ asynchronous/generator.vala \ + asynchronous/out-parameter-invalid.test \ asynchronous/result-pos.vala \ asynchronous/yield.vala \ generics/bug640330.test \ @@ -443,6 +444,7 @@ TESTS = \ gir/bug792998.test \ gir/array-fixed-length.test \ gir/async-result-pos.test \ + gir/async-sync-out.test \ gir/class.test \ gir/delegate-alias-without-target.test \ gir/delegate-closure-destroy-index-conflict.test \ diff --git a/tests/asynchronous/out-parameter-invalid.test b/tests/asynchronous/out-parameter-invalid.test new file mode 100644 index 000000000..070218315 --- /dev/null +++ b/tests/asynchronous/out-parameter-invalid.test @@ -0,0 +1,7 @@ +Invalid Code + +async void foo (out int i, int j) { +} + +void main () { +} diff --git a/tests/gir/async-sync-out.test b/tests/gir/async-sync-out.test new file mode 100644 index 000000000..48956f61d --- /dev/null +++ b/tests/gir/async-sync-out.test @@ -0,0 +1,58 @@ +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="sync_output" direction="out" transfer-ownership="full"> + <type name="utf8" c:type="gchar**"/> + </parameter> + <parameter name="_callback_" transfer-ownership="none" allow-none="1" closure="3" 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="_res_" transfer-ownership="none"> + <type name="Gio.AsyncResult" c:type="GAsyncResult*"/> + </parameter> + <parameter name="output" direction="out" transfer-ownership="full"> + <type name="utf8" c:type="gchar**"/> + </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 (); + public async void method_async (string input, string* sync_output, out string output) throws GLib.Error; +} diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala index 061eb17c5..e522d3029 100644 --- a/vala/valagirparser.vala +++ b/vala/valagirparser.vala @@ -4073,6 +4073,20 @@ public class Vala.GirParser : CodeVisitor { void process_async_method (Node node) { var m = (Method) node.symbol; + + // TODO: async methods with out-parameters before in-parameters are not supported + bool requires_pointer = false; + foreach (var param in m.get_parameters ()) { + if (param.direction == ParameterDirection.IN) { + requires_pointer = true; + } else if (requires_pointer) { + param.direction = ParameterDirection.IN; + param.variable_type.nullable = false; + param.variable_type = new PointerType (param.variable_type); + Report.warning (param.source_reference, "Synchronous out-parameters are not supported in async methods"); + } + } + string finish_method_base; if (m.name == null) { assert (m is CreationMethod); diff --git a/vala/valamethod.vala b/vala/valamethod.vala index bd203ab36..22980085f 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -815,6 +815,20 @@ public class Vala.Method : Subroutine, Callable { } } + if (coroutine) { + // TODO: async methods with out-parameters before in-parameters are not supported + bool requires_pointer = false; + for (int i = parameters.size - 1; i >= 0; i--) { + var param = parameters[i]; + if (param.direction == ParameterDirection.IN) { + requires_pointer = true; + } else if (requires_pointer) { + error = true; + Report.error (param.source_reference, "Synchronous out-parameters are not supported in async methods"); + } + } + } + if (error_types != null) { foreach (DataType error_type in error_types) { error_type.check (context); |