diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-10-20 17:38:32 -0200 |
---|---|---|
committer | Luciano Miguel Wolf <luciano.wolf@indt.org.br> | 2009-10-21 16:34:20 -0300 |
commit | 071233773dd5a4f3ccacebf77f2102780a9dc624 (patch) | |
tree | f441d12177b63d9f634e12edb4bed9341f6d5e84 | |
parent | 73f6ac4faafed5c8c275ff01a22a53bfbc7fc515 (diff) |
Added support for add-function tag into typesystem.
-rw-r--r-- | abstractmetabuilder.cpp | 57 | ||||
-rw-r--r-- | abstractmetabuilder.h | 2 | ||||
-rw-r--r-- | abstractmetalang.h | 3 | ||||
-rw-r--r-- | tests/testaddfunction.cpp | 95 | ||||
-rw-r--r-- | tests/testaddfunction.h | 2 | ||||
-rw-r--r-- | typesystem.cpp | 30 | ||||
-rw-r--r-- | typesystem.h | 30 |
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&)' 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; |