From a985b59d402b189b90f5c15d291bc4fecd727d56 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <qtc-committer@nokia.com>
Date: Mon, 29 Dec 2008 11:53:40 +0100
Subject: [PATCH] Initial support for typedefs.

---
 src/libs/cplusplus/ResolveExpression.cpp   | 66 ++++++++++++++++++++++
 src/libs/cplusplus/ResolveExpression.h     | 14 +++++
 src/plugins/cpptools/cppcodecompletion.cpp | 22 ++++----
 3 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 7ce0e42c69d..1f4dc9c51af 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -792,3 +792,69 @@ bool ResolveExpression::visit(PostIncrDecrAST *)
 {
     return false;
 }
+
+////////////////////////////////////////////////////////////////////////////////
+QList<Symbol *> SymbolsForDotAccess::operator()(NamedType *namedTy,
+                                                ResolveExpression::Result p,
+                                                const LookupContext &context)
+{
+    QList<Symbol *> resolvedSymbols;
+
+    if (_blackList.contains(p))
+        return resolvedSymbols;
+
+    _blackList.append(p);
+
+    const QList<Symbol *> candidates =
+            context.resolve(namedTy->name(), context.visibleScopes(p));
+
+    foreach (Symbol *candidate, candidates) {
+        if (Class *klass = candidate->asClass()) {
+            if (resolvedSymbols.contains(klass))
+                continue; // we already know about `klass'
+            resolvedSymbols.append(klass);
+        } else if (candidate->isTypedef()) {
+            if (Declaration *decl = candidate->asDeclaration()) {
+                if (Class *asClass = decl->type()->asClass()) {
+                    // typedef struct { } Point;
+                    // Point pt;
+                    // pt.
+                    resolvedSymbols.append(asClass);
+                } else {
+                    // typedef Point Boh;
+                    // Boh b;
+                    // b.
+                    const ResolveExpression::Result r(decl->type(), decl);
+                    resolvedSymbols += operator()(r, context);
+                }
+            }
+        } else if (Declaration *decl = candidate->asDeclaration()) {
+            if (Function *funTy = decl->type()->asFunction()) {
+                // QString foo("ciao");
+                // foo.
+                if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) {
+                    const ResolveExpression::Result r(funTy->returnType(), decl);
+                    resolvedSymbols += operator()(r, context);
+                }
+            }
+        }
+    }
+
+    return resolvedSymbols;
+}
+
+QList<Symbol *> SymbolsForDotAccess::operator()(ResolveExpression::Result p,
+                                                const LookupContext &context)
+{
+    FullySpecifiedType ty = p.first;
+
+    if (NamedType *namedTy = ty->asNamedType()) {
+        return operator()(namedTy, p, context);
+    } else if (ReferenceType *refTy = ty->asReferenceType()) {
+        const ResolveExpression::Result e(refTy->elementType(), p.second);
+        return operator()(e, context);
+    }
+
+    return QList<Symbol *>();
+}
+
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index ac4a675b459..35a32c84655 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -128,6 +128,20 @@ private:
     QList<Result> _results;
 };
 
+class CPLUSPLUS_EXPORT SymbolsForDotAccess
+{
+    QList<ResolveExpression::Result> _blackList;
+
+public:
+    QList<Symbol *> operator()(NamedType *namedTy,
+                               ResolveExpression::Result p,
+                               const LookupContext &context);
+
+    QList<Symbol *> operator()(ResolveExpression::Result p,
+                               const LookupContext &context);
+};
+
+
 } // end of namespace CPlusPlus
 
 #endif // CPLUSPLUS_RESOLVEEXPRESSION_H
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index f8c5fe9b48a..075a55b96e9 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -180,8 +180,6 @@ protected:
 } // namespace Internal
 } // namespace CppTools
 
-
-
 using namespace CppTools::Internal;
 
 FunctionArgumentWidget::FunctionArgumentWidget(Core::ICore *core)
@@ -581,12 +579,12 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType,
                                        const QList<TypeOfExpression::Result> &results,
                                        const LookupContext &context)
 {
-    QTC_ASSERT(!results.isEmpty(), return false);
+    if (results.isEmpty())
+        return false;
 
+    const TypeOfExpression::Result p = results.first();
     QList<Symbol *> classObjectCandidates;
 
-    TypeOfExpression::Result p = results.first();
-
     if (m_completionOperator == T_ARROW)  {
         FullySpecifiedType ty = p.first;
 
@@ -666,13 +664,13 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType,
         }
 
         if (namedTy) {
-            const QList<Symbol *> classes =
-                    context.resolveClass(namedTy->name(),
-                                         context.visibleScopes(p));
-
-            foreach (Symbol *c, classes) {
-                if (! classObjectCandidates.contains(c))
-                    classObjectCandidates.append(c);
+            SymbolsForDotAccess symbolsForDotAccess;
+            const QList<Symbol *> symbols = symbolsForDotAccess(namedTy, p, context);
+            foreach (Symbol *symbol, symbols) {
+                if (classObjectCandidates.contains(symbol))
+                    continue;
+                if (Class *klass = symbol->asClass())
+                    classObjectCandidates.append(klass);
             }
         }
     }
-- 
GitLab