From a2cd5db6ce8495202b12778fb9cac38dc2aa29a7 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <qtc-committer@nokia.com>
Date: Tue, 13 Jan 2009 09:41:07 +0100
Subject: [PATCH] Improved the lookup of qualified name ids.

---
 src/libs/cplusplus/LookupContext.cpp | 84 ++++++++++++++++++++++++----
 src/libs/cplusplus/LookupContext.h   |  4 ++
 2 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index bf5df8b499b..41fe83b7cc1 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -143,19 +143,59 @@ Identifier *LookupContext::identifier(Name *name) const
     return 0;
 }
 
+bool LookupContext::maybeValidSymbol(Symbol *symbol,
+                                     ResolveMode mode,
+                                     const QList<Symbol *> &candidates)
+{
+    if (((mode & ResolveNamespace) && symbol->isNamespace()) ||
+        ((mode & ResolveClass)     && symbol->isClass())     ||
+         (mode & ResolveSymbol)) {
+        return ! candidates.contains(symbol);
+    }
+
+    return false;
+}
+
 QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visibleScopes,
                                        ResolveMode mode) const
 {
     if (QualifiedNameId *q = name->asQualifiedNameId()) {
+        QList<Symbol *> candidates;
         QList<Scope *> scopes = visibleScopes;
+        Identifier *id = identifier(name);
+
+        foreach (Scope *scope, visibleScopes) {
+            Symbol *symbol = scope->lookat(id);
+            for (; symbol; symbol = symbol->next()) {
+                if (! symbol->name())
+                    continue;
+                else if (! maybeValidSymbol(symbol, mode, candidates))
+                    continue;
+                QualifiedNameId *qq = symbol->name()->asQualifiedNameId();
+                if (! qq)
+                    continue;
+                if (q->nameCount() > qq->nameCount())
+                    continue;
+
+                for (int i = q->nameCount() - 1; i != -1; --i) {
+                    Name *a = q->nameAt(i);
+                    Name *b = qq->nameAt(i);
+
+                    if (! a->isEqualTo(b))
+                        break;
+                    else if (i == 0)
+                        candidates.append(symbol);
+                }
+            }
+        }
+
         for (unsigned i = 0; i < q->nameCount(); ++i) {
             Name *name = q->nameAt(i);
 
-            QList<Symbol *> candidates;
             if (i + 1 == q->nameCount())
-                candidates = resolve(name, scopes, mode);
+                candidates += resolve(name, scopes, mode);
             else
-                candidates = resolveClassOrNamespace(name, scopes);
+                candidates += resolveClassOrNamespace(name, scopes);
 
             if (candidates.isEmpty() || i + 1 == q->nameCount())
                 return candidates;
@@ -176,19 +216,41 @@ QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visible
         for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) {
             Scope *scope = visibleScopes.at(scopeIndex);
             for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) {
-                if (! symbol->name())
+                if (! symbol->name()) {
                     continue;
-                else if (symbol->name()->isQualifiedNameId())
+                } else if (! maybeValidSymbol(symbol, mode, candidates)) {
                     continue;
-                else if (! isNameCompatibleWithIdentifier(symbol->name(), id))
+                } else if (QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
+                    if (! q->unqualifiedNameId()->isEqualTo(name))
+                        continue;
+
+                    if (q->nameCount() > 1) {
+                        Name *classOrNamespaceName =
+                                control()->qualifiedNameId(q->names(),
+                                                           q->nameCount() - 1);
+
+                        const QList<Symbol *> resolvedClassOrNamespace =
+                                resolveClassOrNamespace(classOrNamespaceName, visibleScopes);
+
+                        bool good = false;
+                        foreach (Symbol *classOrNamespace, resolvedClassOrNamespace) {
+                            ScopedSymbol *scoped = classOrNamespace->asScopedSymbol();
+                            if (visibleScopes.contains(scoped->members())) {
+                                good = true;
+                                break;
+                            }
+                        }
+
+                        if (! good)
+                            continue;
+                    }
+                } else if (! isNameCompatibleWithIdentifier(symbol->name(), id)) {
                     continue;
-                else if (symbol->name()->isDestructorNameId() != name->isDestructorNameId())
+                } else if (symbol->name()->isDestructorNameId() != name->isDestructorNameId()) {
                     continue;
-                else if ((((mode & ResolveNamespace) && symbol->isNamespace()) ||
-                          ((mode & ResolveClass) && symbol->isClass())         ||
-                          (mode & ResolveSymbol)) && ! candidates.contains(symbol)) {
-                    candidates.append(symbol);
                 }
+
+                candidates.append(symbol);
             }
         }
     } else if (OperatorNameId *opId = name->asOperatorNameId()) {
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 8759a79210e..b8399720b85 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -134,6 +134,10 @@ private:
     QList<Scope *> buildVisibleScopes();
     static bool isNameCompatibleWithIdentifier(Name *name, Identifier *id);
 
+    static bool maybeValidSymbol(Symbol *symbol,
+                                 ResolveMode mode,
+                                 const QList<Symbol *> &candidates);
+
 private:
     Control *_control;
 
-- 
GitLab