summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2008-08-13 16:10:09 +0000
committerColin Walters <walters@src.gnome.org>2008-08-13 16:10:09 +0000
commit5ec7b60569fce361c5f78a042aebc5ad570dfb40 (patch)
tree0d4aa8846a9ecfd6e0dbedb3e54029739058bd6a
parent316f0ee0af07331e07624e769edfc11e457cd838 (diff)
downloadgobject-introspection-5ec7b60569fce361c5f78a042aebc5ad570dfb40.tar.gz
Record typedefs as <alias> elements. Also attempt to look up types in
2008-08-12 Colin Walters <walters@verbum.org> * giscanner/transformer.py: Record typedefs as <alias> elements. Also attempt to look up types in external namespaces. * giscanner/girwriter.py: Write them. * giscanner/glibtransformer.py: Rework resolver using real instanceof checks. Resolve interface methods and properties. * tests/scanner/foo-object.h: Add a method with typedef. * tests/scanner/Foo-expected.gir: Update. * girepository/girnode.c: Debug tweaks. * girepository/girparser.c: Make a first pass through the XML where we record all the aliases. This lets us resolve them as we go through the second pass. * gir/Makefile.am: Don't install gobject-2.0.gir; we want that to come from gir-repository. svn path=/trunk/; revision=355
-rw-r--r--ChangeLog25
-rw-r--r--gir/Makefile.am4
-rw-r--r--girepository/girnode.c6
-rw-r--r--girepository/girparser.c144
-rw-r--r--giscanner/ast.py11
-rw-r--r--giscanner/girwriter.py10
-rw-r--r--giscanner/glibtransformer.py33
-rw-r--r--giscanner/transformer.py14
-rw-r--r--tests/scanner/Foo-expected.gir23
-rw-r--r--tests/scanner/foo-object.h8
10 files changed, 250 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 68faefca..be93fb15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
2008-08-12 Colin Walters <walters@verbum.org>
+ * giscanner/transformer.py: Record typedefs as <alias> elements.
+ Also attempt to look up types in external namespaces.
+ * giscanner/girwriter.py: Write them.
+ * giscanner/glibtransformer.py: Rework resolver using real instanceof
+ checks. Resolve interface methods and properties.
+ * tests/scanner/foo-object.h: Add a method with typedef.
+ * tests/scanner/Foo-expected.gir: Update.
+ * girepository/girnode.c: Debug tweaks.
+ * girepository/girparser.c: Make a first pass through the XML where we
+ record all the aliases. This lets us resolve them as we go through the
+ second pass.
+ * gir/Makefile.am: Don't install gobject-2.0.gir; we want that to come
+ from gir-repository.
+
+2008-08-12 Colin Walters <walters@verbum.org>
+
+ * giscanner/glibtransformer.py: Resolve typedefs (e.g. AtkAttributeSet -> GSList).
+ Correctly do subclasseing in 2nd pass resolution. Handle callbacks in structure
+ fields.
+ * giscanner/transformer.py: Record typedefs and expose public API for resolving
+ them.
+ * tests/scanner/Foo-expected.gir: Fix expected callback types.
+
+2008-08-12 Colin Walters <walters@verbum.org>
+
* giscanner/glibtransformer.py: Also transform object properties.
2008-08-12 Colin Walters <walters@verbum.org>
diff --git a/gir/Makefile.am b/gir/Makefile.am
index dce5152e..97e3c2d6 100644
--- a/gir/Makefile.am
+++ b/gir/Makefile.am
@@ -1,2 +1,2 @@
-girdir = $(datadir)/gir
-dist_gir_DATA = gobject-2.0.gir
+#girdir = $(datadir)/gir
+#dist_gir_DATA = gobject-2.0.gir
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 2aeba30e..7961da37 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -880,7 +880,7 @@ g_ir_node_get_full_size_internal (GIrNode *parent, GIrNode *node)
size = 0;
}
- g_debug ("node %p type '%s' full size %d", node,
+ g_debug ("node '%s' %p type '%s' full size %d", node->name, node,
g_ir_node_type_to_string (node->type), size);
return size;
@@ -2173,8 +2173,8 @@ g_ir_node_build_typelib (GIrNode *node,
g_assert_not_reached ();
}
- g_debug ("node %p type '%s', offset %d -> %d, offset2 %d -> %d",
- node, g_ir_node_type_to_string (node->type),
+ g_debug ("node '%s' %p type '%s', offset %d -> %d, offset2 %d -> %d",
+ node->name, node, g_ir_node_type_to_string (node->type),
old_offset, *offset, old_offset2, *offset2);
if (*offset2 - old_offset2 + *offset - old_offset > g_ir_node_get_full_size (node))
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 0bc8af39..2e875d7f 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -53,7 +53,8 @@ typedef enum
STATE_STRUCT_FIELD,
STATE_ERRORDOMAIN,
STATE_UNION,
- STATE_CONSTANT
+ STATE_CONSTANT,
+ STATE_ALIAS, /* 25 */
} ParseState;
typedef struct _ParseContext ParseContext;
@@ -63,6 +64,7 @@ struct _ParseContext
ParseState prev_state;
GList *modules;
+ GHashTable *aliases;
GIrModule *current_module;
GIrNode *current_node;
@@ -123,6 +125,18 @@ state_switch (ParseContext *ctx, ParseState newstate)
ctx->state = newstate;
}
+static GIrNodeType * parse_type_internal (gchar *str, gchar **rest);
+
+static GIrNodeType *
+create_pointer ()
+{
+ char *pointer = g_strdup ("any");
+ char *pointer_rest;
+ GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest);
+ g_free (pointer);
+ return ret;
+}
+
static GIrNodeType *
parse_type_internal (gchar *str, gchar **rest)
{
@@ -258,6 +272,10 @@ parse_type_internal (gchar *str, gchar **rest)
goto error;
(*rest)++;
}
+ else
+ {
+ type->parameter_type1 = create_pointer ();
+ }
}
else if (g_str_has_prefix (*rest, "GHashTable"))
{
@@ -290,6 +308,12 @@ parse_type_internal (gchar *str, gchar **rest)
goto error;
(*rest)++;
}
+ else
+ {
+ type->parameter_type1 = create_pointer ();
+ type->parameter_type2 = create_pointer ();
+ }
+
}
else if (g_str_has_prefix (*rest, "GError"))
{
@@ -396,13 +420,28 @@ parse_type_internal (gchar *str, gchar **rest)
return NULL;
}
+static const char *
+resolve_aliases (ParseContext *ctx, const gchar *type)
+{
+ gpointer orig;
+ gpointer value;
+
+ while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value))
+ {
+ g_debug ("Resolved: %s => %s", type, value);
+ type = value;
+ }
+ return type;
+}
+
static GIrNodeType *
-parse_type (const gchar *type)
+parse_type (ParseContext *ctx, const gchar *type)
{
gchar *str;
gchar *rest;
GIrNodeType *node;
+ type = resolve_aliases (ctx, type);
str = g_strdup (type);
node = parse_type_internal (str, &rest);
g_free (str);
@@ -849,6 +888,34 @@ start_field (GMarkupParseContext *context,
}
static gboolean
+start_alias (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ const gchar *name;
+ const gchar *target;
+ const gchar *type;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ if (name == NULL) {
+ MISSING_ATTRIBUTE (context, error, element_name, "name");
+ return FALSE;
+ }
+
+ target = find_attribute ("target", attribute_names, attribute_values);
+ if (name == NULL) {
+ MISSING_ATTRIBUTE (context, error, element_name, "target");
+ return FALSE;
+ }
+
+ g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
+ return TRUE;
+}
+
+static gboolean
start_enum (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
@@ -1075,7 +1142,7 @@ start_constant (GMarkupParseContext *context,
((GIrNode *)constant)->name = g_strdup (name);
constant->value = g_strdup (value);
- constant->type = parse_type (type);
+ constant->type = parse_type (ctx, type);
if (deprecated && strcmp (deprecated, "1") == 0)
constant->deprecated = TRUE;
@@ -1310,19 +1377,19 @@ start_type (GMarkupParseContext *context,
{
GIrNodeParam *param;
param = (GIrNodeParam *)ctx->current_typed;
- param->type = parse_type (name);
+ param->type = parse_type (ctx, name);
}
break;
case G_IR_NODE_FIELD:
{
GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
- field->type = parse_type (name);
+ field->type = parse_type (ctx, name);
}
break;
case G_IR_NODE_PROPERTY:
{
GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
- property->type = parse_type (name);
+ property->type = parse_type (ctx, name);
}
break;
default:
@@ -1661,7 +1728,7 @@ start_discriminator (GMarkupParseContext *context,
MISSING_ATTRIBUTE (context, error, element_name, "offset");
{
((GIrNodeUnion *)ctx->current_node)->discriminator_type
- = parse_type (type);
+ = parse_type (ctx, type);
((GIrNodeUnion *)ctx->current_node)->discriminator_offset
= atoi (offset);
}
@@ -1705,6 +1772,13 @@ start_element_handler (GMarkupParseContext *context,
switch (element_name[0])
{
+ case 'a':
+ if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
+ {
+ state_switch (ctx, STATE_ALIAS);
+ goto out;
+ }
+ break;
case 'b':
if (start_enum (context, element_name,
attribute_names, attribute_values,
@@ -2047,6 +2121,13 @@ end_element_handler (GMarkupParseContext *context,
}
break;
+ case STATE_ALIAS:
+ if (require_end_element (context, "alias", element_name, error))
+ {
+ state_switch (ctx, STATE_NAMESPACE);
+ }
+ break;
+
case STATE_FUNCTION_RETURN:
if (strcmp ("type", element_name) == 0)
break;
@@ -2262,6 +2343,44 @@ cleanup (GMarkupParseContext *context,
ctx->current_module = NULL;
}
+static void
+firstpass_start_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+
+ if (strcmp (element_name, "alias") == 0)
+ {
+ start_alias (context, element_name, attribute_names, attribute_values,
+ ctx, error);
+ }
+}
+
+static void
+firstpass_end_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+
+}
+
+
+static GMarkupParser firstpass_parser =
+{
+ firstpass_start_element_handler,
+ firstpass_end_element_handler,
+ NULL,
+ NULL,
+ NULL,
+};
+
+
static GMarkupParser parser =
{
start_element_handler,
@@ -2280,6 +2399,15 @@ g_ir_parse_string (const gchar *buffer,
GMarkupParseContext *context;
ctx.state = STATE_START;
+ ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
+
+ if (!g_markup_parse_context_parse (context, buffer, length, error))
+ goto out;
+
+ if (!g_markup_parse_context_end_parse (context, error))
+ goto out;
context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
if (!g_markup_parse_context_parse (context, buffer, length, error))
@@ -2289,6 +2417,8 @@ g_ir_parse_string (const gchar *buffer,
goto out;
out:
+
+ g_hash_table_destroy (ctx.aliases);
g_markup_parse_context_free (context);
diff --git a/giscanner/ast.py b/giscanner/ast.py
index a0955c10..93736f30 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -141,6 +141,17 @@ class Type(Node):
self.ctype = ctype
+class Alias(Node):
+
+ def __init__(self, name, target,ctype=None):
+ Node.__init__(self, name)
+ self.target = target
+ self.ctype = ctype
+
+ def __repr__(self):
+ return 'Alias(%r, %r)' % (self.name, self.target)
+
+
class Parameter(Node):
def __init__(self, name, typenode):
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 45d2b23c..427c04f5 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -21,7 +21,7 @@
from __future__ import with_statement
from .ast import (Callback, Class, Enum, Function, Interface, Member,
- Sequence, Struct)
+ Sequence, Struct, Alias)
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
GLibFlags, GLibObject, GLibInterface)
from .xmlwriter import XMLWriter
@@ -65,9 +65,17 @@ class GIRWriter(XMLWriter):
elif isinstance(node, Member):
# FIXME: atk_misc_instance singleton
pass
+ elif isinstance(node, Alias):
+ self._write_alias(node)
else:
print 'WRITER: Unhandled node', node
+ def _write_alias(self, alias):
+ attrs = [('name', alias.name), ('target', alias.target)]
+ if alias.ctype is not None:
+ attrs.append(('c:type', ntype.ctype))
+ self.write_tag('alias', attrs)
+
def _write_function(self, func, tag_name='function'):
attrs = [('name', func.name),
('c:identifier', func.symbol)]
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 43c1dea6..ceb98907 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -25,7 +25,7 @@ import sys
from . import cgobject
from .odict import odict
from .ast import (Callback, Enum, Function, Member, Namespace, Parameter,
- Property, Return, Sequence, Struct, Field, Type,
+ Property, Return, Sequence, Struct, Field, Type, Alias,
type_name_from_ctype)
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
GLibInterface, GLibObject, GLibSignal)
@@ -95,6 +95,7 @@ class GLibTransformer(object):
def _resolve_param_type(self, ptype):
type_name = ptype.name.replace('*', '')
+ type_name = self._transformer.resolve_possible_typedef(type_name)
ptype.name = self._resolve_type_name(type_name)
return ptype
@@ -107,6 +108,8 @@ class GLibTransformer(object):
self._parse_struct(node)
elif isinstance(node, Callback):
self._parse_callback(node)
+ elif isinstance(node, Alias):
+ self._parse_alias(node)
elif isinstance(node, Member):
# FIXME: atk_misc_instance singletons
pass
@@ -114,21 +117,35 @@ class GLibTransformer(object):
print 'GOBJECT BUILDER: Unhandled node:', node
def _resolve_node(self, node):
- ntype = type(node)
- if ntype in (Callback, Function):
+
+ def isany(*klasses):
+ for klass in klasses:
+ if isinstance(node, klass):
+ return True
+ return False
+
+ if isany(Callback, Function):
self._resolve_function(node)
- if ntype in (GLibObject, GLibBoxed):
+ if isany(GLibObject, GLibBoxed, GLibInterface):
for meth in node.methods:
self._resolve_function(meth)
+ if isany(GLibObject, GLibBoxed):
for ctor in node.constructors:
self._resolve_function(ctor)
- if ntype in (Struct, ):
+ if isany(GLibObject, GLibInterface):
+ for prop in node.properties:
+ self._resolve_property(prop)
+ for sig in node.signals:
+ self._resolve_function(sig)
+ if isany(Struct, ):
for field in node.fields:
if isinstance(field, Field):
self._resolve_field(field)
- if ntype in (GLibObject, ):
- for prop in node.properties:
- self._resolve_property(prop)
+ elif isinstance(field, Callback):
+ self._resolve_function(field)
+
+ def _parse_alias(self, alias):
+ self._add_attribute(alias)
def _parse_enum(self, enum):
self._add_attribute(enum)
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index a843c3ea..f2fe6fc4 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -18,9 +18,12 @@
# 02110-1301, USA.
#
+import os
+import sys
+
from giscanner.ast import (Callback, Enum, Function, Namespace, Member,
Parameter, Return, Sequence, Struct, Field,
- Type, type_name_from_ctype)
+ Type, Alias, type_name_from_ctype)
from giscanner.sourcescanner import (
SourceSymbol, ctype_name, symbol_type_name, CTYPE_POINTER,
CTYPE_BASIC_TYPE, CTYPE_UNION, CTYPE_ARRAY,
@@ -40,6 +43,7 @@ class Transformer(object):
self._type_names = {}
self._typedefs_ns = {}
self._strip_prefix = ''
+ self._typedefs = {}
def get_type_names(self):
return self._type_names
@@ -47,6 +51,9 @@ class Transformer(object):
def set_strip_prefix(self, strip_prefix):
self._strip_prefix = strip_prefix
+ def resolve_possible_typedef(self, tname):
+ return self._typedefs.get(tname, tname)
+
def parse(self):
nodes = []
for symbol in self.generator.get_symbols():
@@ -200,7 +207,7 @@ class Transformer(object):
CTYPE_BASIC_TYPE,
CTYPE_UNION,
CTYPE_VOID):
- return
+ return Alias(symbol.ident, symbol.base_type.name)
else:
raise NotImplementedError(
"symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
@@ -209,7 +216,8 @@ class Transformer(object):
def _create_type(self, source_type):
ctype = self._create_source_type(source_type)
type_name = type_name_from_ctype(ctype)
- return Type(type_name, ctype)
+ resolved_type_name = self._resolve_type_name(type_name)
+ return Type(resolved_type_name, ctype)
def _create_parameter(self, symbol, options):
ptype = self._create_type(symbol.base_type)
diff --git a/tests/scanner/Foo-expected.gir b/tests/scanner/Foo-expected.gir
index d1b45a7f..b0cfd897 100644
--- a/tests/scanner/Foo-expected.gir
+++ b/tests/scanner/Foo-expected.gir
@@ -184,7 +184,7 @@
</parameter>
</parameters>
</method>
- <method name="with_voidp" c:identifier="foo_object_with_voidp">
+ <method name="various" c:identifier="foo_object_various">
<return-value>
<type name="none" c:type="void"/>
</return-value>
@@ -195,6 +195,22 @@
<parameter name="data">
<type name="any" c:type="void*"/>
</parameter>
+ <parameter name="some_type">
+ <type name="GType" c:type="GType"/>
+ </parameter>
+ </parameters>
+ </method>
+ <method name="with_tdef" c:identifier="foo_object_with_tdef">
+ <return-value>
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="object">
+ <type name="Object" c:type="FooObject*"/>
+ </parameter>
+ <parameter name="blah">
+ <type name="FooList" c:type="FooList*"/>
+ </parameter>
</parameters>
</method>
<property name="string">
@@ -206,7 +222,7 @@
</return-value>
<parameters>
<parameter name="object">
- <type name="FooObject*" c:type="FooObject*"/>
+ <type name="Object" c:type="FooObject*"/>
</parameter>
<parameter name="first_param">
<type name="int32" c:type="int"/>
@@ -219,7 +235,7 @@
</return-value>
<parameters>
<parameter name="object">
- <type name="GObject" c:type="GObject"/>
+ <type name="GLib.Object" c:type="GObject"/>
</parameter>
<parameter name="p0">
<type name="any" c:type="gpointer"/>
@@ -227,6 +243,7 @@
</parameters>
</glib:signal>
</class>
+ <alias name="FooList" target="GSList"/>
<class name="Subobject"
c:type="FooSubobject"
parent="Object"
diff --git a/tests/scanner/foo-object.h b/tests/scanner/foo-object.h
index aefa2cd1..2ac76465 100644
--- a/tests/scanner/foo-object.h
+++ b/tests/scanner/foo-object.h
@@ -61,7 +61,13 @@ gint foo_object_calleesowns (FooObject *object, GObject *
GList* foo_object_get_strings (FooObject *object);
GSList* foo_object_get_objects (FooObject *object);
-void foo_object_with_voidp (FooObject *object, void *data);
+void foo_object_various (FooObject *object, void *data, GType some_type);
+
+/* A random typedef */
+typedef GSList FooList;
+
+void foo_object_with_tdef (FooObject *object, FooList *blah);
+
struct _FooSubobject
{