[vala/wip/transform: 48/107] GDBus server transformer



commit 1681b5bfdab68368e3c1ad6986be10d855aaed48
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      | 951 ++++++--------------------------
 codegen/valagdbusservertransformer.vala | 315 +++++++++++
 codegen/valagvarianttransformer.vala    |  12 +-
 compiler/valacompiler.vala              |   2 +-
 vala/valacodebuilder.vala               |  19 +
 vala/valacodetransformer.vala           |  11 +
 8 files changed, 557 insertions(+), 808 deletions(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 49421eb45..234900661 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -43,6 +43,7 @@ libvalaccodegen_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 5e8b9da2a..79f40ccda 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, int method_timeout) {
                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;
                        }
@@ -149,9 +160,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), 
GDBusModule.get_dbus_timeout_for_member (m));
+               pop_builder ();
        }
 
        void generate_dbus_proxy_methods (Class proxy_class, Interface iface) {
@@ -205,7 +217,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 ()"));
@@ -221,6 +233,7 @@ public class Vala.GDBusClientTransformer : GVariantTransformer {
                        b.add_break ();
                }
                b.close ();
+               pop_builder ();
        }
 
        public int get_dbus_timeout (Symbol symbol) {
@@ -251,7 +264,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"));
@@ -260,14 +273,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);
@@ -325,7 +340,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 ();
@@ -341,6 +356,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 904e04502..f4cd9957e 100644
--- a/codegen/valagdbusservermodule.vala
+++ b/codegen/valagdbusservermodule.vala
@@ -21,661 +21,28 @@
  */
 
 public class Vala.GDBusServerModule : GDBusClientModule {
-       string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
-               string wrapper_name = "_dbus_%s".printf (get_ccode_name (m));
-               bool need_goto_label = ready;
-
-               if (m.base_method != null) {
-                       m = m.base_method;
-               } else if (m.base_interface_method != null) {
-                       m = m.base_interface_method;
+       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;
                }
 
-               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);
-
-               CCodeIdentifier ready_data_expr = m.coroutine ? new CCodeIdentifier ("_ready_data") : null;
-               string ready_data_struct_name = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + 
"ReadyData";
-
-               if (ready) {
-                       ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator 
("_ready_data", new CCodeIdentifier ("_user_data_")));
-                       ccode.add_declaration ("GDBusMethodInvocation*", new CCodeVariableDeclarator 
("invocation", new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_")));
-               }
-
-               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");
-                       ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
-               }
-
-               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")));
-                               ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
-                       }
-
-                       CCodeStruct? ready_data_struct = null;
-
-                       if (m.coroutine) {
-                               ready_data_struct = new CCodeStruct ("_" + ready_data_struct_name);
-                               ready_data_struct.add_field ("GDBusMethodInvocation*", "_invocation_");
-                               append_struct (ready_data_struct);
-
-                               var ready_data_alloc = new CCodeFunctionCall (new CCodeIdentifier 
("g_slice_new0"));
-                               ready_data_alloc.add_argument (new CCodeIdentifier (ready_data_struct_name));
-
-                               ccode.add_declaration (ready_data_struct_name + "*", new 
CCodeVariableDeclarator ("_ready_data"));
-                               ccode.add_assignment (ready_data_expr, ready_data_alloc);
-
-                               ccode.add_assignment (new CCodeMemberAccess.pointer (ready_data_expr, 
"_invocation_"), new CCodeIdentifier ("invocation"));
-                       }
-
-                       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;
-                               }
-
-                               CCodeExpression param_expr;
-                               if (ready_data_expr != null) {
-                                       param_expr = new CCodeMemberAccess.pointer (ready_data_expr, 
param_name);
-                               } else {
-                                       param_expr = new CCodeIdentifier (param_name);
-                               }
-
-                               var owned_type = param.variable_type.copy ();
-                               owned_type.value_owned = true;
-
-                               if (ready_data_struct != null) {
-                                       ready_data_struct.add_field (get_ccode_name (owned_type), param_name);
-                               } else {
-                                       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) {
-                                       var length_ctype = get_ccode_array_length_type (array_type);
-                                       for (int dim = 1; dim <= array_type.rank; dim++) {
-                                               string length_cname = get_parameter_array_length_cname 
(param, dim);
-
-                                               if (ready_data_struct != null) {
-                                                       ready_data_struct.add_field (length_ctype, 
length_cname);
-                                               } else {
-                                                       ccode.add_declaration (length_ctype, 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"), param_expr, 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);
-
-                                       var free_error = new CCodeFunctionCall (new CCodeIdentifier 
("g_error_free"));
-                                       free_error.add_argument (new CCodeIdentifier ("error"));
-                                       ccode.add_expression (free_error);
-
-                                       if (need_goto_label || requires_destroy (owned_type)) {
-                                               ccode.add_goto ("_error");
-                                               need_goto_label = true;
-                                       } else {
-                                               ccode.add_return ();
-                                       }
-
-                                       ccode.close ();
-                               }
-                       }
-               }
-
-               foreach (Parameter param in m.get_parameters ()) {
-                       string param_name = get_variable_cname (param.name);
-
-                       CCodeExpression param_expr;
-                       if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
-                               param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
-                       } else {
-                               param_expr = new CCodeIdentifier (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, param_expr));
-                               } else {
-                                       ccall.add_argument (param_expr);
-                               }
-                       } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
-                               ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, 
param_expr));
-                       }
-
-                       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);
-
-                                       CCodeExpression length_expr;
-                                       if (ready_data_expr != null && param.direction == 
ParameterDirection.IN)
-                                               length_expr = new CCodeMemberAccess.pointer (ready_data_expr, 
length_cname);
-                                       else
-                                               length_expr = new CCodeIdentifier (length_cname);
-
-                                       if (param.direction == ParameterDirection.IN && !ready) {
-                                               ccall.add_argument (length_expr);
-                                       } else if (param.direction == ParameterDirection.OUT && !no_reply && 
(!m.coroutine || ready)) {
-                                               ccall.add_argument (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, length_expr));
-                                       }
-                               }
-                       }
-               }
-
-               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 (ready_data_expr);
-               }
-
-               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);
-
-                               var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free"));
-                               free_error.add_argument (new CCodeIdentifier ("error"));
-                               ccode.add_expression (free_error);
-
-                               if (need_goto_label) {
-                                       ccode.add_goto ("_error");
-                               } else {
-                                       ccode.add_return ();
-                               }
-
-                               ccode.close ();
-                       }
-
-                       ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero 
("_reply_message", new CCodeConstant ("NULL")));
-
-                       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_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) {
-                                       var length_ctype = get_ccode_array_length_type (array_type);
-                                       for (int dim = 1; dim <= array_type.rank; dim++) {
-                                               string length_cname = get_parameter_array_length_cname 
(param, dim);
-
-                                               ccode.add_declaration (length_ctype, 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) {
-                                               var length_ctype = get_ccode_array_length_type (array_type);
-                                               for (int dim = 1; dim <= array_type.rank; dim++) {
-                                                       string length_cname = get_array_length_cname 
("result", dim);
-
-                                                       ccode.add_declaration (length_ctype, 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);
-               }
-
-               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);
-               }
-
-               if (need_goto_label) {
-                       ccode.add_label ("_error");
-               }
-
-               foreach (Parameter param in m.get_parameters ()) {
-                       if ((param.direction == ParameterDirection.IN && (ready_data_expr == null || 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)) {
-                                       if (ready_data_expr != null && param.direction == 
ParameterDirection.IN) {
-                                               var target = new GLibValue (owned_type, new 
CCodeMemberAccess.pointer (ready_data_expr, param.name), true);
-
-                                               var array_type = owned_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);
-
-                                                               target.append_array_length_cvalue (new 
CCodeMemberAccess.pointer (ready_data_expr, length_cname));
-                                                       }
-                                               }
-
-                                               ccode.add_expression (destroy_value (target));
-                                       } else {
-                                               // 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 (ready) {
-                       var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
-                       freecall.add_argument (new CCodeIdentifier (ready_data_struct_name));
-                       freecall.add_argument (ready_data_expr);
-                       ccode.add_expression (freecall);
-               } else if (need_goto_label) {
-                       ccode.add_statement (new CCodeEmptyStatement ());
-               }
-
-               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;
+               return true;
        }
 
