diff --git a/src/libs/clangbackendipc/codecompletion.cpp b/src/libs/clangbackendipc/codecompletion.cpp index f84d44a70cc404b11b23eebdba202aaeb8491329..6cd2625facf0570fb405a75ae49be747f9433c6d 100644 --- a/src/libs/clangbackendipc/codecompletion.cpp +++ b/src/libs/clangbackendipc/codecompletion.cpp @@ -37,6 +37,7 @@ static const char *completionKindToString(CodeCompletion::Kind kind) case CodeCompletion::Other: return "Other"; case CodeCompletion::FunctionCompletionKind: return "Function"; case CodeCompletion::TemplateFunctionCompletionKind: return "TemplateFunction"; + case CodeCompletion::FunctionOverloadCompletionKind: return "FunctionOverload"; case CodeCompletion::ConstructorCompletionKind: return "Constructor"; case CodeCompletion::DestructorCompletionKind: return "Destructor"; case CodeCompletion::VariableCompletionKind: return "Variable"; diff --git a/src/libs/clangbackendipc/codecompletion.h b/src/libs/clangbackendipc/codecompletion.h index ef7e832388348c450fa5e44c888f418acd221812..fa952db25233cc9d7831ea8792d9d077361cd61e 100644 --- a/src/libs/clangbackendipc/codecompletion.h +++ b/src/libs/clangbackendipc/codecompletion.h @@ -44,6 +44,7 @@ public: enum Kind : quint32 { Other = 0, FunctionCompletionKind, + FunctionOverloadCompletionKind, TemplateFunctionCompletionKind, ConstructorCompletionKind, DestructorCompletionKind, diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp index 34b4b9b2dd1d9ea3e8161e2ae694c649551bbe9d..c668484ccc41541812503cd286e2cb2360c59203 100644 --- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp @@ -276,6 +276,8 @@ QIcon ClangAssistProposalItem::icon() const return snippetIcon; case CodeCompletion::Other: return Icons::iconForType(Icons::UnknownIconType); + default: + break; } return QIcon(); diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 8dcc8849d7cdd0597c8d3b5cadf32f7a05f46870..54a31a66622a3a418646e3a6fc48d2f3dfa4a8e1 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -175,11 +175,8 @@ void IpcReceiver::codeCompleted(const CodeCompletedMessage &message) const quint64 ticket = message.ticketNumber(); QScopedPointer processor(m_assistProcessorsTable.take(ticket)); if (processor) { - const bool finished = processor->handleAvailableAsyncCompletions( - message.codeCompletions(), - message.neededCorrection()); - if (!finished) - processor.take(); + processor->handleAvailableCompletions(message.codeCompletions(), + message.neededCorrection()); } } diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index f71f586855764534d4c99eaa4a5fcb128f4661e0..631736279d01b7f0132d54a044c108b908c5f74a 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -51,6 +51,7 @@ #include +#include #include #include @@ -106,30 +107,6 @@ QList toAssistProposalItems(const CodeCompletions return results; } -bool isFunctionHintLikeCompletion(CodeCompletion::Kind kind) -{ - return kind == CodeCompletion::FunctionCompletionKind - || kind == CodeCompletion::ConstructorCompletionKind - || kind == CodeCompletion::DestructorCompletionKind - || kind == CodeCompletion::SignalCompletionKind - || kind == CodeCompletion::SlotCompletionKind; -} - -CodeCompletions matchingFunctionCompletions(const CodeCompletions completions, - const QString &functionName) -{ - CodeCompletions matching; - - foreach (const CodeCompletion &completion, completions) { - if (isFunctionHintLikeCompletion(completion.completionKind()) - && completion.text().toString() == functionName) { - matching.append(completion); - } - } - - return matching; -} - } // Anonymous using namespace CPlusPlus; @@ -157,25 +134,32 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface * return startCompletionHelper(); // == 0 if results are calculated asynchronously } -bool ClangCompletionAssistProcessor::handleAvailableAsyncCompletions( +static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions) +{ + return ::Utils::filtered(completions, [](const CodeCompletion &completion) { + return completion.completionKind() == CodeCompletion::FunctionOverloadCompletionKind; + }); +} + +void ClangCompletionAssistProcessor::handleAvailableCompletions( const CodeCompletions &completions, CompletionCorrection neededCorrection) { - bool handled = true; + QTC_CHECK(m_completions.isEmpty()); - switch (m_sentRequestType) { - case CompletionRequestType::NormalCompletion: - handleAvailableCompletions(completions, neededCorrection); - break; - case CompletionRequestType::FunctionHintCompletion: - handled = handleAvailableFunctionHintCompletions(completions); - break; - default: - QTC_CHECK(!"Unhandled ClangCompletionAssistProcessor::CompletionRequestType"); - break; - } + if (m_sentRequestType == NormalCompletion) { + m_completions = toAssistProposalItems(completions); + + if (m_addSnippets && !m_completions.isEmpty()) + addSnippets(); - return handled; + setAsyncProposalAvailable(createProposal(neededCorrection)); + } else { + const CodeCompletions functionSignatures = filterFunctionSignatures(completions); + if (!functionSignatures.isEmpty()) + setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures)); + // else: Not a function call, but e.g. a function declaration like "void f(" + } } const TextEditorWidget *ClangCompletionAssistProcessor::textEditorWidget() const @@ -268,7 +252,6 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper() } case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: { m_sentRequestType = FunctionHintCompletion; - m_functionName = analyzer.functionName(); const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray()); setPerformWasApplicable(requestSent); break; @@ -599,38 +582,12 @@ TextEditor::IAssistProposal *ClangCompletionAssistProcessor::createProposal( return new ClangAssistProposal(m_positionForProposal, model); } -void ClangCompletionAssistProcessor::handleAvailableCompletions( - const CodeCompletions &completions, - CompletionCorrection neededCorrection) +IAssistProposal *ClangCompletionAssistProcessor::createFunctionHintProposal( + const ClangBackEnd::CodeCompletions &completions) const { - QTC_CHECK(m_completions.isEmpty()); - - m_completions = toAssistProposalItems(completions); - if (m_addSnippets && !m_completions.isEmpty()) - addSnippets(); - - setAsyncProposalAvailable(createProposal(neededCorrection)); -} - -bool ClangCompletionAssistProcessor::handleAvailableFunctionHintCompletions( - const CodeCompletions &completions) -{ - QTC_CHECK(!m_functionName.isEmpty()); - const auto relevantCompletions = matchingFunctionCompletions(completions, m_functionName); - - if (!relevantCompletions.isEmpty()) { - auto *model = new ClangFunctionHintModel(relevantCompletions); - auto *proposal = new FunctionHintProposal(m_positionForProposal, model); - - setAsyncProposalAvailable(proposal); - return true; - } else { - m_addSnippets = false; - m_functionName.clear(); - m_sentRequestType = NormalCompletion; - sendCompletionRequest(m_interface->position(), QByteArray()); - return false; // We are not yet finished. - } + auto *model = new ClangFunctionHintModel(completions); + auto *proposal = new FunctionHintProposal(m_positionForProposal, model); + return proposal; } } // namespace Internal diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h index 854d3332a95c904de801222a2377a26b64536dad..8b67116e8744372f42f5f66a9cbcf5f5afd6fd1e 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h @@ -50,8 +50,8 @@ public: TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override; - bool handleAvailableAsyncCompletions(const CodeCompletions &completions, - CompletionCorrection neededCorrection); + void handleAvailableCompletions(const CodeCompletions &completions, + CompletionCorrection neededCorrection); const TextEditor::TextEditorWidget *textEditorWidget() const; @@ -63,6 +63,8 @@ private: TextEditor::IAssistProposal *createProposal( CompletionCorrection neededCorrection = CompletionCorrection::NoCorrection) const; + TextEditor::IAssistProposal *createFunctionHintProposal( + const CodeCompletions &completions) const; bool completeInclude(const QTextCursor &cursor); bool completeInclude(int position); @@ -82,15 +84,10 @@ private: void sendFileContent(const QByteArray &customFileContent); bool sendCompletionRequest(int position, const QByteArray &customFileContent); - void handleAvailableCompletions(const CodeCompletions &completions, - CompletionCorrection neededCorrection); - bool handleAvailableFunctionHintCompletions(const CodeCompletions &completions); - private: QScopedPointer m_interface; unsigned m_completionOperator; enum CompletionRequestType { NormalCompletion, FunctionHintCompletion } m_sentRequestType; - QString m_functionName; // For type == Type::FunctionHintCompletion bool m_addSnippets = false; // For type == Type::NormalCompletion }; diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp index 77eccac70d1e61120051a38263a1b063f4ff6a57..2852be4697b7edadbfaa6394e7811aa408a11b56 100644 --- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp +++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp @@ -167,7 +167,11 @@ void CompletionChunksToTextConverter::parse( switch (codeCompletionChunk.kind()) { case CodeCompletionChunk::ResultType: parseResultType(codeCompletionChunk.text()); break; - case CodeCompletionChunk::Placeholder: parsePlaceHolder(codeCompletionChunk); break; + // Do not rely on CurrentParameter because it might be wrong for + // invalid code. Instead, handle it as PlaceHolder. + case CodeCompletionChunk::CurrentParameter: + case CodeCompletionChunk::Placeholder: + parsePlaceHolder(codeCompletionChunk); break; case CodeCompletionChunk::LeftParen: parseLeftParen(codeCompletionChunk); break; case CodeCompletionChunk::LeftBrace: parseLeftBrace(codeCompletionChunk); break; default: parseText(codeCompletionChunk.text()); break; diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp index 71e3214a5a1ac42ae78cb83bf9633a06a2a76cae..00a8f96c6d77c887329c70246b85284d2a16a62a 100644 --- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp +++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp @@ -91,8 +91,7 @@ void ClangCompletionContextAnalyzer::analyze() } } -ClangCompletionContextAnalyzer::FunctionInfo -ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const +bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) const { int index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, endOfOperator); @@ -104,15 +103,15 @@ ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, index); const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface, index); + if (functionNameStart == -1) + return false; - QTextCursor textCursor2(m_interface->textDocument()); - textCursor2.setPosition(functionNameStart); - textCursor2.setPosition(index, QTextCursor::KeepAnchor); + QTextCursor functionNameSelector(m_interface->textDocument()); + functionNameSelector.setPosition(functionNameStart); + functionNameSelector.setPosition(index, QTextCursor::KeepAnchor); + const QString functionName = functionNameSelector.selectedText().trimmed(); - FunctionInfo info; - info.functionNamePosition = functionNameStart; - info.functionName = textCursor2.selectedText().trimmed(); - return info; + return !functionName.isEmpty(); } void ClangCompletionContextAnalyzer::setActionAndClangPosition(CompletionAction action, @@ -158,16 +157,15 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio // No function completion if cursor is not after '(' or ',' m_positionForProposal = afterOperatorPosition; setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition); - } else { - const FunctionInfo functionInfo = analyzeFunctionCall(afterOperatorPosition); - if (functionInfo.isValid()) { - m_functionName = functionInfo.functionName; - setActionAndClangPosition(PassThroughToLibClangAfterLeftParen, - functionInfo.functionNamePosition); - } else { - m_positionForProposal = afterOperatorPosition; - setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition); - } + } else if (looksLikeAFunctionCall(afterOperatorPosition)) { + // Always pass the position right after '(' to libclang because + // positions after the comma might be problematic if a preceding + // argument is invalid code. + setActionAndClangPosition(PassThroughToLibClangAfterLeftParen, + m_positionForProposal); + } else { // e.g. "(" without any function name in front + m_positionForProposal = afterOperatorPosition; + setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition); } } } diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h index 9313810a2908f88b10c7d8270d4fb6707aaf47ee..3aa3bc58045e9a8e7df8a4516266e1054920f813 100644 --- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h +++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h @@ -58,18 +58,10 @@ public: int positionForClang() const { return m_positionForClang; } int positionEndOfExpression() const { return m_positionEndOfExpression; } - QString functionName() const { return m_functionName; } - private: ClangCompletionContextAnalyzer(); - struct FunctionInfo { - bool isValid() const { return functionNamePosition != -1 && !functionName.isEmpty(); } - - int functionNamePosition = -1; - QString functionName; - }; - FunctionInfo analyzeFunctionCall(int endOfExpression) const; + bool looksLikeAFunctionCall(int endOfExpression) const; void setActionAndClangPosition(CompletionAction action, int position); void setAction(CompletionAction action); @@ -88,7 +80,6 @@ private: int m_positionForProposal = -1; int m_positionForClang = -1; int m_positionEndOfExpression = -1; - QString m_functionName; }; } // namespace Internal diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index 9d2008662f90d255332d5c3c17883cb654a76deb..f06753ebc63f583ce0256b997916a43a36345d1c 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -819,13 +819,14 @@ void ClangCodeCompletionTest::testCompleteFunctions() QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)")); } -void ClangCodeCompletionTest::testCompleteConstructorAndFallbackToGlobalCompletion() +void ClangCodeCompletionTest::testCompleteConstructor() { ProjectLessCompletionTest t("constructorCompletion.cpp"); - QVERIFY(hasItem(t.proposal, "globalVariable")); - QVERIFY(hasItem(t.proposal, "GlobalClassWithCustomConstructor")); - QVERIFY(!hasSnippet(t.proposal, "class")); + QVERIFY(!hasItem(t.proposal, "globalVariable")); + QVERIFY(!hasItem(t.proposal, "class")); + QVERIFY(hasItem(t.proposal, "Foo(int)")); + QVERIFY(hasItem(t.proposal, "Foo(int, double)")); } // Explicitly Inserting The Dot diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h index 3f163c6266332b9689c7f82f7604f8d9e02ac3b5..24b36da4f0db07c8b201af9b799cdce08210a0f6 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h @@ -45,7 +45,7 @@ private slots: void testCompleteGlobals(); void testCompleteMembers(); void testCompleteFunctions(); - void testCompleteConstructorAndFallbackToGlobalCompletion(); + void testCompleteConstructor(); void testCompleteWithDotToArrowCorrection(); void testDontCompleteWithDotToArrowCorrectionForFloats(); diff --git a/src/plugins/clangcodemodel/test/data/constructorCompletion.cpp b/src/plugins/clangcodemodel/test/data/constructorCompletion.cpp index 1b19b68a1051dc5497c976fde627413110872216..211fda71bdc7f5f85fe11444251635d49baa985c 100644 --- a/src/plugins/clangcodemodel/test/data/constructorCompletion.cpp +++ b/src/plugins/clangcodemodel/test/data/constructorCompletion.cpp @@ -1,9 +1,10 @@ int globalVariable; -struct GlobalClassWithCustomConstructor { - GlobalClassWithCustomConstructor(int) {} +struct Foo { + Foo(int) {} + Foo(int, double) {} }; void f() { - GlobalClassWithCustomConstructor foo( /* COMPLETE HERE */ + Foo foo( /* COMPLETE HERE */ } diff --git a/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp b/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp index ea54d580273552fde200609cfce6445d7b00b5ce..c00ce0d8fde2af073ca5690d781088e3293f7088 100644 --- a/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp +++ b/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp @@ -152,6 +152,9 @@ void CodeCompletionsExtractor::extractCompletionKind() case CXCursor_NotImplemented: currentCodeCompletion_.setCompletionKind(CodeCompletion::KeywordCompletionKind); break; + case CXCursor_OverloadCandidate: + currentCodeCompletion_.setCompletionKind(CodeCompletion::FunctionOverloadCompletionKind); + break; default: currentCodeCompletion_.setCompletionKind(CodeCompletion::Other); } diff --git a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp index 445bfb73ecadaaf9a78cfeb98ab206ffc95b6094..5ca579a1d40bc71d291dd43e016ed42b408e0791 100644 --- a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp +++ b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp @@ -238,28 +238,28 @@ TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtCall) { auto analyzer = runAnalyzer("f(@"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -2, 0, positionInText)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText)); } TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoAtCall) { auto analyzer = runAnalyzer("f(1,@"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -4, -2, positionInText)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -2, -2, positionInText)); } TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtCall) { auto analyzer = runAnalyzer("f(1, @"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, -3, positionInText)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText)); } TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName) { auto analyzer = runAnalyzer("foo (@"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, 0, positionInText)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText)); } TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis) diff --git a/tests/unit/unittest/codecompletionsextractor-test.cpp b/tests/unit/unittest/codecompletionsextractor-test.cpp index 28eb6a7548c49a3ecf1cbe8edffd3c1ab07c9711..585e9301d2fe436b9f52f891d5cc8db30fb9c26a 100644 --- a/tests/unit/unittest/codecompletionsextractor-test.cpp +++ b/tests/unit/unittest/codecompletionsextractor-test.cpp @@ -153,6 +153,7 @@ protected: ClangBackEnd::UnsavedFiles unsavedFiles; ClangBackEnd::Documents documents{projects, unsavedFiles}; Document functionDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_function.cpp"), project, Utf8StringVector(), documents}; + Document functionOverloadDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_functionoverload.cpp"), project, Utf8StringVector(), documents}; Document variableDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_variable.cpp"), project, Utf8StringVector(), documents}; Document classDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_class.cpp"), project, Utf8StringVector(), documents}; Document namespaceDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_namespace.cpp"), project, Utf8StringVector(), documents}; @@ -678,6 +679,21 @@ TEST_F(CodeCompletionsExtractorSlowTest, BriefComment) ASSERT_THAT(extractor, HasBriefComment(Utf8StringLiteral("BriefComment"), Utf8StringLiteral("A brief comment"))); } +TEST_F(CodeCompletionsExtractorSlowTest, OverloadCandidate) +{ + ClangCodeCompleteResults completeResults(getResults(functionOverloadDocument, 8, 13)); + + ::CodeCompletionsExtractor extractor(completeResults.data()); + + ASSERT_THAT(extractor, HasCompletionChunks(Utf8String(), + CodeCompletionChunks({ + {CodeCompletionChunk::Text, Utf8StringLiteral("Foo")}, + {CodeCompletionChunk::LeftParen, Utf8StringLiteral("(")}, + {CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("const Foo &foo")}, + {CodeCompletionChunk::RightParen, Utf8StringLiteral(")")}, + }))); +} + ClangCodeCompleteResults CodeCompletionsExtractor::getResults(const Document &document, uint line, uint column, diff --git a/tests/unit/unittest/completionchunkstotextconverter-test.cpp b/tests/unit/unittest/completionchunkstotextconverter-test.cpp index 853e777c9c69a948241e8b94b241827c4d568396..8df3cf806d8eb82dc8348d8b500f0c2ad23e3eb1 100644 --- a/tests/unit/unittest/completionchunkstotextconverter-test.cpp +++ b/tests/unit/unittest/completionchunkstotextconverter-test.cpp @@ -53,7 +53,9 @@ protected: CodeCompletionChunk semicolon{CodeCompletionChunk::SemiColon, Utf8StringLiteral(";")}; CodeCompletionChunk colonColonText{CodeCompletionChunk::Text, Utf8StringLiteral("::")}; CodeCompletionChunk functionArgumentX{CodeCompletionChunk::Placeholder, Utf8StringLiteral("char x")}; + CodeCompletionChunk functionArgumentXAsCurrentParameter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("char x")}; CodeCompletionChunk functionArgumentY{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int y")}; + CodeCompletionChunk functionArgumentYAsCurrentParamter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("int y")}; CodeCompletionChunk functionArgumentZ{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z")}; CodeCompletionChunk functionArgumentTemplate{CodeCompletionChunk::Placeholder, Utf8StringLiteral("const Foo &foo")}; CodeCompletionChunk switchName{CodeCompletionChunk::TypedText, Utf8StringLiteral("switch")}; @@ -78,6 +80,7 @@ protected: CodeCompletionChunk optionalEnableIfTType{CodeCompletionChunk::Placeholder, Utf8StringLiteral("_Tp"), true}; CodeCompletionChunk optionalComma{CodeCompletionChunk::Comma, Utf8StringLiteral(", "), true}; CodeCompletionChunk optionalFunctionArgumentY{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int y"), true}; + CodeCompletionChunk optionalFunctionArgumentYAsCurrentParameter{CodeCompletionChunk::CurrentParameter, Utf8StringLiteral("int y"), true}; CodeCompletionChunk optionalFunctionArgumentZ{CodeCompletionChunk::Placeholder, Utf8StringLiteral("int z"), true}; }; @@ -117,7 +120,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneArgumen CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, - functionArgumentX, + functionArgumentXAsCurrentParameter, rightParen}); ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks), @@ -129,7 +132,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithOneParamet CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, - functionArgumentX, + functionArgumentXAsCurrentParameter, rightParen}); ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 1), @@ -143,7 +146,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParamet leftParen, functionArgumentX, comma, - functionArgumentY, + functionArgumentYAsCurrentParamter, rightParen}); ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 2), @@ -157,7 +160,7 @@ TEST_F(CompletionChunksToTextConverter, ConvertToFunctionSignatureWithTwoParamet leftParen, functionArgumentX, optionalComma, - optionalFunctionArgumentY, + optionalFunctionArgumentYAsCurrentParameter, rightParen}); ASSERT_THAT(converter.convertToFunctionSignatureWithHtml(completionChunks, 2), diff --git a/tests/unit/unittest/data/complete_extractor_functionoverload.cpp b/tests/unit/unittest/data/complete_extractor_functionoverload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa447158f4f719e76541f6ba6a162b89461bf33c --- /dev/null +++ b/tests/unit/unittest/data/complete_extractor_functionoverload.cpp @@ -0,0 +1,9 @@ +struct Foo { + Foo(const Foo &foo); + Foo(char c); +}; + +void f() +{ + Foo foo( +}