From 9aa86f91356630b3609ffc577c0232992dca3050 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= <thorbjorn.lindeijer@nokia.com>
Date: Wed, 4 Feb 2009 16:40:42 +0100
Subject: [PATCH] Completion for constructors used on initialization

Deals with cases like "QString s(", but for the moment doesn't handle
yet "QString const s(".

Done with Roberto Raggi.

(cherry picked from commit fca3ec1f3288ac4bcbfaed7f6c613af5cc762dda)
---
 src/plugins/cpptools/cppcodecompletion.cpp | 85 ++++++++++++++++------
 src/plugins/cpptools/cppcodecompletion.h   |  4 +-
 2 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 0ff66aaa6ee..20faa6e7a3c 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -432,7 +432,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
         return -1;
 
     m_editor = editor;
-    m_startPosition = findStartOfName(editor);
+    m_startPosition = findStartOfName();
     m_completionOperator = T_EOF_SYMBOL;
 
     int endOfOperator = m_startPosition;
@@ -520,7 +520,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
 
             if (m_completionOperator == T_LPAREN && completeFunction(exprTy, resolvedTypes, context)) {
                 return m_startPosition;
-            } if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
+            } else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) &&
                       completeMember(resolvedTypes, context)) {
                 return m_startPosition;
             } else if (m_completionOperator == T_COLON_COLON && completeScope(resolvedTypes, context)) {
@@ -531,6 +531,32 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
                 return m_startPosition;
             }
         }
+
+        if (m_completionOperator == T_LPAREN) {
+            // Find the expression that precedes the current name
+            int index = endOfExpression;
+            while (m_editor->characterAt(index - 1).isSpace())
+                --index;
+            index = findStartOfName(index);
+
+            QTextCursor tc(edit->document());
+            tc.setPosition(index);
+            QString baseExpression = expressionUnderCursor(tc);
+
+            // Resolve the type of this expression
+            QList<TypeOfExpression::Result> results =
+                    typeOfExpression(baseExpression, thisDocument, symbol, TypeOfExpression::Preprocess);
+
+            // If it's a class, add completions for the constructors
+            foreach (const TypeOfExpression::Result &result, results) {
+                if (result.first->isClass()) {
+                    FullySpecifiedType exprTy = result.first;
+                    if (completeConstructors(exprTy->asClass()))
+                        return m_startPosition;
+                    break;
+                }
+            }
+        }
     }
 
     // nothing to do.
@@ -541,26 +567,14 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy,
                                          const QList<TypeOfExpression::Result> &resolvedTypes,
                                          const LookupContext &)
 {
-    ConvertToCompletionItem toCompletionItem(this);
-    Overview o;
-    o.setShowReturnTypes(true);
-    o.setShowArgumentNames(true);
-
     if (Class *klass = exprTy->asClass()) {
-        for (unsigned i = 0; i < klass->memberCount(); ++i) {
-            Symbol *member = klass->memberAt(i);
-            if (! member->type()->isFunction())
-                continue;
-            else if (! member->identity())
-                continue;
-            else if (! member->identity()->isEqualTo(klass->identity()))
-                continue;
-            if (TextEditor::CompletionItem item = toCompletionItem(member)) {
-                item.m_text = o(member->type(), member->name());
-                m_completions.append(item);
-            }
-        }
+        completeConstructors(klass);
     } else {
+        ConvertToCompletionItem toCompletionItem(this);
+        Overview o;
+        o.setShowReturnTypes(true);
+        o.setShowArgumentNames(true);
+
         QSet<QString> signatures;
         foreach (TypeOfExpression::Result p, resolvedTypes) {
             FullySpecifiedType ty = p.first;
@@ -873,6 +887,30 @@ void CppCodeCompletion::completeClass(const QList<Symbol *> &candidates,
     }
 }
 
+bool CppCodeCompletion::completeConstructors(Class *klass)
+{
+    ConvertToCompletionItem toCompletionItem(this);
+    Overview o;
+    o.setShowReturnTypes(true);
+    o.setShowArgumentNames(true);
+
+    for (unsigned i = 0; i < klass->memberCount(); ++i) {
+        Symbol *member = klass->memberAt(i);
+        if (! member->type()->isFunction())
+            continue;
+        else if (! member->identity())
+            continue;
+        else if (! member->identity()->isEqualTo(klass->identity()))
+            continue;
+        if (TextEditor::CompletionItem item = toCompletionItem(member)) {
+            item.m_text = o(member->type(), member->name());
+            m_completions.append(item);
+        }
+    }
+
+    return ! m_completions.isEmpty();
+}
+
 bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType,
                                          const QList<TypeOfExpression::Result> &results,
                                          const LookupContext &context,
@@ -1150,14 +1188,15 @@ void CppCodeCompletion::cleanup()
     typeOfExpression.setSnapshot(Snapshot());
 }
 
-int CppCodeCompletion::findStartOfName(const TextEditor::ITextEditor *editor)
+int CppCodeCompletion::findStartOfName(int pos) const
 {
-    int pos = editor->position();
+    if (pos == -1)
+        pos = m_editor->position();
     QChar chr;
 
     // Skip to the start of a name
     do {
-        chr = editor->characterAt(--pos);
+        chr = m_editor->characterAt(--pos);
     } while (chr.isLetterOrNumber() || chr == QLatin1Char('_'));
 
     return pos + 1;
diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h
index 08a767ea6ce..02bcdc0f524 100644
--- a/src/plugins/cpptools/cppcodecompletion.h
+++ b/src/plugins/cpptools/cppcodecompletion.h
@@ -103,6 +103,8 @@ private:
                        const CPlusPlus::LookupContext &context,
                        bool staticLookup = true);
 
+    bool completeConstructors(CPlusPlus::Class *klass);
+
     bool completeQtMethod(CPlusPlus::FullySpecifiedType exprTy,
                           const QList<CPlusPlus::TypeOfExpression::Result> &,
                           const CPlusPlus::LookupContext &context,
@@ -118,7 +120,7 @@ private:
                       const CPlusPlus::LookupContext &context)
     { return completeQtMethod(exprTy, results, context, false); }
 
-    static int findStartOfName(const TextEditor::ITextEditor *editor);
+    int findStartOfName(int pos = -1) const;
 
     QList<TextEditor::CompletionItem> m_completions;
 
-- 
GitLab