-       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_lower_case_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;
-                               var length_ctype = get_ccode_array_length_type (array_type);
-                               for (int dim = 1; dim <= array_type.rank; dim++) {
-                                       function.add_parameter (new CCodeParameter 
(get_parameter_array_length_cname (param, dim), length_ctype));
-                               }
-                       }
-               }
-
-               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);
+       public static string dbus_result_name (Method m) {
+               var dbus_name = m.get_attribute_string ("DBus", "result");
+               if (dbus_name != null && dbus_name != "") {
+                       return dbus_name;
                }
 
-               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;
+               return "result";
        }
 
-       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) {
-                               var length_ctype = get_ccode_array_length_type (array_type);
-                               for (int dim = 1; dim <= array_type.rank; dim++) {
-                                       string length_cname = get_array_length_cname ("result", dim);
-
-                                       ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero 
(length_cname, new CCodeConstant ("0")));
-                                       ccall.add_argument (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
-                               }
-                       }
-               }
-
-               ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
-
-               if (get_dbus_signature (prop) != null) {
-                       // raw GVariant
-                       ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result"));
-               } else {
-                       var reply_expr = serialize_expression (prop.get_accessor.value_type, new 
CCodeIdentifier ("result"));
-
-                       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) {
-                               var length_ctype = get_ccode_array_length_type (array_type);
-                               for (int dim = 1; dim <= array_type.rank; dim++) {
-                                       ccode.add_declaration (length_ctype, new CCodeVariableDeclarator 
(get_array_length_cname ("value", dim)));
-                                       ccall.add_argument (new CCodeIdentifier (get_array_length_cname 
("value", dim)));
-                               }
-                       }
-               }
-
-               var target = new CCodeIdentifier ("value");
-
-               if (get_dbus_signature (prop) != null) {
-                       ccode.add_assignment (target, new CCodeIdentifier("_value"));
-                       ccode.add_expression (ccall);
-               } else {
-                       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;
+       string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
+               return "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name 
(sig));
        }
 
        void handle_signals (ObjectTypeSymbol sym, bool connect) {
@@ -710,25 +77,8 @@ 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;
+       CCodeExpression get_method_info (ObjectTypeSymbol sym) {
+               var infos = new CCodeInitializerList ();
 
                foreach (Method m in sym.get_methods ()) {
                        if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
@@ -739,129 +89,149 @@ public class Vala.GDBusServerModule : GDBusClientModule {
                                continue;
                        }
 
-                       cfile.add_include ("string.h");
+                       var in_args_info = new CCodeInitializerList ();
+                       var out_args_info = new CCodeInitializerList ();
 
-                       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))));
+                       foreach (Parameter param in m.get_parameters ()) {
+                               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") {
+                                       continue;
+                               }
 
