From 2324db9d4100e7df2a97fe5da968d76deebef23f Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Date: Mon, 18 Jan 2016 11:22:39 +0100
Subject: [PATCH] Clang: Fix html code in completion list item

E.g. "dynamic_cast&lt&gt;()" showed up as item.

Let CompletionChunksToTextConverter default to plain text format and
explicitly request HTML where needed.

Change-Id: Iebce85cb888a5bd697ffdce364118b6dc65a435d
Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
---
 .../clangcompletionassistprocessor.cpp        |  3 +-
 .../clangcompletionchunkstotextconverter.cpp  | 29 ++++++++++++++-----
 .../clangcompletionchunkstotextconverter.h    | 20 +++++++++----
 .../clangcodemodel/clangfunctionhintmodel.cpp |  3 +-
 .../completionchunkstotextconvertertest.cpp   | 20 ++++++-------
 5 files changed, 51 insertions(+), 24 deletions(-)

diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
index 0cd362d4da2..a918b101401 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
@@ -103,7 +103,8 @@ QList<AssistProposalItem *> toAssistProposalItems(const CodeCompletions &complet
             items.insert(name, item);
             item->setText(name);
             item->setOrder(ccr.priority());
-            QString detail = CompletionChunksToTextConverter::convertToToolTip(ccr.chunks());
+            QString detail
+                    = CompletionChunksToTextConverter::convertToToolTipWithHtml(ccr.chunks());
 
             if (!ccr.briefComment().isEmpty())
                 detail += QStringLiteral("\n\n") + ccr.briefComment().toString();
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
index ec733c87d71..4954979e38c 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
@@ -118,7 +118,7 @@ bool CompletionChunksToTextConverter::hasPlaceholderPositions() const
     return m_placeholderPositions.size() > 0;
 }
 
