From a2730a4570641c5a803eca78236842e4ca97376b Mon Sep 17 00:00:00 2001
From: Sergey Shambir <sergey.shambir.auto@gmail.com>
Date: Thu, 4 Apr 2013 11:27:06 +0400
Subject: [PATCH] CppTools: added template function params to completions

Change-Id: I67e9685406a0bf9a7cc358ce24f0e862d7938be6
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
---
 src/libs/cplusplus/Icons.cpp                 |  2 +
 src/plugins/cpptools/cppcompletion_test.cpp  | 58 ++++++++++++++++++++
 src/plugins/cpptools/cppcompletionassist.cpp |  7 ++-
 src/plugins/cpptools/cpptoolsplugin.h        |  2 +
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp
index 3b3e3e1fb0b..db57e05e594 100644
--- a/src/libs/cplusplus/Icons.cpp
+++ b/src/libs/cplusplus/Icons.cpp
@@ -124,6 +124,8 @@ Icons::IconType Icons::iconTypeForSymbol(const Symbol *symbol)
         return FuncPublicIconType;
     } else if (symbol->isNamespace()) {
         return NamespaceIconType;
+    } else if (symbol->isTypenameArgument()) {
+        return ClassIconType;
     } else if (symbol->isUsingNamespaceDirective() ||
                symbol->isUsingDeclaration()) {
         // TODO: Might be nice to have a different icons for these things
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index 5096262a3c1..657b6397aae 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -1185,6 +1185,64 @@ void CppToolsPlugin::test_completion_cyclic_inheritance_data()
             << code << completions;
 }
 
+void CppToolsPlugin::test_completion_template_function()
+{
+    QFETCH(QByteArray, code);
+    QFETCH(QStringList, expectedCompletions);
+
+    TestData data;
+    data.srcText = code;
+    setup(&data);
+
+    QStringList actualCompletions = getCompletions(data);
+    actualCompletions.sort();
+    expectedCompletions.sort();
+
+    QString errorPattern(QLatin1String("Completion not found: %1"));
+    foreach (const QString &completion, expectedCompletions) {
+        QByteArray errorMessage = errorPattern.arg(completion).toUtf8();
+        QVERIFY2(actualCompletions.contains(completion), errorMessage.data());
+    }
+}
+
+void CppToolsPlugin::test_completion_template_function_data()
+{
+    QTest::addColumn<QByteArray>("code");
+    QTest::addColumn<QStringList>("expectedCompletions");
+
+    QByteArray code;
+    QStringList completions;
+
+    code = "\n"
+           "template <class tclass, typename tname, int tint>\n"
+           "tname Hello(const tclass &e)\n"
+           "{\n"
+           "    tname e2 = e;\n"
+           "    @\n"
+           "}";
+
+    completions.append(QLatin1String("tclass"));
+    completions.append(QLatin1String("tname"));
+    completions.append(QLatin1String("tint"));
+    QTest::newRow("case: template parameters in template function body")
+            << code << completions;
+
+    completions.clear();
+
+    code = "\n"
+           "template <class tclass, typename tname, int tint>\n"
+           "tname Hello(const tclass &e, @)\n"
+           "{\n"
+           "    tname e2 = e;\n"
+           "}";
+
+    completions.append(QLatin1String("tclass"));
+    completions.append(QLatin1String("tname"));
+    completions.append(QLatin1String("tint"));
+    QTest::newRow("case: template parameters in template function parameters list")
+            << code << completions;
+}
+
 void CppToolsPlugin::test_completion_enclosing_template_class()
 {
     test_completion();
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index 6511b775458..8f90aefb997 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -1354,8 +1354,11 @@ void CppCompletionAssistProcessor::globalCompletion(CPlusPlus::Scope *currentSco
             for (unsigned i = 0, argc = fun->argumentCount(); i < argc; ++i) {
                 addCompletionItem(fun->argumentAt(i), FunctionArgumentsOrder);
             }
-            break;
-        } else {
+        } else if (scope->isTemplate()) {
+            Template *templ = scope->asTemplate();
+            for (unsigned i = 0, argc = templ->templateParameterCount(); i < argc; ++i) {
+                addCompletionItem(templ->templateParameterAt(i), FunctionArgumentsOrder);
+            }
             break;
         }
     }
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index 96d79de4377..179fa417623 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -104,6 +104,8 @@ private slots:
     void test_completion_base_class_has_name_the_same_as_derived_data();
     void test_completion_cyclic_inheritance();
     void test_completion_cyclic_inheritance_data();
+    void test_completion_template_function();
+    void test_completion_template_function_data();
     void test_completion_enclosing_template_class();
     void test_completion_enclosing_template_class_data();
     void test_completion_instantiate_nested_class_when_enclosing_is_template();
-- 
GitLab