[vala/staging: 2/2] vala: Allow prototype access to signal with emitter



commit 168310dd0223c2b5a9c0d4e5c8d339e887a3330b
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Mon Jul 20 20:11:13 2020 +0200

    vala: Allow prototype access to signal with emitter
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/1040

 tests/Makefile.am                                  |  3 ++
 .../signals-prototype-access-invalid-2.test        | 12 ++++++
 .../objects/signals-prototype-access-invalid.test  | 16 ++++++++
 tests/objects/signals-prototype-access.vala        | 47 ++++++++++++++++++++++
 vala/valamemberaccess.vala                         | 22 ++++++++++
 vala/valasignal.vala                               |  6 ++-
 6 files changed, 104 insertions(+), 2 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fc4ec5042..a5dc4b037 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -441,6 +441,9 @@ TESTS = \
        objects/signals-fundamental-return.vala \
        objects/signals-gobject-return.vala \
        objects/signals-lambda-delegate.vala \
+       objects/signals-prototype-access.vala \
+       objects/signals-prototype-access-invalid.test \
+       objects/signals-prototype-access-invalid-2.test \
        objects/signals-struct-return.vala \
        objects/singleton.vala \
        objects/test-025.vala \
diff --git a/tests/objects/signals-prototype-access-invalid-2.test 
b/tests/objects/signals-prototype-access-invalid-2.test
new file mode 100644
index 000000000..ad1c800fb
--- /dev/null
+++ b/tests/objects/signals-prototype-access-invalid-2.test
@@ -0,0 +1,12 @@
+Invalid Code
+
+delegate void FooFunc ();
+
+class Foo {
+       public signal int bar ();
+}
+
+void main () {
+       var foo = new Foo ();
+       FooFunc func = Foo.bar;
+}
diff --git a/tests/objects/signals-prototype-access-invalid.test 
b/tests/objects/signals-prototype-access-invalid.test
new file mode 100644
index 000000000..83a1b79d7
--- /dev/null
+++ b/tests/objects/signals-prototype-access-invalid.test
@@ -0,0 +1,16 @@
+Invalid Code
+
+[CCode (has_target = false)]
+delegate void FooFunc (Foo foo);
+
+class Foo {
+       public signal int bar ();
+
+       public void manam (FooFunc func) {
+       }
+}
+
+void main () {
+       var foo = new Foo ();
+       foo.manam (Foo.bar);
+}
diff --git a/tests/objects/signals-prototype-access.vala b/tests/objects/signals-prototype-access.vala
new file mode 100644
index 000000000..39d70aeeb
--- /dev/null
+++ b/tests/objects/signals-prototype-access.vala
@@ -0,0 +1,47 @@
+[CCode (has_target = false)]
+delegate int FooFunc (Foo foo);
+
+delegate int BarFunc ();
+
+class Foo {
+       [HasEmitter]
+       public virtual signal int bar () {
+               return 23;
+       }
+
+       public void manam (FooFunc func) {
+               assert (func (this) == 23);
+       }
+
+       public void minim (BarFunc func) {
+               assert (func () == 23);
+       }
+}
+
+void main () {
+       var foo = new Foo ();
+       {
+               foo.manam (Foo.bar);
+               foo.manam ((FooFunc) Foo.bar);
+       }
+       {
+               FooFunc func = Foo.bar;
+               assert (func (foo) == 23);
+       }
+       {
+               FooFunc func = (FooFunc) Foo.bar;
+               assert (func (foo) == 23);
+       }
+       {
+               foo.minim (foo.bar);
+               foo.minim ((BarFunc) foo.bar);
+       }
+       {
+               BarFunc func = foo.bar;
+               assert (func () == 23);
+       }
+       {
+               BarFunc func = (BarFunc) foo.bar;
+               assert (func () == 23);
+       }
+}
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 3aa9d21fa..88af4c0ca 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -557,6 +557,28 @@ public class Vala.MemberAccess : Expression {
                        return false;
                }
 
+               if (symbol_reference is Signal) {
+                       unowned Signal sig = (Signal) symbol_reference;
+                       unowned CodeNode? ma = this;
+                       while (ma.parent_node is MemberAccess) {
+                               ma = ma.parent_node;
+                       }
+                       unowned CodeNode? parent = ma.parent_node;
+                       if (parent != null && !(parent is ElementAccess) && !(((MemberAccess) ma).inner is 
BaseAccess)
+                           && (!(parent is MethodCall) || ((MethodCall) parent).get_argument_list 
().contains (this))) {
+                               if (sig.get_attribute ("HasEmitter") != null) {
+                                       if (!sig.check (context)) {
+                                               return false;
+                                       }
+                                       symbol_reference = sig.emitter;
+                               } else {
+                                       error = true;
+                                       Report.error (source_reference, "Signal `%s' requires emitter in this 
context".printf (symbol_reference.get_full_name ()));
+                                       return false;
+                               }
+                       }
+               }
+
                unowned Symbol? member = symbol_reference;
                var access = SymbolAccessibility.PUBLIC;
                bool instance = false;
diff --git a/vala/valasignal.vala b/vala/valasignal.vala
index a07a0f5d6..392b31489 100644
--- a/vala/valasignal.vala
+++ b/vala/valasignal.vala
@@ -250,7 +250,7 @@ public class Vala.Signal : Symbol, Callable {
                        default_handler.check (context);
                }
 
-               if (!external_package && get_attribute ("HasEmitter") != null) {
+               if (get_attribute ("HasEmitter") != null) {
                        emitter = new Method (name, return_type, source_reference);
 
                        emitter.owner = owner;
@@ -274,7 +274,9 @@ public class Vala.Signal : Symbol, Callable {
                        unowned ObjectTypeSymbol? cl = parent_symbol as ObjectTypeSymbol;
 
                        cl.add_hidden_method (emitter);
-                       emitter.check (context);
+                       if (!external_package) {
+                               emitter.check (context);
+                       }
                }
 
 


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