aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-09-10 11:17:11 -0300
committerHugo Lima <hugo.lima@openbossa.org>2009-09-15 14:01:38 -0300
commit752c22056f4ba61961a01819992f9af71a3b0416 (patch)
treede1531dc76801c6d7fdc6688be3879b920f95975
parent2bf0c409590c15b72a960d693fad4ac48ce4b8a6 (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.cpp93
-rw-r--r--abstractmetabuilder.h3
-rw-r--r--tests/testabstractmetaclass.cpp53
-rw-r--r--tests/testabstractmetaclass.h2
4 files changed, 56 insertions, 95 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp
index 0ba989dc..243bbae3 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 4f097912..fb401931 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 2050fca2..63df5459 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 54336e7b..c89cbc5d 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