Commit f371f443 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

add experimental D-Bus client support

2007-08-06  Juerg Billeter  <j@bitron.ch>

	* vala/Makefile.am, vala/parser.y, vala/valaarray.vala,
	  vala/valabindingprovider.vala, vala/valaclass.vala,
	  vala/valaenum.vala, vala/valainterface.vala,
	  vala/valamemorymanager.vala, vala/valamethod.vala,
	  vala/valasemanticanalyzer.vala, vala/valasymbol.vala,
	  vala/valasymbolresolver.vala, vala/valavariabledeclarator.vala,
	  gobject/Makefile.am, gobject/valacodegenerator.vala,
	  gobject/valacodegeneratorassignment.vala,
	  gobject/valacodegeneratorclass.vala,
	  gobject/valacodegeneratorinterface.vala,
	  gobject/valacodegeneratorinvocationexpression.vala,
	  gobject/valacodegeneratormethod.vala,
	  gobject/valadbusbindingprovider.vala, gobject/valadbusmethod.vala,
	  gobject/valadbussignal.vala, compiler/valacompiler.vala,
	  vapi/dbus-glib-1.vala, vapi/hal.vala: add experimental D-Bus client
	  support

svn path=/trunk/; revision=419
parent fa628f64
2007-08-06 Jürg Billeter <j@bitron.ch>
* vala/Makefile.am, vala/parser.y, vala/valaarray.vala,
vala/valabindingprovider.vala, vala/valaclass.vala,
vala/valaenum.vala, vala/valainterface.vala,
vala/valamemorymanager.vala, vala/valamethod.vala,
vala/valasemanticanalyzer.vala, vala/valasymbol.vala,
vala/valasymbolresolver.vala, vala/valavariabledeclarator.vala,
gobject/Makefile.am, gobject/valacodegenerator.vala,
gobject/valacodegeneratorassignment.vala,
gobject/valacodegeneratorclass.vala,
gobject/valacodegeneratorinterface.vala,
gobject/valacodegeneratorinvocationexpression.vala,
gobject/valacodegeneratormethod.vala,
gobject/valadbusbindingprovider.vala, gobject/valadbusmethod.vala,
gobject/valadbussignal.vala, compiler/valacompiler.vala,
vapi/dbus-glib-1.vala, vapi/hal.vala: add experimental D-Bus client
support
2007-08-06 Jürg Billeter <j@bitron.ch>
* gobject/valacodegenerator.vala,
......
......@@ -217,8 +217,12 @@ class Vala.Compiler {
if (Report.get_errors () > 0) {
return quit ();
}
var dbus_binding_provider = new DBusBindingProvider ();
dbus_binding_provider.context = context;
var analyzer = new SemanticAnalyzer (!disable_memory_management);
analyzer.add_binding_provider (dbus_binding_provider);
analyzer.analyze (context);
if (Report.get_errors () > 0) {
......
......@@ -48,6 +48,15 @@ libvala_la_SOURCES = \
valacodegeneratorstruct.c \
valacodegeneratorstruct.h \
valacodegeneratorstruct.vala \
valadbusbindingprovider.c \
valadbusbindingprovider.h \
valadbusbindingprovider.vala \
valadbusmethod.c \
valadbusmethod.h \
valadbusmethod.vala \
valadbussignal.c \
valadbussignal.h \
valadbussignal.vala \
valainterfaceregisterfunction.c \
valainterfaceregisterfunction.h \
valainterfaceregisterfunction.vala \
......@@ -71,6 +80,9 @@ gobjectinclude_HEADERS = \
valacodegeneratorsignal.h \
valacodegeneratorsourcefile.h \
valacodegeneratorstruct.h \
valadbusbindingprovider.h \
valadbusmethod.h \
valadbussignal.h \
valainterfaceregisterfunction.h \
valatyperegisterfunction.h \
$(NULL)
......
......@@ -99,12 +99,14 @@ public class Vala.CodeGenerator : CodeVisitor {
DataType glist_type;
DataType gslist_type;
DataType gstring_type;
DataType garray_type;
TypeReference mutex_type;
DataType type_module_type;
DataType iterable_type;
DataType iterator_type;
DataType list_type;
DataType map_type;
DataType connection_type;
Method substring_method;
......@@ -246,6 +248,7 @@ public class Vala.CodeGenerator : CodeVisitor {
glist_type = (DataType) glib_ns.scope.lookup ("List");
gslist_type = (DataType) glib_ns.scope.lookup ("SList");
gstring_type = (DataType) glib_ns.scope.lookup ("String");
garray_type = (DataType) glib_ns.scope.lookup ("Array");
mutex_type = new TypeReference ();
mutex_type.data_type = (DataType) glib_ns.scope.lookup ("Mutex");
......@@ -270,6 +273,11 @@ public class Vala.CodeGenerator : CodeVisitor {
list_type = (DataType) gee_ns.scope.lookup ("List");
map_type = (DataType) gee_ns.scope.lookup ("Map");
}
var dbus_ns = root_symbol.scope.lookup ("DBus");
if (dbus_ns != null) {
connection_type = (DataType) dbus_ns.scope.lookup ("Connection");
}
/* we're only interested in non-pkg source files */
var source_files = context.get_source_files ();
......@@ -807,6 +815,8 @@ public class Vala.CodeGenerator : CodeVisitor {
}
public override void visit_variable_declarator (VariableDeclarator! decl) {
decl.accept_children (this);
if (decl.type_reference.data_type is Array) {
// create variables to store array dimensions
var arr = (Array) decl.type_reference.data_type;
......
......@@ -125,12 +125,20 @@ public class Vala.CodeGenerator {
bool disconnect = false;
if (a.operator == AssignmentOperator.ADD) {
connect_func = "g_signal_connect_object";
if (!m.instance) {
connect_func = "g_signal_connect";
if (sig is DBusSignal) {
connect_func = "dbus_g_proxy_connect_signal";
} else {
connect_func = "g_signal_connect_object";
if (!m.instance) {
connect_func = "g_signal_connect";
}
}
} else if (a.operator == AssignmentOperator.SUB) {
connect_func = "g_signal_handlers_disconnect_matched";
if (sig is DBusSignal) {
connect_func = "dbus_g_proxy_disconnect_signal";
} else {
connect_func = "g_signal_handlers_disconnect_matched";
}
disconnect = true;
} else {
a.error = true;
......@@ -146,7 +154,7 @@ public class Vala.CodeGenerator {
ccall.add_argument (new CCodeIdentifier ("self"));
}
if (!disconnect) {
if (!disconnect || sig is DBusSignal) {
ccall.add_argument (sig.get_canonical_cconstant ());
} else {
ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
......@@ -185,13 +193,74 @@ public class Vala.CodeGenerator {
ccall.add_argument (new CCodeIdentifier ("self"));
}
if (!disconnect) {
ccall.add_argument (new CCodeConstant ("0"));
if (sig is DBusSignal) {
// free_data_func
ccall.add_argument (new CCodeConstant ("NULL"));
} else {
// connect_flags
ccall.add_argument (new CCodeConstant ("0"));
}
}
} else {
ccall.add_argument (new CCodeConstant ("NULL"));
}
a.ccodenode = ccall;
if (sig is DBusSignal && !disconnect) {
bool first = true;
foreach (FormalParameter param in m.get_parameters ()) {
if (first) {
// skip sender parameter
first = false;
continue;
}
sig.add_parameter (param);
}
sig.accept (this);
// FIXME should only be done once per marshaller
var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
register_call.add_argument (new CCodeIdentifier (get_signal_marshaller_function (sig)));
register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
if (ma.inner != null) {
add_call.add_argument ((CCodeExpression) ma.inner.ccodenode);
} else {
add_call.add_argument (new CCodeIdentifier ("self"));
}
add_call.add_argument (sig.get_canonical_cconstant ());
first = true;
foreach (FormalParameter param in m.get_parameters ()) {
if (first) {
// skip sender parameter
first = false;
continue;
}
if (param.type_reference.data_type is Array && ((Array) param.type_reference.data_type).element_type != string_type.data_type) {
var array = (Array) param.type_reference.data_type;
var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
carray_type.add_argument (new CCodeConstant ("\"GArray\""));
carray_type.add_argument (new CCodeIdentifier (array.element_type.get_type_id ()));
register_call.add_argument (carray_type);
add_call.add_argument (carray_type);
} else {
register_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
add_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
}
}
register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
var ccomma = new CCodeCommaExpression ();
ccomma.append_expression (register_call);
ccomma.append_expression (add_call);
ccomma.append_expression (ccall);
a.ccodenode = ccomma;
}
} else if (a.left is ElementAccess && !(((ElementAccess) a.left).container.static_type.data_type is Array)) {
// custom element access
CCodeExpression rhs = (CCodeExpression) a.right.ccodenode;
......
......@@ -97,7 +97,7 @@ public class Vala.CodeGenerator {
def_frag.append (instance_struct);
def_frag.append (type_struct);
/* only add the *Private struct if it is not empty, i.e. we actually have private data */
if (cl.has_private_fields) {
if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
source_type_member_declaration.append (instance_priv_struct);
macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
......@@ -107,10 +107,10 @@ public class Vala.CodeGenerator {
cl.accept_children (this);
if (!cl.is_static) {
if (class_has_readable_properties (cl)) {
if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
add_get_property_function (cl);
}
if (class_has_writable_properties (cl)) {
if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
add_set_property_function (cl);
}
add_class_init_function (cl);
......@@ -176,7 +176,7 @@ public class Vala.CodeGenerator {
init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
/* add struct for private fields */
if (cl.has_private_fields) {
if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private"));
ccall.add_argument (new CCodeIdentifier ("klass"));
ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
......@@ -186,10 +186,10 @@ public class Vala.CodeGenerator {
/* set property handlers */
ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
ccall.add_argument (new CCodeIdentifier ("klass"));
if (class_has_readable_properties (cl)) {
if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%s_get_property".printf (cl.get_lower_case_cname (null))))));
}
if (class_has_writable_properties (cl)) {
if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%s_set_property".printf (cl.get_lower_case_cname (null))))));
}
......@@ -337,7 +337,7 @@ public class Vala.CodeGenerator {
var init_block = new CCodeBlock ();
instance_init.block = init_block;
if (cl.has_private_fields) {
if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
ccall.add_argument (new CCodeIdentifier ("self"));
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)));
......
......@@ -28,7 +28,7 @@ public class Vala.CodeGenerator {
current_symbol = iface;
current_type_symbol = iface;
if (!iface.is_static) {
if (!iface.is_static && !iface.declaration_only) {
type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
header_type_declaration.append (new CCodeNewline ());
......@@ -61,7 +61,7 @@ public class Vala.CodeGenerator {
iface.accept_children (this);
if (!iface.is_static) {
if (!iface.is_static && !iface.declaration_only) {
add_interface_base_init_function (iface);
var type_fun = new InterfaceRegisterFunction (iface);
......
......@@ -73,12 +73,12 @@ public class Vala.CodeGenerator {
if (ma.inner == null) {
instance = new CCodeIdentifier ("self");
/* require casts for overriden and inherited methods */
req_cast = m.overrides || m.base_interface_method != null || (m.parent_symbol != current_type_symbol);
req_cast = m.overrides || m.base_interface_method != null || (m.parent_symbol != null && m.parent_symbol != current_type_symbol);
} else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* reqiure casts if the type of the used instance is
* different than the type which declared the method */
req_cast = base_method.parent_symbol != ma.inner.static_type.data_type;
req_cast = base_method.parent_symbol != null && base_method.parent_symbol != ma.inner.static_type.data_type;
}
if (m.instance_by_reference && (ma.inner != null || m.parent_symbol != current_type_symbol)) {
......@@ -102,6 +102,103 @@ public class Vala.CodeGenerator {
var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
csizeof.add_argument (new CCodeIdentifier (array.get_cname ()));
ccall.add_argument (csizeof);
} else if (m is DBusMethod) {
bool found_out = false;
Expression callback = null;
foreach (Expression arg in expr.get_argument_list ()) {
if (arg.symbol_reference is Method) {
// callback
if (callback != null) {
Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method");
expr.error = true;
return;
} else if (found_out) {
Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
expr.error = true;
return;
}
callback = arg;
} else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) {
// out arg
if (callback != null) {
Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
expr.error = true;
return;
}
found_out = true;
} else {
// in arg
if (callback != null || found_out) {
Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method");
expr.error = true;
return;
}
}
}
ccall.add_argument (new CCodeConstant ("\"%s\"".printf (m.name)));
if (callback != null) {
var reply_method = (Method) callback.symbol_reference;
var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void");
cb_fun.modifiers = CCodeModifiers.STATIC;
cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*"));
cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*"));
cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
cb_fun.block = new CCodeBlock ();
var cerrdecl = new CCodeDeclaration ("GError*");
cerrdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("error", new CCodeConstant ("NULL")));
cb_fun.block.add_statement (cerrdecl);
var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call"));
cend_call.add_argument (new CCodeIdentifier ("proxy"));
cend_call.add_argument (new CCodeIdentifier ("call"));
cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode);
creply_call.add_argument (new CCodeIdentifier ("user_data"));
int param_count = reply_method.get_parameters ().size;
int i = 0;
foreach (FormalParameter param in reply_method.get_parameters ()) {
if ((++i) == param_count) {
// error parameter
break;
}
if (param.type_reference.data_type is Array && ((Array) param.type_reference.data_type).element_type != string_type.data_type) {
var array = (Array) param.type_reference.data_type;
var cdecl = new CCodeDeclaration ("GArray*");
cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
cb_fun.block.add_statement (cdecl);
cend_call.add_argument (get_dbus_array_type (array));
cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "data"));
} else {
var cdecl = new CCodeDeclaration (param.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
cb_fun.block.add_statement (cdecl);
cend_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
creply_call.add_argument (new CCodeIdentifier (param.name));
}
}
cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
creply_call.add_argument (new CCodeIdentifier ("error"));
cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
source_type_member_definition.append (cb_fun);
ccall.add_argument (new CCodeIdentifier (cb_fun.name));
ccall.add_argument (new CCodeConstant ("self"));
ccall.add_argument (new CCodeConstant ("NULL"));
} else if (found_out || m.return_type.data_type != null) {
ccall.call = new CCodeIdentifier ("dbus_g_proxy_call");
// method can fail
current_method_inner_error = true;
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
} else {
ccall.call = new CCodeIdentifier ("dbus_g_proxy_call_no_reply");
}
}
bool ellipsis = false;
......@@ -109,9 +206,15 @@ public class Vala.CodeGenerator {
var i = 1;
Iterator<FormalParameter> params_it = params.iterator ();
foreach (Expression arg in expr.get_argument_list ()) {
/* explicitly use strong reference as ccall gets
* unrefed at end of inner block
*/
if (m is DBusMethod) {
if (arg.symbol_reference is Method) {
// callback parameter
break;
}
ccall.add_argument (new CCodeIdentifier (arg.static_type.data_type.get_type_id ()));
}
CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
if (params_it.next ()) {
var param = params_it.get ();
......@@ -175,7 +278,7 @@ public class Vala.CodeGenerator {
}
/* add length argument for methods returning arrays */
if (m != null && m.return_type.data_type is Array) {
if (m != null && m.return_type.data_type is Array && !(m is DBusMethod)) {
var arr = (Array) m.return_type.data_type;
for (int dim = 1; dim <= arr.rank; dim++) {
if (!m.no_array_length) {
......@@ -193,7 +296,15 @@ public class Vala.CodeGenerator {
}
}
if (expr.can_fail) {
if (connection_type != null && ma.inner != null && ma.inner.static_type != null && ma.inner.static_type.data_type == connection_type && m.name == "get_object") {
var dbus_iface = (Interface) m.return_type.data_type;
var dbus_attr = dbus_iface.get_attribute ("DBusInterface");
ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_attr.get_string ("name"))));
} else if (m is DBusMethod) {
ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
}
if (expr.can_fail && !(m is DBusMethod)) {
// method can fail
current_method_inner_error = true;
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
......@@ -204,7 +315,7 @@ public class Vala.CodeGenerator {
} else if (ellipsis) {
/* ensure variable argument list ends with NULL
* except when using printf-style arguments */
if (m == null || !m.printf_format) {
if ((m == null || !m.printf_format) && !(m is DBusMethod)) {
ccall.add_argument (new CCodeConstant ("NULL"));
}
}
......@@ -282,7 +393,52 @@ public class Vala.CodeGenerator {
ccomma.append_expression (cndupcall);
expr.ccodenode = ccomma;
} else if (m is DBusMethod && m.return_type.data_type != null) {
if (m.return_type.data_type is Array && ((Array) m.return_type.data_type).element_type != string_type.data_type) {
var array = (Array) m.return_type.data_type;
ccall.add_argument (get_dbus_array_type (array));
var garray_type_reference = new TypeReference ();
garray_type_reference.data_type = garray_type;
var temp_decl = get_temp_variable_declarator (garray_type_reference);
temp_vars.insert (0, temp_decl);
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
var ccomma = new CCodeCommaExpression ();
ccomma.append_expression (ccall);
ccomma.append_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier (temp_decl.name), "data"));
expr.ccodenode = ccomma;
if (!m.no_array_length) {
expr.append_array_size (new CCodeMemberAccess.pointer (new CCodeIdentifier (temp_decl.name), "len"));
} else {
expr.append_array_size (new CCodeConstant ("-1"));
}
} else {
ccall.add_argument (new CCodeIdentifier (m.return_type.data_type.get_type_id ()));
var temp_decl = get_temp_variable_declarator (m.return_type);
temp_vars.insert (0, temp_decl);
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
var ccomma = new CCodeCommaExpression ();
ccomma.append_expression (ccall);
ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
expr.ccodenode = ccomma;
}
}
}
private CCodeExpression! get_dbus_array_type (Array! array) {
var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
carray_type.add_argument (new CCodeConstant ("\"GArray\""));
carray_type.add_argument (new CCodeIdentifier (array.element_type.get_type_id ()));
return carray_type;
}
}
......@@ -454,7 +454,7 @@ public class Vala.CodeGenerator {
private CCodeStatement create_type_check_statement (CodeNode! method_node, DataType ret_type, DataType! t, bool non_null, string! var_name) {
var ccheck = new CCodeFunctionCall ();
if (t is Class || t is Interface) {
if (t is Class || (t is Interface && !((Interface) t).declaration_only)) {
var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (t.get_upper_case_cname ("IS_")));
ctype_check.add_argument (new CCodeIdentifier (var_name));
......
/* valadbusbindingprovider.vala
*
* Copyright (C) 2007 Jürg Billeter
*
* 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 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:
* Jürg Billeter <j@bitron.ch>
*/
using GLib;
using Gee;
/**
* Dynamic binding provider for DBus objects.
*/
public class Vala.DBusBindingProvider : BindingProvider {
public CodeContext context {
set {
_context = value;
string_type = (DataType) _context.root.scope.lookup ("string");
var dbus_ns = _context.root.scope.lookup ("DBus");
if (dbus_ns != null) {
connection_type = (DataType) dbus_ns.scope.lookup ("Connection");
dbus_error_type = (DataType) dbus_ns.scope.lookup ("Error");
}
}
}
private CodeContext _context;
private DataType string_type;
private DataType connection_type;
private DataType dbus_error_type;
private Collection<Symbol> symbols = new ArrayList<Symbol> ();
public DBusBindingProvider () {
}
public Symbol get_binding (MemberAccess! ma) {
if (connection_type != null && ma.inner != null && ma.inner.static_type.data_type == connection_type) {
var type_args = ma.get_type_arguments ();
if (type_args.size != 1) {
return null;
}
Iterator<TypeReference> type_args_it = type_args.iterator ();
type_args_it.next ();
var ret_type = new TypeReference ();
ret_type.data_type = type_args_it.get ().data_type;
if (!is_dbus_interface (ret_type.data_type)) {
return null;
}
var m = new Method ("get_object", ret_type, ma.source_reference);
m.set_cname ("dbus_g_proxy_new_for_name");
m.add_cheader_filename ("dbus/dbus-glib.h");
m.access = MemberAccessibility.PUBLIC;
var string_type_ref = new TypeReference ();
string_type_ref.data_type = string_type;
m.add_parameter (new FormalParameter ("name", string_type_ref));
m.add_parameter (new FormalParameter ("path", string_type_ref));
symbols.add (m);
return m;
} else if (ma.inner != null && is_dbus_interface (ma.inner.static_type.data_type)) {
if (ma.parent_node is InvocationExpression) {
var expr = (InvocationExpression) ma.parent_node;
var ret_type = new TypeReference ();
if (expr.expected_type != null) {
ret_type.data_type = expr.expected_type.data_type;
ret_type.transfers_ownership = ret_type.data_type.is_reference_type ();
}
var m = new DBusMethod (ma.member_name, ret_type, ma.source_reference);
if (expr.expected_type != null) {
var error_type = new TypeReference ();
error_type.data_type = dbus_error_type;
m.add_error_domain (error_type);
}
m.access = MemberAccessibility.PUBLIC;
m.add_parameter (new FormalParameter.with_ellipsis ());
symbols.add (m);
return m;
} else if (ma.parent_node is Assignment) {
var a = (Assignment) ma.parent_node;
if (a.left != ma) {
return null;
}
var s = new DBusSignal (ma.member_name, new TypeReference (), ma.source_reference);
s.access = MemberAccessibility.PUBLIC;
symbols.add (s);
return s;
}
}
return null;
}
private bool is_dbus_interface (DataType! t) {
if (!(t is Interface)) {
return false;
}
return (t.get_attribute ("DBusInterface") != null);
}
}
/* valadbusmethod.vala
*
* Copyright (C) 2007 Jürg Billeter
*
* 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 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:
* Jürg Billeter <j@bitron.ch>
*/
using GLib;
using Gee;
/**
* Represents a dynamic bound DBus method.
*/
public class Vala.DBusMethod : Method {
public DBusMethod (construct string name, construct TypeReference return_type, construct SourceReference source_reference = null) {
}
public override Collection<string> get_cheader_filenames () {
return new ReadOnlyCollection<string> ();
}
public override string! get_default_cname () {
return "dbus_g_proxy_begin_call";
}
}
/* valadbussignal.vala
*
* Copyright (C) 2007 Jürg Billeter
*
* 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 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