diff options
-rw-r--r-- | abstractmetabuilder.cpp | 12 | ||||
-rw-r--r-- | abstractmetalang.cpp | 20 | ||||
-rw-r--r-- | abstractmetalang.h | 3 | ||||
-rw-r--r-- | tests/testaddfunction.cpp | 32 | ||||
-rw-r--r-- | tests/testaddfunction.h | 1 | ||||
-rw-r--r-- | typesystem.cpp | 33 | ||||
-rw-r--r-- | typesystem.h | 23 |
7 files changed, 114 insertions, 10 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 45e24f282..6ce0232ec 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -300,6 +300,8 @@ bool AbstractMetaBuilder::build(QIODevice* input) return false; } + TypeDatabase* types = TypeDatabase::instance(); + QByteArray contents = input->readAll(); input->close(); @@ -318,7 +320,6 @@ bool AbstractMetaBuilder::build(QIODevice* input) QHash<QString, ClassModelItem> typeMap = m_dom->classMap(); // fix up QObject's in the type system.. - TypeDatabase *types = TypeDatabase::instance(); fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom)); // Start the generation... @@ -496,6 +497,14 @@ bool AbstractMetaBuilder::build(QIODevice* input) m_globalFunctions << metaFunc; } } + + // Functions added to the module on the type system. + foreach (AddedFunction addedFunc, types->addedFunctions()) { + AbstractMetaFunction* metaFunc = traverseFunction(addedFunc); + metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction); + m_globalFunctions << metaFunc; + } + std::puts(""); return true; } @@ -2642,7 +2651,6 @@ AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const Abstra return result; } - AbstractMetaArgumentList AbstractMetaBuilder::reverseList(const AbstractMetaArgumentList& list) { AbstractMetaArgumentList ret; diff --git a/abstractmetalang.cpp b/abstractmetalang.cpp index 5e8020db7..9643d5f85 100644 --- a/abstractmetalang.cpp +++ b/abstractmetalang.cpp @@ -675,12 +675,22 @@ QString AbstractMetaFunction::minimalSignature() const return minimalSignature; } -FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const +FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass* implementor) const { - // FIXME Global functions do not support modifications if (!implementor) - return FunctionModificationList(); - return implementor->typeEntry()->functionModifications(minimalSignature()); + implementor = ownerClass(); + + if (!implementor) + return TypeDatabase::instance()->functionModifications(minimalSignature()); + + FunctionModificationList mods; + while (implementor) { + mods += implementor->typeEntry()->functionModifications(minimalSignature()); + if (implementor == implementor->baseClass()) + break; + implementor = implementor->baseClass(); + } + return mods; } bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const @@ -714,7 +724,7 @@ CodeSnipList AbstractMetaFunction::injectedCodeSnips(CodeSnip::Position position bool AbstractMetaFunction::hasSignatureModifications() const { - foreach (const FunctionModification mod, modifications(ownerClass())) { + foreach (const FunctionModification mod, modifications()) { foreach (const ArgumentModification argmod, mod.argument_mods) { // since zero represents the return type and we're // interested only in checking the function arguments, diff --git a/abstractmetalang.h b/abstractmetalang.h index 13e3270a5..eb51dc643 100644 --- a/abstractmetalang.h +++ b/abstractmetalang.h @@ -1063,13 +1063,14 @@ public: */ CodeSnipList injectedCodeSnips(CodeSnip::Position position = CodeSnip::Any, TypeSystem::Language language = TypeSystem::All) const; + /** * Verifies if any modification to the function alters/removes its * arguments types or default values. * \return true if there is some modification to function signature */ bool hasSignatureModifications() const; - FunctionModificationList modifications(const AbstractMetaClass *implementor) const; + FunctionModificationList modifications(const AbstractMetaClass* implementor = 0) const; // If this function stems from an interface, this returns the // interface that declares it. diff --git a/tests/testaddfunction.cpp b/tests/testaddfunction.cpp index 781736ba4..3188ca23d 100644 --- a/tests/testaddfunction.cpp +++ b/tests/testaddfunction.cpp @@ -229,6 +229,38 @@ void TestAddFunction::testAddFunctionWithDefaultArgs() QCOMPARE(arg->defaultValueExpression(), QString("2")); } +void TestAddFunction::testAddFunctionAtModuleLevel() +{ + const char cppCode[] = "struct A { };"; + const char xmlCode[] = "\ + <typesystem package=\"Foo\">\ + <primitive-type name='int'/> \ + <value-type name='A'/>\ + <add-function signature='func(int, int)'>\ + <inject-code class='target' position='beginning'>custom_code();</inject-code>\ + </add-function>\ + </typesystem>"; + + TestUtil t(cppCode, xmlCode, false); + AbstractMetaClassList classes = t.builder()->classes(); + AbstractMetaClass* classA = classes.findClass("A"); + QVERIFY(classA); + + TypeDatabase* typeDb = TypeDatabase::instance(); + + AddedFunctionList addedFuncs = typeDb->findAddedFunctions("func"); + + QCOMPARE(addedFuncs.size(), 1); + + FunctionModificationList mods = typeDb->functionModifications("func(int,int)"); + + QCOMPARE(mods.size(), 1); + QVERIFY(mods.first().isCodeInjection()); + CodeSnip snip = mods.first().snips.first(); + QCOMPARE(snip.code(), QString("custom_code();")); +} + QTEST_APPLESS_MAIN(TestAddFunction) #include "testaddfunction.moc" + diff --git a/tests/testaddfunction.h b/tests/testaddfunction.h index 98c0f83ba..276184da1 100644 --- a/tests/testaddfunction.h +++ b/tests/testaddfunction.h @@ -36,6 +36,7 @@ private slots: void testAddFunctionCodeSnippets(); void testAddFunctionWithoutParenteses(); void testAddFunctionWithDefaultArgs(); + void testAddFunctionAtModuleLevel(); }; #endif diff --git a/typesystem.cpp b/typesystem.cpp index 2e1fe0e52..74bb6c384 100644 --- a/typesystem.cpp +++ b/typesystem.cpp @@ -259,6 +259,11 @@ bool Handler::endElement(const QString &, const QString &localName, const QStrin return true; switch (m_current->type) { + case StackElement::Root: { + TypeDatabase::instance()->setAddedFunctions(m_addedFunctions); + TypeDatabase::instance()->setFunctionModifications(m_functionMods); + } + break; case StackElement::ObjectTypeEntry: case StackElement::ValueTypeEntry: case StackElement::InterfaceTypeEntry: @@ -803,6 +808,7 @@ bool Handler::startElement(const QString &, const QString &n, || element->type == StackElement::LoadTypesystem || element->type == StackElement::InjectCode || element->type == StackElement::ConversionRule + || element->type == StackElement::AddFunction || element->type == StackElement::Template; if (!topLevel && m_current->type == StackElement::Root) { @@ -1280,8 +1286,8 @@ bool Handler::startElement(const QString &, const QString &n, } break; case StackElement::AddFunction: { - if (!(topElement.type & StackElement::ComplexTypeEntryMask)) { - m_error = QString::fromLatin1("Add function requires complex type as parent" + if (!(topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::Root))) { + m_error = QString::fromLatin1("Add function requires a complex type or a root tag as parent" ", was=%1").arg(topElement.type, 0, 16); return false; } @@ -1972,11 +1978,34 @@ FlagsTypeEntry *TypeDatabase::findFlagsType(const QString &name) const return fte ? fte : (FlagsTypeEntry *) m_flagsEntries.value(name); } +AddedFunctionList TypeDatabase::findAddedFunctions(const QString& name) const +{ + AddedFunctionList addedFunctions; + foreach (AddedFunction func, m_addedFunctions) { + if (func.name() == name) + addedFunctions.append(func); + } + return addedFunctions; +} + + QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) { return QLatin1String("Global"); } +FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const +{ + FunctionModificationList lst; + for (int i = 0; i < m_functionMods.count(); ++i) { + const FunctionModification& mod = m_functionMods.at(i); + if (mod.signature == signature) + lst << mod; + } + + return lst; +} + /*! * The Visual Studio 2002 compiler doesn't support these symbols, diff --git a/typesystem.h b/typesystem.h index cb26c1dbd..2c9be3e31 100644 --- a/typesystem.h +++ b/typesystem.h @@ -1876,6 +1876,26 @@ public: m_templates[t->name()] = t; } + AddedFunctionList addedFunctions() const + { + return m_addedFunctions; + } + void setAddedFunctions(const AddedFunctionList& addedFunctions) + { + m_addedFunctions = addedFunctions; + } + AddedFunctionList findAddedFunctions(const QString& name) const; + + void setFunctionModifications(const FunctionModificationList& functionModifications) + { + m_functionMods = functionModifications; + } + void addFunctionModification(const FunctionModification& functionModification) + { + m_functionMods << functionModification; + } + FunctionModificationList functionModifications(const QString& signature) const; + void setSuppressWarnings(bool on) { m_suppressWarnings = on; @@ -1932,6 +1952,9 @@ private: TemplateEntryHash m_templates; QStringList m_suppressedWarnings; + AddedFunctionList m_addedFunctions; + FunctionModificationList m_functionMods; + QStringList m_requiredTargetImports; QStringList m_typesystemPaths; |