[clangd] Add parantheses while auto-completing functions.

Summary:
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.

Reviewers: ioeric, ilya-biryukov, hokein

Reviewed By: ioeric

Subscribers: MaskRay, jkorous, arphaman, cfe-commits

Differential Revision: https://reviews.llvm.org/D50835

llvm-svn: 340040
This commit is contained in:
Kadir Cetinkaya 2018-08-17 15:42:54 +00:00
parent 2532ac880a
commit 6c9f15c533
3 changed files with 67 additions and 2 deletions

View File

@ -1413,8 +1413,17 @@ CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
LSP.additionalTextEdits.push_back(FixIt);
}
}
if (Opts.EnableSnippets)
LSP.textEdit->newText += SnippetSuffix;
if (Opts.EnableSnippets && !SnippetSuffix.empty()) {
if (!Opts.EnableFunctionArgSnippets &&
((Kind == CompletionItemKind::Function) ||
(Kind == CompletionItemKind::Method)) &&
(SnippetSuffix.front() == '(') && (SnippetSuffix.back() == ')'))
// 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;

View File

@ -82,6 +82,10 @@ struct CodeCompleteOptions {
/// Include completions that require small corrections, e.g. change '.' to
/// '->' on member access etc.
bool IncludeFixIts = false;
/// Whether to generate snippets for function arguments on code-completion.
/// Needs snippets to be enabled as well.
bool EnableFunctionArgSnippets = true;
};
// Semi-structured representation of a code-complete suggestion for our C++ API.

View File

@ -1648,6 +1648,58 @@ TEST(SignatureHelpTest, IndexDocumentation) {
SigDoc("Doc from sema"))));
}
TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
CodeCompleteOptions Opts;
Opts.EnableFunctionArgSnippets = 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;
Opts.EnableFunctionArgSnippets = false;
{
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 = "()";
C.Kind = CompletionItemKind::Method;
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})";
C.Kind = CompletionItemKind::Function;
auto R = C.render(Opts);
EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
}
}
} // namespace
} // namespace clangd
} // namespace clang