]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Add DelegateType.target/destroy fields to access its user-data c054da918a40f8ef93c1a006034fb6ab4717c135
authorRico Tzschichholz <ricotz@ubuntu.com>
Wed, 2 Oct 2019 17:07:17 +0000 (19:07 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Thu, 3 Oct 2019 13:15:46 +0000 (15:15 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/857

codegen/valaccodememberaccessmodule.vala
tests/Makefile.am
tests/delegates/member-target-destroy.vala [new file with mode: 0644]
vala/Makefile.am
vala/valaassignment.vala
vala/valadelegatedestroyfield.vala [new file with mode: 0644]
vala/valadelegatetargetfield.vala [new file with mode: 0644]
vala/valadelegatetype.vala

index 4c0c9f009b1ab11303d8152dcda904d014216b28..54a71a3e2bfca726f505a31f5a2ac38a9350616d 100644 (file)
@@ -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) {
index d0e75c29b92f5c85927d6a72b909c8791ac67d47..b404f7af32e6b10e00ab8167a0d804494f3b44c5 100644 (file)
@@ -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 (file)
index 0000000..468bff9
--- /dev/null
@@ -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);
+}
index 7fb1e26f7ac3a7ef08cfdc0a311ebebd6920ee04..57c758fdce359560a7aad713449122b98459fbcc 100644 (file)
@@ -64,6 +64,8 @@ libvala_la_VALASOURCES = \
        valadatatype.vala \
        valadeclarationstatement.vala \
        valadelegate.vala \
+       valadelegatedestroyfield.vala \
+       valadelegatetargetfield.vala \
        valadelegatetype.vala \
        valadeletestatement.vala \
        valadestructor.vala \
index 9a4c2c97e27b7825ff57e5de1db39ca334d55ee3..c2ac1a1890a8c01081fc0a04628155af79d49b41 100644 (file)
@@ -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 (file)
index 0000000..e175b17
--- /dev/null
@@ -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 (file)
index 0000000..6f37827
--- /dev/null
@@ -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;
+       }
+}
index 539b53050ea1e1a90cd6c175bbd07f13030124ac..2c5efb91199b08b548cb5852b51a81083d9049fb 100644 (file)
@@ -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;