-                       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 info = new CCodeInitializerList ();
+                               info.append (new CCodeConstant ("-1"));
+                               info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
+                               info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature 
(param.variable_type, param))));
+                               info.append (new CCodeConstant ("NULL"));
+
+                               var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
+                               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + 
get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name, info));
+                               cdecl.modifiers = CCodeModifiers.STATIC;
+                               cfile.add_constant_declaration (cdecl);
+
+                               if (param.direction == ParameterDirection.IN) {
+                                       in_args_info.append (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_arg_info_" + m.name + "_" + param.name)));
+                               } else {
+                                       out_args_info.append (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_arg_info_" + m.name + "_" + param.name)));
+                               }
                        }
 
-                       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 (!(m.return_type is VoidType)) {
+                               var info = new CCodeInitializerList ();
+                               info.append (new CCodeConstant ("-1"));
+                               info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m))));
+                               info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature 
(m.return_type, m))));
+                               info.append (new CCodeConstant ("NULL"));
 
-               if (!first) {
-                       ccode.add_else ();
-               }
+                               var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
+                               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + 
get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_result", info));
+                               cdecl.modifiers = CCodeModifiers.STATIC;
+                               cfile.add_constant_declaration (cdecl);
 
-               var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
-               ccall.add_argument (new CCodeIdentifier ("invocation"));
-               ccode.add_expression (ccall);
+                               out_args_info.append (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_arg_info_" + m.name + "_result")));
+                       }
 
-               if (!first) {
-                       ccode.close ();
-               }
+                       in_args_info.append (new CCodeConstant ("NULL"));
+                       out_args_info.append (new CCodeConstant ("NULL"));
 
