aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.lima@openbossa.org>2010-04-14 19:32:37 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-09 19:09:59 -0300
commit74d3c1bb12280ffb2b810ee4bd1272ba6fb8127f (patch)
treec87daaa1939b537b50ea94c824f620d236717003
parent46cd570358601d83be0e23a378fc688d8ed706b6 (diff)
Added the "function" tag to ApiExtractor.
This change the behaviour of ApiExtractor regarding to global functions. All global function you want to be exported to python *need* to be especified in the type system with the function tag, otherwise they wont be exported at all. The syntax for this new tag is: <function signature="..." /> This is just the initial work for this tag, it is missign support for: - Function modifications. - Add a function overload with add-function tag.
-rw-r--r--abstractmetabuilder.cpp19
-rw-r--r--abstractmetalang.h14
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/testabstractmetatype.cpp3
-rw-r--r--tests/testenum.cpp7
-rw-r--r--tests/testfunctiontag.cpp64
-rw-r--r--tests/testfunctiontag.h36
-rw-r--r--typesystem.cpp39
-rw-r--r--typesystem.h30
9 files changed, 194 insertions, 19 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp
index 182f4456d..4d8a4f1d8 100644
--- a/abstractmetabuilder.cpp
+++ b/abstractmetabuilder.cpp
@@ -503,16 +503,27 @@ bool AbstractMetaBuilder::build(QIODevice* input)
m_currentClass = 0;
+ // Global functions
foreach (FunctionModelItem func, m_dom->functions()) {
if (func->accessPolicy() != CodeModel::Public || func->name().startsWith("operator"))
continue;
+ FunctionTypeEntry* funcEntry = types->findFunctionType(func->name());
+ if (!funcEntry)
+ continue;
+
AbstractMetaFunction* metaFunc = traverseFunction(func);
- if (metaFunc) {
- QFileInfo info(func->fileName());
- metaFunc->setIncludeFile(Include(Include::IncludePath, info.fileName()));
- m_globalFunctions << metaFunc;
+ if (!metaFunc)
+ continue;
+
+ if (!funcEntry->hasSignature(metaFunc->minimalSignature())) {
+ delete metaFunc;
+ continue;
}
+
+ QFileInfo info(func->fileName());
+ funcEntry->setInclude(Include(Include::IncludePath, info.fileName()));
+ m_globalFunctions << metaFunc;
}
// Functions added to the module on the type system.
diff --git a/abstractmetalang.h b/abstractmetalang.h
index d27e1df9e..9cba7e411 100644
--- a/abstractmetalang.h
+++ b/abstractmetalang.h
@@ -758,7 +758,8 @@ public:
};
AbstractMetaFunction()
- : m_functionType(NormalFunction),
+ : m_typeEntry(0),
+ m_functionType(NormalFunction),
m_type(0),
m_class(0),
m_implementingClass(0),
@@ -1089,14 +1090,9 @@ public:
return m_propertySpec;
}
- Include includeFile() const
+ FunctionTypeEntry* typeEntry() const
{
- return m_includeFile;
- }
-
- void setIncludeFile(const Include& include)
- {
- m_includeFile = include;
+ return m_typeEntry;
}
private:
QString m_name;
@@ -1104,7 +1100,7 @@ private:
mutable QString m_cachedMinimalSignature;
mutable QString m_cachedModifiedName;
- Include m_includeFile;
+ FunctionTypeEntry* m_typeEntry;
FunctionType m_functionType;
AbstractMetaType *m_type;
const AbstractMetaClass *m_class;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 61f40ce2e..189ff42a7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -24,3 +24,4 @@ declare_test(testreferencetopointer)
declare_test(testremoveimplconv)
declare_test(testreverseoperators)
declare_test(testtoposort)
+declare_test(testfunctiontag)
diff --git a/tests/testabstractmetatype.cpp b/tests/testabstractmetatype.cpp
index 3e75539fb..81e194fd3 100644
--- a/tests/testabstractmetatype.cpp
+++ b/tests/testabstractmetatype.cpp
@@ -30,6 +30,7 @@ void TestAbstractMetaType::testConstCharPtrType()
const char* cppCode ="const char* justAtest();";
const char* xmlCode = "<typesystem package=\"Foo\">\
<primitive-type name='char'/>\
+ <function signature='justAtest()' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
QCOMPARE(t.builder()->globalFunctions().size(), 1);
@@ -57,6 +58,7 @@ void TestAbstractMetaType::testCharType()
const char* xmlCode = "<typesystem package=\"Foo\">\
<primitive-type name='char'/>\
<value-type name='A' />\
+ <function signature='justAtest()' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
@@ -118,6 +120,7 @@ void TestAbstractMetaType::testTypedefWithTemplates()
const char* xmlCode = "<typesystem package=\"Foo\">\
<container-type name='A' type='list'/>\
<value-type name='B' />\
+ <function signature='func(A&lt;B&gt;)' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
diff --git a/tests/testenum.cpp b/tests/testenum.cpp
index 93a678e73..24cb4d963 100644
--- a/tests/testenum.cpp
+++ b/tests/testenum.cpp
@@ -41,12 +41,13 @@ void TestEnum::testEnumCppSignature()
<value-type name='A'/> \
<enum-type name='GlobalEnum' />\
<enum-type name='A::ClassEnum' />\
+ <function signature='func(A::ClassEnum)' />\
</typesystem>";
TestUtil t(cppCode, xmlCode);
AbstractMetaClassList classes = t.builder()->classes();
QCOMPARE(classes.count(), 1);
-
+
AbstractMetaEnumList globalEnums = t.builder()->globalEnums();
QCOMPARE(globalEnums.count(), 1);
QCOMPARE(globalEnums.first()->name(), QString("GlobalEnum"));
@@ -56,7 +57,7 @@ void TestEnum::testEnumCppSignature()
QCOMPARE(functions.count(), 1);
QCOMPARE(functions.first()->arguments().count(), 1);
QCOMPARE(functions.first()->arguments().first()->type()->cppSignature(), QString("A::ClassEnum"));
-
+
// enum as parameter of a method
AbstractMetaClass* classA = classes.findClass("A");
QCOMPARE(classA->enums().count(), 1);
@@ -72,8 +73,6 @@ void TestEnum::testEnumCppSignature()
AbstractMetaEnumList classEnums = classA->enums();
QCOMPARE(classEnums.first()->name(), QString("ClassEnum"));
-
-
}
QTEST_APPLESS_MAIN(TestEnum)
diff --git a/tests/testfunctiontag.cpp b/tests/testfunctiontag.cpp
new file mode 100644
index 000000000..79e3142a5
--- /dev/null
+++ b/tests/testfunctiontag.cpp
@@ -0,0 +1,64 @@
+/*
+* This file is part of the API Extractor project.
+*
+* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+*/
+
+#include "testfunctiontag.h"
+#include <QtTest/QTest>
+#include "testutil.h"
+
+void TestFunctionTag::testFunctionTagForSpecificSignature()
+{
+ const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy()";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\
+ <primitive-type name='int'/> \
+ <primitive-type name='float'/> \
+ <function signature='globalFunction(int)'/>\
+ </typesystem>";
+ TestUtil t(cppCode, xmlCode, false);
+
+ FunctionTypeEntry* func = (FunctionTypeEntry*) TypeDatabase::instance()->findType("globalFunction");
+ QVERIFY(func);
+ QCOMPARE(t.builder()->globalFunctions().size(), 1);
+}
+
+void TestFunctionTag::testFunctionTagForAllSignatures()
+{
+ const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\
+ <primitive-type name='int'/> \
+ <primitive-type name='float'/> \
+ <function signature='globalFunction(int)'/>\
+ <function signature='globalFunction(float)'/>\
+ </typesystem>";
+ TestUtil t(cppCode, xmlCode, false);
+
+ FunctionTypeEntry* func = (FunctionTypeEntry*) TypeDatabase::instance()->findType("globalFunction");
+ QVERIFY(func);
+ QCOMPARE(t.builder()->globalFunctions().size(), 2);
+}
+
+QTEST_APPLESS_MAIN(TestFunctionTag)
+
+#include "testfunctiontag.moc"
+
diff --git a/tests/testfunctiontag.h b/tests/testfunctiontag.h
new file mode 100644
index 000000000..8f42774c6
--- /dev/null
+++ b/tests/testfunctiontag.h
@@ -0,0 +1,36 @@
+/*
+* This file is part of the API Extractor project.
+*
+* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+*/
+
+#ifndef TESTFUNCTIONTAG_H
+#define TESTFUNCTIONTAG_H
+#include <QObject>
+
+class TestFunctionTag : public QObject
+{
+ Q_OBJECT
+private slots:
+ void testFunctionTagForSpecificSignature();
+ void testFunctionTagForAllSignatures();
+};
+
+#endif
diff --git a/typesystem.cpp b/typesystem.cpp
index e1992b867..32da2ca8d 100644
--- a/typesystem.cpp
+++ b/typesystem.cpp
@@ -48,6 +48,7 @@ public:
PrimitiveTypeEntry = 0x8,
EnumTypeEntry = 0x9,
ContainerTypeEntry = 0xa,
+ FunctionTypeEntry = 0xb,
TypeEntryMask = 0xf,
// Documentation tags
@@ -130,6 +131,7 @@ public:
tagNames["interface-type"] = StackElement::InterfaceTypeEntry;
tagNames["namespace-type"] = StackElement::NamespaceTypeEntry;
tagNames["enum-type"] = StackElement::EnumTypeEntry;
+ tagNames["function"] = StackElement::FunctionTypeEntry;
tagNames["extra-includes"] = StackElement::ExtraIncludes;
tagNames["include"] = StackElement::Include;
tagNames["inject-code"] = StackElement::InjectCode;
@@ -519,6 +521,9 @@ bool Handler::startElement(const QString &, const QString &n,
attributes["target-type"] = QString();
attributes["generic-class"] = QString("no");
break;
+ case StackElement::FunctionTypeEntry:
+ attributes["signature"] = QString();
+ break;
default:
{ } // nada
};
@@ -526,11 +531,18 @@ bool Handler::startElement(const QString &, const QString &n,
fetchAttributeValues(tagName, atts, &attributes);
QString name = attributes["name"];
+ // The top level tag 'function' has only the 'signature' tag
+ // and we should extract the 'name' value from it.
+ if (element->type == StackElement::FunctionTypeEntry) {
+ QString signature = attributes["signature"];
+ name = signature.left(signature.indexOf('(')).trimmed();
+ }
// We need to be able to have duplicate primitive type entries,
// or it's not possible to cover all primitive target language
// types (which we need to do in order to support fake meta objects)
- if (element->type != StackElement::PrimitiveTypeEntry) {
+ if (element->type != StackElement::PrimitiveTypeEntry
+ && element->type != StackElement::FunctionTypeEntry) {
TypeEntry *tmp = m_database->findType(name);
if (tmp)
ReportHandler::warning(QString("Duplicate type entry: '%1'").arg(name));
@@ -728,6 +740,22 @@ bool Handler::startElement(const QString &, const QString &n,
}
break;
+ case StackElement::FunctionTypeEntry: {
+ QString signature = attributes["signature"];
+ signature = TypeDatabase::normalizedSignature(signature.toLatin1().constData());
+ element->entry = m_database->findType(name);
+ if (element->entry) {
+ if (element->entry->type() == TypeEntry::FunctionType) {
+ reinterpret_cast<FunctionTypeEntry*>(element->entry)->addSignature(signature);
+ } else {
+ m_error = QString("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.").arg(name);
+ return false;
+ }
+ } else {
+ element->entry = new FunctionTypeEntry(name, signature);
+ }
+ }
+ break;
default:
Q_ASSERT(false);
};
@@ -1768,6 +1796,15 @@ ContainerTypeEntry *TypeDatabase::findContainerType(const QString &name)
return 0;
}
+FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name)
+{
+ TypeEntry* entry = findType(name);
+ if (entry && entry->type() == TypeEntry::FunctionType)
+ return static_cast<FunctionTypeEntry*>(entry);
+ return 0;
+}
+
+
PrimitiveTypeEntry *TypeDatabase::findTargetLangPrimitiveType(const QString &targetLangName)
{
foreach (QList<TypeEntry *> entries, m_entries.values()) {
diff --git a/typesystem.h b/typesystem.h
index 1c1c08299..662cb53e1 100644
--- a/typesystem.h
+++ b/typesystem.h
@@ -583,7 +583,8 @@ public:
ArrayType,
TypeSystemType,
CustomType,
- TargetLangType
+ TargetLangType,
+ FunctionType
};
enum CodeGeneration {
@@ -1699,6 +1700,32 @@ private:
};
+class APIEXTRACTOR_API FunctionTypeEntry : public TypeEntry
+{
+public:
+ FunctionTypeEntry(const QString& name, const QString& signature)
+ : TypeEntry(name, FunctionType)
+ {
+ addSignature(signature);
+ }
+ void addSignature(const QString& signature)
+ {
+ m_signatures << signature;
+ }
+
+ QStringList signatures()
+ {
+ return m_signatures;
+ }
+
+ inline bool hasSignature(const QString& signature)
+ {
+ return m_signatures.contains(signature);
+ }
+private:
+ QStringList m_signatures;
+};
+
class APIEXTRACTOR_API ObjectTypeEntry : public ComplexTypeEntry
{
public:
@@ -1779,6 +1806,7 @@ public:
inline ObjectTypeEntry *findObjectType(const QString &name);
inline NamespaceTypeEntry *findNamespaceType(const QString &name);
ContainerTypeEntry *findContainerType(const QString &name);
+ FunctionTypeEntry* findFunctionType(const QString& name);
TypeEntry *findType(const QString &name) const
{