gobject-introspection r773 - in trunk: . girepository giscanner tests/repository tests/scanner



Author: jobi
Date: Tue Oct 21 17:04:11 2008
New Revision: 773
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=773&view=rev

Log:
2008-10-21  Johan Bilien  <jobi via ecp fr>

	Bug 557241 â "throws" flag for functions

	* tests/scanner/drawable-1.0-expected.gir,
	tests/scanner/drawable-injected-1.0-expected.gir,
	tests/scanner/drawable.[ch]: add simple test for throwing
	function (has GError ** as last argument)

	* giscanner/ast.py: add a 'throws' flag to Function
	* giscanner/glibtransformer.py: if a function's last paramerter is
	a GError, set the 'throws' flag and remove that parameter
	* giscanner/girwriter.py: write out the 'throws' attribute
	* giscanner/girparser.py: support parsing the 'throws' attribute

	* tests/repository/gitestthrows.c: add a simple test to check the
	throws flag in a typelib and invoke the function

	* girepository/ginfo.c, girepository/girnode.[ch],
	girepository/girnode.h, girepository/girparser.c,
	girepository/girepository.h: Add and parse the GI_FUNCTION_THROWS flag

	* girepository/ginvoke.c: if a function throws, add a GError as last
	arguments, and propagate the error to the invoker.



Added:
   trunk/tests/repository/gitestthrows.c
Modified:
   trunk/ChangeLog
   trunk/girepository/ginfo.c
   trunk/girepository/ginvoke.c
   trunk/girepository/girepository.h
   trunk/girepository/girnode.c
   trunk/girepository/girnode.h
   trunk/girepository/girparser.c
   trunk/girepository/gtypelib.h
   trunk/giscanner/ast.py
   trunk/giscanner/girparser.py
   trunk/giscanner/girwriter.py
   trunk/giscanner/glibtransformer.py
   trunk/tests/repository/Makefile.am
   trunk/tests/scanner/drawable-1.0-expected.gir
   trunk/tests/scanner/drawable-injected-1.0-expected.gir
   trunk/tests/scanner/drawable.c
   trunk/tests/scanner/drawable.h

Modified: trunk/girepository/ginfo.c
==============================================================================
--- trunk/girepository/ginfo.c	(original)
+++ trunk/girepository/ginfo.c	Tue Oct 21 17:04:11 2008
@@ -492,6 +492,9 @@
   if (blob->wraps_vfunc)
     flags = flags | GI_FUNCTION_WRAPS_VFUNC;
 
+  if (blob->throws)
+    flags = flags | GI_FUNCTION_THROWS;
+
   return flags;
 }
 

Modified: trunk/girepository/ginvoke.c
==============================================================================
--- trunk/girepository/ginvoke.c	(original)
+++ trunk/girepository/ginvoke.c	Tue Oct 21 17:04:11 2008
@@ -159,9 +159,11 @@
   GITypeInfo *tinfo;
   GIArgInfo *ainfo;
   gboolean is_method;
+  gboolean throws;
   gint n_args, n_invoke_args, in_pos, out_pos, i;
   gpointer *args;
   gboolean success = FALSE;
+  GError *local_error;
 
   symbol = g_function_info_get_symbol (info);
 
@@ -178,6 +180,7 @@
 
   is_method = (g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0
     && (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0;
+  throws = g_function_info_get_flags (info) & GI_FUNCTION_THROWS;
 
   tinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
   rtype = get_ffi_type (tinfo);
@@ -202,6 +205,11 @@
     }
   else
     n_invoke_args = n_args;
+
+  if (throws)
+    /* Add an argument for the GError */
+    n_invoke_args ++;
+
   atypes = g_alloca (sizeof (ffi_type*) * n_invoke_args);
   args = g_alloca (sizeof (gpointer) * n_invoke_args);
   
@@ -279,6 +287,15 @@
 	}
       g_base_info_unref ((GIBaseInfo *)ainfo);
     }
