[vala/staging] codegen: Support non-virtual signals with default handler



commit 5da90d7c5bfe9a977720221717c774300c24484c
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Fri Aug 7 18:54:51 2020 +0200

    codegen: Support non-virtual signals with default handler
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/1056

 codegen/valaccodeattribute.vala                  |  2 +-
 codegen/valagsignalmodule.vala                   | 11 +++++++++--
 codegen/valagtypemodule.vala                     | 22 +++++++++++++++++-----
 tests/Makefile.am                                |  1 +
 tests/objects/signals-default-class-handler.vala | 23 +++++++++++++++++++++++
 vala/valasignal.vala                             | 13 +++----------
 6 files changed, 54 insertions(+), 18 deletions(-)
---
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index 935810d2a..c73d124c0 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -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);
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index 108622815..e005f6b38 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -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"));
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 8b2c6c03d..88a1cd14b 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -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);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b28a2a45f..e98e4dca6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 000000000..aff938726
--- /dev/null
+++ b/tests/objects/signals-default-class-handler.vala
@@ -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);
+}
diff --git a/vala/valasignal.vala b/vala/valasignal.vala
index 392b31489..df7d76199 100644
--- a/vala/valasignal.vala
+++ b/vala/valasignal.vala
@@ -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);
                        }


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