]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Support non-virtual signals with default handler
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 7 Aug 2020 16:54:51 +0000 (18:54 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Fri, 7 Aug 2020 17:04:45 +0000 (19:04 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1056

codegen/valaccodeattribute.vala
codegen/valagsignalmodule.vala
codegen/valagtypemodule.vala
tests/Makefile.am
tests/objects/signals-default-class-handler.vala [new file with mode: 0644]
vala/valasignal.vala

index 935810d2a1b58b79fcca759e56414695224b7452..c73d124c0714688607c7e8a24d5ebf5257498cde 100644 (file)
@@ -1437,7 +1437,7 @@ public class Vala.CCodeAttribute : AttributeCache {
                        }
                } else if (sym is Method) {
                        unowned Method m = (Method) sym;
-                       if (m.base_method != null || m.base_interface_method != null) {
+                       if (m.base_method != null || m.base_interface_method != null || m.signal_reference != null) {
                                string m_name;
                                if (m.signal_reference != null) {
                                        m_name = get_ccode_lower_case_name (m.signal_reference);
index 108622815a59b7cc96b3d50b1004b2499e65cbca..e005f6b3845da7a9adfafb1ab39044aed79e80b5 100644 (file)
@@ -347,7 +347,12 @@ public class Vala.GSignalModule : GObjectModule {
        }
 
        public override CCodeExpression get_signal_creation (Signal sig, TypeSymbol type) {
-               var csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new"));
+               CCodeFunctionCall csignew;
+               if (sig.default_handler == null || sig.is_virtual) {
+                       csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new"));
+               } else {
+                       csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new_class_handler"));
+               }
                csignew.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (sig))));
                csignew.add_argument (new CCodeIdentifier (get_ccode_type_id (type)));
                string[] flags = new string[0];
@@ -383,7 +388,7 @@ public class Vala.GSignalModule : GObjectModule {
 
                if (sig.default_handler == null) {
                        csignew.add_argument (new CCodeConstant ("0"));
-               } else {
+               } else if (sig.is_virtual) {
                        var struct_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET"));
                        if (type is Class) {
                                struct_offset.add_argument (new CCodeIdentifier ("%sClass".printf (get_ccode_name (type))));
@@ -393,6 +398,8 @@ public class Vala.GSignalModule : GObjectModule {
                        }
                        struct_offset.add_argument (new CCodeIdentifier (get_ccode_vfunc_name (sig.default_handler)));
                        csignew.add_argument (struct_offset);
+               } else {
+                       csignew.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_real_name (sig.default_handler)), "GCallback"));
                }
                csignew.add_argument (new CCodeConstant ("NULL"));
                csignew.add_argument (new CCodeConstant ("NULL"));
index 8b2c6c03d96db105d1872424abd9dcf94a4f6940..88a1cd14bc540df7501d4f79eaa7c702857ccf8f 100644 (file)
@@ -271,7 +271,11 @@ public class Vala.GTypeModule : GErrorModule {
                                } else if (s is Signal) {
                                        var sig = (Signal) s;
                                        if (sig.default_handler != null) {
-                                               generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                                               if (sig.is_virtual) {
+                                                       generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                                               } else {
+                                                       generate_method_declaration (sig.default_handler, cfile);
+                                               }
                                        }
                                } else if (s is Property) {
                                        var prop = (Property) s;
@@ -291,7 +295,11 @@ public class Vala.GTypeModule : GErrorModule {
 
                        foreach (Signal sig in cl.get_signals ()) {
                                if (sig.default_handler != null) {
-                                       generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                                       if (sig.is_virtual) {
+                                               generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                                       } else {
+                                               generate_method_declaration (sig.default_handler, cfile);
+                                       }
                                }
                        }
 
@@ -1281,7 +1289,7 @@ public class Vala.GTypeModule : GErrorModule {
 
                /* connect default signal handlers */
                foreach (Signal sig in cl.get_signals ()) {
-                       if (sig.default_handler == null) {
+                       if (sig.default_handler == null || !sig.is_virtual) {
                                continue;
                        }
                        generate_method_declaration (sig.default_handler, cfile);
@@ -2118,7 +2126,11 @@ public class Vala.GTypeModule : GErrorModule {
                                generate_struct_method_declaration (iface, m, instance_struct, type_struct, decl_space, ref has_struct_member);
                        } else if ((sig = sym as Signal) != null) {
                                if (sig.default_handler != null) {
-                                       generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                                       if (sig.is_virtual) {
+                                               generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                                       } else {
+                                               generate_method_declaration (sig.default_handler, cfile);
+                                       }
                                }
                        } else if ((prop = sym as Property) != null) {
                                generate_struct_property_declaration (iface, prop, instance_struct, type_struct, decl_space, ref has_struct_member);
@@ -2222,7 +2234,7 @@ public class Vala.GTypeModule : GErrorModule {
 
                /* connect default signal handlers */
                foreach (Signal sig in iface.get_signals ()) {
-                       if (sig.default_handler == null) {
+                       if (sig.default_handler == null || !sig.is_virtual) {
                                continue;
                        }
                        var cname = get_ccode_real_name (sig.default_handler);
index b28a2a45f5fec45bf66082927f50bf33650b29e7..e98e4dca651311e3f52c5293d06af949cb272585 100644 (file)
@@ -436,6 +436,7 @@ TESTS = \
        objects/sealed-class.test \
        objects/sealed-compact-class.test \
        objects/signals.vala \
+       objects/signals-default-class-handler.vala \
        objects/signals-enum-marshal.vala \
        objects/signals-delegate.vala \
        objects/signals-delegate-parameter.vala \
diff --git a/tests/objects/signals-default-class-handler.vala b/tests/objects/signals-default-class-handler.vala
new file mode 100644 (file)
index 0000000..aff9387
--- /dev/null
@@ -0,0 +1,23 @@
+bool success = false;
+bool success2 = false;
+
+class Foo {
+       public signal void foo () {
+               success = true;
+       }
+
+       [HasEmitter]
+       public signal void foo_with_emitter () {
+               success2 = true;
+       }
+}
+
+void main () {
+       var foo = new Foo ();
+
+       foo.foo ();
+       assert (success);
+
+       foo.foo_with_emitter ();
+       assert (success2);
+}
index 392b3148913311e5e9db990a3fb1779a2eecf97e..df7d761990b92e04b51232315a8fd84669ac50e9 100644 (file)
@@ -222,24 +222,17 @@ public class Vala.Signal : Symbol, Callable {
                        }
                }
 
-               if (!is_virtual && body != null) {
-                       error = true;
-                       Report.error (source_reference, "Only virtual signals can have a default signal handler body");
-               }
-
-
-               if (is_virtual) {
+               if (body != null || (is_virtual && external_package)) {
                        default_handler = new Method (name, return_type, source_reference);
 
                        default_handler.owner = owner;
-                       default_handler.access = access;
+                       default_handler.access = (is_virtual ? access : SymbolAccessibility.PRIVATE);
                        default_handler.external = external;
                        default_handler.hides = hides;
-                       default_handler.is_virtual = true;
+                       default_handler.is_virtual = is_virtual;
                        default_handler.signal_reference = this;
                        default_handler.body = body;
 
-
                        foreach (Parameter param in parameters) {
                                default_handler.add_parameter (param);
                        }