+
+  local_error = NULL;
+  if (throws)
+    {
+      gpointer address = &local_error;
+      args[n_invoke_args - 1] = &address;
+      atypes[n_invoke_args - 1] = &ffi_type_pointer;
+    }
+
   if (in_pos < n_in_args)
     {
       g_set_error (error,
@@ -301,7 +318,15 @@
 
   ffi_call (&cif, func, return_value, args);
 
-  success = TRUE;
+  if (local_error)
+    {
+      g_propagate_error (error, local_error);
+      success = FALSE;
+    }
+  else
+    {
+      success = TRUE;
+    }
  out:
   return success;
 }

Modified: trunk/girepository/girepository.h
==============================================================================
--- trunk/girepository/girepository.h	(original)
+++ trunk/girepository/girepository.h	Tue Oct 21 17:04:11 2008
@@ -190,7 +190,8 @@
   GI_FUNCTION_IS_CONSTRUCTOR = 1 << 1,
   GI_FUNCTION_IS_GETTER      = 1 << 2,
   GI_FUNCTION_IS_SETTER      = 1 << 3,
-  GI_FUNCTION_WRAPS_VFUNC    = 1 << 4
+  GI_FUNCTION_WRAPS_VFUNC    = 1 << 4,
+  GI_FUNCTION_THROWS         = 1 << 5
 } GIFunctionInfoFlags;
 
 const gchar *           g_function_info_get_symbol     (GIFunctionInfo *info);

Modified: trunk/girepository/girnode.c
==============================================================================
--- trunk/girepository/girnode.c	(original)
+++ trunk/girepository/girnode.c	Tue Oct 21 17:04:11 2008
@@ -1477,7 +1477,7 @@
 	blob->getter = function->is_getter;
 	blob->constructor = function->is_constructor;
 	blob->wraps_vfunc = function->wraps_vfunc;
-	blob->reserved = 0;
+	blob->throws = function->throws;
 	blob->index = 0;
 	blob->name = write_string (node->name, strings, data, offset2);
 	blob->symbol = write_string (function->symbol, strings, data, offset2);

Modified: trunk/girepository/girnode.h
==============================================================================
--- trunk/girepository/girnode.h	(original)
+++ trunk/girepository/girnode.h	Tue Oct 21 17:04:11 2008
@@ -92,6 +92,7 @@
   gboolean is_getter;
   gboolean is_constructor;
   gboolean wraps_vfunc;
+  gboolean throws;
 
   gchar *symbol;
 

Modified: trunk/girepository/girparser.c
==============================================================================
--- trunk/girepository/girparser.c	(original)
+++ trunk/girepository/girparser.c	Tue Oct 21 17:04:11 2008
@@ -527,6 +527,7 @@
   const gchar *name;
   const gchar *symbol;
   const gchar *deprecated;
+  const gchar *throws;
   GIrNodeFunction *function;
   gboolean found = FALSE;
   