-               pop_function ();
+                       var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix 
(sym) + "dbus_arg_info_" + m.name + "_in[]", in_args_info));
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+                       cfile.add_constant_declaration (cdecl);
 
-               cfile.add_function_declaration (cfunc);
-               cfile.add_function (cfunc);
-       }
+                       cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix 
(sym) + "dbus_arg_info_" + m.name + "_out[]", out_args_info));
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+                       cfile.add_constant_declaration (cdecl);
 
-       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"));
+                       var info = new CCodeInitializerList ();
+                       info.append (new CCodeConstant ("-1"));
+                       info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
+                       info.append (new CCodeCastExpression (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_arg_info_" + m.name + "_in")), "GDBusArgInfo **"));
+                       info.append (new CCodeCastExpression (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_arg_info_" + m.name + "_out")), "GDBusArgInfo **"));
+                       info.append (new CCodeConstant ("NULL"));
 
-               cfunc.modifiers |= CCodeModifiers.STATIC;
+                       cdecl = new CCodeDeclaration ("const GDBusMethodInfo");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix 
(sym) + "dbus_method_info_" + m.name, info));
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+                       cfile.add_constant_declaration (cdecl);
 
-               cfile.add_function_declaration (cfunc);
+                       infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new 
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info_" + m.name)));
+               }
 
-               push_function (cfunc);
+               infos.append (new CCodeConstant ("NULL"));
 
-               ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier 
("user_data")));
+               var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const");
+               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_method_info[]", infos));
+               cdecl.modifiers = CCodeModifiers.STATIC;
+               cfile.add_constant_declaration (cdecl);
 
-               ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new 
CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
+               return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info");
+       }
 
-               bool firstif = true;
+       CCodeExpression get_signal_info (ObjectTypeSymbol sym) {
+               var infos = new CCodeInitializerList ();
 
-               foreach (Property prop in sym.get_properties ()) {
-                       if (prop.binding != MemberBinding.INSTANCE
-                           || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
-                               continue;
-                       }
-                       if (!is_dbus_visible (prop)) {
+               foreach (Signal sig in sym.get_signals ()) {
+                       if (sig.access != SymbolAccessibility.PUBLIC) {
                                continue;
                        }
-                       if (prop.get_accessor == null) {
+                       if (!is_dbus_visible (sig)) {
                                continue;
                        }
 
-                       cfile.add_include ("string.h");
+                       var args_info = new CCodeInitializerList ();
 
-                       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))));
+                       foreach (Parameter param in sig.get_parameters ()) {
+                               var info = new CCodeInitializerList ();
+                               info.append (new CCodeConstant ("-1"));
+                               info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
+                               info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature 
(param.variable_type, param))));
+                               info.append (new CCodeConstant ("NULL"));
 
-                       var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new 
CCodeConstant ("0"));
-                       if (firstif) {
-                               ccode.open_if (cond);
-                               firstif = false;
-                       } else {
-                               ccode.else_if (cond);
+                               var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
+                               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + 
get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "_" + param.name, 
info));
+                               cdecl.modifiers = CCodeModifiers.STATIC;
+                               cfile.add_constant_declaration (cdecl);
+
+                               args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, 
new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name 
(sig) + "_" + param.name)));
                        }
 
-                       var ccall = new CCodeFunctionCall (new CCodeIdentifier 
(generate_dbus_property_get_wrapper (prop, sym)));
-                       ccall.add_argument (new CCodeIdentifier ("object"));
+                       args_info.append (new CCodeConstant ("NULL"));
 
-                       ccode.add_return (ccall);
-               }
-               if (!firstif) {
-                       ccode.close ();
-               }
+                       var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix 
(sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "[]", args_info));
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+                       cfile.add_constant_declaration (cdecl);
 
-               ccode.add_return (new CCodeConstant ("NULL"));
+                       var info = new CCodeInitializerList ();
+                       info.append (new CCodeConstant ("-1"));
+                       info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
+                       info.append (new CCodeCastExpression (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_arg_info_" + get_ccode_lower_case_name (sig))), "GDBusArgInfo **"));
+                       info.append (new CCodeConstant ("NULL"));
 
-               pop_function ();
-               cfile.add_function (cfunc);
-       }
+                       cdecl = new CCodeDeclaration ("const GDBusSignalInfo");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix 
(sym) + "dbus_signal_info_" + get_ccode_lower_case_name (sig), info));
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+                       cfile.add_constant_declaration (cdecl);
 
