From dfa24f09ad4b707b8b5076d92f48f019e6a346ee Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 12 Feb 2021 11:36:17 +0100 Subject: [PATCH] ClangCodeModel: Show only valid applicable overloads when completing libclang is smart enough to filter the overloads according to which arguments have already been entered, so let's make use of that. Fixes: QTCREATORBUG-650 Change-Id: Ic2711f460c908c6fd9c8efe28c3c63a0ce2d9205 Reviewed-by: Christian Stenger --- .../clangcompletioncontextanalyzer.cpp | 5 +---- .../clangcodemodel/test/clangcodecompletion_test.cpp | 12 ++++++++++++ .../clangcodemodel/test/clangcodecompletion_test.h | 1 + .../clangcodemodel/test/data/clangtestdata.qrc | 2 ++ .../test/data/functionCompletionFiltered.cpp | 9 +++++++++ .../test/data/functionCompletionFiltered2.cpp | 9 +++++++++ .../unittest/clangcompletioncontextanalyzer-test.cpp | 8 ++++---- 7 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 src/plugins/clangcodemodel/test/data/functionCompletionFiltered.cpp create mode 100644 src/plugins/clangcodemodel/test/data/functionCompletionFiltered2.cpp diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp index 060c5016949..034b5298939 100644 --- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp +++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp @@ -183,11 +183,8 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio const int functionNameStart = startOfFunctionCall(afterOperatorPosition); if (functionNameStart >= 0) { m_addSnippets = functionNameStart == 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, + afterOperatorPosition, functionNameStart); } else { // e.g. "(" without any function name in front m_addSnippets = true; diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index c77dbfc08e2..c4dd8e882ec 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -608,6 +608,18 @@ void ClangCodeCompletionTest::testCompleteFunctions() QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)")); } +void ClangCodeCompletionTest::testCompleteOverloads() +{ + ProjectLessCompletionTest t("functionCompletionFiltered.cpp"); + QCOMPARE(t.proposal->size(), 1); + QVERIFY(hasItem(t.proposal, "void func(int i, int j)")); + + ProjectLessCompletionTest t2("functionCompletionFiltered2.cpp"); + QCOMPARE(t2.proposal->size(), 2); + QVERIFY(hasItem(t2.proposal, "void func(const S &s, int j)")); + QVERIFY(hasItem(t2.proposal, "void func(const S &s, int j, int k)")); +} + void ClangCodeCompletionTest::testCompleteConstructor() { ProjectLessCompletionTest t("constructorCompletion.cpp"); diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h index 150ef9651ba..cf8bac668e5 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h @@ -48,6 +48,7 @@ private slots: void testCompleteMembersFromOutside(); void testCompleteMembersFromFriend(); void testCompleteFunctions(); + void testCompleteOverloads(); void testCompleteConstructor(); void testCompleteClassAndConstructor(); diff --git a/src/plugins/clangcodemodel/test/data/clangtestdata.qrc b/src/plugins/clangcodemodel/test/data/clangtestdata.qrc index 9690d8bee6e..d1013a7d29a 100644 --- a/src/plugins/clangcodemodel/test/data/clangtestdata.qrc +++ b/src/plugins/clangcodemodel/test/data/clangtestdata.qrc @@ -27,5 +27,7 @@ membercompletion-outside.cpp membercompletion-inside.cpp membercompletion-friend.cpp + functionCompletionFiltered.cpp + functionCompletionFiltered2.cpp diff --git a/src/plugins/clangcodemodel/test/data/functionCompletionFiltered.cpp b/src/plugins/clangcodemodel/test/data/functionCompletionFiltered.cpp new file mode 100644 index 00000000000..f242eb6eea4 --- /dev/null +++ b/src/plugins/clangcodemodel/test/data/functionCompletionFiltered.cpp @@ -0,0 +1,9 @@ +struct S; +void func(int i, int j); +void func(const S &s, int j); +void func(const S &s, int j, int k); + +void g() +{ + func(1, /* COMPLETE HERE */ +} diff --git a/src/plugins/clangcodemodel/test/data/functionCompletionFiltered2.cpp b/src/plugins/clangcodemodel/test/data/functionCompletionFiltered2.cpp new file mode 100644 index 00000000000..c4d77913867 --- /dev/null +++ b/src/plugins/clangcodemodel/test/data/functionCompletionFiltered2.cpp @@ -0,0 +1,9 @@ +struct S {}; +void func(int i, int j); +void func(const S &s, int j); +void func(const S &s, int j, int k); + +void g() +{ + func(S(), /* COMPLETE HERE */ +} diff --git a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp index b1ac930295c..66ed01b19db 100644 --- a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp +++ b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp @@ -261,14 +261,14 @@ TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoAtCall) { auto analyzer = runAnalyzer("f(1,@"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -2, -2, positionInText, false)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -2, positionInText, false)); } TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtCall) { auto analyzer = runAnalyzer("f(1, @"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText, false)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false)); } TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName) @@ -289,7 +289,7 @@ TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtConstructorCallWith { auto analyzer = runAnalyzer("f{1, @"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText, false)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false)); } TEST_F(ClangCompletionContextAnalyzer, WhitespaceBeforeConstructorCallWithBraceInitializer) @@ -546,7 +546,7 @@ TEST_F(ClangCompletionContextAnalyzer, TemplatedFunctionSecondArgument) { auto analyzer = runAnalyzer("f < decltype(bar -> member) > (1, @"); - ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText, false)); + ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false)); } TEST_F(ClangCompletionContextAnalyzer, FunctionNameStartPosition)