[vala/staging] vala: Add DelegateType.target/destroy fields to access its user-data



commit c054da918a40f8ef93c1a006034fb6ab4717c135
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Wed Oct 2 19:07:17 2019 +0200

    vala: Add DelegateType.target/destroy fields to access its user-data
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/857

 codegen/valaccodememberaccessmodule.vala   | 13 +++++++++++
 tests/Makefile.am                          |  1 +
 tests/delegates/member-target-destroy.vala | 23 +++++++++++++++++++
 vala/Makefile.am                           |  2 ++
 vala/valaassignment.vala                   |  2 ++
 vala/valadelegatedestroyfield.vala         | 36 ++++++++++++++++++++++++++++++
 vala/valadelegatetargetfield.vala          | 36 ++++++++++++++++++++++++++++++
 vala/valadelegatetype.vala                 | 28 +++++++++++++++++++++++
 8 files changed, 141 insertions(+)
---
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 4c0c9f009..54a71a3e2 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -113,6 +113,19 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                Report.error (expr.source_reference, "unsupported use of length field of 
multi-dimensional array");
                        }
                        set_cvalue (expr, get_array_length_cexpression (expr.inner, 1));
+               } else if (expr.symbol_reference is DelegateTargetField) {
+                       if (!((DelegateType) expr.inner.value_type).delegate_symbol.has_target) {
+                               Report.error (expr.source_reference, "unsupported use of target field of 
delegate without target");
+                       }
+                       CCodeExpression delegate_target_destroy_notify;
+                       set_cvalue (expr, get_delegate_target_cexpression (expr.inner, out 
delegate_target_destroy_notify));
+               } else if (expr.symbol_reference is DelegateDestroyField) {
+                       if (!((DelegateType) expr.inner.value_type).delegate_symbol.has_target) {
+                               Report.error (expr.source_reference, "unsupported use of destroy field of 
delegate without target");
+                       }
+                       CCodeExpression delegate_target_destroy_notify;
+                       get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify);
+                       set_cvalue (expr, delegate_target_destroy_notify);
                } else if (expr.symbol_reference is Field) {
                        var field = (Field) expr.symbol_reference;
                        if (expr.lvalue) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d0e75c29b..b404f7af3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -277,6 +277,7 @@ TESTS = \
        delegates/instance-method-to-no-target.test \
        delegates/lambda-mixed-instance-static.vala \
        delegates/lambda-shared-closure.vala \
+       delegates/member-target-destroy.vala \
        delegates/reference_transfer.vala \
        delegates/return-array-null-terminated.vala \
        delegates/wrapper.vala \
diff --git a/tests/delegates/member-target-destroy.vala b/tests/delegates/member-target-destroy.vala
new file mode 100644
index 000000000..468bff95f
--- /dev/null
+++ b/tests/delegates/member-target-destroy.vala
@@ -0,0 +1,23 @@
+delegate string Foo ();
+
+string bar (string s) {
+       return s;
+}
+
+void foo_free (void* data) {
+       GLib.free (data);
+}
+
+void main () {
+       Foo foo = (Foo) bar;
+       assert (foo.target == null);
+       assert (foo.destroy == null);
+
+       string* foo_data = "foo".dup ();
+       foo.target = foo_data;
+       foo.destroy = (GLib.DestroyNotify) foo_free;
+
+       assert (foo () == "foo");
+       assert (foo.target == foo_data);
+       assert (foo.destroy == (GLib.DestroyNotify) foo_free);
+}
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 7fb1e26f7..57c758fdc 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -64,6 +64,8 @@ libvala_la_VALASOURCES = \
        valadatatype.vala \
        valadeclarationstatement.vala \
        valadelegate.vala \
+       valadelegatedestroyfield.vala \
+       valadelegatetargetfield.vala \
        valadelegatetype.vala \
        valadeletestatement.vala \
        valadestructor.vala \
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index 9a4c2c97e..c2ac1a189 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -451,6 +451,8 @@ public class Vala.Assignment : Expression {
                            (local != null || param != null || field != null) &&
                            !is_array_add () &&
                            !(field is ArrayLengthField) &&
+                           !(field is DelegateTargetField) &&
+                           !(field is DelegateDestroyField) &&
                                !(left.value_type.is_real_non_null_struct_type () && right is 
ObjectCreationExpression)) {
                                // visit_assignment not necessary
                                if (instance && ma.inner != null) {
diff --git a/vala/valadelegatedestroyfield.vala b/vala/valadelegatedestroyfield.vala
new file mode 100644
index 000000000..e175b172a
--- /dev/null
+++ b/vala/valadelegatedestroyfield.vala
@@ -0,0 +1,36 @@
+/* valadelegatedestroyfield.vala
+ *
+ * Copyright (C) 2019  Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Rico Tzschichholz <ricotz ubuntu com>
+ */
+
+/**
+ * Represents the Delegate.destroy field.
+ */
+public class Vala.DelegateDestroyField : Field {
+       /**
+        * Creates a new delegate destroy field.
+        *
+        * @return newly created field
+        */
+       public DelegateDestroyField (SourceReference source_reference) {
+               base ("destroy", CodeContext.get ().analyzer.delegate_target_destroy_type, null, 
source_reference);
+               external = true;
+       }
+}
diff --git a/vala/valadelegatetargetfield.vala b/vala/valadelegatetargetfield.vala
new file mode 100644
index 000000000..6f3782782
--- /dev/null
+++ b/vala/valadelegatetargetfield.vala
@@ -0,0 +1,36 @@
+/* valadelegatetargetfield.vala
+ *
+ * Copyright (C) 2019  Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Rico Tzschichholz <ricotz ubuntu com>
+ */
+
+/**
+ * Represents the Delegate.target field.
+ */
+public class Vala.DelegateTargetField : Field {
+       /**
+        * Creates a new delegate target field.
+        *
+        * @return newly created field
+        */
+       public DelegateTargetField (SourceReference source_reference) {
+               base ("target", new PointerType (new VoidType ()), null, source_reference);
+               external = true;
+       }
+}
diff --git a/vala/valadelegatetype.vala b/vala/valadelegatetype.vala
index 539b53050..2c5efb911 100644
--- a/vala/valadelegatetype.vala
+++ b/vala/valadelegatetype.vala
@@ -34,11 +34,39 @@ public class Vala.DelegateType : CallableType {
 
        public bool is_called_once { get; set; }
 
+       DelegateTargetField? target_field;
+       DelegateDestroyField? destroy_field;
+
        public DelegateType (Delegate delegate_symbol) {
                base (delegate_symbol);
                this.is_called_once = (delegate_symbol.get_attribute_string ("CCode", "scope") == "async");
        }
 
+       public override Symbol? get_member (string member_name) {
+               if (member_name == "target") {
+                       return get_target_field ();
+               } else if (member_name == "destroy") {
+                       return get_destroy_field ();
+               }
+               return null;
+       }
+
+       unowned DelegateTargetField get_target_field () {
+               if (target_field == null) {
+                       target_field = new DelegateTargetField (source_reference);
+                       target_field.access = SymbolAccessibility.PUBLIC;
+               }
+               return target_field;
+       }
+
+       unowned DelegateDestroyField get_destroy_field () {
+               if (destroy_field == null) {
+                       destroy_field = new DelegateDestroyField (source_reference);
+                       destroy_field.access = SymbolAccessibility.PUBLIC;
+               }
+               return destroy_field;
+       }
+
        public override DataType copy () {
                var result = new DelegateType (delegate_symbol);
                result.source_reference = source_reference;


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