diff --git a/plugins/clang/codecompletion/context.cpp b/plugins/clang/codecompletion/context.cpp --- a/plugins/clang/codecompletion/context.cpp +++ b/plugins/clang/codecompletion/context.cpp @@ -55,6 +55,7 @@ #include "../duchain/navigationwidget.h" #include "../clangsettings/clangsettingsmanager.h" +#include #include #include @@ -105,6 +106,12 @@ CCP_Unlikely = 80 }; +QStringRef trimLeft(const QStringRef string) { + const int position = std::find_if_not(string.begin(), string.end(), + [](QChar c){ return c.isSpace(); }) - string.begin(); + return string.mid(position); +} + /** * Common base class for Clang code completion items. */ @@ -338,7 +345,16 @@ void execute(KTextEditor::View* view, const KTextEditor::Range& word) override { - view->document()->replaceText(word, m_replacement); + KTextEditor::Document* const document = view->document(); + + // try and replace leading typed text that match the proposed implementation + const QStringRef leading = trimLeft(document->line(word.end().line()).leftRef(word.end().column())); + if (!leading.isEmpty() && (m_display.startsWith(leading) || m_replacement.startsWith(leading))) { + const KTextEditor::Cursor newStart = {word.end().line(), word.end().column() - leading.size()}; + document->replaceText({newStart, word.end()}, m_replacement); + } else { + document->replaceText(word, m_replacement); + } } }; diff --git a/plugins/clang/tests/test_codecompletion.cpp b/plugins/clang/tests/test_codecompletion.cpp --- a/plugins/clang/tests/test_codecompletion.cpp +++ b/plugins/clang/tests/test_codecompletion.cpp @@ -1387,6 +1387,24 @@ << CompletionItems({5, 0}, {"Test", "Test::bar(B a)"}) << "Test::bar(B a)" << "template class X, typename B>\nclass Test {\npublic:\nvoid bar(B a);\n};\ntemplate class X, typename B> void Test::bar(B a)\n{\n}\n"; + + QTest::newRow("replace-leading-return-type") + << "void foo(int x);\nvoid " + << CompletionItems({1, 5}, {"foo(int x)"}) + << "foo(int x)" + << "void foo(int x);\nvoid foo(int x)\n{\n}\n"; + + QTest::newRow("replace-leading-function-name") + << "void foo(int x);\nfoo" + << CompletionItems({1, 3}, {"foo(int x)"}) + << "foo(int x)" + << "void foo(int x);\nvoid foo(int x)\n{\n}\n"; + + QTest::newRow("replace-leading-with-class-method") + << "class Foo { void bar(int x); };\nvoid " + << CompletionItems({1, 5}, {"Foo", "Foo::bar(int x)"}) + << "Foo::bar(int x)" + << "class Foo { void bar(int x); };\nvoid Foo::bar(int x)\n{\n}\n"; } void TestCodeCompletion::testIgnoreGccBuiltins()