-QString CompletionChunksToTextConverter::convertToFunctionSignature(
+QString CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(
         const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
         int parameterToEmphasize)
 {
@@ -126,6 +126,7 @@ QString CompletionChunksToTextConverter::convertToFunctionSignature(
     converter.setAddPlaceHolderText(true);
     converter.setAddResultType(true);
 
+    converter.setTextFormat(TextFormat::Html);
     converter.setAddOptional(true);
     converter.setEmphasizeOptional(true);
 
@@ -147,7 +148,7 @@ QString CompletionChunksToTextConverter::convertToName(
     return converter.text();
 }
 
-QString CompletionChunksToTextConverter::convertToToolTip(
+QString CompletionChunksToTextConverter::convertToToolTipWithHtml(
         const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks)
 {
     CompletionChunksToTextConverter converter;
@@ -155,6 +156,7 @@ QString CompletionChunksToTextConverter::convertToToolTip(
     converter.setAddSpaces(true);
     converter.setAddExtraVerticalSpaceBetweenBraces(true);
     converter.setAddOptional(true);
+    converter.setTextFormat(TextFormat::Html);
     converter.setEmphasizeOptional(true);
     converter.setAddResultType(true);
 
@@ -189,7 +191,7 @@ void CompletionChunksToTextConverter::parseDependendOnTheOptionalState(
 void CompletionChunksToTextConverter::parseResultType(const Utf8String &resultTypeText)
 {
     if (m_addResultType)
-        m_text += resultTypeText.toString().toHtmlEscaped() + QChar(QChar::Space);
+        m_text += inDesiredTextFormat(resultTypeText) + QChar(QChar::Space);
 }
 
 void CompletionChunksToTextConverter::parseText(const Utf8String &text)
@@ -199,14 +201,14 @@ void CompletionChunksToTextConverter::parseText(const Utf8String &text)
         m_text += QChar(QChar::Space);
     }
 
-    m_text += text.toString().toHtmlEscaped();
+    m_text += inDesiredTextFormat(text);
 }
 
 void CompletionChunksToTextConverter::wrapInCursiveTagIfOptional(
         const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
 {
     if (m_addOptional) {
-        if (m_emphasizeOptional) {
+        if (m_emphasizeOptional && m_textFormat == TextFormat::Html) {
             if (!m_previousCodeCompletionChunk.isOptional() && codeCompletionChunk.isOptional())
                 m_text += QStringLiteral("<i>");
             else if (m_previousCodeCompletionChunk.isOptional() && !codeCompletionChunk.isOptional())
@@ -219,7 +221,7 @@ void CompletionChunksToTextConverter::parsePlaceHolder(
         const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
 {
     if (m_addPlaceHolderText) {
-        appendText(codeCompletionChunk.text().toString().toHtmlEscaped(),
+        appendText(inDesiredTextFormat(codeCompletionChunk.text()),
                    emphasizeCurrentPlaceHolder());
     }
 
@@ -294,6 +296,14 @@ void CompletionChunksToTextConverter::addExtraVerticalSpaceBetweenBraces(
     }
 }
 
+QString CompletionChunksToTextConverter::inDesiredTextFormat(const Utf8String &text)
+{
+    if (m_textFormat == TextFormat::Html)
+        return text.toString().toHtmlEscaped();
+    else
+        return text.toString();
+}
+
 bool CompletionChunksToTextConverter::emphasizeCurrentPlaceHolder() const
 {
     if (m_addPlaceHolderPositions) {
@@ -304,9 +314,14 @@ bool CompletionChunksToTextConverter::emphasizeCurrentPlaceHolder() const
     return false;
 }
 
+void CompletionChunksToTextConverter::setTextFormat(TextFormat textFormat)
+{
+    m_textFormat = textFormat;
+}
+
 void CompletionChunksToTextConverter::appendText(const QString &text, bool boldFormat)
 {
-    if (boldFormat)
+    if (boldFormat && m_textFormat == TextFormat::Html)
         m_text += QStringLiteral("<b>") + text + QStringLiteral("</b>");
     else
         m_text += text;
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
index fec927eb446..6d88778c640 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
@@ -47,12 +47,17 @@ class CompletionChunksToTextConverter
 public:
     void parseChunks(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
 
+    enum class TextFormat {
+        Plain,
+        Html
+    };
+    void setTextFormat(TextFormat textFormat);
     void setAddPlaceHolderText(bool addPlaceHolderText);
     void setAddPlaceHolderPositions(bool addPlaceHolderPositions);
     void setAddResultType(bool addResultType);
     void setAddSpaces(bool addSpaces);
     void setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces);
-    void setEmphasizeOptional(bool emphasizeOptional);
+    void setEmphasizeOptional(bool emphasizeOptional); // Only for Html format
     void setAddOptional(bool addOptional);
     void setPlaceHolderToEmphasize(int placeHolderNumber);
 
@@ -62,10 +67,13 @@ public:
     const std::vector<int> &placeholderPositions() const;
     bool hasPlaceholderPositions() const;
 
-    static QString convertToFunctionSignature(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
-                                              int parameterToEmphasize = -1);
     static QString convertToName(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
-    static QString convertToToolTip(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
+    static QString convertToKeywords(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
+    static QString convertToToolTipWithHtml(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks);
+    static QString convertToFunctionSignatureWithHtml(
+            const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks,
+            int parameterToEmphasize = -1);
+
 private:
     void parse(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
     void parseDependendOnTheOptionalState(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
@@ -78,7 +86,8 @@ private:
     void addExtraVerticalSpaceBetweenBraces();
     void addExtraVerticalSpaceBetweenBraces(const ClangBackEnd::CodeCompletionChunks::iterator &);
 
-    void appendText(const QString &text, bool boldFormat = false);
+    QString inDesiredTextFormat(const Utf8String &text) const;
+    void appendText(const QString &text, bool boldFormat = false); // Boldness only in Html format
     bool canAddSpace() const;
     bool isNotOptionalOrAddOptionals(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) const;
 
@@ -90,6 +99,7 @@ private:
     ClangBackEnd::CodeCompletionChunk m_previousCodeCompletionChunk;
     QString m_text;
     int m_placeHolderPositionToEmphasize = -1;
+    TextFormat m_textFormat = TextFormat::Plain;
     bool m_addPlaceHolderText = false;
     bool m_addPlaceHolderPositions = false;
     bool m_addResultType = false;
diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
index 03dfa6d6c99..730cecbbc1f 100644
--- a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
+++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
@@ -58,7 +58,8 @@ QString ClangFunctionHintModel::text(int index) const
 {
     const ClangBackEnd::CodeCompletionChunks chunks = m_functionSymbols.at(index).chunks();
     const QString signatureWithEmphasizedCurrentParameter
-        = CompletionChunksToTextConverter::convertToFunctionSignature(chunks, m_currentArgument + 1);
+        = CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(chunks,
+                                                                              m_currentArgument + 1);
 
     return signatureWithEmphasizedCurrentParameter;
 }
diff --git a/tests/unit/unittest/completionchunkstotextconvertertest.cpp b/tests/unit/unittest/completionchunkstotextconvertertest.cpp
index 175da498e4e..38607c0979c 100644
--- a/tests/unit/unittest/completionchunkstotextconvertertest.cpp
+++ b/tests/unit/unittest/completionchunkstotextconvertertest.cpp
@@ -131,7 +131,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneArgumen
 
     using ClangCodeModel::Internal::CompletionChunksToTextConverter;
 
-    ASSERT_THAT(converter.convertToFunctionSignature(completionChunks),
+    ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks),
                 QStringLiteral("int Function(char x)"));
 }
 
@@ -143,7 +143,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParamet
                                             functionArgumentX,
                                            rightParen});
 
-    ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, 1),
+    ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 1),
                 QStringLiteral("int Function(<b>char x</b>)"));
 }
 
@@ -155,7 +155,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParamet
                                             functionArgumentX,
                                            rightParen});
 
-    ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, -1),
+    ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, -1),
                 QStringLiteral("int Function(char x)"));
 }
 
@@ -169,7 +169,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParamet
                                             functionArgumentY,
                                            rightParen});
 
-    ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, 2),
+    ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 2),
                 QStringLiteral("int Function(char x, <b>int y</b>)"));
 }
 
