From: Rico Tzschichholz Date: Wed, 2 Oct 2019 17:07:17 +0000 (+0200) Subject: vala: Add DelegateType.target/destroy fields to access its user-data X-Git-Tag: 0.47.1~114 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=c054da918a40f8ef93c1a006034fb6ab4717c135;p=thirdparty%2Fvala.git vala: Add DelegateType.target/destroy fields to access its user-data Fixes https://gitlab.gnome.org/GNOME/vala/issues/857 --- 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 + */ + +/** + * 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 + */ + +/** + * 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;