diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2011-09-01 18:53:22 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-09 19:10:19 -0300 |
commit | e7fdca6465740132bd881ffd9d20e61be47472d0 (patch) | |
tree | 00b4b44348d9389e4e394d08b99b11478f88d63c /abstractmetabuilder.cpp | |
parent | 2d3a55bd847616a9b666531795d3b99e5c78a56a (diff) |
Fixes method's argument types that are templates but the template variable wasn't declared.
An unit test was added.
Other unrelated tests had minor improvements.
Reviewed by Hugo Parente <hugo.lima@openbossa.org>
Reviewed by Luciano Wolf <luciano.wolf@openbossa.org>
Diffstat (limited to 'abstractmetabuilder.cpp')
-rw-r--r-- | abstractmetabuilder.cpp | 229 |
1 files changed, 156 insertions, 73 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 12c0aebde..9fc1674d8 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -1344,97 +1344,180 @@ void AbstractMetaBuilder::fixReturnTypeOfConversionOperator(AbstractMetaFunction metaFunction->replaceType(metaType); } +static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other) +{ + if (!type && !other) + return true; + if (!type || !other) + return false; + return type->typeEntry() == other->typeEntry() + && type->isConstant() == other->isConstant() + && type->isReference() == other->isReference() + && type->indirections() == other->indirections(); +} + +static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other) +{ + if (!func && !other) + return true; + if (!func || !other) + return false; + if (func->arguments().count() != other->arguments().count() + || func->isConstant() != other->isConstant() + || func->isStatic() != other->isStatic() + || !_compareAbstractMetaTypes(func->type(), other->type())) { + return false; + } + for (int i = 0; i < func->arguments().count(); ++i) { + if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type())) + return false; + } + return true; +} + +static bool _fixFunctionModelItemType(TypeInfo& type, const AbstractMetaClass* metaClass) +{ + if (metaClass->templateArguments().isEmpty() + || type.qualifiedName().isEmpty() + || type.qualifiedName().first() != metaClass->typeEntry()->qualifiedCppName()) { + return false; + } + QStringList templateTypes; + foreach (TypeEntry* templateType, metaClass->templateArguments()) + templateTypes << templateType->qualifiedCppName(); + QString fixedTypeName = QString("%1<%2 >").arg(metaClass->typeEntry()->qualifiedCppName()).arg(templateTypes.join(", ")); + type.setQualifiedName(QStringList(fixedTypeName)); + return true; +} + +static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass) +{ + TypeInfo functionType = function->type(); + bool templateTypeFixed = _fixFunctionModelItemType(functionType, metaClass); + if (templateTypeFixed) + function->setType(functionType); + + ArgumentList arguments = function->arguments(); + for (int i = 0; i < arguments.size(); ++i) { + ArgumentModelItem arg = arguments.at(i); + TypeInfo type = arg->type(); + bool tmpTypeFixed = _fixFunctionModelItemType(type, metaClass); + if (tmpTypeFixed) + arg->setType(type); + templateTypeFixed |= tmpTypeFixed; + } + return templateTypeFixed; +} + void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scopeItem, AbstractMetaClass* metaClass) { foreach (FunctionModelItem function, scopeItem->functions()) { + + // This fixes method's arguments and return types that are templates + // but the template variable wasn't declared in the C++ header. + bool templateTypeFixed = _fixFunctionModelItemTypes(function, metaClass); + AbstractMetaFunction* metaFunction = traverseFunction(function); - if (metaFunction) { - metaFunction->setOriginalAttributes(metaFunction->attributes()); - if (metaClass->isNamespace()) - *metaFunction += AbstractMetaAttributes::Static; - - QPropertySpec *read = 0; - if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) { - // Property reader must be in the form "<type> name()" - if (metaFunction->type() && (read->type() == metaFunction->type()->typeEntry()) && (metaFunction->arguments().size() == 0)) { - *metaFunction += AbstractMetaAttributes::PropertyReader; - metaFunction->setPropertySpec(read); - } - } else if (QPropertySpec* write = metaClass->propertySpecForWrite(metaFunction->name())) { - // Property setter must be in the form "void name(<type>)" - // make sure the function was created with all aguments, some argument can be missing during the pareser because of errors on typesystem - if ((!metaFunction->type()) && (metaFunction->arguments().size() == 1) && (write->type() == metaFunction->arguments().at(0)->type()->typeEntry())) { - *metaFunction += AbstractMetaAttributes::PropertyWriter; - metaFunction->setPropertySpec(write); - } - } else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) { - // Property resetter must be in the form "void name()" - if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) { - *metaFunction += AbstractMetaAttributes::PropertyResetter; - metaFunction->setPropertySpec(reset); + if (!metaFunction) + continue; + + if (templateTypeFixed) { + foreach (AbstractMetaFunction* func, metaClass->queryFunctionsByName(metaFunction->name())) { + if (_compareAbstractMetaFunctions(metaFunction, func)) { + delete metaFunction; + metaFunction = 0; + break; } } + if (!metaFunction) + continue; + } - // Can not use metaFunction->isCopyConstructor() because - // the function wasn't assigned to its owner class yet. - bool isCopyCtor = false; - if (metaFunction->isConstructor() && metaFunction->arguments().size() == 1) { - const AbstractMetaType* argType = metaFunction->arguments().first()->type(); - isCopyCtor = argType->isConstant() - && argType->isReference() - && argType->typeEntry()->name() == metaFunction->name(); + metaFunction->setOriginalAttributes(metaFunction->attributes()); + if (metaClass->isNamespace()) + *metaFunction += AbstractMetaAttributes::Static; + + QPropertySpec *read = 0; + if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) { + // Property reader must be in the form "<type> name()" + if (metaFunction->type() && (read->type() == metaFunction->type()->typeEntry()) && (metaFunction->arguments().size() == 0)) { + *metaFunction += AbstractMetaAttributes::PropertyReader; + metaFunction->setPropertySpec(read); } - - bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); - bool isInvalidConstructor = metaFunction->isConstructor() - && ((metaFunction->isPrivate() && !isCopyCtor) || metaFunction->isInvalid()); - - if ((isInvalidDestructor || isInvalidConstructor) - && !metaClass->hasNonPrivateConstructor()) { - *metaClass += AbstractMetaAttributes::Final; - } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) { - *metaClass -= AbstractMetaAttributes::Final; - metaClass->setHasNonPrivateConstructor(true); + } else if (QPropertySpec* write = metaClass->propertySpecForWrite(metaFunction->name())) { + // Property setter must be in the form "void name(<type>)" + // make sure the function was created with all aguments, some argument can be missing during the pareser because of errors on typesystem + if ((!metaFunction->type()) && (metaFunction->arguments().size() == 1) && (write->type() == metaFunction->arguments().at(0)->type()->typeEntry())) { + *metaFunction += AbstractMetaAttributes::PropertyWriter; + metaFunction->setPropertySpec(write); + } + } else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) { + // Property resetter must be in the form "void name()" + if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) { + *metaFunction += AbstractMetaAttributes::PropertyResetter; + metaFunction->setPropertySpec(reset); } + } - // Classes with virtual destructors should always have a shell class - // (since we aren't registering the destructors, we need this extra check) - if (metaFunction->isDestructor() && !metaFunction->isFinal()) - metaClass->setForceShellClass(true); + // Can not use metaFunction->isCopyConstructor() because + // the function wasn't assigned to its owner class yet. + bool isCopyCtor = false; + if (metaFunction->isConstructor() && metaFunction->arguments().size() == 1) { + const AbstractMetaType* argType = metaFunction->arguments().first()->type(); + isCopyCtor = argType->isConstant() + && argType->isReference() + && argType->typeEntry()->name() == metaFunction->name(); + } - if (!metaFunction->isDestructor() - && !metaFunction->isInvalid() - && !(metaFunction->isPrivate() && metaFunction->isConstructor() && !isCopyCtor)) { + bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); + bool isInvalidConstructor = metaFunction->isConstructor() + && ((metaFunction->isPrivate() && !isCopyCtor) || metaFunction->isInvalid()); - setupFunctionDefaults(metaFunction, metaClass); + if ((isInvalidDestructor || isInvalidConstructor) + && !metaClass->hasNonPrivateConstructor()) { + *metaClass += AbstractMetaAttributes::Final; + } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) { + *metaClass -= AbstractMetaAttributes::Final; + metaClass->setHasNonPrivateConstructor(true); + } - if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction)) { - QString warn = QString("signal '%1' in class '%2' is overloaded.") - .arg(metaFunction->name()).arg(metaClass->name()); - ReportHandler::warning(warn); - } + // Classes with virtual destructors should always have a shell class + // (since we aren't registering the destructors, we need this extra check) + if (metaFunction->isDestructor() && !metaFunction->isFinal()) + metaClass->setForceShellClass(true); - if (metaFunction->isSignal() && !metaClass->isQObject()) { - QString warn = QString("signal '%1' in non-QObject class '%2'") - .arg(metaFunction->name()).arg(metaClass->name()); - ReportHandler::warning(warn); - } + if (!metaFunction->isDestructor() + && !metaFunction->isInvalid() + && !(metaFunction->isPrivate() && metaFunction->isConstructor() && !isCopyCtor)) { - if (metaFunction->isConversionOperator()) - fixReturnTypeOfConversionOperator(metaFunction); + setupFunctionDefaults(metaFunction, metaClass); - metaClass->addFunction(metaFunction); - applyFunctionModifications(metaFunction); - } else if (metaFunction->isDestructor()) { - metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); - metaClass->setHasProtectedDestructor(metaFunction->isProtected()); - metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); + if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction)) { + QString warn = QString("signal '%1' in class '%2' is overloaded.") + .arg(metaFunction->name()).arg(metaClass->name()); + ReportHandler::warning(warn); } - if (!metaFunction->ownerClass()) { - delete metaFunction; - metaFunction = 0; + + if (metaFunction->isSignal() && !metaClass->isQObject()) { + QString warn = QString("signal '%1' in non-QObject class '%2'") + .arg(metaFunction->name()).arg(metaClass->name()); + ReportHandler::warning(warn); } + + if (metaFunction->isConversionOperator()) + fixReturnTypeOfConversionOperator(metaFunction); + + metaClass->addFunction(metaFunction); + applyFunctionModifications(metaFunction); + } else if (metaFunction->isDestructor()) { + metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); + metaClass->setHasProtectedDestructor(metaFunction->isProtected()); + metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); + } + if (!metaFunction->ownerClass()) { + delete metaFunction; + metaFunction = 0; } } @@ -1738,7 +1821,6 @@ AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(FunctionModelItem fu return 0; } - Q_ASSERT(functionItem->functionType() == CodeModel::Normal || functionItem->functionType() == CodeModel::Signal || functionItem->functionType() == CodeModel::Slot); @@ -1845,6 +1927,7 @@ AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(FunctionModelItem fu metaFunction->setInvalid(true); return metaFunction; } + AbstractMetaArgument* metaArgument = createMetaArgument(); metaArgument->setType(metaType); |