Index: clangd/CodeComplete.h =================================================================== --- clangd/CodeComplete.h +++ clangd/CodeComplete.h @@ -82,6 +82,10 @@ /// Include completions that require small corrections, e.g. change '.' to /// '->' on member access etc. bool IncludeFixIts = false; + + /// Disables snippet generation for function arguments. Does nothing if + /// snippets are not enabled. + bool DisableSnippetTemplateForFunctionArgs = false; }; // Semi-structured representation of a code-complete suggestion for our C++ API. Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -1371,8 +1371,14 @@ LSP.additionalTextEdits.push_back(FixIt); } } - if (Opts.EnableSnippets) - LSP.textEdit->newText += SnippetSuffix; + if (Opts.EnableSnippets && !SnippetSuffix.empty()) { + if (Opts.DisableSnippetTemplateForFunctionArgs) + // Check whether function has any parameters or not. + LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()"; + else + LSP.textEdit->newText += SnippetSuffix; + } + // FIXME(kadircet): Do not even fill insertText after making sure textEdit is // compatible with most of the editors. LSP.insertText = LSP.textEdit->newText; Index: unittests/clangd/CodeCompleteTests.cpp =================================================================== --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -1590,6 +1590,55 @@ ElementsAre(Sig("foo(T, U) -> void", {"T", "U"}))); } +TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) { + CodeCompleteOptions Opts; + Opts.DisableSnippetTemplateForFunctionArgs = true; + { + CodeCompletion C; + C.RequiredQualifier = "Foo::"; + C.Name = "x"; + C.SnippetSuffix = "()"; + + auto R = C.render(Opts); + EXPECT_EQ(R.textEdit->newText, "Foo::x"); + EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText); + } + + Opts.EnableSnippets = true; + { + CodeCompletion C; + C.RequiredQualifier = "Foo::"; + C.Name = "x"; + C.SnippetSuffix = ""; + + auto R = C.render(Opts); + EXPECT_EQ(R.textEdit->newText, "Foo::x"); + EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet); + } + + { + CodeCompletion C; + C.RequiredQualifier = "Foo::"; + C.Name = "x"; + C.SnippetSuffix = "()"; + + auto R = C.render(Opts); + EXPECT_EQ(R.textEdit->newText, "Foo::x()"); + EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet); + } + + { + CodeCompletion C; + C.RequiredQualifier = "Foo::"; + C.Name = "x"; + C.SnippetSuffix = "(${0:bool})"; + + auto R = C.render(Opts); + EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})"); + EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet); + } +} + } // namespace } // namespace clangd } // namespace clang