From 74d3c1bb12280ffb2b810ee4bd1272ba6fb8127f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 14 Apr 2010 19:32:37 -0300 Subject: 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: This is just the initial work for this tag, it is missign support for: - Function modifications. - Add a function overload with add-function tag. --- abstractmetabuilder.cpp | 19 ++++++++++--- abstractmetalang.h | 14 ++++----- tests/CMakeLists.txt | 1 + tests/testabstractmetatype.cpp | 3 ++ tests/testenum.cpp | 7 ++--- tests/testfunctiontag.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++ tests/testfunctiontag.h | 36 ++++++++++++++++++++++++ typesystem.cpp | 39 ++++++++++++++++++++++++- typesystem.h | 30 +++++++++++++++++++- 9 files changed, 194 insertions(+), 19 deletions(-) create mode 100644 tests/testfunctiontag.cpp create mode 100644 tests/testfunctiontag.h 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 = "\ \ + \ "; TestUtil t(cppCode, xmlCode); QCOMPARE(t.builder()->globalFunctions().size(), 1); @@ -57,6 +58,7 @@ void TestAbstractMetaType::testCharType() const char* xmlCode = "\ \ \ + \ "; TestUtil t(cppCode, xmlCode); @@ -118,6 +120,7 @@ void TestAbstractMetaType::testTypedefWithTemplates() const char* xmlCode = "\ \ \ + \ "; 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() \ \ \ + \ "; 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 +* +* 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 +#include "testutil.h" + +void TestFunctionTag::testFunctionTagForSpecificSignature() +{ + const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy()"; + const char xmlCode[] = "\ + \ + \ + \ + \ + "; + 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[] = "\ + \ + \ + \ + \ + \ + "; + 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 +* +* 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 + +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(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(entry); + return 0; +} + + PrimitiveTypeEntry *TypeDatabase::findTargetLangPrimitiveType(const QString &targetLangName) { foreach (QList 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 { -- cgit v1.2.3