From fa69d6030a3e53967d72cf9b7ba428f3b35d0af5 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Mon, 20 Jul 2020 20:11:13 +0200 Subject: [PATCH] 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 +++++ .../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(-) create mode 100644 tests/objects/signals-prototype-access-invalid-2.test create mode 100644 tests/objects/signals-prototype-access-invalid.test create mode 100644 tests/objects/signals-prototype-access.vala diff --git a/tests/Makefile.am b/tests/Makefile.am index 7183499d7..49f2b3a99 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -416,6 +416,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 89e0a795f..2bb8d462d 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -512,6 +512,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; + } + } + } + var member = symbol_reference; var access = SymbolAccessibility.PUBLIC; bool instance = false; diff --git a/vala/valasignal.vala b/vala/valasignal.vala index 2881c3b2f..a79fae7f5 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 { var cl = parent_symbol as ObjectTypeSymbol; cl.add_hidden_method (emitter); - emitter.check (context); + if (!external_package) { + emitter.check (context); + } } -- 2.47.2