From: Rico Tzschichholz Date: Tue, 27 Nov 2018 22:53:56 +0000 (+0100) Subject: codegen: Add support for delegate parameters in signals X-Git-Tag: 0.43.1~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1139c1a9cfb50e989a6d50f671128b2e0c5df52;p=thirdparty%2Fvala.git codegen: Add support for delegate parameters in signals Fixes https://gitlab.gnome.org/GNOME/vala/issues/205 --- diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala index 0b89230e8..1c3665f80 100644 --- a/codegen/valaccodeattribute.vala +++ b/codegen/valaccodeattribute.vala @@ -1063,6 +1063,16 @@ public class Vala.CCodeAttribute : AttributeCache { } return ret; } + } else if (node is DelegateType) { + unowned DelegateType delegate_type = (DelegateType) node; + var ret = "POINTER"; + if (delegate_type.delegate_symbol.has_target) { + ret = "%s,POINTER".printf (ret); + if (delegate_type.is_disposable ()) { + ret = "%s,POINTER".printf (ret); + } + } + return ret; } else if (node is VoidType) { return "VOID"; } else { diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala index a8aa450e6..562fc9cf6 100644 --- a/codegen/valagsignalmodule.vala +++ b/codegen/valagsignalmodule.vala @@ -71,6 +71,8 @@ public class Vala.GSignalModule : GObjectModule { return "gint"; } else if (t is ArrayType) { return "gpointer"; + } else if (t is DelegateType) { + return "gpointer"; } else if (t is ErrorType) { return "gpointer"; } @@ -199,6 +201,16 @@ public class Vala.GSignalModule : GObjectModule { callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), length_ctype)); n_params++; } + } else if (p.variable_type is DelegateType) { + unowned DelegateType delegate_type = (DelegateType) p.variable_type; + if (delegate_type.delegate_symbol.has_target) { + callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_ccode_name (delegate_target_type))); + n_params++; + if (delegate_type.is_disposable ()) { + callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_ccode_name (delegate_target_destroy_type))); + n_params++; + } + } } } callback_decl.add_parameter (new CCodeParameter ("data2", "gpointer")); @@ -253,6 +265,8 @@ public class Vala.GSignalModule : GObjectModule { } else { get_value_function = "g_value_get_pointer"; } + } else if (p.variable_type is DelegateType) { + get_value_function = "g_value_get_pointer"; } else if (p.variable_type is PointerType || p.variable_type is GenericType) { get_value_function = "g_value_get_pointer"; } else if (p.variable_type is ErrorType) { @@ -276,6 +290,20 @@ public class Vala.GSignalModule : GObjectModule { fc.add_argument (inner_fc); i++; } + } else if (p.variable_type is DelegateType) { + unowned DelegateType delegate_type = (DelegateType) p.variable_type; + if (delegate_type.delegate_symbol.has_target) { + inner_fc = new CCodeFunctionCall (new CCodeIdentifier (get_value_function)); + inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ()))); + fc.add_argument (inner_fc); + i++; + if (delegate_type.is_disposable ()) { + inner_fc = new CCodeFunctionCall (new CCodeIdentifier (get_value_function)); + inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ()))); + fc.add_argument (inner_fc); + i++; + } + } } } fc.add_argument (new CCodeIdentifier ("data2")); @@ -392,6 +420,14 @@ public class Vala.GSignalModule : GObjectModule { params_len++; if (param.variable_type is ArrayType) { params_len += ((ArrayType) param.variable_type).rank; + } else if (param.variable_type is DelegateType) { + unowned DelegateType delegate_type = (DelegateType) param.variable_type; + if (delegate_type.delegate_symbol.has_target) { + params_len++; + if (delegate_type.is_disposable ()) { + params_len++; + } + } } } @@ -409,6 +445,15 @@ public class Vala.GSignalModule : GObjectModule { for (var i = 0; i < array_type.rank; i++) { csignew.add_argument (new CCodeConstant (length_type_id)); } + } else if (param.variable_type is DelegateType) { + unowned DelegateType delegate_type = (DelegateType) param.variable_type; + csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); + if (delegate_type.delegate_symbol.has_target) { + csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); + if (delegate_type.is_disposable ()) { + csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); + } + } } else if (param.variable_type is PointerType || param.variable_type is GenericType || param.direction != ParameterDirection.IN) { csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); } else if (param.variable_type is ErrorType) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 919f95842..2fbed86b6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -268,6 +268,7 @@ TESTS = \ objects/regex.vala \ objects/signals.vala \ objects/signals-delegate.vala \ + objects/signals-delegate-parameter.vala \ objects/singleton.vala \ objects/test-025.vala \ objects/test-026.vala \ diff --git a/tests/objects/signals-delegate-parameter.vala b/tests/objects/signals-delegate-parameter.vala new file mode 100644 index 000000000..e3de21eb8 --- /dev/null +++ b/tests/objects/signals-delegate-parameter.vala @@ -0,0 +1,69 @@ +delegate void FooFunc (); +[CCode (has_target = false)] +delegate void BarFunc (); + +class Foo : Object { + public signal void delegate_param_no_target (BarFunc f); + public signal void delegate_param_with_target (FooFunc f); + public signal void delegate_param_with_destroy (owned FooFunc f); +} + +void no_target_cb (BarFunc f) { + f (); +} + +void with_target_cb (FooFunc f) { + f (); +} + +void with_destroy_cb (owned FooFunc f) { + f (); +} + +bool success1 = false; + +class Bar : Object { + Foo foo; + + bool success2 = false; + bool success3 = false; + + public Bar () { + foo = new Foo (); + } + + public void test_no_target () { + foo.delegate_param_no_target.connect (no_target_cb); + foo.delegate_param_no_target (() => { + success1 = true; + }); + assert (success1); + } + + public void test_with_target () { + foo.delegate_param_with_target.connect (with_target_cb); + foo.delegate_param_with_target (() => { + assert (this.ref_count == 1); + success2 = true; + }); + assert (this.ref_count == 1); + assert (success2); + } + + public void test_with_destroy () { + foo.delegate_param_with_destroy.connect (with_destroy_cb); + foo.delegate_param_with_destroy (() => { + assert (this.ref_count == 2); + success3 = true; + }); + assert (this.ref_count == 1); + assert (success3); + } +} + +void main () { + var bar = new Bar (); + bar.test_no_target (); + bar.test_with_target (); + bar.test_with_destroy (); +}