@@ -557,6 +558,7 @@
   name = find_attribute ("name", attribute_names, attribute_values);
   symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+  throws = find_attribute ("throws", attribute_names, attribute_values);
       
   if (name == NULL)
     {
@@ -598,7 +600,12 @@
       if (strcmp (element_name, "callback") == 0)
 	((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
     }
-	  
+
+  if (throws && strcmp (throws, "1") == 0)
+    function->throws = TRUE;
+  else
+    function->throws = FALSE;
+
   if (ctx->current_node == NULL)
     {
       ctx->current_module->entries = 

Modified: trunk/girepository/gtypelib.h
==============================================================================
--- trunk/girepository/gtypelib.h	(original)
+++ trunk/girepository/gtypelib.h	Tue Oct 21 17:04:11 2008
@@ -166,11 +166,11 @@
   guint16 blob_type;  /* 1 */
 
   guint16 deprecated  : 1;
-  guint16 setter      : 1; 
+  guint16 setter      : 1;
   guint16 getter      : 1;
   guint16 constructor : 1;
   guint16 wraps_vfunc : 1;
-  guint16 reserved    : 1;
+  guint16 throws      : 1;
   guint16 index       :10;
 
   guint32 name;

Modified: trunk/giscanner/ast.py
==============================================================================
--- trunk/giscanner/ast.py	(original)
+++ trunk/giscanner/ast.py	Tue Oct 21 17:04:11 2008
@@ -188,11 +188,12 @@
 
 class Function(Node):
 
-    def __init__(self, name, retval, parameters, symbol):
+    def __init__(self, name, retval, parameters, symbol, throws=None):
         Node.__init__(self, name)
         self.retval = retval
         self.parameters = parameters
         self.symbol = symbol
+        self.throws = not not throws
 
     def __repr__(self):
         return '%s(%r, %r, %r)' % (self.__class__.__name__,

Modified: trunk/giscanner/girparser.py
==============================================================================
--- trunk/giscanner/girparser.py	(original)
+++ trunk/giscanner/girparser.py	Tue Oct 21 17:04:11 2008
@@ -178,7 +178,8 @@
                          node.attrib.get(_cns('type')))
         else:
             identifier = node.attrib.get(_cns('identifier'))
-            return klass(name, retval, parameters, identifier)
+            throws = (node.attrib.get('throws') == '1')
+            return klass(name, retval, parameters, identifier, throws)
 
     def _parse_struct(self, node):
         if _glibns('type-name') in node.attrib:

Modified: trunk/giscanner/girwriter.py
==============================================================================
--- trunk/giscanner/girwriter.py	(original)
+++ trunk/giscanner/girwriter.py	Tue Oct 21 17:04:11 2008
@@ -95,6 +95,10 @@
                 attrs.append(('deprecated-version',
                               node.deprecated_version))
 
+    def _append_throws(self, func, attrs):
+        if func.throws:
+            attrs.append(('throws', '1'))
+
     def _write_alias(self, alias):
         attrs = [('name', alias.name), ('target', alias.target)]
         if alias.ctype is not None:
@@ -105,6 +109,7 @@
         attrs = [('name', func.name),
                  ('c:identifier', func.symbol)]
         self._append_deprecated(func, attrs)
+        self._append_throws(func, attrs)
         with self.tagcontext(tag_name, attrs):
             self._write_return_type(func.retval)
             self._write_parameters(func.parameters)

Modified: trunk/giscanner/glibtransformer.py
==============================================================================
--- trunk/giscanner/glibtransformer.py	(original)
+++ trunk/giscanner/glibtransformer.py	Tue Oct 21 17:04:11 2008
@@ -790,9 +790,23 @@
               and param.type.name == 'Object'))):
             param.transfer = 'full'
 
+    def _adjust_throws(self, func):
+        if func.parameters == []:
+            return
+
+        last_param = func.parameters.pop()
+
+        if (last_param.type.name == 'GLib.Error' or
+            (self._namespace_name == 'GLib' and
+             last_param.type.name == 'Error')):
+            func.throws = True
+        else:
+            func.parameters.append(last_param)
+
     def _resolve_function(self, func):
         self._resolve_parameters(func.parameters)
         func.retval.type = self._resolve_param_type(func.retval.type)
+        self._adjust_throws(func)
         self._adjust_transfer(func.retval)
 
     def _resolve_parameters(self, parameters):

Modified: trunk/tests/repository/Makefile.am
==============================================================================
--- trunk/tests/repository/Makefile.am	(original)
+++ trunk/tests/repository/Makefile.am	Tue Oct 21 17:04:11 2008
@@ -2,11 +2,15 @@
 AM_LDFLAGS = -module -avoid-version
 LIBS = $(GOBJECT_LIBS)
 
-noinst_PROGRAMS = gitestrepo
+noinst_PROGRAMS = gitestrepo gitestthrows
 
 gitestrepo_SOURCES = $(srcdir)/gitestrepo.c
 gitestrepo_CPPFLAGS = $(GIREPO_CFLAGS) -I$(top_srcdir)/girepository
 gitestrepo_LDADD = $(GIREPO_LIBS) $(top_builddir)/girepository/libgirepository.la
 
-TESTS = gitestrepo
-TESTS_ENVIRONMENT=env top_builddir="$(top_builddir)" $(DEBUG)
\ No newline at end of file
+gitestthrows_SOURCES = $(srcdir)/gitestthrows.c
+gitestthrows_CPPFLAGS = $(GIREPO_CFLAGS) -I$(top_srcdir)/girepository
+gitestthrows_LDADD = $(GIREPO_LIBS) $(top_builddir)/girepository/libgirepository.la
+
+TESTS = gitestrepo gitestthrows
+TESTS_ENVIRONMENT=env top_builddir="$(top_builddir)" $(DEBUG)

