Commit ab8a6d96 authored by Matthew Booth's avatar Matthew Booth Committed by Johan Dahlin

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
parent c2fc7cb4
......@@ -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
......
......@@ -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):
......
......@@ -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'):
......
......@@ -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):
......
<?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>
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
......
#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;
}
#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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment