From 8dc369bc2d631ec94cecfec542b5dd0ce8f20946 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri, 16 Oct 2009 11:08:06 +0200
Subject: [PATCH] Simplified member completion.

Share code with ResolveExpression.
---
 src/libs/cplusplus/ResolveExpression.cpp   |  18 ++-
 src/libs/cplusplus/ResolveExpression.h     |   6 +-
 src/plugins/cpptools/cppcodecompletion.cpp | 147 ++++-----------------
 3 files changed, 46 insertions(+), 125 deletions(-)

diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 23aa23a66d4..033d61aad86 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -647,7 +647,8 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
 }
 
 QList<ResolveExpression::Result>
-ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp) const
+ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp,
+                                         bool *replacedDotOperator) const
 {
     QList<Result> results;
 
@@ -715,6 +716,16 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a
                 results.append(Result(elementTy, lastVisibleSymbol));
         }
     } else if (accessOp == T_DOT) {
+        if (replacedDotOperator) {
+            if (PointerType *ptrTy = ty->asPointerType()) {
+                *replacedDotOperator = true;
+                ty = ptrTy->elementType().simplified();
+            } else if (ArrayType *arrTy = ty->asArrayType()) {
+                *replacedDotOperator = true;
+                ty = arrTy->elementType().simplified();
+            }
+        }
+
         if (ty->isClassType() || ty->isNamedType())
             results.append(Result(ty, lastVisibleSymbol));
 
@@ -734,12 +745,13 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a
 QList<ResolveExpression::Result>
 ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults,
                                            unsigned accessOp,
-                                           Name *memberName) const
+                                           Name *memberName,
+                                           bool *replacedDotOperator) const
 {
     ResolveClass resolveClass;
     QList<Result> results;
 
-    const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp);
+    const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp, replacedDotOperator);
     foreach (const Result &r, classObjectResults) {
         FullySpecifiedType ty = r.first;
 
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index fb00f9e23f6..8d6f321bf71 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -51,7 +51,8 @@ public:
 
     QList<Result> resolveMemberExpression(const QList<Result> &baseResults,
                                           unsigned accessOp,
-                                          Name *memberName) const;
+                                          Name *memberName,
+                                          bool *replacedDotOperator = 0) const;
 
     QList<Result> resolveMember(Name *memberName, Class *klass, Name *className = 0) const;
 
@@ -65,7 +66,8 @@ public:
 
 
     QList<Result> resolveBaseExpression(const QList<Result> &baseResults,
-                                        int accessOp) const;
+                                        int accessOp,
+                                        bool *replacedDotOperator = 0) const;
 
 protected:
     QList<Result> switchResults(const QList<Result> &symbols);
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 0a30af6f78c..16bda304487 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -984,135 +984,42 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
     return false;
 }
 
-bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &results,
+bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &baseResults,
                                        const LookupContext &context)
 {
-    if (results.isEmpty())
+    if (baseResults.isEmpty())
         return false;
 
-    TypeOfExpression::Result result = results.first();
-    QList<Symbol *> classObjectCandidates;
-
-    if (m_completionOperator == T_ARROW)  {
-        FullySpecifiedType ty = result.first.simplified();
-
-        if (Class *classTy = ty->asClassType()) {
-            Symbol *symbol = result.second;
-            if (symbol && ! symbol->isClass())
-                classObjectCandidates.append(classTy);
-        } else if (NamedType *namedTy = ty->asNamedType()) {
-            // ### This code is pretty slow.
-            const QList<Symbol *> candidates = context.resolve(namedTy->name());
-            foreach (Symbol *candidate, candidates) {
-                if (candidate->isTypedef()) {
-                    ty = candidate->type();
-                    const ResolveExpression::Result r(ty, candidate);
-                    result = r;
-                    break;
-                }
-            }
-        }
-
-        if (NamedType *namedTy = ty->asNamedType()) {
-            ResolveExpression resolveExpression(context);
-            ResolveClass resolveClass;
-
-            const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, context);
-            foreach (Symbol *classObject, candidates) {
-                const QList<TypeOfExpression::Result> overloads =
-                        resolveExpression.resolveArrowOperator(result, namedTy,
-                                                               classObject->asClass());
-
-                foreach (TypeOfExpression::Result r, overloads) {
-                    FullySpecifiedType ty = r.first;
-                    Function *funTy = ty->asFunctionType();
-                    if (! funTy)
-                        continue;
-
-                    ty = funTy->returnType().simplified();
-
-                    if (PointerType *ptrTy = ty->asPointerType()) {
-                        FullySpecifiedType elementTy = ptrTy->elementType().simplified();
-                        if (NamedType *namedTy = elementTy->asNamedType()) {
-                            const QList<Symbol *> classes =
-                                    resolveClass(namedTy->name(), result, context);
-
-                            foreach (Symbol *c, classes) {
-                                if (! classObjectCandidates.contains(c))
-                                    classObjectCandidates.append(c);
-                            }
-                        }
-                    }
-                }
-            }
-        } else if (PointerType *ptrTy = ty->asPointerType()) {
-            FullySpecifiedType elementTy = ptrTy->elementType().simplified();
-            if (NamedType *namedTy = elementTy->asNamedType()) {
-                ResolveClass resolveClass;
-
-                const QList<Symbol *> classes = resolveClass(namedTy->name(), result,
-                                                             context);
-
-                foreach (Symbol *c, classes) {
-                    if (! classObjectCandidates.contains(c))
-                        classObjectCandidates.append(c);
-                }
-            } else if (Class *classTy = elementTy->asClassType()) {
-                // typedef struct { int x } *Ptr;
-                // Ptr p;
-                // p->
-                classObjectCandidates.append(classTy);
-            }
-        }
-    } else if (m_completionOperator == T_DOT) {
-        FullySpecifiedType ty = result.first.simplified();
-
-        NamedType *namedTy = 0;
+    ResolveExpression resolveExpression(context);
+    ResolveClass resolveClass;
 
-        if (ArrayType *arrayTy = ty->asArrayType()) {
-            // Replace . with [0]. when `ty' is an array type.
-            FullySpecifiedType elementTy = arrayTy->elementType().simplified();
+    bool replacedDotOperator = false;
+    const QList<TypeOfExpression::Result> classObjectResults =
+            resolveExpression.resolveBaseExpression(baseResults,
+                                                    m_completionOperator,
+                                                    &replacedDotOperator);
+
+    if (replacedDotOperator) {
+        // Replace . with ->
+        int length = m_editor->position() - m_startPosition + 1;
+        m_editor->setCurPos(m_startPosition - 1);
+        m_editor->replace(length, QLatin1String("->"));
+        ++m_startPosition;
+    }
 
-            if (elementTy->isNamedType() || elementTy->isPointerType()) {
-                ty = elementTy;
+    QList<Symbol *> classObjectCandidates;
+    foreach (const TypeOfExpression::Result &r, classObjectResults) {
+        FullySpecifiedType ty = r.first.simplified();
 
-                const int length = m_editor->position() - m_startPosition + 1;
-                m_editor->setCurPos(m_startPosition - 1);
-                m_editor->replace(length, QLatin1String("[0]."));
-                m_startPosition += 3;
-            }
-        }
+        if (Class *klass = ty->asClassType())
+            classObjectCandidates.append(klass);
 
-        if (PointerType *ptrTy = ty->asPointerType()) {
-            if (ptrTy->elementType()->isNamedType()) {
-                // Replace . with ->
-                int length = m_editor->position() - m_startPosition + 1;
-                m_editor->setCurPos(m_startPosition - 1);
-                m_editor->replace(length, QLatin1String("->"));
-                ++m_startPosition;
-                namedTy = ptrTy->elementType()->asNamedType();
-            }
-        } else if (Class *classTy = ty->asClassType()) {
-            Symbol *symbol = result.second;
-            if (symbol && ! symbol->isClass())
-                classObjectCandidates.append(classTy);
-        } else {
-            namedTy = ty->asNamedType();
-            if (! namedTy) {
-                Function *fun = ty->asFunctionType();
-                if (fun && fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope()))
-                    namedTy = fun->returnType()->asNamedType();
-            }
-        }
+        else if (NamedType *namedTy = ty->asNamedType()) {
+            Name *className = namedTy->name();
+            const QList<Symbol *> classes = resolveClass(className, r, context);
 
-        if (namedTy) {
-            ResolveClass resolveClass;
-            const QList<Symbol *> symbols = resolveClass(namedTy->name(), result,
-                                                         context);
-            foreach (Symbol *symbol, symbols) {
-                if (classObjectCandidates.contains(symbol))
-                    continue;
-                if (Class *klass = symbol->asClass())
+            foreach (Symbol *c, classes) {
+                if (Class *klass = c->asClass())
                     classObjectCandidates.append(klass);
             }
         }
-- 
GitLab