[vala/wip/transform: 32/50] GDBus server transformer
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 32/50] GDBus server transformer
- Date: Fri, 13 Apr 2012 13:09:56 +0000 (UTC)
commit a3f69b0ef69e1f82ef632d6774f522a55f5857ca
Author: Luca Bruno <lucabru src gnome org>
Date: Wed Jan 4 12:08:19 2012 +0100
GDBus server transformer
codegen/Makefile.am | 1 +
codegen/valagdbusclienttransformer.vala | 54 ++-
codegen/valagdbusservermodule.vala | 741 +------------------------------
codegen/valagdbusservertransformer.vala | 315 +++++++++++++
codegen/valagvarianttransformer.vala | 12 +-
compiler/valacompiler.vala | 2 +-
vala/valacodebuilder.vala | 19 +
vala/valacodetransformer.vala | 11 +
vala/valasemanticanalyzer.vala | 9 +-
9 files changed, 398 insertions(+), 766 deletions(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index c941c43..2c6324f 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -46,6 +46,7 @@ libvala_la_VALASOURCES = \
valagdbusclienttransformer.vala \
valagdbusmodule.vala \
valagdbusservermodule.vala \
+ valagdbusservertransformer.vala \
valagerrormodule.vala \
valagirwriter.vala \
valagobjectmodule.vala \
diff --git a/codegen/valagdbusclienttransformer.vala b/codegen/valagdbusclienttransformer.vala
index 13974bb..84456fc 100644
--- a/codegen/valagdbusclienttransformer.vala
+++ b/codegen/valagdbusclienttransformer.vala
@@ -41,7 +41,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
return Symbol.lower_case_to_camel_case (symbol.name);
}
- Expression read_dbus_value (DataType type, string iter, string message, ref string? fd_list, ref string? fd_index) {
+ public Expression read_dbus_value (DataType type, string iter, string message, ref string? fd_list, ref string? fd_index) {
string? type_name = null;
if (type.data_type != null) {
type_name = type.data_type.get_full_name ();
@@ -61,11 +61,33 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
// socket
return expression (@"new GLib.Socket.from_fd ($fd_list.get ($fd_index))");
}
+ } else if (type_name == "GLib.Variant") {
+ return expression (@"$iter.next_value().get_variant ()");
} else {
return expression (@"($(type)) ($iter.next_value ())");
}
}
+ public void write_dbus_value (DataType type, string builder, string value, ref string? fd_list) {
+ string? type_name = null;
+ if (type is ObjectType) {
+ type_name = type.data_type.get_full_name ();
+ }
+ if (type_name == "GLib.Cancellable" || type_name == "GLib.BusName") {
+ return;
+ }
+ if (type_name == "GLib.UnixInputStream" || type_name == "GLib.UnixOutputStream" || type_name == "GLib.Socket") {
+ if (fd_list == null) {
+ fd_list = b.add_temp_declaration (null, expression ("new GLib.UnixFDList ()"));
+ }
+ b.add_expression (expression (@"$builder.add (\"h\", $fd_list.append ($value.get_fd ()))"));
+ } else if (type_name == "GLib.Variant") {
+ b.add_expression (expression (@"$builder.add (\"v\", $value)"));
+ } else {
+ b.add_expression (expression (@"$builder.add_value ($value)"));
+ }
+ }
+
void generate_marshalling (Method m, string? iface_name, string? method_name) {
var interface_name = iface_name != null ? @"\"$iface_name\"" : "this.get_interface_name ()";
@@ -81,21 +103,10 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
foreach (var param in m.get_parameters ()) {
if (param.direction == ParameterDirection.IN) {
string? type_name = null;
- if (param.variable_type.data_type != null) {
- type_name = param.variable_type.data_type.get_full_name ();
- }
- if (type_name == "GLib.Cancellable") {
+ if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
cancellable = param.name;
- } else if (type_name == "GLib.BusName") {
- // ignore BusName sender
- } else if (type_name == "GLib.UnixInputStream" || type_name == "GLib.UnixOutputStream" || type_name == "GLib.Socket") {
- if (fd_list == null) {
- fd_list = b.add_temp_declaration (null, expression ("new GLib.UnixFDList ()"));
- }
- b.add_expression (expression (@"$builder.add (\"h\", $fd_list.append ($(param.name).get_fd ()))"));
- } else {
- b.add_expression (expression (@"$builder.add_value ($(param.name))"));
}
+ write_dbus_value (param.variable_type, builder, param.name, ref fd_list);
} else if (param.direction == ParameterDirection.OUT) {
has_result = true;
}
@@ -148,9 +159,10 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
}
proxy_class.add_method (proxy);
- b = new CodeBuilder.for_subroutine (proxy);
+ push_builder (new CodeBuilder.for_subroutine (proxy));
string dbus_iface_name = get_dbus_name (iface);
generate_marshalling (m, dbus_iface_name, get_dbus_name_for_member (m));
+ pop_builder ();
}
void generate_dbus_proxy_methods (Class proxy_class, Interface iface) {
@@ -204,7 +216,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
}
proxy_class.add_method (m);
- b = new CodeBuilder.for_subroutine (m);
+ push_builder (new CodeBuilder.for_subroutine (m));
b.open_switch (expression ("signal_name"), null);
b.add_expression (expression ("assert_not_reached ()"));
@@ -220,6 +232,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
b.add_break ();
}
b.close ();
+ pop_builder ();
}
public int get_dbus_timeout (Symbol symbol) {
@@ -250,7 +263,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
proxy_get = new PropertyAccessor (true, false, false, owned_type, null, prop.get_accessor.source_reference);
- b = new CodeBuilder.for_subroutine (proxy_get);
+ push_builder (new CodeBuilder.for_subroutine (proxy_get));
// first try cached value
var result = b.add_temp_declaration (null, expression (@"get_cached_property (\"$dbus_name\")"));
b.open_if (expression (@"$result == null"));
@@ -259,14 +272,16 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
b.close ();
b.add_return (expression (@"($(prop.property_type)) ($result)"));
+ pop_builder ();
}
PropertyAccessor proxy_set = null;
if (prop.set_accessor != null) {
proxy_set = new PropertyAccessor (false, true, false, prop.set_accessor.value_type, null, prop.set_accessor.source_reference);
- b = new CodeBuilder.for_subroutine (proxy_set);
+ push_builder (new CodeBuilder.for_subroutine (proxy_set));
var variant = b.add_temp_declaration (data_type ("GLib.Variant"), expression ("value"));
b.add_expression (expression (@"call_sync (\"org.freedesktop.DBus.Properties.Set\", new Variant (\"(ssv)\", \"$dbus_iface_name\", \"$dbus_name\", $variant), GLib.DBusCallFlags.NONE, $timeout, null)"));
+ pop_builder ();
}
Property proxy = new Property (prop.name, prop.property_type, proxy_get, proxy_set, prop.source_reference);
@@ -324,7 +339,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
return;
}
- b = new CodeBuilder (context, expr.parent_statement, expr.source_reference);
+ push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference));
Method wrapper;
var cache_key = "gdbus_client_dynamic_method_call "+m.return_type.to_string ();
@@ -340,6 +355,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
check (wrapper);
}
+ pop_builder ();
expr.call.symbol_reference = wrapper;
base.visit_method_call (expr);
}
diff --git a/codegen/valagdbusservermodule.vala b/codegen/valagdbusservermodule.vala
index 436db89..5d4fec9 100644
--- a/codegen/valagdbusservermodule.vala
+++ b/codegen/valagdbusservermodule.vala
@@ -41,548 +41,8 @@ public class Vala.GDBusServerModule : GDBusClientModule {
return "result";
}
- string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
- string wrapper_name = "_dbus_%s".printf (get_ccode_name (m));
-
- if (m.base_method != null) {
- m = m.base_method;
- } else if (m.base_interface_method != null) {
- m = m.base_interface_method;
- }
-
- if (ready) {
- // async ready function
- wrapper_name += "_ready";
- }
-
- var function = new CCodeFunction (wrapper_name);
- function.modifiers = CCodeModifiers.STATIC;
-
- if (!ready) {
- function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
- function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
- function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
- } else {
- function.add_parameter (new CCodeParameter ("source_object", "GObject *"));
- function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *"));
- function.add_parameter (new CCodeParameter ("_user_data_", "gpointer"));
- }
-
- push_function (function);
-
- if (ready) {
- ccode.add_declaration ("GDBusMethodInvocation *", new CCodeVariableDeclarator ("invocation", new CCodeIdentifier ("_user_data_")));
- }
-
- var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
- connection.add_argument (new CCodeIdentifier ("invocation"));
-
- bool no_reply = is_dbus_no_reply (m);
- bool uses_fd = dbus_method_uses_file_descriptor (m);
- if (uses_fd) {
- cfile.add_include ("gio/gunixfdlist.h");
- }
-
- bool uses_error = false;
-
- if (!m.coroutine || ready) {
- ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
- uses_error = true;
- }
-
- if (!ready) {
- ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
-
- var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
- iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
- iter_init.add_argument (new CCodeIdentifier ("parameters"));
- ccode.add_expression (iter_init);
- }
-
- CCodeFunctionCall ccall;
- if (!ready) {
- ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
- ccall.add_argument (new CCodeIdentifier ("self"));
- } else {
- ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
- ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), get_ccode_name (sym) + "*"));
- ccall.add_argument (new CCodeIdentifier ("_res_"));
- }
-
- if (!ready) {
- if (uses_fd) {
- ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
- }
-
- foreach (Parameter param in m.get_parameters ()) {
- string param_name = get_variable_cname (param.name);
- if (param.direction != ParameterDirection.IN) {
- continue;
- }
-
- if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
- continue;
- }
-
- if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
- // ignore BusName sender parameters
- continue;
- }
-
- var owned_type = param.variable_type.copy ();
- owned_type.value_owned = true;
-
- ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
-
- var array_type = param.variable_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_parameter_array_length_cname (param, dim);
-
- ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
- }
- }
-
- var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
- message_expr.add_argument (new CCodeIdentifier ("invocation"));
-
- bool may_fail;
- receive_dbus_value (param.variable_type, message_expr, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param_name), param, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")), out may_fail);
-
- if (may_fail) {
- if (!uses_error) {
- ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
- uses_error = true;
- }
-
- ccode.open_if (new CCodeIdentifier ("error"));
-
- var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
- return_error.add_argument (new CCodeIdentifier ("invocation"));
- return_error.add_argument (new CCodeIdentifier ("error"));
- ccode.add_expression (return_error);
-
- ccode.add_return ();
-
- ccode.close ();
- }
- }
- }
-
- foreach (Parameter param in m.get_parameters ()) {
- string param_name = get_variable_cname (param.name);
- if (param.direction == ParameterDirection.IN && !ready) {
- if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
- ccall.add_argument (new CCodeConstant ("NULL"));
- continue;
- }
-
- if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
- // ignore BusName sender parameters
- var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
- sender.add_argument (new CCodeIdentifier ("invocation"));
- ccall.add_argument (sender);
- continue;
- }
-
- var st = param.variable_type.data_type as Struct;
- if (st != null && !st.is_simple_type ()) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
- } else {
- ccall.add_argument (new CCodeIdentifier (param_name));
- }
- } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
- }
-
- var array_type = param.variable_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_parameter_array_length_cname (param, dim);
-
- if (param.direction == ParameterDirection.IN && !ready) {
- ccall.add_argument (new CCodeIdentifier (length_cname));
- } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
- }
- }
- }
- }
-
- if (!m.coroutine || ready) {
- if (!(m.return_type is VoidType)) {
- if (m.return_type.is_real_non_null_struct_type ()) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
- } else {
- var array_type = m.return_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_array_length_cname ("result", dim);
-
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
- }
- }
- }
- }
- }
-
- if (m.coroutine && !ready) {
- ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
- ccall.add_argument (new CCodeIdentifier ("invocation"));
- }
-
- if (!m.coroutine || ready) {
- if (m.tree_can_fail) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
- }
- }
-
- if (!no_reply && (!m.coroutine || ready)) {
- if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
- ccode.add_expression (ccall);
- } else {
- ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
- }
-
- if (m.tree_can_fail) {
- ccode.open_if (new CCodeIdentifier ("error"));
-
- var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
- return_error.add_argument (new CCodeIdentifier ("invocation"));
- return_error.add_argument (new CCodeIdentifier ("error"));
- ccode.add_expression (return_error);
-
- ccode.add_return ();
-
- ccode.close ();
- }
-
- ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator ("_reply_message"));
-
- var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
- message_expr.add_argument (new CCodeIdentifier ("invocation"));
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
- ccall.add_argument (message_expr);
- ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
-
- ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
- ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
-
- var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
- builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
- builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
- ccode.add_expression (builder_init);
-
- if (uses_fd) {
- ccode.add_declaration ("GUnixFDList", new CCodeVariableDeclarator ("*_fd_list"));
- ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
- }
-
- foreach (Parameter param in m.get_parameters ()) {
- if (param.direction != ParameterDirection.OUT) {
- continue;
- }
-
- string param_name = get_variable_cname (param.name);
- var owned_type = param.variable_type.copy ();
- owned_type.value_owned = true;
-
- ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
-
- var array_type = param.variable_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_parameter_array_length_cname (param, dim);
-
- ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
- }
- }
-
- send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
- }
-
- if (!(m.return_type is VoidType)) {
- if (m.return_type.is_real_non_null_struct_type ()) {
- ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
-
- send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
-
- if (requires_destroy (m.return_type)) {
- // keep local alive (symbol_reference is weak)
- var local = new LocalVariable (m.return_type, ".result");
- ccode.add_expression (destroy_local (local));
- }
- } else {
- ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
-
- var array_type = m.return_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_array_length_cname ("result", dim);
-
- ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
- }
- }
-
- send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
-
- if (requires_destroy (m.return_type)) {
- // keep local alive (symbol_reference is weak)
- var local = new LocalVariable (m.return_type, ".result");
- ccode.add_expression (destroy_local (local));
- }
- }
- }
-
- var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
- builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
- ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
-
- var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
- set_body.add_argument (new CCodeIdentifier ("_reply_message"));
- set_body.add_argument (new CCodeIdentifier ("_reply"));
- ccode.add_expression (set_body);
-
- if (uses_fd) {
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
- ccall.add_argument (new CCodeIdentifier ("_reply_message"));
- ccall.add_argument (new CCodeIdentifier ("_fd_list"));
- ccode.add_expression (ccall);
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- ccall.add_argument (new CCodeIdentifier ("_fd_list"));
- ccode.add_expression (ccall);
- }
- } else {
- ccode.add_expression (ccall);
- }
-
- foreach (Parameter param in m.get_parameters ()) {
- if ((param.direction == ParameterDirection.IN && !ready) ||
- (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
- if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
- continue;
- }
-
- if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
- // ignore BusName sender parameters
- continue;
- }
-
- var owned_type = param.variable_type.copy ();
- owned_type.value_owned = true;
-
- if (requires_destroy (owned_type)) {
- // keep local alive (symbol_reference is weak)
- var local = new LocalVariable (owned_type, get_variable_cname (param.name));
- ccode.add_expression (destroy_local (local));
- }
- }
- }
-
- if (!no_reply && (!m.coroutine || ready)) {
- var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
- return_value.add_argument (connection);
- return_value.add_argument (new CCodeIdentifier ("_reply_message"));
- return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
- return_value.add_argument (new CCodeConstant ("NULL"));
- return_value.add_argument (new CCodeConstant ("NULL"));
- ccode.add_expression (return_value);
-
- // free invocation like g_dbus_method_invocation_return_*
- var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- unref_call.add_argument (new CCodeIdentifier ("invocation"));
- ccode.add_expression (unref_call);
-
- unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
- ccode.add_expression (unref_call);
- }
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- if (m.coroutine && !ready) {
- // generate ready function
- generate_dbus_wrapper (m, sym, true);
- }
-
- return wrapper_name;
- }
-
string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
- string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_name (sig));
-
- var function = new CCodeFunction (wrapper_name, "void");
- function.modifiers = CCodeModifiers.STATIC;
-
- function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
-
- foreach (var param in sig.get_parameters ()) {
- // ensure ccodenode of parameter is set
- var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
-
- function.add_parameter (cparam);
- if (param.variable_type is ArrayType) {
- var array_type = (ArrayType) param.variable_type;
- for (int dim = 1; dim <= array_type.rank; dim++) {
- function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
- }
- }
- }
-
- function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
-
- push_function (function);
-
- ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
- ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
- ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
-
- var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
- builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
- builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
- ccode.add_expression (builder_init);
-
- foreach (Parameter param in sig.get_parameters ()) {
- string param_name = get_variable_cname (param.name);
- CCodeExpression expr = new CCodeIdentifier (param_name);
- if (param.variable_type.is_real_struct_type ()) {
- expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
- }
- write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
- }
-
- var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
- builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
- ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
- ccall.add_argument (new CCodeIdentifier ("_connection"));
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (new CCodeIdentifier ("_path"));
- ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
- ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
- ccall.add_argument (new CCodeIdentifier ("_arguments"));
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccode.add_expression (ccall);
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return wrapper_name;
- }
-
- string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
- string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor));
-
- var function = new CCodeFunction (wrapper_name, "GVariant*");
- function.modifiers = CCodeModifiers.STATIC;
- function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
-
- push_function (function);
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor)));
- ccall.add_argument (new CCodeIdentifier ("self"));
-
- if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
- ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true)));
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
-
- ccode.add_expression (ccall);
- } else {
- ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result"));
- ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
-
- var array_type = prop.get_accessor.value_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_array_length_cname ("result", dim);
-
- ccode.add_declaration ("int", new CCodeVariableDeclarator (length_cname));
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
- }
- }
- }
-
- var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
-
- ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
- ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
-
- if (requires_destroy (prop.get_accessor.value_type)) {
- // keep local alive (symbol_reference is weak)
- var local = new LocalVariable (prop.get_accessor.value_type, ".result");
- ccode.add_expression (destroy_local (local));
- }
-
- ccode.add_return (new CCodeIdentifier ("_reply"));
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return wrapper_name;
- }
-
- string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
- string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor));
-
- var function = new CCodeFunction (wrapper_name);
- function.modifiers = CCodeModifiers.STATIC;
- function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
- function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
-
- push_function (function);
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor)));
- ccall.add_argument (new CCodeIdentifier ("self"));
-
- var owned_type = prop.property_type.copy ();
- owned_type.value_owned = true;
-
- ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
-
- var st = prop.property_type.data_type as Struct;
- if (st != null && !st.is_simple_type ()) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
- } else {
- ccall.add_argument (new CCodeIdentifier ("value"));
-
- var array_type = prop.property_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
- ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
- }
- }
- }
-
- var target = new CCodeIdentifier ("value");
- var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
- ccode.add_assignment (target, expr);
-
- ccode.add_expression (ccall);
-
- if (requires_destroy (owned_type)) {
- // keep local alive (symbol_reference is weak)
- var local = new LocalVariable (owned_type, "value");
- ccode.add_expression (destroy_local (local));
- }
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return wrapper_name;
+ return "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_name (sig));
}
void handle_signals (ObjectTypeSymbol sym, bool connect) {
@@ -617,201 +77,6 @@ public class Vala.GDBusServerModule : GDBusClientModule {
}
}
- void generate_interface_method_call_function (ObjectTypeSymbol sym) {
- var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void");
- cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
- cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
- cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
- cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
-
- cfunc.modifiers |= CCodeModifiers.STATIC;
-
- push_function (cfunc);
-
- ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
- ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
-
- bool first = true;
-
- foreach (Method m in sym.get_methods ()) {
- if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
- || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
- continue;
- }
- if (!is_dbus_visible (m)) {
- continue;
- }
-
- cfile.add_include ("string.h");
-
- var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
- ccheck.add_argument (new CCodeIdentifier ("method_name"));
- ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
-
- if (first) {
- ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
- first = false;
- } else {
- ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
- }
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
- ccall.add_argument (new CCodeIdentifier ("object"));
- ccall.add_argument (new CCodeIdentifier ("parameters"));
- ccall.add_argument (new CCodeIdentifier ("invocation"));
- ccode.add_expression (ccall);
- }
-
- if (!first) {
- ccode.add_else ();
- }
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- ccall.add_argument (new CCodeIdentifier ("invocation"));
- ccode.add_expression (ccall);
-
- if (!first) {
- ccode.close ();
- }
-
- pop_function ();
-
- cfile.add_function_declaration (cfunc);
- cfile.add_function (cfunc);
- }
-
- void generate_interface_get_property_function (ObjectTypeSymbol sym) {
- var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*");
- cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
- cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
- cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
-
- cfunc.modifiers |= CCodeModifiers.STATIC;
-
- cfile.add_function_declaration (cfunc);
-
- push_function (cfunc);
-
- ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
-
- ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
-
- bool firstif = true;
-
- foreach (Property prop in sym.get_properties ()) {
- if (prop.binding != MemberBinding.INSTANCE
- || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
- continue;
- }
- if (!is_dbus_visible (prop)) {
- continue;
- }
- if (prop.get_accessor == null) {
- continue;
- }
-
- cfile.add_include ("string.h");
-
- var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
- ccheck.add_argument (new CCodeIdentifier ("property_name"));
- ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
-
- var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
- if (firstif) {
- ccode.open_if (cond);
- firstif = false;
- } else {
- ccode.else_if (cond);
- }
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
- ccall.add_argument (new CCodeIdentifier ("object"));
-
- ccode.add_return (ccall);
- }
- if (!firstif) {
- ccode.close ();
- }
-
- ccode.add_return (new CCodeConstant ("NULL"));
-
- pop_function ();
- cfile.add_function (cfunc);
- }
-
- void generate_interface_set_property_function (ObjectTypeSymbol sym) {
- var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean");
- cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
- cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
- cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
- cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
-
- cfunc.modifiers |= CCodeModifiers.STATIC;
-
- cfile.add_function_declaration (cfunc);
-
- push_function (cfunc);
-
- ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
-
- ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
-
- bool firstif = true;
-
- foreach (Property prop in sym.get_properties ()) {
- if (prop.binding != MemberBinding.INSTANCE
- || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
- continue;
- }
- if (!is_dbus_visible (prop)) {
- continue;
- }
- if (prop.set_accessor == null) {
- continue;
- }
-
- cfile.add_include ("string.h");
-
- var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
- ccheck.add_argument (new CCodeIdentifier ("property_name"));
- ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
-
- var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
- if (firstif) {
- ccode.open_if (cond);
- firstif = false;
- } else {
- ccode.else_if (cond);
- }
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
- ccall.add_argument (new CCodeIdentifier ("object"));
- ccall.add_argument (new CCodeIdentifier ("value"));
-
- ccode.add_expression (ccall);
- ccode.add_return (new CCodeConstant ("TRUE"));
- }
- if (!firstif) {
- ccode.close ();
- }
- ccode.add_return (new CCodeConstant ("FALSE"));
-
- pop_function ();
- cfile.add_function (cfunc);
- }
-
CCodeExpression get_method_info (ObjectTypeSymbol sym) {
var infos = new CCodeInitializerList ();
@@ -1026,10 +291,6 @@ public class Vala.GDBusServerModule : GDBusClientModule {
vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property"));
vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property"));
- generate_interface_method_call_function (sym);
- generate_interface_get_property_function (sym);
- generate_interface_set_property_function (sym);
-
var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable));
cdecl.modifiers = CCodeModifiers.STATIC;
diff --git a/codegen/valagdbusservertransformer.vala b/codegen/valagdbusservertransformer.vala
new file mode 100644
index 0000000..16570c7
--- /dev/null
+++ b/codegen/valagdbusservertransformer.vala
@@ -0,0 +1,315 @@
+/* valagdbusservertransformer.vala
+ *
+ * Copyright (C) 2011 Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Luca Bruno <lucabru src gnome org>
+ */
+
+/**
+ * Code visitor for transforming the code tree related to DBus server.
+ */
+public class Vala.GDBusServerTransformer : GDBusClientTransformer {
+ public override void visit_class (Class cl) {
+ visit_object_type_symbol (cl);
+
+ base.visit_class (cl);
+ }
+
+ public override void visit_interface (Interface iface) {
+ visit_object_type_symbol (iface);
+
+ base.visit_interface (iface);
+ }
+
+ string generate_dbus_method_wrapper (Method m, ObjectTypeSymbol sym) {
+ Method wrapper;
+ wrapper_method (new VoidType (), "gdbus_server "+m.get_full_name (), out wrapper);
+ var object_type = context.analyzer.get_data_type_for_symbol (sym);
+ wrapper.add_parameter (new Parameter ("object", object_type));
+ wrapper.add_parameter (new Parameter ("arguments", data_type ("GLib.Variant", false)));
+ wrapper.add_parameter (new Parameter ("invocation", data_type ("GLib.DBusMethodInvocation", false)));
+ b.push_method (wrapper);
+
+ var iter = b.add_temp_declaration (null, expression ("arguments.iterator ()"));
+
+ var call = (MethodCall) expression (@"object.$(m.name) ()");
+ var finish_call = call;
+ Method ready = null;
+ CodeBuilder ready_builder = null;
+ if (m.coroutine) {
+ wrapper_method (new VoidType (), "gdbus_server_async_ready "+m.get_full_name (), out ready);
+ ready.add_parameter (new Parameter ("source_object", data_type ("GLib.Object", false)));
+ ready.add_parameter (new Parameter ("res", data_type ("GLib.AsyncResult", false)));
+ ready.add_parameter (new Parameter ("invocation", data_type ("GLib.DBusMethodInvocation", false)));
+ ready_builder = new CodeBuilder.for_subroutine (ready);
+
+ finish_call = (MethodCall) expression (@"(($object_type)(source_object)).$(m.name).end (res)");
+ }
+
+ var out_args = new string[0];
+ var out_types = new DataType[0];
+ string fd_list = null;
+ string fd_index = null;
+ foreach (var param in m.get_parameters ()) {
+ string? type_name = null;
+ if (param.variable_type is ObjectType) {
+ type_name = param.variable_type.data_type.get_full_name ();
+ }
+ if (type_name == "GLib.Cancellable") {
+ call.add_argument (expression ("null"));
+ continue;
+ }
+ if (type_name == "GLib.BusName") {
+ continue;
+ }
+
+ if (param.direction == ParameterDirection.IN) {
+ var arg = b.add_temp_declaration (copy_type (param.variable_type, true));
+ b.add_assignment (expression (arg), read_dbus_value (param.variable_type, iter, "invocation.get_message ()", ref fd_list, ref fd_index));
+ call.add_argument (expression (arg));
+ } else if (param.direction == ParameterDirection.OUT) {
+ if (m.coroutine) {
+ // declare the out argument in the ready callback
+ push_builder (ready_builder);
+ }
+ var arg = b.add_temp_declaration (copy_type (param.variable_type, true));
+ out_args += arg;
+ out_types += param.variable_type;
+ finish_call.add_argument (new UnaryExpression (UnaryOperator.OUT, expression (arg), m.source_reference));
+ if (m.coroutine) {
+ pop_builder ();
+ }
+ }
+ }
+
+ if (m.coroutine) {
+ call.add_argument (expression (@"(s,r) => $(ready.name) (s, r, invocation)"));
+ b.add_expression (call);
+ push_builder (ready_builder);
+ }
+
+ b.open_try ();
+ string result = null;
+ if (m.has_result) {
+ result = b.add_temp_declaration (m.return_type);
+ b.add_assignment (expression (result), finish_call);
+ } else {
+ b.add_expression (finish_call);
+ }
+ b.add_catch (data_type ("GLib.Error"), "e");
+ b.add_expression (expression ("invocation.return_gerror (e)"));
+ b.add_return ();
+ b.close ();
+
+ fd_list = null;
+ var reply = b.add_temp_declaration (null, expression ("new GLib.DBusMessage.method_reply (invocation.get_message ())"));
+ var builder = b.add_temp_declaration (null, expression ("new GLib.VariantBuilder (GLib.VariantType.TUPLE)"));
+ for (int i=0; i < out_args.length; i++) {
+ write_dbus_value (out_types[i], builder, out_args[i], ref fd_list);
+ }
+ if (result != null) {
+ write_dbus_value (m.return_type, builder, result, ref fd_list);
+ }
+ b.add_expression (expression (@"$reply.set_body ($builder.end ())"));
+ if (fd_list != null) {
+ b.add_expression (expression (@"$reply.set_unix_fd_list ($fd_list)"));
+ }
+ b.add_expression (expression (@"invocation.get_connection().send_message ($reply, GLib.DBusSendMessageFlags.NONE, null)"));
+
+ if (m.coroutine) {
+ pop_builder ();
+ check (ready);
+ }
+
+ b.pop_method ();
+ check (wrapper);
+ return wrapper.name;
+ }
+
+ public static bool is_dbus_visible (CodeNode node) {
+ var dbus_attribute = node.get_attribute ("DBus");
+ if (dbus_attribute != null
+ && dbus_attribute.has_argument ("visible")
+ && !dbus_attribute.get_bool ("visible")) {
+ return false;
+ }
+
+ return true;
+ }
+
+ void generate_interface_method_call (ObjectTypeSymbol sym) {
+ if (sym.scope.lookup ("dbus_interface_method_call") != null) {
+ return;
+ }
+
+ var im = new Method ("dbus_interface_method_call", new VoidType (), sym.source_reference);
+ im.access = SymbolAccessibility.PRIVATE;
+ im.binding = MemberBinding.STATIC;
+ im.add_parameter (new Parameter ("connection", data_type ("GLib.DBusConnection", false)));
+ im.add_parameter (new Parameter ("sender", data_type ("string", false)));
+ im.add_parameter (new Parameter ("object_path", data_type ("string", false)));
+ im.add_parameter (new Parameter ("interface_name", data_type ("string", false)));
+ im.add_parameter (new Parameter ("method_name", data_type ("string", false)));
+ im.add_parameter (new Parameter ("parameters", data_type ("GLib.Variant", false)));
+ im.add_parameter (new Parameter ("invocation", data_type ("GLib.DBusMethodInvocation", false)));
+ im.add_parameter (new Parameter ("user_data", new PointerType (new VoidType ())));
+ sym.add_method (im);
+
+ push_builder (new CodeBuilder.for_subroutine (im));
+ var object_type = context.analyzer.get_data_type_for_symbol (sym);
+ var object = b.add_temp_declaration (null, expression (@"($object_type) (((Object[])user_data)[0])"));
+ b.open_switch (expression ("method_name"), null);
+ b.add_return ();
+ foreach (var m in sym.get_methods ()) {
+ if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
+ || m.overrides || m.access != SymbolAccessibility.PUBLIC
+ || !is_dbus_visible (m)) {
+ continue;
+ }
+ b.add_section (expression (@"\"$(get_dbus_name_for_member (m))\""));
+ var wrapper = generate_dbus_method_wrapper (m, sym);
+ b.add_expression (expression (@"$wrapper ($object, parameters, invocation)"));
+ b.add_break ();
+ }
+ b.close ();
+ pop_builder ();
+ check (im);
+ }
+
+ void generate_interface_get_property (ObjectTypeSymbol sym) {
+ if (sym.scope.lookup ("dbus_interface_get_property") != null) {
+ return;
+ }
+
+ var m = new Method ("dbus_interface_get_property", data_type ("GLib.Variant", true, true), sym.source_reference);
+ m.access = SymbolAccessibility.PRIVATE;
+ m.binding = MemberBinding.STATIC;
+ m.add_parameter (new Parameter ("connection", data_type ("GLib.DBusConnection", false)));
+ m.add_parameter (new Parameter ("sender", data_type ("string", false)));
+ m.add_parameter (new Parameter ("object_path", data_type ("string", false)));
+ m.add_parameter (new Parameter ("interface_name", data_type ("string", false)));
+ m.add_parameter (new Parameter ("property_name", data_type ("string", false)));
+ m.add_parameter (new Parameter ("error", new PointerType (new PointerType (new VoidType ()))));
+ m.add_parameter (new Parameter ("user_data", new PointerType (new VoidType ())));
+ sym.add_method (m);
+
+ push_builder (new CodeBuilder.for_subroutine (m));
+ var object_type = context.analyzer.get_data_type_for_symbol (sym);
+ var object = b.add_temp_declaration (null, expression (@"($object_type) (((Object[])user_data)[0])"));
+ b.open_switch (expression ("property_name"), null);
+ b.add_return (expression ("null"));
+ foreach (var prop in sym.get_properties ()) {
+ if (prop.binding != MemberBinding.INSTANCE
+ || prop.overrides || prop.access != SymbolAccessibility.PUBLIC
+ || !is_dbus_visible (prop)
+ || prop.get_accessor == null) {
+ continue;
+ }
+ b.add_section (expression (@"\"$(get_dbus_name_for_member (prop))\""));
+ b.add_return (expression (@"$object.$(prop.name)"));
+ }
+ pop_builder ();
+ check (m);
+ }
+
+ void generate_interface_set_property (ObjectTypeSymbol sym) {
+ if (sym.scope.lookup ("dbus_interface_set_property") != null) {
+ return;
+ }
+
+ var m = new Method ("dbus_interface_set_property", data_type ("bool"), sym.source_reference);
+ m.access = SymbolAccessibility.PRIVATE;
+ m.binding = MemberBinding.STATIC;
+ m.add_parameter (new Parameter ("connection", data_type ("GLib.DBusConnection", false)));
+ m.add_parameter (new Parameter ("sender", data_type ("string", false)));
+ m.add_parameter (new Parameter ("object_path", data_type ("string", false)));
+ m.add_parameter (new Parameter ("interface_name", data_type ("string", false)));
+ m.add_parameter (new Parameter ("property_name", data_type ("string", false)));
+ m.add_parameter (new Parameter ("value", data_type ("GLib.Variant", false)));
+ m.add_parameter (new Parameter ("error", new PointerType (new PointerType (new VoidType ()))));
+ m.add_parameter (new Parameter ("user_data", new PointerType (new VoidType ())));
+ sym.add_method (m);
+
+ push_builder (new CodeBuilder.for_subroutine (m));
+ var object_type = context.analyzer.get_data_type_for_symbol (sym);
+ var object = b.add_temp_declaration (null, expression (@"($object_type) (((Object[])user_data)[0])"));
+ b.open_switch (expression ("property_name"), null);
+ b.add_return (expression ("false"));
+ foreach (var prop in sym.get_properties ()) {
+ if (prop.binding != MemberBinding.INSTANCE
+ || prop.overrides || prop.access != SymbolAccessibility.PUBLIC
+ || !is_dbus_visible (prop)
+ || prop.set_accessor == null) {
+ continue;
+ }
+ b.add_section (expression (@"\"$(get_dbus_name_for_member (prop))\""));
+ b.add_expression (expression (@"$object.$(prop.name) = ($(prop.property_type)) value"));
+ b.add_return (expression ("true"));
+ }
+ pop_builder ();
+ check (m);
+ }
+
+ void generate_interface_signal_emitter (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
+ var wrapper_name = "_dbus_%s_%s".printf (CCodeBaseModule.get_ccode_lower_case_name (sym), CCodeBaseModule.get_ccode_name (sig));
+ if (context.root.scope.lookup (wrapper_name) != null) {
+ return;
+ }
+
+ var m = new Method (wrapper_name, new VoidType (), sym.source_reference);
+ context.root.add_method (m);
+ m.access = SymbolAccessibility.PRIVATE;
+ m.binding = MemberBinding.STATIC;
+ m.add_parameter (new Parameter ("_sender", data_type ("GLib.Object", false)));
+ foreach (var param in sig.get_parameters ()) {
+ m.add_parameter (param.copy ());
+ }
+ m.add_parameter (new Parameter ("_data", new PointerType (new PointerType (new VoidType ()))));
+ push_builder (new CodeBuilder.for_subroutine (m));
+
+ var builder = b.add_temp_declaration (null, expression ("new GLib.VariantBuilder (GLib.VariantType.TUPLE)"));
+ foreach (var param in sig.get_parameters ()) {
+ if (param.variable_type.data_type == context.analyzer.gvariant_type.data_type) {
+ b.add_expression (expression (@"$builder.add (\"v\", $(param.name))"));
+ } else {
+ b.add_expression (expression (@"$builder.add_value ($(param.name))"));
+ }
+ }
+ b.add_expression (expression (@"((GLib.DBusConnection) _data[1]).emit_signal (null, (string) _data[2], \"$dbus_iface_name\", \"$(get_dbus_name_for_member (sig))\", $builder.end ())"));
+ pop_builder ();
+ check (m);
+ }
+
+ void visit_object_type_symbol (ObjectTypeSymbol sym) {
+ string dbus_iface_name = get_dbus_name (sym);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ generate_interface_method_call (sym);
+ generate_interface_get_property (sym);
+ generate_interface_set_property (sym);
+
+ foreach (var sig in sym.get_signals ()) {
+ if (sig.access != SymbolAccessibility.PUBLIC || !is_dbus_visible (sig)) {
+ continue;
+ }
+ generate_interface_signal_emitter (sig, sym, dbus_iface_name);
+ }
+ }
+}
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index 491240c..f1b9e51 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -414,7 +414,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
en.add_method (m);
m.binding = MemberBinding.STATIC;
m.access = SymbolAccessibility.PUBLIC;
- b = new CodeBuilder.for_subroutine (m);
+ push_builder (new CodeBuilder.for_subroutine (m));
b.open_switch (expression ("str"), null);
b.add_throw (expression ("new GLib.DBusError.INVALID_ARGS (\"Invalid value for enum `%s'\")".printf (CCodeBaseModule.get_ccode_name (en))));
@@ -424,6 +424,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
b.add_return (expression (@"$(en.get_full_name()).$(enum_value.name)"));
}
b.close ();
+ pop_builder ();
check (m);
}
@@ -435,7 +436,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
var m = new Method ("to_string", data_type ("string", false, true), en.source_reference);
en.add_method (m);
m.access = SymbolAccessibility.PUBLIC;
- b = new CodeBuilder.for_subroutine (m);
+ push_builder (new CodeBuilder.for_subroutine (m));
b.open_switch (expression ("this"), null);
b.add_return (expression ("null"));
@@ -445,6 +446,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
b.add_return (expression (@"\"$dbus_value\""));
}
b.close ();
+ pop_builder ();
check (m);
}
@@ -463,7 +465,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
return;
}
- b = new CodeBuilder (context, expr.parent_statement, expr.source_reference);
+ push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference));
var old_parent_node = expr.parent_node;
var target_type = expr.target_type.copy ();
var type = expr.value_type;
@@ -494,6 +496,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
context.analyzer.replaced_nodes.add (expr);
old_parent_node.replace_expression (expr, result);
b.check (this);
+ pop_builder ();
check (result);
}
@@ -504,7 +507,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
return;
}
- b = new CodeBuilder (context, expr.parent_statement, expr.source_reference);
+ push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference));
var old_parent_node = expr.parent_node;
var target_type = expr.target_type.copy ();
var type = expr.value_type;
@@ -534,6 +537,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
context.analyzer.replaced_nodes.add (expr);
old_parent_node.replace_expression (expr, result);
b.check (this);
+ pop_builder ();
check (result);
}
}
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index 5ccf586..fe8f8ed 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -342,7 +342,7 @@ class Vala.Compiler {
}
}
- var transformer = new GDBusClientTransformer ();
+ var transformer = new GDBusServerTransformer ();
transformer.transform (context);
if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
index 825fd12..f32cca3 100644
--- a/vala/valacodebuilder.vala
+++ b/vala/valacodebuilder.vala
@@ -196,6 +196,25 @@ public class Vala.CodeBuilder {
section.add_label (label);
}
+ public void open_try () {
+ build_context.statement_stack.add (build_context.current_block);
+ var parent_block = build_context.current_block;
+
+ build_context.current_block = new Block (source_reference);
+
+ var stmt = new TryStatement (build_context.current_block, null, source_reference);
+ build_context.statement_stack.add (stmt);
+
+ parent_block.add_statement (stmt);
+ }
+
+ public void add_catch (DataType? error_type, string? variable_name) {
+ build_context.current_block = new Block (source_reference);
+
+ var stmt = (TryStatement) build_context.statement_stack[build_context.statement_stack.size-1];
+ stmt.add_catch_clause (new CatchClause (error_type, variable_name, build_context.current_block, source_reference));
+ }
+
public void add_statement (Statement statement) {
build_context.current_block.add_statement (statement);
}
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 8df4099..6ee1e77 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -27,8 +27,19 @@ public class Vala.CodeTransformer : CodeVisitor {
public CodeContext context;
public CodeBuilder b;
+ public ArrayList<CodeBuilder> builder_stack = new ArrayList<CodeBuilder> ();
public HashMap<string, CodeNode> wrapper_cache = new HashMap<string, CodeNode> (str_hash, str_equal);
+ public void push_builder (CodeBuilder builder) {
+ builder_stack.add (b);
+ b = builder;
+ }
+
+ public void pop_builder () {
+ b = builder_stack[builder_stack.size - 1];
+ builder_stack.remove_at (builder_stack.size - 1);
+ }
+
/**
* Transform the code tree for the specified code context.
*
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index ad30589..198b074 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -357,8 +357,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
List<TypeParameter> type_parameters = null;
if (sym is ObjectTypeSymbol) {
- type = new ObjectType ((ObjectTypeSymbol) sym);
- type_parameters = ((ObjectTypeSymbol) sym).get_type_parameters ();
+ var cl = sym as Class;
+ if (cl != null && cl.is_error_base) {
+ type = new ErrorType (null, null);
+ } else {
+ type = new ObjectType ((ObjectTypeSymbol) sym);
+ type_parameters = ((ObjectTypeSymbol) sym).get_type_parameters ();
+ }
} else if (sym is Struct) {
var st = (Struct) sym;
if (st.is_boolean_type ()) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]