aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2017-03-15 15:59:17 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2017-03-16 07:22:25 +0000
commit3c325a0004a377da14ad255addb42e23c4e9cf17 (patch)
treee124c854dc8657d834758a72595537b4b79a86b0
parent5d3329c54f7173e3ec5c76348ba7994e39f3641f (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.cpp86
-rw-r--r--ApiExtractor/abstractmetabuilder_p.h3
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);