[vala] Extend signal details to support string expressions



commit 0a14bd53061db9d40164354794ab44831a0c8aa0
Author: Luca Bruno <lethalman88 gmail com>
Date:   Fri Aug 20 17:13:44 2010 +0200

    Extend signal details to support string expressions
    
    Fixes bug 566909.

 codegen/valadbusservermodule.vala  |    2 +-
 codegen/valagdbusservermodule.vala |    2 +-
 codegen/valagsignalmodule.vala     |   60 +++++++++++++++++++++++++++---------
 tests/Makefile.am                  |    1 +
 tests/objects/bug566909.vala       |   18 +++++++++++
 5 files changed, 66 insertions(+), 17 deletions(-)
---
diff --git a/codegen/valadbusservermodule.vala b/codegen/valadbusservermodule.vala
index 5a2ea3e..3986d97 100644
--- a/codegen/valadbusservermodule.vala
+++ b/codegen/valadbusservermodule.vala
@@ -1488,7 +1488,7 @@ public class Vala.DBusServerModule : DBusClientModule {
 
 			var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
 			connect.add_argument (new CCodeIdentifier ("object"));
-			connect.add_argument (sig.get_canonical_cconstant (null));
+			connect.add_argument (sig.get_canonical_cconstant ());
 			connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
 			connect.add_argument (new CCodeIdentifier ("connection"));
 			block.add_statement (new CCodeExpressionStatement (connect));
diff --git a/codegen/valagdbusservermodule.vala b/codegen/valagdbusservermodule.vala
index c924d93..8d22467 100644
--- a/codegen/valagdbusservermodule.vala
+++ b/codegen/valagdbusservermodule.vala
@@ -597,7 +597,7 @@ public class Vala.GDBusServerModule : GDBusClientModule {
 
 			var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
 			connect.add_argument (new CCodeIdentifier ("object"));
-			connect.add_argument (sig.get_canonical_cconstant (null));
+			connect.add_argument (sig.get_canonical_cconstant ());
 			connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
 			connect.add_argument (new CCodeIdentifier ("data"));
 			block.add_statement (new CCodeExpressionStatement (connect));
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index e36f5f2..2605f2b 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -147,7 +147,37 @@ public class Vala.GSignalModule : GObjectModule {
 		
 		return signature;
 	}
-	
+
+	private CCodeExpression? get_signal_name_cexpression (Signal sig, Expression? detail_expr, CodeNode node) {
+		if (detail_expr == null) {
+			return sig.get_canonical_cconstant ();
+		}
+
+		if (detail_expr.value_type is NullType || !detail_expr.value_type.compatible (string_type)) {
+			node.error = true;
+			Report.error (detail_expr.source_reference, "only string details are supported");
+			return null;
+		}
+
+		if (detail_expr is StringLiteral) {
+			return sig.get_canonical_cconstant (((StringLiteral) detail_expr).eval ());
+		}
+
+		var detail_decl = get_temp_variable (detail_expr.value_type, true, node);
+		temp_vars.insert (0, detail_decl);
+		temp_ref_vars.insert (0, detail_decl);
+
+		var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
+		ccall.add_argument (sig.get_canonical_cconstant (""));
+		ccall.add_argument ((CCodeExpression) detail_expr.ccodenode);
+		ccall.add_argument (new CCodeConstant ("NULL"));
+
+		var ccomma = new CCodeCommaExpression ();
+		ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (detail_decl.name), ccall));
+		ccomma.append_expression (get_variable_cexpression (detail_decl.name));
+		return ccomma;
+	}
+
 	public override void visit_signal (Signal sig) {
 		// parent_symbol may be null for dynamic signals
 
@@ -457,13 +487,14 @@ public class Vala.GSignalModule : GObjectModule {
 			var sig = (Signal) expr.symbol_reference;
 			var ma = (MemberAccess) expr.container;
 
-			var detail_expr = expr.get_indices ().get (0) as StringLiteral;
-			string signal_detail = detail_expr.eval ();
+			var detail_expr = expr.get_indices ().get (0);
+			var signal_name_cexpr = get_signal_name_cexpression (sig, detail_expr, expr);
 			
 			var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
 			ccall.add_argument ((CCodeExpression) ma.inner.ccodenode);
-			ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
-			
+			if (signal_name_cexpr != null) {
+				ccall.add_argument (signal_name_cexpr);
+			}
 			expr.ccodenode = ccall;
 		} else {
 			base.visit_element_access (expr);
@@ -601,22 +632,21 @@ public class Vala.GSignalModule : GObjectModule {
 
 		var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
 
-		string signal_detail = null;
+		CCodeExpression signal_name_cexpr = null;
 
 		// first argument: instance of sender
 		MemberAccess ma;
 		if (signal_access is ElementAccess) {
 			var ea = (ElementAccess) signal_access;
 			ma = (MemberAccess) ea.container;
-			var detail_expr = ea.get_indices ().get (0) as StringLiteral;
-			if (detail_expr == null) {
-				expr.error = true;
-				Report.error (detail_expr.source_reference, "internal error: only literal string details supported");
+			var detail_expr = ea.get_indices ().get (0);
+			signal_name_cexpr = get_signal_name_cexpression (sig, detail_expr, expr);
+			if (signal_name_cexpr == null) {
 				return null;
 			}
-			signal_detail = detail_expr.eval ();
 		} else {
 			ma = (MemberAccess) signal_access;
+			signal_name_cexpr = get_signal_name_cexpression (sig, null, expr);
 		}
 		if (ma.inner != null) {
 			ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
@@ -635,12 +665,12 @@ public class Vala.GSignalModule : GObjectModule {
 			// g_signal_connect_object or g_signal_connect
 
 			// second argument: signal name
-			ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
+			ccall.add_argument (signal_name_cexpr);
 		} else {
 			// g_signal_handlers_disconnect_matched
 
 			// second argument: mask
-			if (signal_detail == null) {
+			if (!(signal_access is ElementAccess)) {
 				ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
 			} else {
 				ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
@@ -651,12 +681,12 @@ public class Vala.GSignalModule : GObjectModule {
 			var temp_decl = get_temp_variable (uint_type);
 			temp_vars.add (temp_decl);
 			var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name"));
-			parse_call.add_argument (sig.get_canonical_cconstant (signal_detail));
+			parse_call.add_argument (signal_name_cexpr);
 			var decl_type = (TypeSymbol) sig.parent_symbol;
 			parse_call.add_argument (new CCodeIdentifier (decl_type.get_type_id ()));
 			parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_decl.name)));
 			LocalVariable? detail_temp_decl = null;
-			if (signal_detail == null) {
+			if (!(signal_access is ElementAccess)) {
 				parse_call.add_argument (new CCodeConstant ("NULL"));
 				parse_call.add_argument (new CCodeConstant ("FALSE"));
 			} else {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e09841a..2430407 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -63,6 +63,7 @@ TESTS = \
 	objects/test-026.vala \
 	objects/test-029.vala \
 	objects/test-034.vala \
+	objects/bug566909.vala \
 	objects/bug593260.vala \
 	objects/bug596621.vala \
 	objects/bug597155.vala \
diff --git a/tests/objects/bug566909.vala b/tests/objects/bug566909.vala
new file mode 100644
index 0000000..0af250b
--- /dev/null
+++ b/tests/objects/bug566909.vala
@@ -0,0 +1,18 @@
+class Maman.Foo : Object {
+	[Signal (detailed = true)]
+	public signal void bar ();
+}
+
+void main () {
+	bool detailed1 = false;
+	bool detailed2 = false;
+	string detail1 = "detail1";
+	string detail2 = "detail2";
+
+	var foo = new Maman.Foo ();
+	foo.bar[detail1].connect (() => { detailed1 = true; });
+	foo.bar[detail2].connect (() => { detailed2 = true; });
+	foo.bar[detail1] ();
+	foo.bar[detail2] ();
+	assert (detailed1 && detailed2);
+}



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