diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-09-10 11:17:11 -0300 |
---|---|---|
committer | Hugo Lima <hugo.lima@openbossa.org> | 2009-09-15 14:01:38 -0300 |
commit | 752c22056f4ba61961a01819992f9af71a3b0416 (patch) | |
tree | de1531dc76801c6d7fdc6688be3879b920f95975 | |
parent | 2bf0c409590c15b72a960d693fad4ac48ce4b8a6 (diff) |
Fix a bug related to function default values.
ApiExtractor tries to modify the defaultValue every time, so then return value of
originalDefaultValue() if diferent from the return value of defaultValue() when
they dont need to be.
Unit test included.
-rw-r--r-- | abstractmetabuilder.cpp | 93 | ||||
-rw-r--r-- | abstractmetabuilder.h | 3 | ||||
-rw-r--r-- | tests/testabstractmetaclass.cpp | 53 | ||||
-rw-r--r-- | tests/testabstractmetaclass.h | 2 |
4 files changed, 56 insertions, 95 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 0ba989dc7..243bbae32 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -1517,10 +1517,7 @@ AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem fu if (!expr.isEmpty()) metaArg->setOriginalDefaultValueExpression(expr); - if (m_currentClass) { - expr = translateDefaultValue(arg, metaArg->type(), metaFunction, m_currentClass, i); - metaArg->setDefaultValueExpression(expr); - } + metaArg->setDefaultValueExpression(metaArg->originalDefaultValueExpression()); if (expr.isEmpty()) firstDefaultArgument = i; @@ -1853,94 +1850,6 @@ void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *metaType) } } -QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type, - AbstractMetaFunction *fnc, AbstractMetaClass *implementingClass, - int argumentIndex) -{ - QString functionName = fnc->name(); - QString className = implementingClass->qualifiedCppName(); - - QString replacedExpression = fnc->replacedDefaultExpression(implementingClass, argumentIndex + 1); - if (fnc->removedDefaultExpression(implementingClass, argumentIndex + 1)) - return ""; - else if (!replacedExpression.isEmpty()) - return replacedExpression; - - QString expr = item->defaultValueExpression(); - if (type) { - if (type->isPrimitive()) { - if (type->name() == "boolean") { - if (expr != "false" && expr != "true") { - bool ok = false; - int number = expr.toInt(&ok); - if (ok && number) - expr = "true"; - else - expr = "false"; - } - } else if (expr == "QVariant::Invalid") { - expr = QString::number(QVariant::Invalid); - } else { - // This can be an enum or flag so I need to delay the - // translation untill all namespaces are completly - // processed. This is done in figureOutEnumValues() - } - } else if (type->isFlags() || type->isEnum()) { - bool isNumber; - expr.toInt(&isNumber); - if (!isNumber && expr.indexOf("::") < 0) { - // Add the enum/flag scope to default value, making it usable - // from other contexts beside its owner class hierarchy - QRegExp typeRegEx("[^<]*[<]([^:]*::).*"); - typeRegEx.indexIn(type->minimalSignature()); - expr = typeRegEx.cap(1) + expr; - } - } else if (type->isContainer() && expr.contains('<')) { - QRegExp typeRegEx("[^<]*<(.*)>"); - typeRegEx.indexIn(type->minimalSignature()); - QRegExp defaultRegEx("([^<]*<).*(>[^>]*)"); - defaultRegEx.indexIn(expr); - expr = defaultRegEx.cap(1) + typeRegEx.cap(1) + defaultRegEx.cap(2); - } else { - // Here the default value is supposed to be a constructor, - // a class field, or a constructor receiving a class field - QRegExp defaultRegEx("([^\\(]*\\(|)([^\\)]*)(\\)|)"); - defaultRegEx.indexIn(expr); - - QString defaultValueCtorName = defaultRegEx.cap(1); - if (defaultValueCtorName.endsWith('(')) - defaultValueCtorName.chop(1); - - // Fix the scope for constructor using the already - // resolved argument type as a reference. - // The following regular expression extracts any - // use of namespaces/scopes from the type string. - QRegExp typeRegEx("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$"); - typeRegEx.indexIn(type->minimalSignature()); - - QString typeNamespace = typeRegEx.cap(1); - QString typeCtorName = typeRegEx.cap(2); - if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName) - expr.prepend(typeNamespace); - - // Fix scope if the parameter is a field of the current class - foreach (const AbstractMetaField* field, implementingClass->fields()) { - if (defaultRegEx.cap(2) == field->name()) { - expr = defaultRegEx.cap(1) + implementingClass->name() + "::" + defaultRegEx.cap(2) + defaultRegEx.cap(3); - break; - } - } - } - } else { - QString warn = QString("undefined type for default value '%3' of argument in function '%1', class '%2'") - .arg(functionName).arg(className).arg(item->defaultValueExpression()); - ReportHandler::warning(warn); - expr = QString(); - } - - return expr; -} - bool AbstractMetaBuilder::isQObject(const QString &qualifiedName) { if (qualifiedName == "QObject") diff --git a/abstractmetabuilder.h b/abstractmetabuilder.h index 4f0979129..fb4019317 100644 --- a/abstractmetabuilder.h +++ b/abstractmetabuilder.h @@ -117,9 +117,6 @@ public: void setupClonable(AbstractMetaClass *cls); void setupFunctionDefaults(AbstractMetaFunction *metaFunction, AbstractMetaClass *metaClass); - QString translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type, - AbstractMetaFunction *fnc, AbstractMetaClass *, - int argumentIndex); AbstractMetaType *translateType(const TypeInfo &type, bool *ok, bool resolveType = true, bool resolveScope = true); void decideUsagePattern(AbstractMetaType *type); diff --git a/tests/testabstractmetaclass.cpp b/tests/testabstractmetaclass.cpp index 2050fca20..63df54598 100644 --- a/tests/testabstractmetaclass.cpp +++ b/tests/testabstractmetaclass.cpp @@ -137,6 +137,59 @@ void TestAbstractMetaClass::testVirtualMethods() QCOMPARE(funcC->implementingClass(), c); } +void TestAbstractMetaClass::testDefaultValues() +{ + const char* cppCode ="\ + struct A {\ + class B {};\ + void method(B b = B());\ + };\ + "; + const char* xmlCode = "\ + <typesystem package=\"Foo\"> \ + <value-type name='A'/> \ + <value-type name='A::B'/> \ + </typesystem>"; + TestUtil t(cppCode, xmlCode, false); + AbstractMetaClassList classes = t.builder()->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* classA = classes.findClass("A"); + QCOMPARE(classA->queryFunctionsByName("method").count(), 1); + AbstractMetaFunction* method = classA->queryFunctionsByName("method").first(); + AbstractMetaArgument* arg = method->arguments().first(); + QCOMPARE(arg->defaultValueExpression(), arg->originalDefaultValueExpression()); +} + +void TestAbstractMetaClass::testModifiedDefaultValues() +{ + const char* cppCode ="\ + struct A {\ + class B {};\ + void method(B b = B());\ + };\ + "; + const char* xmlCode = "\ + <typesystem package=\"Foo\"> \ + <value-type name='A'> \ + <modify-function signature='method'>\ + <modify-argument index='1'>\ + <replace-default-expression with='Hello'/>\ + </modify-argument>\ + </modify-function>\ + </value-type>\ + <value-type name='A::B'/> \ + </typesystem>"; + TestUtil t(cppCode, xmlCode, false); + AbstractMetaClassList classes = t.builder()->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* classA = classes.findClass("A"); + QCOMPARE(classA->queryFunctionsByName("method").count(), 1); + AbstractMetaFunction* method = classA->queryFunctionsByName("method").first(); + AbstractMetaArgument* arg = method->arguments().first(); + QCOMPARE(arg->defaultValueExpression(), QString("B()")); + QCOMPARE(arg->originalDefaultValueExpression(), QString("Hello")); +} + QTEST_APPLESS_MAIN(TestAbstractMetaClass) diff --git a/tests/testabstractmetaclass.h b/tests/testabstractmetaclass.h index 54336e7bf..c89cbc5d1 100644 --- a/tests/testabstractmetaclass.h +++ b/tests/testabstractmetaclass.h @@ -35,6 +35,8 @@ private slots: void testClassName(); void testClassNameUnderNamespace(); void testVirtualMethods(); + void testDefaultValues(); + void testModifiedDefaultValues(); }; #endif // TESTABSTRACTMETACLASS_H |