aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-10-20 17:38:32 -0200
committerLuciano Miguel Wolf <luciano.wolf@indt.org.br>2009-10-21 16:34:20 -0300
commit071233773dd5a4f3ccacebf77f2102780a9dc624 (patch)
treef441d12177b63d9f634e12edb4bed9341f6d5e84
parent73f6ac4faafed5c8c275ff01a22a53bfbc7fc515 (diff)
Added support for add-function tag into typesystem.
-rw-r--r--abstractmetabuilder.cpp57
-rw-r--r--abstractmetabuilder.h2
-rw-r--r--abstractmetalang.h3
-rw-r--r--tests/testaddfunction.cpp95
-rw-r--r--tests/testaddfunction.h2
-rw-r--r--typesystem.cpp30
-rw-r--r--typesystem.h30
7 files changed, 166 insertions, 53 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp
index 5df7328fd..773dda22b 100644
--- a/abstractmetabuilder.cpp
+++ b/abstractmetabuilder.cpp
@@ -1210,6 +1210,15 @@ void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scopeItem, AbstractMe
applyFunctionModifications(metaFunction);
}
}
+
+ // Add the functions added by the typesystem
+ foreach (AddedFunction addedFunc, metaClass->typeEntry()->addedFunctions()) {
+ AbstractMetaFunction* func = traverseFunction(addedFunc);
+ func->setDeclaringClass(metaClass);
+ func->setImplementingClass(metaClass);
+ metaClass->addFunction(func);
+ }
+
}
void AbstractMetaBuilder::applyFunctionModifications(AbstractMetaFunction* func)
@@ -1373,6 +1382,33 @@ void AbstractMetaBuilder::traverseEnums(ScopeModelItem scopeItem, AbstractMetaCl
}
}
+AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(const AddedFunction& addedFunc)
+{
+ AbstractMetaFunction* metaFunction = createMetaFunction();
+ metaFunction->setConstant(addedFunc.isConstant());
+ metaFunction->setName(addedFunc.name());
+ metaFunction->setOriginalName(addedFunc.name());
+ int visibility = addedFunc.access() == AddedFunction::Public ? AbstractMetaAttributes::Public : AbstractMetaAttributes::Protected;
+ metaFunction->setVisibility(visibility);
+ metaFunction->setFunctionType(AbstractMetaFunction::UserAddedFunction);
+ metaFunction->setType(translateType(addedFunc.returnType()));
+
+ QList<AddedFunction::TypeInfo> args = addedFunc.arguments();
+ for (int i = 0; i < args.count(); ++i) {
+ AddedFunction::TypeInfo& typeInfo = args[i];
+ AbstractMetaArgument* metaArg = createMetaArgument();
+ AbstractMetaType* type = translateType(typeInfo);
+ metaArg->setType(type);
+ metaArg->setArgumentIndex(i);
+ metaArg->setDefaultValueExpression(typeInfo.defaultValue);
+ metaArg->setOriginalDefaultValueExpression(typeInfo.defaultValue);
+ metaArg->setName(typeInfo.name);
+ metaFunction->addArgument(metaArg);
+ }
+
+ return metaFunction;
+}
+
AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem functionItem)
{
QString functionName = functionItem->name();
@@ -1546,6 +1582,27 @@ AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem fu
return metaFunction;
}
+AbstractMetaType* AbstractMetaBuilder::translateType(const AddedFunction::TypeInfo& typeInfo)
+{
+ Q_ASSERT(!typeInfo.name.isEmpty());
+ AbstractMetaType *metaType = createMetaType();
+ TypeDatabase* typeDb = TypeDatabase::instance();
+ TypeEntry* type;
+
+ if (typeInfo.name == "void") {
+ return 0;
+ }
+
+ type = typeDb->findType(typeInfo.name);
+ if (!type)
+ type = new TypeEntry(typeInfo.name, TypeEntry::TargetLangType);
+
+ metaType->setTypeEntry(type);
+ metaType->setIndirections(typeInfo.indirections);
+ metaType->setReference(typeInfo.isReference);
+ metaType->setConstant(typeInfo.isConstant);
+ return metaType;
+}
AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
{
diff --git a/abstractmetabuilder.h b/abstractmetabuilder.h
index 1b66ac5a9..18ee74365 100644
--- a/abstractmetabuilder.h
+++ b/abstractmetabuilder.h
@@ -105,6 +105,7 @@ public:
void traverseFields(ScopeModelItem item, AbstractMetaClass *parent);
void traverseStreamOperator(FunctionModelItem functionItem);
void traverseOperatorFunction(FunctionModelItem item);
+ AbstractMetaFunction *traverseFunction(const AddedFunction& addedFunc);
AbstractMetaFunction *traverseFunction(FunctionModelItem function);
AbstractMetaField *traverseField(VariableModelItem field, const AbstractMetaClass *cls);
void checkFunctionModifications();
@@ -120,6 +121,7 @@ public:
QString fixDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
AbstractMetaFunction *fnc, AbstractMetaClass *,
int argumentIndex);
+ AbstractMetaType* translateType(const AddedFunction::TypeInfo& typeInfo);
AbstractMetaType *translateType(const TypeInfo &type, bool *ok, bool resolveType = true, bool resolveScope = true);
void decideUsagePattern(AbstractMetaType *type);
diff --git a/abstractmetalang.h b/abstractmetalang.h
index 13ec712cc..d53c5656a 100644
--- a/abstractmetalang.h
+++ b/abstractmetalang.h
@@ -746,7 +746,8 @@ public:
SignalFunction,
EmptyFunction,
SlotFunction,
- GlobalScopeFunction
+ GlobalScopeFunction,
+ UserAddedFunction, // Function added by the typesystem
};
enum CompareResult {
diff --git a/tests/testaddfunction.cpp b/tests/testaddfunction.cpp
index a47cd28af..d36411cc8 100644
--- a/tests/testaddfunction.cpp
+++ b/tests/testaddfunction.cpp
@@ -28,53 +28,118 @@
void TestAddFunction::testParsingFuncNameAndConstness()
{
+ // generic test...
const char sig1[] = "func(type1, const type2, const type3* const)";
AddedFunction f1(sig1, "void");
QCOMPARE(f1.name(), QString("func"));
+ QCOMPARE(f1.arguments().count(), 3);
AddedFunction::TypeInfo retval = f1.returnType();
QCOMPARE(retval.name, QString("void"));
QCOMPARE(retval.indirections, 0);
- QCOMPARE(retval.isConst, false);
- QCOMPARE(retval.isRef, false);
+ QCOMPARE(retval.isConstant, false);
+ QCOMPARE(retval.isReference, false);
+ // test with a ugly template as argument and other ugly stuff
const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *, const type3* const ) const ";
AddedFunction f2(sig2, "const Abc<int& , C<char*> * > * *");
QCOMPARE(f2.name(), QString("_fu__nc_"));
+ QList< AddedFunction::TypeInfo > args = f2.arguments();
+ QCOMPARE(args.count(), 4);
retval = f2.returnType();
QCOMPARE(retval.name, QString("Abc<int& , C<char*> * >"));
QCOMPARE(retval.indirections, 2);
- QCOMPARE(retval.isConst, true);
- QCOMPARE(retval.isRef, false);
- QList< AddedFunction::TypeInfo > args = f2.arguments();
- QCOMPARE(args.count(), 4);
+ QCOMPARE(retval.isConstant, true);
+ QCOMPARE(retval.isReference, false);
retval = args[2];
QCOMPARE(retval.name, QString("Abc<int& , C<char*> * >"));
QCOMPARE(retval.indirections, 2);
- QCOMPARE(retval.isConst, true);
- QCOMPARE(retval.isRef, false);
-
+ QCOMPARE(retval.isConstant, true);
+ QCOMPARE(retval.isReference, false);
+ // function with no args.
+ const char sig3[] = "func()";
+ AddedFunction f3(sig3, "void");
+ QCOMPARE(f3.name(), QString("func"));
+ QCOMPARE(f3.arguments().count(), 0);
}
void TestAddFunction::testAddFunction()
{
-#if 0
- const char cppCode[] = "struct A { void a(); };";
+ const char cppCode[] = "struct B {}; struct A { void a(int); };";
const char xmlCode[] = "\
- <typesystem package=\"Foo\"> \
- <value-type name='A'> \
- <add-function signature='b(int, float)' return-type='int' acess='protected'>\
+ <typesystem package=\"Foo\">\
+ <primitive-type name='int' />\
+ <primitive-type name='float' />\
+ <value-type name='B' />\
+ <value-type name='A'>\
+ <add-function signature='b(int, float = 4.6, const B&amp;)' return-type='int' access='protected'>\
</add-function>\
</value-type>\
</typesystem>";
TestUtil t(cppCode, xmlCode);
+ TypeDatabase* typeDb = TypeDatabase::instance();
+ AbstractMetaClassList classes = t.builder()->classes();
+ AbstractMetaClass* classA = classes.findClass("A");
+ QVERIFY(classA);
+ QCOMPARE(classA->functions().count(), 3); // default ctor, func a() and the added function
+
+ AbstractMetaFunction* addedFunc = classA->functions().last();
+ QCOMPARE(addedFunc->visibility(), uint(AbstractMetaFunction::Protected));
+ QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::UserAddedFunction);
+ QCOMPARE(addedFunc->ownerClass(), classA);
+ QCOMPARE(addedFunc->implementingClass(), classA);
+ QCOMPARE(addedFunc->declaringClass(), classA);
+ AbstractMetaType* returnType = addedFunc->type();
+ QCOMPARE(returnType->typeEntry(), typeDb->findPrimitiveType("int"));
+ AbstractMetaArgumentList args = addedFunc->arguments();
+ QCOMPARE(args.count(), 3);
+ QCOMPARE(args[0]->type()->typeEntry(), returnType->typeEntry());
+ QCOMPARE(args[1]->defaultValueExpression(), QString("4.6"));
+ QCOMPARE(args[2]->type()->typeEntry(), typeDb->findType("B"));
+}
+
+void TestAddFunction::testAddFunctionTagDefaultValues()
+{
+ const char cppCode[] = "struct A {};";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\
+ <value-type name='A'>\
+ <add-function signature='func()' />\
+ </value-type>\
+ </typesystem>";
+ TestUtil t(cppCode, xmlCode, false);
AbstractMetaClassList classes = t.builder()->classes();
AbstractMetaClass* classA = classes.findClass("A");
QVERIFY(classA);
QCOMPARE(classA->functions().count(), 2); // default ctor and the added function
-#endif
+ AbstractMetaFunction* addedFunc = classA->functions().last();
+ QCOMPARE(addedFunc->visibility(), uint(AbstractMetaFunction::Public));
+ QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::UserAddedFunction);
+ QVERIFY(!addedFunc->type());
+}
+
+
+void TestAddFunction::testAddFunctionCodeSnippets()
+{
+ const char cppCode[] = "struct A {};";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\
+ <value-type name='A'>\
+ <add-function signature='func()'>\
+ <inject-code class='target' position='end'>Hi!, I am the code.</inject-code>\
+ </add-function>\
+ </value-type>\
+ </typesystem>";
+
+ TestUtil t(cppCode, xmlCode, false);
+ AbstractMetaClassList classes = t.builder()->classes();
+ AbstractMetaClass* classA = classes.findClass("A");
+ QVERIFY(classA);
+ AbstractMetaFunction* addedFunc = classA->functions().last();
+ QVERIFY(addedFunc->hasInjectedCode());
}
+
QTEST_APPLESS_MAIN(TestAddFunction)
#include "testaddfunction.moc"
diff --git a/tests/testaddfunction.h b/tests/testaddfunction.h
index 7fe07d6a4..45a562d4b 100644
--- a/tests/testaddfunction.h
+++ b/tests/testaddfunction.h
@@ -31,6 +31,8 @@ class TestAddFunction : public QObject
private slots:
void testParsingFuncNameAndConstness();
void testAddFunction();
+ void testAddFunctionTagDefaultValues();
+ void testAddFunctionCodeSnippets();
};
#endif \ No newline at end of file
diff --git a/typesystem.cpp b/typesystem.cpp
index e10ff380a..9c1e51df7 100644
--- a/typesystem.cpp
+++ b/typesystem.cpp
@@ -166,6 +166,7 @@ public:
tagNames["parent"] = StackElement::ParentOwner;
tagNames["inject-documentation"] = StackElement::InjectDocumentation;
tagNames["modify-documentation"] = StackElement::ModifyDocumentation;
+ tagNames["add-function"] = StackElement::AddFunction;
}
bool startElement(const QString &namespaceURI, const QString &localName,
@@ -348,12 +349,10 @@ bool Handler::characters(const QString &ch)
((TypeSystemTypeEntry *) m_current->parent->entry)->codeSnips().last().addCode(ch);
break;
case StackElement::ModifyFunction:
+ case StackElement::AddFunction:
m_functionMods.last().snips.last().addCode(ch);
m_functionMods.last().modifiers |= FunctionModification::CodeInjection;
break;
- case StackElement::AddFunction:
- m_addedFunctions.last().codeSnips().last().addCode(ch);
- break;
case StackElement::NamespaceTypeEntry:
case StackElement::ObjectTypeEntry:
case StackElement::ValueTypeEntry:
@@ -1281,24 +1280,26 @@ bool Handler::startElement(const QString &, const QString &n,
return false;
}
- AddedFunction func(signature, attributes["return-value"]);
+ AddedFunction func(signature, attributes["return-type"]);
m_currentSignature = signature;
QString access = attributes["access"].toLower();
if (!access.isEmpty()) {
- if (access == QLatin1String("private"))
- func.setAccess(AddedFunction::Private);
- else if (access == QLatin1String("protected"))
+ if (access == QLatin1String("protected")) {
func.setAccess(AddedFunction::Protected);
- else if (access == QLatin1String("public"))
+ } else if (access == QLatin1String("public")) {
func.setAccess(AddedFunction::Public);
- else {
+ } else {
m_error = QString::fromLatin1("Bad access type '%1'").arg(access);
return false;
}
}
m_addedFunctions << func;
+
+ FunctionModification mod;
+ mod.signature = signature;
+ m_functionMods << mod;
}
break;
case StackElement::ModifyFunction: {
@@ -1538,7 +1539,7 @@ bool Handler::startElement(const QString &, const QString &n,
return false;
}
- if (topElement.type == StackElement::ModifyFunction) {
+ if (topElement.type == StackElement::ModifyFunction || topElement.type == StackElement::AddFunction) {
FunctionModification mod = m_functionMods.last();
if (snip.language == TypeSystem::ShellDeclaration) {
m_error = "no function implementation in shell declaration in which to inject code";
@@ -1802,7 +1803,6 @@ FunctionModificationList ComplexTypeEntry::functionModifications(const QString &
const FunctionModification &mod = m_functionMods.at(i);
if (mod.signature == signature)
lst << mod;
-
}
return lst;
@@ -2079,13 +2079,13 @@ static AddedFunction::TypeInfo parseType(const QString& signature, int startPos
// check constness
if (paramString.startsWith("const ")) {
- result.isConst = true;
+ result.isConstant = true;
paramString.remove(0, sizeof("const")/sizeof(char));
paramString = paramString.trimmed();
}
// check reference
if (paramString.endsWith("&")) {
- result.isRef = true;
+ result.isReference = true;
paramString.chop(1);
paramString = paramString.trimmed();
}
@@ -2102,6 +2102,7 @@ static AddedFunction::TypeInfo parseType(const QString& signature, int startPos
AddedFunction::AddedFunction(QString signature, QString returnType) : m_access(Public)
{
+ Q_ASSERT(!returnType.isEmpty());
m_returnType = parseType(returnType);
signature = signature.trimmed();
int endPos = signature.indexOf('(');
@@ -2109,7 +2110,8 @@ AddedFunction::AddedFunction(QString signature, QString returnType) : m_access(P
int signatureLength = signature.length();
while (endPos < signatureLength) {
TypeInfo arg = parseType(signature, endPos, &endPos);
- m_arguments.append(arg);
+ if (!arg.name.isEmpty())
+ m_arguments.append(arg);
// end of parameters...
if (signature[endPos] == ')')
break;
diff --git a/typesystem.h b/typesystem.h
index 7f232ac93..9038b22a6 100644
--- a/typesystem.h
+++ b/typesystem.h
@@ -445,17 +445,16 @@ typedef QList<FieldModification> FieldModificationList;
struct AddedFunction
{
enum Access {
- Private = 0x1,
- Protected = 0x2,
- Public = 0x3
+ Protected = 0x1,
+ Public = 0x2
};
struct TypeInfo {
- TypeInfo() : isConst(false), indirections(0), isRef(false) {}
+ TypeInfo() : isConstant(false), indirections(0), isReference(false) {}
QString name;
- bool isConst;
+ bool isConstant;
int indirections;
- bool isRef;
+ bool isReference;
QString defaultValue;
};
@@ -481,37 +480,22 @@ struct AddedFunction
return m_returnType;
}
- CodeSnipList codeSnips() const
- {
- return m_codeSnips;
- }
-
- void setCodeSnips(const CodeSnipList& codeSnips)
- {
- m_codeSnips = codeSnips;
- }
-
- void addCodeSnip(const CodeSnip& codeSnip)
- {
- m_codeSnips << codeSnip;
- }
-
QList<TypeInfo> arguments() const
{
return m_arguments;
}
- bool isConst() const
+ bool isConstant() const
{
return m_isConst;
}
+
private:
QString m_name;
Access m_access;
QList<TypeInfo> m_arguments;
TypeInfo m_returnType;
bool m_isConst;
- CodeSnipList m_codeSnips;
};
typedef QList<AddedFunction> AddedFunctionList;