From 903c3cafe83fe8434ad6d18b400b73dd2ef50a99 Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Mon, 3 Sep 2012 13:38:20 +0200 Subject: [PATCH] C++: Improve lookup - collect more valid items There was a fix for QTCREATORBUG-7730 in the case of nested forward declarations in commit 74a458bca09b5bd170b64e04bb68c8d958c61932. However, it introduced regressions and actually didn't solve the issue, since the behavior was hidden by another error fixed later. The patch should properly fix the issue and the regression pointed in QTCREATORBUG-7777. Task-number: QTCREATORBUG-7730 Task-number: QTCREATORBUG-7777 Change-Id: I27397fefdc7cc9a60111761df1f76a01407886f7 Reviewed-by: Christian Kamm Reviewed-by: Orgad Shaneh --- src/libs/cplusplus/FindUsages.cpp | 29 ------------ src/libs/cplusplus/FindUsages.h | 2 - src/libs/cplusplus/LookupContext.cpp | 71 ++++++++++++++++++++++++++-- src/libs/cplusplus/LookupContext.h | 4 ++ 4 files changed, 72 insertions(+), 34 deletions(-) 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