From: Rico Tzschichholz Date: Mon, 20 Jul 2020 18:11:13 +0000 (+0200) Subject: vala: Allow prototype access to signal with emitter X-Git-Tag: 0.40.24~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b19f4392c75c18e3ab4750d9413a6951e1626e9;p=thirdparty%2Fvala.git vala: Allow prototype access to signal with emitter Fixes https://gitlab.gnome.org/GNOME/vala/issues/1040 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 8c2128cce..85d6a858d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -366,6 +366,9 @@ TESTS = \ objects/signals-dymanic-invalid-handler.test \ objects/signals-fundamental-return.vala \ objects/signals-gobject-return.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/test-025.vala \ objects/test-026.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 ae287ac6f..deb702a2a 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -515,6 +515,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 e40359811..9c22cbbe0 100644 --- a/vala/valasignal.vala +++ b/vala/valasignal.vala @@ -238,7 +238,7 @@ public class Vala.Signal : Symbol, Lockable, 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; @@ -262,7 +262,9 @@ public class Vala.Signal : Symbol, Lockable, Callable { var cl = parent_symbol as ObjectTypeSymbol; cl.add_hidden_method (emitter); - emitter.check (context); + if (!external_package) { + emitter.check (context); + } }