kadircet created this revision. kadircet added reviewers: ioeric, ilya-biryukov, hokein. Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.
Currently we only add parantheses to the functions if snippets are enabled, which also inserts snippets for parameters into parantheses. Adding a new option to put only parantheses. Also it moves the cursor within parantheses or at the end of them by looking at whether completion item has any parameters or not. Still requires snippets support on the client side. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D50835 Files: clangd/CodeComplete.cpp clangd/CodeComplete.h unittests/clangd/CodeCompleteTests.cpp Index: unittests/clangd/CodeCompleteTests.cpp =================================================================== --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -1590,6 +1590,44 @@ ElementsAre(Sig("foo(T, U) -> void", {"T", "U"}))); } +TEST(CompletionTest, RenderWithCursorRelocation) { + CodeCompleteOptions Opts; + Opts.EnableCursorRelocation = 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 Index: clangd/CodeComplete.h =================================================================== --- clangd/CodeComplete.h +++ clangd/CodeComplete.h @@ -81,6 +81,12 @@ /// Include completions that require small corrections, e.g. change '.' to /// '->' on member access etc. bool IncludeFixIts = false; + + /// Enables cursor to be moved around according to completions needs even when + /// snippets are disabled. For example selecting a function with parameters as + /// completion item moves the cursor within the parameters, whereas without + /// parameters moves to after closing parantheses. + bool EnableCursorRelocation = false; }; // Semi-structured representation of a code-complete suggestion for our C++ API. Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -1373,11 +1373,21 @@ } if (Opts.EnableSnippets) LSP.textEdit->newText += SnippetSuffix; + // Check if we have cursor relocation enabled and completing a function. + else if (SnippetSuffix.size() && Opts.EnableCursorRelocation) { + // Check whether function has any parameters or not. + if (SnippetSuffix.size() > 2) + LSP.textEdit->newText += "(${0})"; + else + LSP.textEdit->newText += "()"; + } + // FIXME(kadircet): Do not even fill insertText after making sure textEdit is // compatible with most of the editors. LSP.insertText = LSP.textEdit->newText; - LSP.insertTextFormat = Opts.EnableSnippets ? InsertTextFormat::Snippet - : InsertTextFormat::PlainText; + LSP.insertTextFormat = Opts.EnableSnippets || Opts.EnableCursorRelocation + ? InsertTextFormat::Snippet + : InsertTextFormat::PlainText; if (HeaderInsertion) LSP.additionalTextEdits.push_back(*HeaderInsertion); return LSP;
Index: unittests/clangd/CodeCompleteTests.cpp =================================================================== --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -1590,6 +1590,44 @@ ElementsAre(Sig("foo(T, U) -> void", {"T", "U"}))); } +TEST(CompletionTest, RenderWithCursorRelocation) { + CodeCompleteOptions Opts; + Opts.EnableCursorRelocation = 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 Index: clangd/CodeComplete.h =================================================================== --- clangd/CodeComplete.h +++ clangd/CodeComplete.h @@ -81,6 +81,12 @@ /// Include completions that require small corrections, e.g. change '.' to /// '->' on member access etc. bool IncludeFixIts = false; + + /// Enables cursor to be moved around according to completions needs even when + /// snippets are disabled. For example selecting a function with parameters as + /// completion item moves the cursor within the parameters, whereas without + /// parameters moves to after closing parantheses. + bool EnableCursorRelocation = false; }; // Semi-structured representation of a code-complete suggestion for our C++ API. Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -1373,11 +1373,21 @@ } if (Opts.EnableSnippets) LSP.textEdit->newText += SnippetSuffix; + // Check if we have cursor relocation enabled and completing a function. + else if (SnippetSuffix.size() && Opts.EnableCursorRelocation) { + // Check whether function has any parameters or not. + if (SnippetSuffix.size() > 2) + LSP.textEdit->newText += "(${0})"; + else + LSP.textEdit->newText += "()"; + } + // FIXME(kadircet): Do not even fill insertText after making sure textEdit is // compatible with most of the editors. LSP.insertText = LSP.textEdit->newText; - LSP.insertTextFormat = Opts.EnableSnippets ? InsertTextFormat::Snippet - : InsertTextFormat::PlainText; + LSP.insertTextFormat = Opts.EnableSnippets || Opts.EnableCursorRelocation + ? InsertTextFormat::Snippet + : InsertTextFormat::PlainText; if (HeaderInsertion) LSP.additionalTextEdits.push_back(*HeaderInsertion); return LSP;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits