[vala/staging: 9/9] vala: Async methods don't allow out-parameters before in-parameters



commit 1dd1749a2b6259b6e3ad640a94e973fadd0cd799
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Sun Oct 21 10:34:28 2018 +0200

    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

 tests/Makefile.am                             |  2 +
 tests/asynchronous/out-parameter-invalid.test |  7 ++++
 tests/gir/async-sync-out.test                 | 58 +++++++++++++++++++++++++++
 vala/valagirparser.vala                       | 13 ++++++
 vala/valamethod.vala                          | 14 +++++++
 5 files changed, 94 insertions(+)
---
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..f9c331008 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -4073,6 +4073,19 @@ 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 = 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);


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