aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--abstractmetabuilder.cpp12
-rw-r--r--abstractmetalang.cpp20
-rw-r--r--abstractmetalang.h3
-rw-r--r--tests/testaddfunction.cpp32
-rw-r--r--tests/testaddfunction.h1
-rw-r--r--typesystem.cpp33
-rw-r--r--typesystem.h23
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;