[clangd] Handle template args for disabled function arg snippets
Reviewers: kadircet, ioeric, sammccall Reviewed By: kadircet Subscribers: MaskRay, jkorous, arphaman, cfe-commits Differential Revision: https://reviews.llvm.org/D52422 llvm-svn: 343066
This commit is contained in:
parent
d8048675f4
commit
4f98470dea
|
@ -482,13 +482,43 @@ private:
|
|||
auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>();
|
||||
if (!Snippet)
|
||||
// All bundles are function calls.
|
||||
// FIXME(ibiryukov): sometimes add template arguments to a snippet, e.g.
|
||||
// we need to complete 'forward<$1>($0)'.
|
||||
return "($0)";
|
||||
if (!Snippet->empty() && !EnableFunctionArgSnippets &&
|
||||
((Completion.Kind == CompletionItemKind::Function) ||
|
||||
(Completion.Kind == CompletionItemKind::Method)) &&
|
||||
(Snippet->front() == '(') && (Snippet->back() == ')'))
|
||||
// Check whether function has any parameters or not.
|
||||
return Snippet->size() > 2 ? "($0)" : "()";
|
||||
if (EnableFunctionArgSnippets)
|
||||
return *Snippet;
|
||||
|
||||
// Replace argument snippets with a simplified pattern.
|
||||
if (Snippet->empty())
|
||||
return "";
|
||||
if (Completion.Kind == CompletionItemKind::Function ||
|
||||
Completion.Kind == CompletionItemKind::Method) {
|
||||
// Functions snippets can be of 2 types:
|
||||
// - containing only function arguments, e.g.
|
||||
// foo(${1:int p1}, ${2:int p2});
|
||||
// We transform this pattern to '($0)' or '()'.
|
||||
// - template arguments and function arguments, e.g.
|
||||
// foo<${1:class}>(${2:int p1}).
|
||||
// We transform this pattern to '<$1>()$0' or '<$0>()'.
|
||||
|
||||
bool EmptyArgs = llvm::StringRef(*Snippet).endswith("()");
|
||||
if (Snippet->front() == '<')
|
||||
return EmptyArgs ? "<$1>()$0" : "<$1>($0)";
|
||||
if (Snippet->front() == '(')
|
||||
return EmptyArgs ? "()" : "($0)";
|
||||
return *Snippet; // Not an arg snippet?
|
||||
}
|
||||
if (Completion.Kind == CompletionItemKind::Reference ||
|
||||
Completion.Kind == CompletionItemKind::Class) {
|
||||
if (Snippet->front() != '<')
|
||||
return *Snippet; // Not an arg snippet?
|
||||
|
||||
// Classes and template using aliases can only have template arguments,
|
||||
// e.g. Foo<${1:class}>.
|
||||
if (llvm::StringRef(*Snippet).endswith("<>"))
|
||||
return "<>"; // can happen with defaulted template arguments.
|
||||
return "<$0>";
|
||||
}
|
||||
return *Snippet;
|
||||
}
|
||||
|
||||
|
|
|
@ -1741,32 +1741,65 @@ TEST(CompletionTest, CompletionFunctionArgsDisabled) {
|
|||
CodeCompleteOptions Opts;
|
||||
Opts.EnableSnippets = true;
|
||||
Opts.EnableFunctionArgSnippets = false;
|
||||
const std::string Header =
|
||||
R"cpp(
|
||||
|
||||
{
|
||||
auto Results = completions(
|
||||
R"cpp(
|
||||
void xfoo();
|
||||
void xfoo(int x, int y);
|
||||
void xbar();
|
||||
void f() {
|
||||
)cpp";
|
||||
{
|
||||
auto Results = completions(Header + "\nxfo^", {}, Opts);
|
||||
void f() { xfo^ })cpp",
|
||||
{}, Opts);
|
||||
EXPECT_THAT(
|
||||
Results.Completions,
|
||||
UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
|
||||
AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
|
||||
}
|
||||
{
|
||||
auto Results = completions(Header + "\nxba^", {}, Opts);
|
||||
auto Results = completions(
|
||||
R"cpp(
|
||||
void xbar();
|
||||
void f() { xba^ })cpp",
|
||||
{}, Opts);
|
||||
EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
|
||||
Named("xbar"), SnippetSuffix("()"))));
|
||||
}
|
||||
{
|
||||
Opts.BundleOverloads = true;
|
||||
auto Results = completions(Header + "\nxfo^", {}, Opts);
|
||||
auto Results = completions(
|
||||
R"cpp(
|
||||
void xfoo();
|
||||
void xfoo(int x, int y);
|
||||
void f() { xfo^ })cpp",
|
||||
{}, Opts);
|
||||
EXPECT_THAT(
|
||||
Results.Completions,
|
||||
UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)"))));
|
||||
}
|
||||
{
|
||||
auto Results = completions(
|
||||
R"cpp(
|
||||
template <class T, class U>
|
||||
void xfoo(int a, U b);
|
||||
void f() { xfo^ })cpp",
|
||||
{}, Opts);
|
||||
EXPECT_THAT(
|
||||
Results.Completions,
|
||||
UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("<$1>($0)"))));
|
||||
}
|
||||
{
|
||||
auto Results = completions(
|
||||
R"cpp(
|
||||
template <class T>
|
||||
class foo_class{};
|
||||
template <class T>
|
||||
using foo_alias = T**;
|
||||
void f() { foo_^ })cpp",
|
||||
{}, Opts);
|
||||
EXPECT_THAT(
|
||||
Results.Completions,
|
||||
UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")),
|
||||
AllOf(Named("foo_alias"), SnippetSuffix("<$0>"))));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CompletionTest, SuggestOverrides) {
|
||||
|
|
Loading…
Reference in New Issue