-       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;
+                       infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new 
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info_" + get_ccode_lower_case_name 
(sig))));
+               }
 
-               cfile.add_function_declaration (cfunc);
+               infos.append (new CCodeConstant ("NULL"));
 
-               push_function (cfunc);
-
-               ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier 
("user_data")));
+               var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const");
+               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_signal_info[]", infos));
+               cdecl.modifiers = CCodeModifiers.STATIC;
+               cfile.add_constant_declaration (cdecl);
 
-               ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new 
CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
+               return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info");
+       }
 
-               bool firstif = true;
+       CCodeExpression get_property_info (ObjectTypeSymbol sym) {
+               var infos = new CCodeInitializerList ();
 
                foreach (Property prop in sym.get_properties ()) {
                        if (prop.binding != MemberBinding.INSTANCE
@@ -871,38 +241,55 @@ public class Vala.GDBusServerModule : GDBusClientModule {
                        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;
+                       var info = new CCodeInitializerList ();
+                       info.append (new CCodeConstant ("-1"));
+                       info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
+                       info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature 
(prop.property_type, prop))));
+                       if (prop.get_accessor != null && prop.set_accessor != null) {
+                               info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | 
G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
+                       } else if (prop.get_accessor != null) {
+                               info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
+                       } else if (prop.set_accessor != null) {
+                               info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
                        } else {
-                               ccode.else_if (cond);
+                               info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
                        }
+                       info.append (new CCodeConstant ("NULL"));
 
-                       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"));
+                       var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix 
(sym) + "dbus_property_info_" + prop.name, info));
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+                       cfile.add_constant_declaration (cdecl);
 
-                       ccode.add_expression (ccall);
-                       ccode.add_return (new CCodeConstant ("TRUE"));
-               }
-               if (!firstif) {
-                       ccode.close ();
+                       infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new 
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info_" + prop.name)));
                }
-               ccode.add_return (new CCodeConstant ("FALSE"));
 
-               pop_function ();
-               cfile.add_function (cfunc);
+               infos.append (new CCodeConstant ("NULL"));
+
+               var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const");
+               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_property_info[]", infos));
+               cdecl.modifiers = CCodeModifiers.STATIC;
+               cfile.add_constant_declaration (cdecl);
+
+               return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info");
+       }
+
+       CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
+               var info = new CCodeInitializerList ();
+               info.append (new CCodeConstant ("-1"));
+               info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym))));
+               info.append (new CCodeCastExpression (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)), "GDBusMethodInfo **"));
+               info.append (new CCodeCastExpression (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)), "GDBusSignalInfo **"));
+               info.append (new CCodeCastExpression (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)), "GDBusPropertyInfo **"));
+               info.append (new CCodeConstant ("NULL"));
+
+               var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo");
+               cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + 
"dbus_interface_info", info));
+               cdecl.modifiers = CCodeModifiers.STATIC;
+               cfile.add_constant_declaration (cdecl);
+
+               return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_info");
        }
 
        CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
@@ -911,10 +298,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 000000000..747c6c160
--- /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 (get_ccode_lower_case_name (sym), 
get_ccode_lower_case_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 81acf5cb7..e88dd05e2 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -416,7 +416,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 (get_ccode_name (en))));
@@ -426,6 +426,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
                        b.add_return (expression (@"$(en.get_full_name()).$(enum_value.name)"));
                }
                b.close ();
+               pop_builder ();
 
                check (m);
        }
@@ -437,7 +438,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"));
@@ -447,6 +448,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
                        b.add_return (expression (@"\"$dbus_value\""));
                }
                b.close ();
+               pop_builder ();
 
                check (m);
        }
@@ -465,7 +467,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;
@@ -496,6 +498,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);
        }
 
@@ -506,7 +509,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;
@@ -536,6 +539,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 56a69d52b..561e4efa8 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -399,7 +399,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 fd0fbf8c0..87989c857 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 d46c10071..22d1b1ad5 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.
         *


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