Skip to content

Commit 8ac9d2a

Browse files
committed
[clangd] Fix function-arg-placeholder suppression with macros.
While here, unhide function-arg-placeholders flag. It's reasonable to want and maybe we should consider making it default. Fixes clangd/clangd#922 Differential Revision: https://reviews.llvm.org/D113765
1 parent d96161a commit 8ac9d2a

File tree

3 files changed

+38
-25
lines changed

3 files changed

+38
-25
lines changed

clang-tools-extra/clangd/CodeComplete.cpp

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -466,32 +466,27 @@ struct CodeCompletionBuilder {
466466
// FIXME(ibiryukov): sometimes add template arguments to a snippet, e.g.
467467
// we need to complete 'forward<$1>($0)'.
468468
return "($0)";
469-
// Suppress function argument snippets cursor is followed by left
470-
// parenthesis (and potentially arguments) or if there are potentially
471-
// template arguments. There are cases where it would be wrong (e.g. next
472-
// '<' token is a comparison rather than template argument list start) but
473-
// it is less common and suppressing snippet provides better UX.
474-
if (Completion.Kind == CompletionItemKind::Function ||
475-
Completion.Kind == CompletionItemKind::Method ||
476-
Completion.Kind == CompletionItemKind::Constructor) {
477-
// If there is a potential template argument list, drop snippet and just
478-
// complete symbol name. Ideally, this could generate an edit that would
479-
// paste function arguments after template argument list but it would be
480-
// complicated. Example:
481-
//
482-
// fu^<int> -> function<int>
469+
470+
bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||
471+
Completion.Kind == CompletionItemKind::Method ||
472+
Completion.Kind == CompletionItemKind::Constructor ||
473+
Completion.Kind == CompletionItemKind::Text /*Macro*/;
474+
// If likely arg list already exists, don't add new parens & placeholders.
475+
// Snippet: function(int x, int y)
476+
// func^(1,2) -> function(1, 2)
477+
// NOT function(int x, int y)(1, 2)
478+
if (MayHaveArgList) {
479+
// Check for a template argument list in the code.
480+
// Snippet: function<class T>(int x)
481+
// fu^<int>(1) -> function<int>(1)
483482
if (NextTokenKind == tok::less && Snippet->front() == '<')
484483
return "";
485-
// Potentially followed by argument list.
484+
// Potentially followed by regular argument list.
486485
if (NextTokenKind == tok::l_paren) {
487-
// If snippet contains template arguments we will emit them and drop
488-
// function arguments. Example:
489-
//
490-
// fu^(42) -> function<int>(42);
486+
// Snippet: function<class T>(int x)
487+
// fu^(1,2) -> function<class T>(1, 2)
491488
if (Snippet->front() == '<') {
492-
// Find matching '>'. Snippet->find('>') will not work in cases like
493-
// template <typename T=std::vector<int>>. Hence, iterate through
494-
// the snippet until the angle bracket balance reaches zero.
489+
// Find matching '>', handling nested brackets.
495490
int Balance = 0;
496491
size_t I = 0;
497492
do {
@@ -512,8 +507,7 @@ struct CodeCompletionBuilder {
512507
// Replace argument snippets with a simplified pattern.
513508
if (Snippet->empty())
514509
return "";
515-
if (Completion.Kind == CompletionItemKind::Function ||
516-
Completion.Kind == CompletionItemKind::Method) {
510+
if (MayHaveArgList) {
517511
// Functions snippets can be of 2 types:
518512
// - containing only function arguments, e.g.
519513
// foo(${1:int p1}, ${2:int p2});

clang-tools-extra/clangd/tool/ClangdMain.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ opt<bool> EnableFunctionArgSnippets{
233233
"function calls. When enabled, completions also contain "
234234
"placeholders for method parameters"),
235235
init(CodeCompleteOptions().EnableFunctionArgSnippets),
236-
Hidden,
237236
};
238237

239238
opt<CodeCompleteOptions::IncludeInsertion> HeaderInsertion{

clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,9 @@ TEST(CompletionTest, OverloadBundling) {
16621662
// Overload with bool
16631663
int a(bool);
16641664
int b(float);
1665+
1666+
X(int);
1667+
X(float);
16651668
};
16661669
int GFuncC(int);
16671670
int GFuncD(int);
@@ -1671,6 +1674,10 @@ TEST(CompletionTest, OverloadBundling) {
16711674
EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,
16721675
UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)")));
16731676

1677+
// Constructor completions are bundled.
1678+
EXPECT_THAT(completions(Context + "X z = X^", {}, Opts).Completions,
1679+
UnorderedElementsAre(Labeled("X"), Labeled("X(…)")));
1680+
16741681
// Non-member completions are bundled, including index+sema.
16751682
Symbol NoArgsGFunc = func("GFuncC");
16761683
EXPECT_THAT(
@@ -2323,6 +2330,15 @@ TEST(CompletionTest, CompletionFunctionArgsDisabled) {
23232330
UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")),
23242331
AllOf(Named("foo_alias"), SnippetSuffix("<$0>"))));
23252332
}
2333+
{
2334+
auto Results = completions(
2335+
R"cpp(
2336+
#define FOO(x, y) x##f
2337+
FO^ )cpp",
2338+
{}, Opts);
2339+
EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
2340+
Named("FOO"), SnippetSuffix("($0)"))));
2341+
}
23262342
}
23272343

23282344
TEST(CompletionTest, SuggestOverrides) {
@@ -3170,6 +3186,7 @@ TEST(CompletionTest, FunctionArgsExist) {
31703186
clangd::CodeCompleteOptions Opts;
31713187
Opts.EnableSnippets = true;
31723188
std::string Context = R"cpp(
3189+
#define MACRO(x)
31733190
int foo(int A);
31743191
int bar();
31753192
struct Object {
@@ -3217,6 +3234,9 @@ TEST(CompletionTest, FunctionArgsExist) {
32173234
Contains(AllOf(Labeled("Container<typename T>(int Size)"),
32183235
SnippetSuffix(""),
32193236
Kind(CompletionItemKind::Constructor))));
3237+
EXPECT_THAT(completions(Context + "MAC^(2)", {}, Opts).Completions,
3238+
Contains(AllOf(Labeled("MACRO(x)"), SnippetSuffix(""),
3239+
Kind(CompletionItemKind::Text))));
32203240
}
32213241

32223242
TEST(CompletionTest, NoCrashDueToMacroOrdering) {

0 commit comments

Comments
 (0)