diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index 3086ca0d0f6..1ae48798d69 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -212,35 +212,6 @@ void FindUsages::reportResult(unsigned tokenIndex) _references.append(tokenIndex); } -bool FindUsages::compareFullyQualifiedName(const QList &path, const QList &other) -{ - if (path.length() != other.length()) - return false; - - for (int i = 0; i < path.length(); ++i) { - if (! compareName(path.at(i), other.at(i))) - return false; - } - - return true; -} - -bool FindUsages::compareName(const Name *name, const Name *other) -{ - if (name == other) - return true; - - else if (name && other) { - const Identifier *id = name->identifier(); - const Identifier *otherId = other->identifier(); - - if (id == otherId || (id && id->isEqualTo(otherId))) - return true; - } - - return false; -} - bool FindUsages::isLocalScope(Scope *scope) { if (scope) { diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h index 2f5ec585b94..bd943238921 100644 --- a/src/libs/cplusplus/FindUsages.h +++ b/src/libs/cplusplus/FindUsages.h @@ -82,8 +82,6 @@ protected: bool checkCandidates(const QList &candidates) const; void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = 0); - static bool compareFullyQualifiedName(const QList &path, const QList &other); - static bool compareName(const Name *name, const Name *other); static bool isLocalScope(Scope *scope); void statement(StatementAST *ast); diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index d41846014ca..8dbaf72cf83 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -88,6 +88,39 @@ static void path_helper(Symbol *symbol, QList *names) } } +static bool compareName(const Name *name, const Name *other) +{ + if (name == other) + return true; + + else if (name && other) { + const Identifier *id = name->identifier(); + const Identifier *otherId = other->identifier(); + + if (id == otherId || (id && id->isEqualTo(otherId))) + return true; + } + + return false; +} + +namespace CPlusPlus { + +bool compareFullyQualifiedName(const QList &path, const QList &other) +{ + if (path.length() != other.length()) + return false; + + for (int i = 0; i < path.length(); ++i) { + if (! compareName(path.at(i), other.at(i))) + return false; + } + + return true; +} + +} + bool ClassOrNamespace::CompareName::operator()(const Name *name, const Name *other) const { Q_ASSERT(name != 0); @@ -416,20 +449,51 @@ QList ClassOrNamespace::lookup_helper(const Name *name, bool searchI QList result; if (name) { - QSet processed; if (const QualifiedNameId *q = name->asQualifiedNameId()) { if (! q->base()) result = globalNamespace()->find(q->name()); - else if (ClassOrNamespace *binding = lookupType(q->base())) + else if (ClassOrNamespace *binding = lookupType(q->base())) { result = binding->find(q->name()); - lookup_helper(name, this, &result, &processed, /*templateId = */ 0); + QList fullName; + addNames(name, &fullName); + + // It's also possible that there are matches in the parent binding through + // a qualified name. For instance, a nested class which is forward declared + // in the class but defined outside it - we should capture both. + Symbol *match = 0; + ClassOrNamespace *parentBinding = binding->parent(); + while (parentBinding && !match) { + for (int j = 0; j < parentBinding->symbols().size() && !match; ++j) { + if (Scope *scope = parentBinding->symbols().at(j)->asScope()) { + for (unsigned i = 0; i < scope->memberCount(); ++i) { + Symbol *candidate = scope->memberAt(i); + if (compareFullyQualifiedName( + fullName, + LookupContext::fullyQualifiedName(candidate))) { + match = candidate; + break; + } + } + } + } + parentBinding = parentBinding->parent(); + } + + if (match) { + LookupItem item; + item.setDeclaration(match); + item.setBinding(binding); + result.append(item); + } + } return result; } + QSet processed; ClassOrNamespace *binding = this; do { lookup_helper(name, binding, &result, &processed, /*templateId = */ 0); @@ -456,6 +520,7 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding else if (s->isUsingNamespaceDirective()) continue; + if (Scope *scope = s->asScope()) { if (Class *klass = scope->asClass()) { if (const Identifier *id = klass->identifier()) { diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index a2de7f8cadf..b2fa81c5609 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -252,6 +252,10 @@ private: QSharedPointer _control; }; +bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList &path, + const QList &other); + + } // namespace CPlusPlus #endif // CPLUSPLUS_LOOKUPCONTEXT_H