Added: trunk/tests/repository/gitestthrows.c
==============================================================================
--- (empty file)
+++ trunk/tests/repository/gitestthrows.c	Tue Oct 21 17:04:11 2008
@@ -0,0 +1,55 @@
+
+#include "girepository.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+main(int argc, char **argv)
+{
+  GIRepository *repo;
+  gboolean ret;
+  GIBaseInfo *info;
+  char *girdir;
+  GArgument in_arg[1];
+  GArgument ret_arg;
+  GError *error;
+  gboolean invoke_return;
+
+  g_type_init ();
+
+  repo = g_irepository_get_default ();
+
+  girdir = g_build_filename (g_getenv ("top_builddir"), "gir", NULL);
+  g_irepository_prepend_search_path (girdir);
+  g_free (girdir);
+
+  error = NULL;
+  ret = g_irepository_require (repo, "GLib", NULL, 0, &error);
+  g_assert (ret);
+  g_assert (error == NULL);
+
+  info = g_irepository_find_by_name (repo, "GLib", "file_read_link");
+  g_assert (info != NULL);
+  g_assert (g_base_info_get_type (info) == GI_INFO_TYPE_FUNCTION);
+  g_assert (g_function_info_get_flags ((GIFunctionInfo *)info) & GI_FUNCTION_THROWS);
+
+  in_arg[0].v_string = g_strdup ("non-existent-file/hope");
+  error = NULL;
+  invoke_return = g_function_info_invoke ((GIFunctionInfo *)info,
+                                          in_arg,
+                                          1,
+                                          NULL,
+                                          0,
+                                          &ret_arg,
+                                          &error);
+  g_free(in_arg[0].v_string);
+
+  g_assert (invoke_return == FALSE);
+  g_assert (error != NULL);
+  g_assert (error->domain == G_FILE_ERROR);
+  g_assert (error->code == G_FILE_ERROR_NOENT);
+
+  exit(0);
+}

Modified: trunk/tests/scanner/drawable-1.0-expected.gir
==============================================================================
--- trunk/tests/scanner/drawable-1.0-expected.gir	(original)
+++ trunk/tests/scanner/drawable-1.0-expected.gir	Tue Oct 21 17:04:11 2008
@@ -49,6 +49,18 @@
           </parameter>
         </parameters>
       </method>
+      <method name="do_foo_maybe_throw"
+              c:identifier="test_drawable_do_foo_maybe_throw"
+              throws="1">
+        <return-value>
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <parameter name="x">
+            <type name="int" c:type="int"/>
+          </parameter>
+        </parameters>
+      </method>
       <field name="parent_instance">
         <type name="GObject.Object" c:type="GObject"/>
       </field>

Modified: trunk/tests/scanner/drawable-injected-1.0-expected.gir
==============================================================================
--- trunk/tests/scanner/drawable-injected-1.0-expected.gir	(original)
+++ trunk/tests/scanner/drawable-injected-1.0-expected.gir	Tue Oct 21 17:04:11 2008
@@ -49,6 +49,18 @@
           </parameter>
         </parameters>
       </method>
+      <method name="do_foo_maybe_throw"
+              c:identifier="test_drawable_do_foo_maybe_throw"
+              throws="1">
+        <return-value>
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <parameter name="x">
+            <type name="int" c:type="int"/>
+          </parameter>
+        </parameters>
+      </method>
       <method name="get_width" c:identifier="girepo_test_drawable_get_width">
         <return-value>
           <type name="int" c:type="gint"/>

Modified: trunk/tests/scanner/drawable.c
==============================================================================
--- trunk/tests/scanner/drawable.c	(original)
+++ trunk/tests/scanner/drawable.c	Tue Oct 21 17:04:11 2008
@@ -33,3 +33,10 @@
   *width = 42;
   *height = 42;
 }
+
+void
+test_drawable_do_foo_maybe_throw (TestDrawable *drawable, int x, GError **error)
+{
+  if (x != 42)
+    g_set_error(error, 0, 12, "The answer should be 42!");
+}

Modified: trunk/tests/scanner/drawable.h
==============================================================================
--- trunk/tests/scanner/drawable.h	(original)
+++ trunk/tests/scanner/drawable.h	Tue Oct 21 17:04:11 2008
@@ -21,6 +21,7 @@
 void test_drawable_do_foo (TestDrawable *drawable, int x);
 void test_drawable_get_origin (TestDrawable *drawable, int *x, int *y);
 void test_drawable_get_size (TestDrawable *drawable, guint *width, guint *height);
+void test_drawable_do_foo_maybe_throw (TestDrawable *drawable, int x, GError **error);
 
 struct _TestPixmapObjectClass
 {



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