@@ -183,7 +183,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParamet
                                             optionalFunctionArgumentY,
                                            rightParen});
 
-    ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, 2),
+    ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 2),
                 QStringLiteral("int Function(char x<i>, <b>int y</b></i>)"));
 }
 
@@ -197,7 +197,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTemplateRe
 
     using ClangCodeModel::Internal::CompletionChunksToTextConverter;
 
-    ASSERT_THAT(CompletionChunksToTextConverter::convertToFunctionSignature(completionChunks),
+    ASSERT_THAT(CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(completionChunks),
                 QStringLiteral("Foo&lt;int&gt; Function(char x)"));
 }
 
@@ -211,7 +211,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTemplateAr
 
     using ClangCodeModel::Internal::CompletionChunksToTextConverter;
 
-    ASSERT_THAT(CompletionChunksToTextConverter::convertToFunctionSignature(completionChunks),
+    ASSERT_THAT(CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(completionChunks),
                 QStringLiteral("int Function(const Foo&lt;int&gt; &amp;foo)"));
 }
 
@@ -227,7 +227,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithOptionalParameter)
                                            optionalFunctionArgumentZ,
                                            rightParen});
 
-    ASSERT_THAT(Converter::convertToToolTip(completionChunks),
+    ASSERT_THAT(Converter::convertToToolTipWithHtml(completionChunks),
                 QStringLiteral("int Function (char x<i>, int y, int z</i>)"));
 }
 
@@ -310,7 +310,7 @@ TEST_F(CompletionChunksToTextConverter, const_cast)
 
     converter.parseChunks(completionChunks);
 
-    ASSERT_THAT(converter.text(), QStringLiteral("const_cast&lt;&gt;()"));
+    ASSERT_THAT(converter.text(), QStringLiteral("const_cast<>()"));
 }
 
 TEST_F(CompletionChunksToTextConverter, Throw)
@@ -352,7 +352,7 @@ TEST_F(CompletionChunksToTextConverter, EnableIfT)
 
     converter.parseChunks(completionChunks);
 
-    ASSERT_THAT(converter.text(), QStringLiteral("enable_if_t&lt;&gt;"));
+    ASSERT_THAT(converter.text(), QStringLiteral("enable_if_t<>"));
 }
 
 }
-- 
GitLab