diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-03-15 15:59:17 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-03-16 07:22:25 +0000 |
commit | 3c325a0004a377da14ad255addb42e23c4e9cf17 (patch) | |
tree | e124c854dc8657d834758a72595537b4b79a86b0 | |
parent | 5d3329c54f7173e3ec5c76348ba7994e39f3641f (diff) |
AbstractMetaBuilder::traverseFunctions() Split out duplicate removal
The removal of duplicate member function entries depended on the
fact that the more specific, out-of-line function definitions were
first in the list of functions returned by ScopeModelItem::functions().
This happened to work by coincidence since ScopeModelItem used a
QHash, which reversed the order returned by the parser.
When trying to replace the QHash by a QList in order to get
rid of the non-determinism,
TestTemplates::testContainerTypeIncompleteArgument() would fail
since it finds 2 entries for "method()".
Change-Id: I7c5a49bef8644d1f05e6a14295b304b1a9b8c46f
Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r-- | ApiExtractor/abstractmetabuilder.cpp | 86 | ||||
-rw-r--r-- | ApiExtractor/abstractmetabuilder_p.h | 3 |
2 files changed, 71 insertions, 18 deletions
diff --git a/ApiExtractor/abstractmetabuilder.cpp b/ApiExtractor/abstractmetabuilder.cpp index 4952aa2c0..d028c9392 100644 --- a/ApiExtractor/abstractmetabuilder.cpp +++ b/ApiExtractor/abstractmetabuilder.cpp @@ -1566,32 +1566,82 @@ static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const Abstra return templateTypeFixed; } -void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, - AbstractMetaClass *metaClass) +AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem) { - foreach (FunctionModelItem function, scopeItem->functions()) { + AbstractMetaFunctionList result; + const FunctionList &scopeFunctionList = scopeItem->functions(); + result.reserve(scopeFunctionList.size()); + foreach (const FunctionModelItem &function, scopeItem->functions()) { + if (AbstractMetaFunction *metaFunction = traverseFunction(function)) + result.append(metaFunction); + } + return result; +} +// For template classes, entries with more specific types may exist from out-of- +// line definitions. If there is a declaration which matches it after fixing +// the parameters, remove it as duplicate. For example: +// template class<T> Vector { public: +// Vector(const Vector &rhs); +// }; +// template class<T> +// Vector<T>::Vector(const Vector<T>&) {} // More specific, remove declaration. + +AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(const ScopeModelItem &scopeItem, + AbstractMetaClass *metaClass) +{ + class DuplicatingFunctionPredicate : public std::unary_function<bool, const AbstractMetaFunction *> { + public: + explicit DuplicatingFunctionPredicate(const AbstractMetaFunction *f) : m_function(f) {} + + bool operator()(const AbstractMetaFunction *rhs) const + { + return rhs != m_function && rhs->name() == m_function->name() + && _compareAbstractMetaFunctions(m_function, rhs); + } + + private: + const AbstractMetaFunction *m_function; + }; + + AbstractMetaFunctionList result; + AbstractMetaFunctionList unchangedFunctions; + + const FunctionList &scopeFunctionList = scopeItem->functions(); + result.reserve(scopeFunctionList.size()); + unchangedFunctions.reserve(scopeFunctionList.size()); + 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); + const bool templateTypeFixed =_fixFunctionModelItemTypes(function, metaClass); + if (AbstractMetaFunction *metaFunction = traverseFunction(function)) { + result.append(metaFunction); + if (!templateTypeFixed) + unchangedFunctions.append(metaFunction); + } + } - AbstractMetaFunction* metaFunction = traverseFunction(function); + const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.begin(); + const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.end(); + for (int i = result.size() - 1; i >= 0; --i) { + AbstractMetaFunction *function = result.at(i); + if (!unchangedFunctions.contains(function) + && unchangedEnd != std::find_if(unchangedBegin, unchangedEnd, DuplicatingFunctionPredicate(function))) { + delete result.takeAt(i); + } + } + return result; +} - if (!metaFunction) - continue; +void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, + AbstractMetaClass *metaClass) +{ - if (templateTypeFixed) { - foreach (AbstractMetaFunction* func, metaClass->queryFunctionsByName(metaFunction->name())) { - if (_compareAbstractMetaFunctions(metaFunction, func)) { - delete metaFunction; - metaFunction = 0; - break; - } - } - if (!metaFunction) - continue; - } + const AbstractMetaFunctionList functions = metaClass->templateArguments().isEmpty() + ? classFunctionList(scopeItem) + : templateClassFunctionList(scopeItem, metaClass); + foreach (AbstractMetaFunction *metaFunction, functions) { metaFunction->setOriginalAttributes(metaFunction->attributes()); if (metaClass->isNamespace()) *metaFunction += AbstractMetaAttributes::Static; diff --git a/ApiExtractor/abstractmetabuilder_p.h b/ApiExtractor/abstractmetabuilder_p.h index 8957de15f..f45f66d0b 100644 --- a/ApiExtractor/abstractmetabuilder_p.h +++ b/ApiExtractor/abstractmetabuilder_p.h @@ -81,6 +81,9 @@ public: const QSet<QString> &enumsDeclarations); void traverseEnums(ScopeModelItem item, AbstractMetaClass *parent, const QStringList &enumsDeclarations); + AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem); + AbstractMetaFunctionList templateClassFunctionList(const ScopeModelItem &scopeItem, + AbstractMetaClass *metaClass); void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); void applyFunctionModifications(AbstractMetaFunction* func); void traverseFields(ScopeModelItem item, AbstractMetaClass *parent); |