[vala/staging] vala: Add support to infer return type of dynamic signals
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] vala: Add support to infer return type of dynamic signals
- Date: Tue, 25 Jan 2022 12:42:59 +0000 (UTC)
commit 3e38dc450eb5a1ebf1dd5d1b88ae69f660097429
Author: Lorenz Wildberg <lorenz wild-fisch de>
Date: Wed Dec 8 18:41:39 2021 +0000
vala: Add support to infer return type of dynamic signals
codegen/valaccodemethodcallmodule.vala | 6 +-
tests/Makefile.am | 1 +
tests/objects/signals-dynamic-emit.c-expected | 76 ++++++++++++++++++++++
tests/objects/signals-dynamic-emit.vala | 15 +++++
.../signals-dynamic-invalid-return-type.test | 12 ++++
tests/objects/signals-emit.c-expected | 76 ++++++++++++++++++++++
tests/objects/signals-emit.vala | 15 +++++
vala/valamemberaccess.vala | 8 ++-
8 files changed, 207 insertions(+), 2 deletions(-)
---
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index d7827741b..6332271ad 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -546,7 +546,11 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
}
}
- arg_pos = get_param_pos (param != null && !ellipsis ? get_ccode_pos (param) : i,
ellipsis);
+ if (itype is SignalType && ((SignalType) itype).signal_symbol is DynamicSignal) {
+ arg_pos = get_param_pos (i, false);
+ } else {
+ arg_pos = get_param_pos (param != null && !ellipsis ? get_ccode_pos (param) :
i, ellipsis);
+ }
carg_map.set (arg_pos, cexpr);
if (m is ArrayResizeMethod && context.profile == Profile.POSIX) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2103afa6e..0b9f71524 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -563,6 +563,7 @@ TESTS = \
objects/signals-dynamic-emit.vala \
objects/signals-dynamic-invalid-disconnect.test \
objects/signals-dymanic-invalid-handler.test \
+ objects/signals-dynamic-invalid-return-type.test \
objects/signals-dynamic-lambda-handler.test \
objects/signals-emit.vala \
objects/signals-error-marshal.vala \
diff --git a/tests/objects/signals-dynamic-emit.c-expected b/tests/objects/signals-dynamic-emit.c-expected
index 5b04c9bbb..7c71e3b42 100644
--- a/tests/objects/signals-dynamic-emit.c-expected
+++ b/tests/objects/signals-dynamic-emit.c-expected
@@ -33,6 +33,7 @@ enum {
static GParamSpec* foo_properties[FOO_NUM_PROPERTIES];
enum {
FOO_SIG_SIGNAL,
+ FOO_SIG2_SIGNAL,
FOO_NUM_SIGNALS
};
static guint foo_signals[FOO_NUM_SIGNALS] = {0};
@@ -65,15 +66,28 @@ static void g_cclosure_user_marshal_VOID__STRING_INT (GClosure * closure,
const GValue * param_values,
gpointer invocation_hint,
gpointer marshal_data);
+static void g_cclosure_user_marshal_BOOLEAN__STRING_INT (GClosure * closure,
+ GValue * return_value,
+ guint n_param_values,
+ const GValue * param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
static GType foo_get_type_once (void);
VALA_EXTERN void sig_cb (GObject* o,
const gchar* s,
gint i);
+VALA_EXTERN gboolean sig2_cb (GObject* o,
+ const gchar* s,
+ gint i);
static void _vala_main (void);
static void _sig_cb_dynamic_sig0_ (GObject* _sender,
const gchar* s,
gint i,
gpointer self);
+static gboolean _sig2_cb_dynamic_sig21_ (GObject* _sender,
+ const gchar* s,
+ gint i,
+ gpointer self);
Foo*
foo_construct (GType object_type)
@@ -115,12 +129,42 @@ g_cclosure_user_marshal_VOID__STRING_INT (GClosure * closure,
callback (data1, g_value_get_string (param_values + 1), g_value_get_int (param_values + 2), data2);
}
+static void
+g_cclosure_user_marshal_BOOLEAN__STRING_INT (GClosure * closure,
+ GValue * return_value,
+ guint n_param_values,
+ const GValue * param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_INT) (gpointer data1, const char* arg_1, gint arg_2,
gpointer data2);
+ register GMarshalFunc_BOOLEAN__STRING_INT callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ gboolean v_return;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 3);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__STRING_INT) (marshal_data ? marshal_data : cc->callback);
+ v_return = callback (data1, g_value_get_string (param_values + 1), g_value_get_int (param_values +
2), data2);
+ g_value_set_boolean (return_value, v_return);
+}
+
static void
foo_class_init (FooClass * klass,
gpointer klass_data)
{
foo_parent_class = g_type_class_peek_parent (klass);
foo_signals[FOO_SIG_SIGNAL] = g_signal_new ("sig", TYPE_FOO, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_user_marshal_VOID__STRING_INT, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
+ foo_signals[FOO_SIG2_SIGNAL] = g_signal_new ("sig2", TYPE_FOO, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_user_marshal_BOOLEAN__STRING_INT, G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_INT);
}
static void
@@ -162,6 +206,21 @@ sig_cb (GObject* o,
_vala_assert (i == 42, "i == 42");
}
+gboolean
+sig2_cb (GObject* o,
+ const gchar* s,
+ gint i)
+{
+ gboolean result;
+ g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (o, G_TYPE_OBJECT), FALSE);
+ g_return_val_if_fail (s != NULL, FALSE);
+ success = TRUE;
+ _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\"");
+ _vala_assert (i == 42, "i == 42");
+ result = TRUE;
+ return result;
+}
+
static void
_sig_cb_dynamic_sig0_ (GObject* _sender,
const gchar* s,
@@ -171,17 +230,34 @@ _sig_cb_dynamic_sig0_ (GObject* _sender,
sig_cb (_sender, s, i);
}
+static gboolean
+_sig2_cb_dynamic_sig21_ (GObject* _sender,
+ const gchar* s,
+ gint i,
+ gpointer self)
+{
+ gboolean result;
+ result = sig2_cb (_sender, s, i);
+ return result;
+}
+
static void
_vala_main (void)
{
GObject* dfoo = NULL;
Foo* _tmp0_;
+ gboolean _tmp1_ = FALSE;
_tmp0_ = foo_new ();
dfoo = G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, G_TYPE_OBJECT, GObject);
g_signal_connect (dfoo, "sig", (GCallback) _sig_cb_dynamic_sig0_, NULL);
success = FALSE;
g_signal_emit_by_name (dfoo, "sig", "foo", 42);
_vala_assert (success, "success");
+ g_signal_connect (dfoo, "sig2", (GCallback) _sig2_cb_dynamic_sig21_, NULL);
+ success = FALSE;
+ g_signal_emit_by_name (dfoo, "sig2", "foo", 42, &_tmp1_);
+ _vala_assert (_tmp1_, "dfoo.sig2.emit (\"foo\", 42)");
+ _vala_assert (success, "success");
_g_object_unref0 (dfoo);
}
diff --git a/tests/objects/signals-dynamic-emit.vala b/tests/objects/signals-dynamic-emit.vala
index 55d6fac98..8605bc5d3 100644
--- a/tests/objects/signals-dynamic-emit.vala
+++ b/tests/objects/signals-dynamic-emit.vala
@@ -1,5 +1,7 @@
class Foo : Object {
public signal void sig (string s, int i);
+
+ public signal bool sig2 (string s, int i);
}
void sig_cb (Object o, string s, int i) {
@@ -8,6 +10,13 @@ void sig_cb (Object o, string s, int i) {
assert (i == 42);
}
+bool sig2_cb (Object o, string s, int i) {
+ success = true;
+ assert (s == "foo");
+ assert (i == 42);
+ return true;
+}
+
bool success = false;
void main () {
@@ -17,4 +26,10 @@ void main () {
success = false;
dfoo.sig.emit ("foo", 42);
assert (success);
+
+ dfoo.sig2.connect (sig2_cb);
+
+ success = false;
+ assert (dfoo.sig2.emit ("foo", 42));
+ assert (success);
}
diff --git a/tests/objects/signals-dynamic-invalid-return-type.test
b/tests/objects/signals-dynamic-invalid-return-type.test
new file mode 100644
index 000000000..4c7c1ceef
--- /dev/null
+++ b/tests/objects/signals-dynamic-invalid-return-type.test
@@ -0,0 +1,12 @@
+Invalid Code
+
+class Foo : Object {
+ public signal void sig ();
+}
+
+void main () {
+ var real = new Foo ();
+ dynamic Object foo = real;
+
+ var bar = foo.sig.emit ();
+}
diff --git a/tests/objects/signals-emit.c-expected b/tests/objects/signals-emit.c-expected
index e249f6fe7..3836abc87 100644
--- a/tests/objects/signals-emit.c-expected
+++ b/tests/objects/signals-emit.c-expected
@@ -33,6 +33,7 @@ enum {
static GParamSpec* foo_properties[FOO_NUM_PROPERTIES];
enum {
FOO_SIG_SIGNAL,
+ FOO_SIG2_SIGNAL,
FOO_NUM_SIGNALS
};
static guint foo_signals[FOO_NUM_SIGNALS] = {0};
@@ -66,15 +67,28 @@ static void g_cclosure_user_marshal_VOID__STRING_INT (GClosure * closure,
const GValue * param_values,
gpointer invocation_hint,
gpointer marshal_data);
+static void g_cclosure_user_marshal_BOOLEAN__STRING_INT (GClosure * closure,
+ GValue * return_value,
+ guint n_param_values,
+ const GValue * param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
static GType foo_get_type_once (void);
VALA_EXTERN void sig_cb (GObject* o,
const gchar* s,
gint i);
+VALA_EXTERN gboolean sig2_cb (GObject* o,
+ const gchar* s,
+ gint i);
static void _vala_main (void);
static void _sig_cb_foo_sig (Foo* _sender,
const gchar* s,
gint i,
gpointer self);
+static gboolean _sig2_cb_foo_sig2 (Foo* _sender,
+ const gchar* s,
+ gint i,
+ gpointer self);
void
foo_fire (Foo* self)
@@ -123,12 +137,42 @@ g_cclosure_user_marshal_VOID__STRING_INT (GClosure * closure,
callback (data1, g_value_get_string (param_values + 1), g_value_get_int (param_values + 2), data2);
}
+static void
+g_cclosure_user_marshal_BOOLEAN__STRING_INT (GClosure * closure,
+ GValue * return_value,
+ guint n_param_values,
+ const GValue * param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_INT) (gpointer data1, const char* arg_1, gint arg_2,
gpointer data2);
+ register GMarshalFunc_BOOLEAN__STRING_INT callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ gboolean v_return;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 3);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__STRING_INT) (marshal_data ? marshal_data : cc->callback);
+ v_return = callback (data1, g_value_get_string (param_values + 1), g_value_get_int (param_values +
2), data2);
+ g_value_set_boolean (return_value, v_return);
+}
+
static void
foo_class_init (FooClass * klass,
gpointer klass_data)
{
foo_parent_class = g_type_class_peek_parent (klass);
foo_signals[FOO_SIG_SIGNAL] = g_signal_new ("sig", TYPE_FOO, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_user_marshal_VOID__STRING_INT, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
+ foo_signals[FOO_SIG2_SIGNAL] = g_signal_new ("sig2", TYPE_FOO, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_user_marshal_BOOLEAN__STRING_INT, G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_INT);
}
static void
@@ -170,6 +214,21 @@ sig_cb (GObject* o,
_vala_assert (i == 42, "i == 42");
}
+gboolean
+sig2_cb (GObject* o,
+ const gchar* s,
+ gint i)
+{
+ gboolean result;
+ g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (o, G_TYPE_OBJECT), FALSE);
+ g_return_val_if_fail (s != NULL, FALSE);
+ success = TRUE;
+ _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\"");
+ _vala_assert (i == 42, "i == 42");
+ result = TRUE;
+ return result;
+}
+
static void
_sig_cb_foo_sig (Foo* _sender,
const gchar* s,
@@ -179,11 +238,23 @@ _sig_cb_foo_sig (Foo* _sender,
sig_cb (_sender, s, i);
}
+static gboolean
+_sig2_cb_foo_sig2 (Foo* _sender,
+ const gchar* s,
+ gint i,
+ gpointer self)
+{
+ gboolean result;
+ result = sig2_cb (_sender, s, i);
+ return result;
+}
+
static void
_vala_main (void)
{
Foo* foo = NULL;
Foo* _tmp0_;
+ gboolean _tmp1_ = FALSE;
_tmp0_ = foo_new ();
foo = _tmp0_;
g_signal_connect (foo, "sig", (GCallback) _sig_cb_foo_sig, NULL);
@@ -193,6 +264,11 @@ _vala_main (void)
success = FALSE;
foo_fire (foo);
_vala_assert (success, "success");
+ success = FALSE;
+ g_signal_connect (foo, "sig2", (GCallback) _sig2_cb_foo_sig2, NULL);
+ g_signal_emit (foo, foo_signals[FOO_SIG2_SIGNAL], 0, "foo", 42, &_tmp1_);
+ _vala_assert (_tmp1_, "foo.sig2.emit (\"foo\", 42)");
+ _vala_assert (success, "success");
_g_object_unref0 (foo);
}
diff --git a/tests/objects/signals-emit.vala b/tests/objects/signals-emit.vala
index 5b49cae8c..5ac682f58 100644
--- a/tests/objects/signals-emit.vala
+++ b/tests/objects/signals-emit.vala
@@ -1,6 +1,8 @@
class Foo : Object {
public signal void sig (string s, int i);
+ public signal bool sig2 (string s, int i);
+
public void fire () {
sig.emit ("foo", 42);
}
@@ -12,6 +14,13 @@ void sig_cb (Object o, string s, int i) {
assert (i == 42);
}
+bool sig2_cb (Object o, string s, int i) {
+ success = true;
+ assert (s == "foo");
+ assert (i == 42);
+ return true;
+}
+
bool success = false;
void main () {
@@ -25,4 +34,10 @@ void main () {
success = false;
foo.fire ();
assert (success);
+
+ success = false;
+ foo.sig2.connect (sig2_cb);
+ assert (foo.sig2.emit ("foo", 42));
+ assert (success);
+
}
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index f083da911..7ee417a29 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -518,7 +518,13 @@ public class Vala.MemberAccess : Expression {
symbol_reference = s;
} else if (ma.member_name == "emit") {
// dynamic signal
- var s = new DynamicSignal (inner.value_type, member_name, new
VoidType (), source_reference);
+ unowned MethodCall mcall = (MethodCall) ma.parent_node;
+ var return_type = mcall.target_type ?? new VoidType ();
+ if (return_type is VarType) {
+ error = true;
+ Report.error (mcall.source_reference, "Cannot infer
return type for dynamic signal `%s' from given context", member_name);
+ }
+ var s = new DynamicSignal (inner.value_type, member_name,
return_type, source_reference);
s.access = SymbolAccessibility.PUBLIC;
s.add_parameter (new Parameter.with_ellipsis ());
dynamic_object_type.type_symbol.scope.add (null, s);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]