From 4382274ba45e70f1c8dea13788d3d57d89be506b Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 9 Dec 2015 14:30:18 +0100 Subject: [PATCH] Clang: Fix emphasizing current parameter in function signature tooltip ...when completing function calls. Task-number: QTCREATORBUG-15108 Change-Id: If55effe117774f3ec5debb03a9c7889981ea27d2 Reviewed-by: Marco Bubke --- .../clangcompletionchunkstotextconverter.cpp | 41 ++++++++++-- .../clangcompletionchunkstotextconverter.h | 12 +++- .../clangcodemodel/clangfunctionhintmodel.cpp | 24 ++----- .../test/clangcodecompletion_test.cpp | 4 +- .../completionchunkstotextconvertertest.cpp | 66 +++++++++++++++++++ 5 files changed, 116 insertions(+), 31 deletions(-) diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp index 46a9c946905..cae1e00fbb2 100644 --- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp +++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp @@ -81,9 +81,9 @@ void CompletionChunksToTextConverter::setAddExtraVerticalSpaceBetweenBraces( m_addExtraVerticalSpaceBetweenBraces = addExtraVerticalSpaceBetweenBraces; } -void CompletionChunksToTextConverter::setAddHtmlTags(bool addHtmlTags) +void CompletionChunksToTextConverter::setEmphasizeOptional(bool emphasizeOptional) { - m_addHtmlTags = addHtmlTags; + m_emphasizeOptional = emphasizeOptional; } void CompletionChunksToTextConverter::setAddOptional(bool addOptional) @@ -91,6 +91,11 @@ void CompletionChunksToTextConverter::setAddOptional(bool addOptional) m_addOptional = addOptional; } +void CompletionChunksToTextConverter::setPlaceHolderToEmphasize(int placeHolderNumber) +{ + m_placeHolderPositionToEmphasize = placeHolderNumber; +} + const QString &CompletionChunksToTextConverter::text() const { return m_text; @@ -107,12 +112,18 @@ bool CompletionChunksToTextConverter::hasPlaceholderPositions() const } QString CompletionChunksToTextConverter::convertToFunctionSignature( - const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks) + const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks, + int parameterToEmphasize) { CompletionChunksToTextConverter converter; converter.setAddPlaceHolderText(true); converter.setAddResultType(true); + converter.setAddOptional(true); + converter.setEmphasizeOptional(true); + + converter.setAddPlaceHolderPositions(true); + converter.setPlaceHolderToEmphasize(parameterToEmphasize); converter.parseChunks(codeCompletionChunks); @@ -137,7 +148,7 @@ QString CompletionChunksToTextConverter::convertToToolTip( converter.setAddSpaces(true); converter.setAddExtraVerticalSpaceBetweenBraces(true); converter.setAddOptional(true); - converter.setAddHtmlTags(true); + converter.setEmphasizeOptional(true); converter.setAddResultType(true); converter.parseChunks(codeCompletionChunks); @@ -188,7 +199,7 @@ void CompletionChunksToTextConverter::wrapInCursiveTagIfOptional( const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) { if (m_addOptional) { - if (m_addHtmlTags) { + if (m_emphasizeOptional) { if (!m_previousCodeCompletionChunk.isOptional() && codeCompletionChunk.isOptional()) m_text += QStringLiteral(""); else if (m_previousCodeCompletionChunk.isOptional() && !codeCompletionChunk.isOptional()) @@ -201,7 +212,7 @@ void CompletionChunksToTextConverter::parsePlaceHolder( const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) { if (m_addPlaceHolderText) - m_text += codeCompletionChunk.text().toString(); + appendText(codeCompletionChunk.text().toString(), emphasizeCurrentPlaceHolder()); if (m_addPlaceHolderPositions) m_placeholderPositions.push_back(m_text.size()); @@ -274,6 +285,24 @@ void CompletionChunksToTextConverter::addExtraVerticalSpaceBetweenBraces( } } +bool CompletionChunksToTextConverter::emphasizeCurrentPlaceHolder() const +{ + if (m_addPlaceHolderPositions) { + const uint currentPlaceHolderPosition = m_placeholderPositions.size() + 1; + return uint(m_placeHolderPositionToEmphasize) == currentPlaceHolderPosition; + } + + return false; +} + +void CompletionChunksToTextConverter::appendText(const QString &text, bool boldFormat) +{ + if (boldFormat) + m_text += QStringLiteral("") + text + QStringLiteral(""); + else + m_text += text; +} + bool CompletionChunksToTextConverter::canAddSpace() const { return m_addSpaces diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h index c08aa0f5b32..e84e0dd84fc 100644 --- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h +++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h @@ -52,14 +52,16 @@ public: void setAddResultType(bool addResultType); void setAddSpaces(bool addSpaces); void setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces); - void setAddHtmlTags(bool addHtmlTags); + void setEmphasizeOptional(bool emphasizeOptional); void setAddOptional(bool addOptional); + void setPlaceHolderToEmphasize(int placeHolderNumber); const QString &text() const; const std::vector &placeholderPositions() const; bool hasPlaceholderPositions() const; - static QString convertToFunctionSignature(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks); + static QString convertToFunctionSignature(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks, + int parameterToEmphasize = -1); static QString convertToName(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks); static QString convertToToolTip(const ClangBackEnd::CodeCompletionChunks &codeCompletionChunks); private: @@ -74,20 +76,24 @@ private: void addExtraVerticalSpaceBetweenBraces(); void addExtraVerticalSpaceBetweenBraces(const ClangBackEnd::CodeCompletionChunks::iterator &); + void appendText(const QString &text, bool boldFormat = false); bool canAddSpace() const; bool isNotOptionalOrAddOptionals(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) const; + bool emphasizeCurrentPlaceHolder() const; + private: std::vector m_placeholderPositions; ClangBackEnd::CodeCompletionChunks m_codeCompletionChunks; ClangBackEnd::CodeCompletionChunk m_previousCodeCompletionChunk; QString m_text; + int m_placeHolderPositionToEmphasize = -1; bool m_addPlaceHolderText = false; bool m_addPlaceHolderPositions = false; bool m_addResultType = false; bool m_addSpaces = false; bool m_addExtraVerticalSpaceBetweenBraces = false; - bool m_addHtmlTags = false; + bool m_emphasizeOptional = false; bool m_addOptional = false; }; diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp index 0ce334975ff..61e0b4cf9b4 100644 --- a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp +++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp @@ -56,27 +56,11 @@ int ClangFunctionHintModel::size() const QString ClangFunctionHintModel::text(int index) const { -#if 0 - // TODO: add the boldening to the result - Overview overview; - overview.setShowReturnTypes(true); - overview.setShowArgumentNames(true); - overview.setMarkedArgument(m_currentArg + 1); - Function *f = m_functionSymbols.at(index); + const ClangBackEnd::CodeCompletionChunks chunks = m_functionSymbols.at(index).chunks(); + const QString signatureWithEmphasizedCurrentParameter + = CompletionChunksToTextConverter::convertToFunctionSignature(chunks, m_currentArg + 1); - const QString prettyMethod = overview(f->type(), f->name()); - const int begin = overview.markedArgumentBegin(); - const int end = overview.markedArgumentEnd(); - - QString hintText; - hintText += prettyMethod.left(begin).toHtmlEscaped()); - hintText += ""; - hintText += prettyMethod.mid(begin, end - begin).toHtmlEscaped()); - hintText += ""; - hintText += prettyMethod.mid(end).toHtmlEscaped()); - return hintText; -#endif - return CompletionChunksToTextConverter::convertToFunctionSignature(m_functionSymbols.at(index).chunks()); + return signatureWithEmphasizedCurrentParameter; } int ClangFunctionHintModel::activeArgument(const QString &prefix) const diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index 02acb42c5ec..929608c2c39 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -962,8 +962,8 @@ void ClangCodeCompletionTest::testCompleteFunctions() QVERIFY(hasItem(t.proposal, "void f()")); QVERIFY(hasItem(t.proposal, "void f(int a)")); QVERIFY(hasItem(t.proposal, "void f(const QString &s)")); - QVERIFY(hasItem(t.proposal, "void f(char c, int optional)")); // TODO: No default argument? - QVERIFY(hasItem(t.proposal, "void f(char c, int optional1, int optional2)")); // TODO: No default argument? + QVERIFY(hasItem(t.proposal, "void f(char c, int optional)")); // TODO: No default argument? + QVERIFY(hasItem(t.proposal, "void f(char c, int optional1, int optional2)")); // TODO: No default argument? QVERIFY(hasItem(t.proposal, "void f(const TType *t)")); QVERIFY(hasItem(t.proposal, "TType f(bool)")); } diff --git a/tests/unit/unittest/completionchunkstotextconvertertest.cpp b/tests/unit/unittest/completionchunkstotextconvertertest.cpp index b9c1dd9a5a8..20008fe8477 100644 --- a/tests/unit/unittest/completionchunkstotextconvertertest.cpp +++ b/tests/unit/unittest/completionchunkstotextconvertertest.cpp @@ -119,6 +119,72 @@ TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithParameters) ASSERT_THAT(converter.text(), QStringLiteral("int Function(char x)")); } +TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneArgument) +{ + CodeCompletionChunks completionChunks({integerResultType, + functionName, + leftParen, + functionArgumentX, + rightParen}); + + using ClangCodeModel::Internal::CompletionChunksToTextConverter; + + ASSERT_THAT(converter.convertToFunctionSignature(completionChunks), + QStringLiteral("int Function(char x)")); +} + +TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParameterThatIsActive) +{ + CodeCompletionChunks completionChunks({integerResultType, + functionName, + leftParen, + functionArgumentX, + rightParen}); + + ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, 1), + QStringLiteral("int Function(char x)")); +} + +TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParameterAndInInvalidActiveParameter) +{ + CodeCompletionChunks completionChunks({integerResultType, + functionName, + leftParen, + functionArgumentX, + rightParen}); + + ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, -1), + QStringLiteral("int Function(char x)")); +} + +TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParametersWhereOneIsActive) +{ + CodeCompletionChunks completionChunks({integerResultType, + functionName, + leftParen, + functionArgumentX, + comma, + functionArgumentY, + rightParen}); + + ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, 2), + QStringLiteral("int Function(char x, int y)")); +} + +TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParametersWhereOneIsOptionalAndActive) +{ + CodeCompletionChunks completionChunks({integerResultType, + functionName, + leftParen, + functionArgumentX, + optionalComma, + optionalFunctionArgumentY, + rightParen}); + + ASSERT_THAT(converter.convertToFunctionSignature(completionChunks, 2), + QStringLiteral("int Function(char x, int y)")); +} + TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithOptionalParameter) { CodeCompletionChunks completionChunks({integerResultType,