summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Regier <garrett.regier@riftio.com>2015-06-03 05:24:21 -0700
committerGarrett Regier <garrett.regier@riftio.com>2015-06-21 13:01:25 -0700
commit0aef39a20bd229170871edda862ade7d24ff7edd (patch)
tree417e9faa0edc487d577b5c3e04d6feaa369c8766
parent5d47bb3a72e12150d7862d602d5032cf920c3543 (diff)
downloadgobject-introspection-0aef39a20bd229170871edda862ade7d24ff7edd.tar.gz
girepository: Support GError exceptions on callbacks
Generalize "throws" attribute to SignatureBlob which can be used by all callable blob types. Keep FunctionBlob and VFuncBlob throw attributes around and functional for compatibility. Refactor girwriter.c to write out throws attribute for all callable types. Based on a patch by Simon Feltman. https://bugzilla.gnome.org/show_bug.cgi?id=729543
-rw-r--r--girepository/gicallableinfo.c11
-rw-r--r--girepository/girnode.c7
-rw-r--r--girepository/girwriter.c11
-rw-r--r--girepository/gitypelib-internal.h9
-rw-r--r--tests/repository/gitestthrows.c81
5 files changed, 106 insertions, 13 deletions
diff --git a/girepository/gicallableinfo.c b/girepository/gicallableinfo.c
index 7e0ec776..8360bbf4 100644
--- a/girepository/gicallableinfo.c
+++ b/girepository/gicallableinfo.c
@@ -96,6 +96,17 @@ gboolean
g_callable_info_can_throw_gerror (GICallableInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo*)info;
+ SignatureBlob *signature;
+
+ signature = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
+ if (signature->throws)
+ return TRUE;
+
+ /* Functions and VFuncs store "throws" in their own blobs.
+ * This info was additionally added to the SignatureBlob
+ * to support the other callables. For Functions and VFuncs,
+ * also check their legacy flag for compatibility.
+ */
switch (rinfo->type) {
case GI_INFO_TYPE_FUNCTION:
{
diff --git a/girepository/girnode.c b/girepository/girnode.c
index a7a77e31..d0a18a31 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -1641,7 +1641,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob->getter = function->is_getter;
blob->constructor = function->is_constructor;
blob->wraps_vfunc = function->wraps_vfunc;
- blob->throws = function->throws;
+ blob->throws = function->throws; /* Deprecated. Also stored in SignatureBlob. */
blob->index = 0;
blob->name = _g_ir_write_string (node->name, strings, data, offset2);
blob->symbol = _g_ir_write_string (function->symbol, strings, data, offset2);
@@ -1667,6 +1667,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob2->instance_transfer_ownership = function->instance_transfer_full;
blob2->reserved = 0;
blob2->n_arguments = n;
+ blob2->throws = function->throws;
signature += 4;
@@ -1708,6 +1709,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob2->caller_owns_return_container = function->result->shallow_transfer;
blob2->reserved = 0;
blob2->n_arguments = n;
+ blob2->throws = function->throws;
signature += 4;
@@ -1797,7 +1799,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob->must_be_implemented = 0; /* FIXME */
blob->must_not_be_implemented = 0; /* FIXME */
blob->class_closure = 0; /* FIXME */
- blob->throws = vfunc->throws;
+ blob->throws = vfunc->throws; /* Deprecated. Also stored in SignatureBlob. */
blob->reserved = 0;
if (vfunc->invoker)
@@ -1825,6 +1827,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob2->instance_transfer_ownership = vfunc->instance_transfer_full;
blob2->reserved = 0;
blob2->n_arguments = n;
+ blob2->throws = vfunc->throws;
signature += 4;
diff --git a/girepository/girwriter.c b/girepository/girwriter.c
index 01f5f506..4bc7fc96 100644
--- a/girepository/girwriter.c
+++ b/girepository/girwriter.c
@@ -454,6 +454,9 @@ write_callable_info (const gchar *namespace,
GITypeInfo *type;
gint i;
+ if (g_callable_info_can_throw_gerror (info))
+ xml_printf (file, " throws=\"1\"");
+
write_attributes (file, (GIBaseInfo*) info);
type = g_callable_info_get_return_type (info);
@@ -558,13 +561,11 @@ write_function_info (const gchar *namespace,
const gchar *name;
const gchar *symbol;
gboolean deprecated;
- gboolean throws;
flags = g_function_info_get_flags (info);
name = g_base_info_get_name ((GIBaseInfo *)info);
symbol = g_function_info_get_symbol (info);
deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
- throws = flags & GI_FUNCTION_THROWS;
if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
tag = "constructor";
@@ -585,9 +586,6 @@ write_function_info (const gchar *namespace,
if (deprecated)
xml_printf (file, " deprecated=\"1\"");
- if (throws)
- xml_printf (file, " throws=\"1\"");
-
write_callable_info (namespace, (GICallableInfo*)info, file);
xml_end_element (file, tag);
}
@@ -914,9 +912,6 @@ write_vfunc_info (const gchar *namespace,
else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
xml_printf (file, " override=\"never\"");
- if (flags & GI_VFUNC_THROWS)
- xml_printf (file, " throws=\"1\"");
-
xml_printf (file, " offset=\"%d\"", offset);
if (invoker)
diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h
index e50ccac4..5ccff719 100644
--- a/girepository/gitypelib-internal.h
+++ b/girepository/gitypelib-internal.h
@@ -467,6 +467,8 @@ typedef struct {
* be skipped.
* @instance_transfer_ownership: When calling, the function assumes ownership of
* the instance parameter.
+ * @throws: Denotes the signature takes an additional #GError argument beyond
+ * the annotated arguments.
* @reserved: Reserved for future use.
* @n_arguments: The number of arguments that this function expects, also the
* length of the array of ArgBlobs.
@@ -482,7 +484,8 @@ typedef struct {
guint16 caller_owns_return_container : 1;
guint16 skip_return : 1;
guint16 instance_transfer_ownership : 1;
- guint16 reserved :11;
+ guint16 throws : 1;
+ guint16 reserved :10;
guint16 n_arguments;
@@ -522,7 +525,7 @@ typedef struct {
* @constructor: The function acts as a constructor for the object it is
* contained in.
* @wraps_vfunc: The function is a simple wrapper for a virtual function.
- * @throws: TODO
+ * @throws: (deprecated): This is now additionally stored in the #SignatureBlob.
* @index: Index of the property that this function is a setter or getter of
* in the array of properties of the containing interface, or index
* of the virtual function that this function wraps.
@@ -990,7 +993,7 @@ typedef struct {
* virtual function.
* @class_closure: Set if this virtual function is the class closure of a
* signal.
- * @throws: TODO
+ * @throws: (deprecated): This is now additionally stored in the #SignatureBlob.
* @reserved: Reserved for future use.
* @signal: The index of the signal in the list of signals of the object or
* interface to which this virtual function belongs.
diff --git a/tests/repository/gitestthrows.c b/tests/repository/gitestthrows.c
index 17694bfb..826ed414 100644
--- a/tests/repository/gitestthrows.c
+++ b/tests/repository/gitestthrows.c
@@ -42,12 +42,93 @@ test_invoke_gerror (void)
g_assert (error->code == G_FILE_ERROR_NOENT);
}
+static void
+test_vfunc_can_throw_gerror (void)
+{
+ GIRepository *repo;
+ GITypelib *ret;
+ GIBaseInfo *object_info;
+ GIFunctionInfo *invoker_info;
+ GIVFuncInfo *vfunc_info;
+ GError *error = NULL;
+
+ repo = g_irepository_get_default ();
+
+ ret = g_irepository_require (repo, "GIMarshallingTests", NULL, 0, &error);
+ g_assert_nonnull (ret);
+ g_assert_no_error (error);
+
+ object_info = g_irepository_find_by_name (repo, "GIMarshallingTests", "Object");
+ g_assert_nonnull (object_info);
+ g_assert (g_base_info_get_type (object_info) == GI_INFO_TYPE_OBJECT);
+
+ invoker_info = g_object_info_find_method ((GIObjectInfo *)object_info,
+ "vfunc_meth_with_error");
+ g_assert_nonnull (invoker_info);
+ g_assert (g_function_info_get_flags (invoker_info) & GI_FUNCTION_THROWS);
+ g_assert (g_callable_info_can_throw_gerror ((GICallableInfo *)invoker_info));
+
+ vfunc_info = g_object_info_find_vfunc ((GIObjectInfo *)object_info,
+ "vfunc_meth_with_err");
+ g_assert_nonnull (vfunc_info);
+ g_assert (g_vfunc_info_get_flags (vfunc_info) & GI_VFUNC_THROWS);
+ g_assert (g_callable_info_can_throw_gerror ((GICallableInfo *)vfunc_info));
+
+ g_base_info_unref (vfunc_info);
+ g_base_info_unref (invoker_info);
+ g_base_info_unref (object_info);
+}
+
+static void
+test_callback_can_throw_gerror (void)
+{
+ GIRepository *repo;
+ GITypelib *ret;
+ GIStructInfo *class_info;
+ GIFieldInfo *field_info;
+ GITypeInfo *field_type;
+ GICallbackInfo *callback_info;
+ GError *error = NULL;
+
+ repo = g_irepository_get_default ();
+
+ ret = g_irepository_require (repo, "GIMarshallingTests", NULL, 0, &error);
+ g_assert_nonnull (ret);
+ g_assert_no_error (error);
+
+ class_info = g_irepository_find_by_name (repo, "GIMarshallingTests", "ObjectClass");
+ g_assert_nonnull (class_info);
+ g_assert (g_base_info_get_type (class_info) == GI_INFO_TYPE_STRUCT);
+
+ field_info = g_struct_info_find_field (class_info, "vfunc_meth_with_err");
+ g_assert_nonnull (field_info);
+ g_assert (g_base_info_get_type (field_info) == GI_INFO_TYPE_FIELD);
+
+ field_type = g_field_info_get_type (field_info);
+ g_assert_nonnull (field_type);
+ g_assert (g_base_info_get_type (field_type) == GI_INFO_TYPE_TYPE);
+ g_assert (g_type_info_get_tag (field_type) == GI_TYPE_TAG_INTERFACE);
+
+ callback_info = g_type_info_get_interface (field_type);
+ g_assert_nonnull (callback_info);
+ g_assert (g_callable_info_can_throw_gerror ((GICallableInfo *)callback_info));
+
+ g_base_info_unref (callback_info);
+ g_base_info_unref (field_type);
+ g_base_info_unref (field_info);
+ g_base_info_unref (class_info);
+}
+
int
main(int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/girepository/throws/invoke-gerror", test_invoke_gerror);
+ g_test_add_func ("/girepository/throws/vfunc-can-throw-gerror",
+ test_vfunc_can_throw_gerror);
+ g_test_add_func ("/girepository/throws/callback-can-throw-gerror",
+ test_callback_can_throw_gerror);
return g_test_run ();
}