summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Booth <mbooth@redhat.com>2012-03-06 11:57:01 -0300
committerJohan Dahlin <jdahlin@litl.com>2012-03-06 11:57:22 -0300
commitab8a6d9694ebd79b202b470c3742e8d521faf722 (patch)
tree8a7552e3b24cbf12d8e52e8758b3b79c7e8a5608
parentc2fc7cb45243aa9e0e1e5569cc742f69c76a671a (diff)
downloadgobject-introspection-ab8a6d9694ebd79b202b470c3742e8d521faf722.tar.gz
Fix matching of methods named *_get_type()
The code which heuristically turned functions into class methods would always ignore any function called *_get_type or *_get_gtype. However, the code which looked for GI metadata functions to execute them was much more comprehensive, checking not just the name, but also that it had no parameters and that it returned a GType. This change abstracts the more comprehensive check into the Function class, and uses the same check in both places. https://bugzilla.gnome.org/show_bug.cgi?id=671218
-rw-r--r--.gitignore1
-rw-r--r--giscanner/ast.py21
-rw-r--r--giscanner/gdumpparser.py16
-rw-r--r--giscanner/maintransformer.py7
-rw-r--r--tests/scanner/GetType-1.0-expected.gir69
-rw-r--r--tests/scanner/Makefile.am28
-rw-r--r--tests/scanner/gettype.c62
-rw-r--r--tests/scanner/gettype.h29
8 files changed, 211 insertions, 22 deletions
diff --git a/.gitignore b/.gitignore
index 7ecec39e..1d4ae8a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,7 @@ tests/repository/gitypelibtest
tests/scanner/Annotation-1.0.gir
tests/scanner/Bar-1.0.gir
tests/scanner/Foo-1.0.gir
+tests/scanner/GetType-1.0.gir
tests/scanner/GtkFrob-1.0.gir
tests/scanner/Headeronly-1.0.gir
tests/scanner/Regress-1.0.gir
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 6df356dd..9e9d7c37 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -21,6 +21,8 @@
import copy
+from . import message
+
from .message import Position
from .odict import odict
from .utils import to_underscores
@@ -589,6 +591,25 @@ class Function(Callable):
clone.parameters = self.parameters[:]
return clone
+ def is_type_meta_function(self):
+ # Named correctly
+ if not (self.name.endswith('_get_type') or
+ self.name.endswith('_get_gtype')):
+ return False
+
+ # Doesn't have any parameters
+ if self.parameters:
+ return False
+
+ # Returns GType
+ rettype = self.retval.type
+ if (not rettype.is_equiv(TYPE_GTYPE) and
+ rettype.target_giname != 'Gtk.Type'):
+ message.warn("function '%s' returns '%r', not a GType" %
+ (self.name, rettype))
+ return False
+
+ return True
class ErrorQuarkFunction(Function):
diff --git a/giscanner/gdumpparser.py b/giscanner/gdumpparser.py
index c0c4ef61..c0b13f4a 100644
--- a/giscanner/gdumpparser.py
+++ b/giscanner/gdumpparser.py
@@ -188,18 +188,12 @@ blob containing data gleaned from GObject's primitive introspection."""
if func.symbol == 'g_variant_get_gtype':
# We handle variants internally, see _initparse_gobject_record
return True
- if func.parameters:
- return False
- # GType *_get_type(void)
- rettype = func.retval.type
- if not (rettype.is_equiv(ast.TYPE_GTYPE)
- or rettype.target_giname == 'Gtk.Type'):
- message.warn("function returns '%r', not a GType" % (
- func.retval.type, ))
- return False
- self._get_type_functions.append(func.symbol)
- return True
+ if func.is_type_meta_function():
+ self._get_type_functions.append(func.symbol)
+ return True
+
+ return False
def _initparse_error_quark_function(self, func):
if (func.retval.type.ctype != 'GQuark'):
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index 3a35b0e7..7d274b34 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -955,10 +955,11 @@ _split_uscored_by_type(text_buffer_try_new) -> (ast.Class(TextBuffer), 'try_new'
def _pair_function(self, func):
"""Check to see whether a toplevel function should be a
method or constructor of some type."""
- if (func.symbol.endswith('_get_type')
- or func.symbol.endswith('_get_gtype')
- or func.symbol.startswith('_')):
+
+ # Ignore internal symbols and type metadata functions
+ if func.symbol.startswith('_') or func.is_type_meta_function():
return
+
(ns, subsymbol) = self._transformer.split_csymbol(func.symbol)
assert ns == self._namespace
if self._is_constructor(func, subsymbol):
diff --git a/tests/scanner/GetType-1.0-expected.gir b/tests/scanner/GetType-1.0-expected.gir
new file mode 100644
index 00000000..3b1dd193
--- /dev/null
+++ b/tests/scanner/GetType-1.0-expected.gir
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!-- This file was automatically generated from C sources - DO NOT EDIT!
+To affect the contents of this file, edit the original C definitions,
+and/or use gtk-doc annotations. -->
+<repository version="1.2"
+ xmlns="http://www.gtk.org/introspection/core/1.0"
+ xmlns:c="http://www.gtk.org/introspection/c/1.0"
+ xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <include name="GLib" version="2.0"/>
+ <include name="GObject" version="2.0"/>
+ <package name="gobject-2.0"/>
+ <c:include name="gettype.h"/>
+ <namespace name="GetType"
+ version="1.0"
+ shared-library="libgettype.so"
+ c:identifier-prefixes="GetType"
+ c:symbol-prefixes="gettype">
+ <class name="Object"
+ c:symbol-prefix="object"
+ c:type="GetTypeObject"
+ parent="GObject.Object"
+ glib:type-name="GetTypeObject"
+ glib:get-type="gettype_object_get_type"
+ glib:type-struct="ObjectClass">
+ <constructor name="new" c:identifier="gettype_object_new">
+ <return-value transfer-ownership="full">
+ <type name="Object" c:type="GetTypeObject*"/>
+ </return-value>
+ </constructor>
+ <function name="nonmeta2_get_type"
+ c:identifier="gettype_object_nonmeta2_get_type">
+ <doc xml:whitespace="preserve">This shouldn't be scanned as a *_get_type function because it doesn't return
+a GType. It will generate a warning.</doc>
+ <return-value transfer-ownership="none">
+ <doc xml:whitespace="preserve">true</doc>
+ <type name="gboolean" c:type="gboolean"/>
+ </return-value>
+ </function>
+ <function name="nonmeta_get_gtype"
+ c:identifier="gettype_object_nonmeta_get_gtype">
+ <doc xml:whitespace="preserve">This shouldn't be scanned as a *_get_type function because it doesn't return
+a GType. It will generate a warning.</doc>
+ <return-value transfer-ownership="none">
+ <doc xml:whitespace="preserve">true</doc>
+ <type name="gboolean" c:type="gboolean"/>
+ </return-value>
+ </function>
+ <method name="nonmeta1_get_type"
+ c:identifier="gettype_object_nonmeta1_get_type">
+ <doc xml:whitespace="preserve">This shouldn't be scanned as a *_get_type function because it takes
+arguments.</doc>
+ <return-value transfer-ownership="none">
+ <doc xml:whitespace="preserve">0</doc>
+ <type name="GType" c:type="GType"/>
+ </return-value>
+ </method>
+ <field name="parent_instance">
+ <type name="GObject.Object" c:type="GObject"/>
+ </field>
+ </class>
+ <record name="ObjectClass"
+ c:type="GetTypeObjectClass"
+ glib:is-gtype-struct-for="Object">
+ <field name="parent_class">
+ <type name="GObject.ObjectClass" c:type="GObjectClass"/>
+ </field>
+ </record>
+ </namespace>
+</repository>
diff --git a/tests/scanner/Makefile.am b/tests/scanner/Makefile.am
index d2bed5ac..0e5ddb53 100644
--- a/tests/scanner/Makefile.am
+++ b/tests/scanner/Makefile.am
@@ -1,14 +1,15 @@
include $(top_srcdir)/common.mk
include $(top_srcdir)/Makefile.introspection
-INTROSPECTION_SCANNER_ARGS += --warn-all --warn-error -I.
+INTROSPECTION_SCANNER_ARGS += --warn-all
check_LTLIBRARIES = \
libannotation.la \
libtestinherit.la \
libfoo.la \
libutility.la \
- libgtkfrob.la
+ libgtkfrob.la \
+ libgettype.la
if HAVE_CAIRO
check_LTLIBRARIES += libregress.la
endif
@@ -28,6 +29,7 @@ libutility_la_SOURCES = $(srcdir)/utility.c $(srcdir)/utility.h
libgtkfrob_la_SOURCES = $(srcdir)/gtkfrob.c $(srcdir)/gtkfrob.h
libregress_la_SOURCES = $(srcdir)/regress.c $(srcdir)/regress.h
libregress_la_LIBADD = $(GIO_LIBS) $(CAIRO_LIBS)
+libgettype_la_SOURCES = $(srcdir)/gettype.c $(srcdir)/gettype.h
testsdir = $(datadir)/gobject-introspection-1.0/tests
tests_DATA = $(libregress_la_SOURCES)
@@ -53,7 +55,7 @@ Regress-1.0.gir: $(top_builddir)/Gio-2.0.gir libregress.la
Regress_1_0_gir_LIBS = libregress.la
Regress_1_0_gir_INCLUDES = cairo-1.0 Gio-2.0
Regress_1_0_gir_FILES = $(libregress_la_SOURCES)
-Regress_1_0_gir_SCANNERFLAGS = --c-include="regress.h"
+Regress_1_0_gir_SCANNERFLAGS = --c-include="regress.h" --warn-error
if HAVE_CAIRO
GIRS += Regress-1.0.gir
endif
@@ -63,7 +65,7 @@ Annotation_1_0_gir_PACKAGES = gobject-2.0
Annotation_1_0_gir_LIBS = libannotation.la
Annotation_1_0_gir_INCLUDES = GObject-2.0 Utility-1.0
Annotation_1_0_gir_FILES = $(libannotation_la_SOURCES)
-Annotation_1_0_gir_SCANNERFLAGS = --c-include="annotation.h"
+Annotation_1_0_gir_SCANNERFLAGS = --c-include="annotation.h" --warn-error
GIRS += Annotation-1.0.gir
TestInherit-1.0.gir: Utility-1.0.gir libtestinherit.la
@@ -71,7 +73,7 @@ TestInherit_1_0_gir_PACKAGES = gobject-2.0
TestInherit_1_0_gir_LIBS = libtestinherit.la
TestInherit_1_0_gir_INCLUDES = GObject-2.0 Utility-1.0
TestInherit_1_0_gir_FILES = $(libtestinherit_la_SOURCES)
-TestInherit_1_0_gir_SCANNERFLAGS = --c-include="drawable.h"
+TestInherit_1_0_gir_SCANNERFLAGS = --c-include="drawable.h" --warn-error
GIRS += TestInherit-1.0.gir
Foo-1.0.gir: Utility-1.0.gir libfoo.la
@@ -79,7 +81,7 @@ Foo_1_0_gir_PACKAGES = gobject-2.0
Foo_1_0_gir_LIBS = libfoo.la
Foo_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0 Utility-1.0
Foo_1_0_gir_FILES = $(srcdir)/foo.h $(srcdir)/foo.c
-Foo_1_0_gir_SCANNERFLAGS = --c-include="foo.h"
+Foo_1_0_gir_SCANNERFLAGS = --c-include="foo.h" --warn-error
GIRS += Foo-1.0.gir
Utility-1.0.gir: libutility.la
@@ -87,7 +89,7 @@ Utility_1_0_gir_PACKAGES = gobject-2.0
Utility_1_0_gir_LIBS = libutility.la
Utility_1_0_gir_INCLUDES = GObject-2.0
Utility_1_0_gir_FILES = $(libutility_la_SOURCES)
-Utility_1_0_gir_SCANNERFLAGS = --c-include="utility.h"
+Utility_1_0_gir_SCANNERFLAGS = --c-include="utility.h" --warn-error
GIRS += Utility-1.0.gir
# This one tests different --namespace and --strip-prefix
@@ -96,9 +98,19 @@ GtkFrob_1_0_gir_PACKAGES = gobject-2.0
GtkFrob_1_0_gir_LIBS = libgtkfrob.la
GtkFrob_1_0_gir_INCLUDES = GObject-2.0
GtkFrob_1_0_gir_FILES = $(libgtkfrob_la_SOURCES)
-GtkFrob_1_0_gir_SCANNERFLAGS = --identifier-prefix=Gtk --symbol-prefix=gtk_frob
+GtkFrob_1_0_gir_SCANNERFLAGS = --identifier-prefix=Gtk --symbol-prefix=gtk_frob --warn-error
GIRS += GtkFrob-1.0.gir
+# This tests that functions called _get_type are only matched if they have no
+# arguments and return GType
+GetType-1.0.gir: libgettype.la
+GetType_1_0_gir_PACKAGES = gobject-2.0
+GetType_1_0_gir_LIBS = libgettype.la
+GetType_1_0_gir_INCLUDES = GObject-2.0
+GetType_1_0_gir_FILES = $(libgettype_la_SOURCES)
+GetType_1_0_gir_SCANNERFLAGS = --c-include="gettype.h" --identifier-prefix=GetType --symbol-prefix=gettype
+GIRS += GetType-1.0.gir
+
if !OS_WIN32
check_PROGRAMS = barapp
diff --git a/tests/scanner/gettype.c b/tests/scanner/gettype.c
new file mode 100644
index 00000000..cd816735
--- /dev/null
+++ b/tests/scanner/gettype.c
@@ -0,0 +1,62 @@
+#include "gettype.h"
+
+G_DEFINE_TYPE(GetTypeObject, gettype_object, G_TYPE_OBJECT);
+
+static void
+gettype_object_class_init (GetTypeObjectClass *klass)
+{
+}
+
+static void
+gettype_object_init (GetTypeObject *object)
+{
+}
+
+GetTypeObject *
+gettype_object_new (void)
+{
+ return g_object_new (GETTYPE_TYPE_OBJECT, NULL);
+}
+
+/**
+ * gettype_object_nonmeta1_get_type:
+ * @obj: self
+ *
+ * This shouldn't be scanned as a *_get_type function because it takes
+ * arguments.
+ *
+ * Returns: 0
+ */
+GType
+gettype_object_nonmeta1_get_type (GetTypeObject *obj)
+{
+ return 0;
+}
+
+/**
+ * gettype_object_nonmeta2_get_type:
+ *
+ * This shouldn't be scanned as a *_get_type function because it doesn't return
+ * a GType. It will generate a warning.
+ *
+ * Returns: true
+ */
+gboolean
+gettype_object_nonmeta2_get_type (void)
+{
+ return TRUE;
+}
+
+/**
+ * gettype_object_nonmeta_get_gtype:
+ *
+ * This shouldn't be scanned as a *_get_type function because it doesn't return
+ * a GType. It will generate a warning.
+ *
+ * Returns: true
+ */
+gboolean
+gettype_object_nonmeta_get_gtype (void)
+{
+ return TRUE;
+}
diff --git a/tests/scanner/gettype.h b/tests/scanner/gettype.h
new file mode 100644
index 00000000..755f091c
--- /dev/null
+++ b/tests/scanner/gettype.h
@@ -0,0 +1,29 @@
+#ifndef __GETTYPE_OBJECT_H__
+#define __GETTYPE_OBJECT_H__
+
+#include <glib-object.h>
+
+#define GETTYPE_TYPE_OBJECT (gettype_object_get_type ())
+#define GETTYPE_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GETTYPE_TYPE_OBJECT, GetTypeObject))
+#define GETTYPE_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GETTYPE_TYPE_OBJECT))
+
+typedef struct _GetTypeObject GetTypeObject;
+typedef struct _GetTypeObjectClass GetTypeObjectClass;
+struct _GetTypeObject
+{
+ GObject parent_instance;
+};
+
+struct _GetTypeObjectClass
+{
+ GObjectClass parent_class;
+};
+
+GType gettype_object_get_type (void) G_GNUC_CONST;
+GetTypeObject* gettype_object_new (void);
+
+GType gettype_object_nonmeta1_get_type (GetTypeObject *obj);
+gboolean gettype_object_nonmeta2_get_type (void);
+gboolean gettype_object_nonmeta_get_gtype (void);
+
+#endif /* __GETTYPE_OBJECT_H__ */