Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp =================================================================== --- clang-tools-extra/trunk/clangd/CodeComplete.cpp +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp @@ -269,7 +269,8 @@ CodeCompletionString *SemaCCS, const IncludeInserter &Includes, StringRef FileName, const CodeCompleteOptions &Opts) - : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) { + : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments), + EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets) { add(C, SemaCCS); if (C.SemaResult) { Completion.Origin |= SymbolOrigin::AST; @@ -385,10 +386,17 @@ } std::string summarizeSnippet() const { - if (auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>()) - return *Snippet; - // All bundles are function calls. - return "(${0})"; + auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>(); + if (!Snippet) + // All bundles are function calls. + 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)" : "()"; + return *Snippet; } std::string summarizeSignature() const { @@ -402,6 +410,7 @@ CodeCompletion Completion; SmallVector Bundled; bool ExtractDocumentation; + bool EnableFunctionArgSnippets; }; // Determine the symbol ID for a Sema code completion result, if possible. @@ -1413,16 +1422,8 @@ LSP.additionalTextEdits.push_back(FixIt); } } - 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; - } + if (Opts.EnableSnippets) + LSP.textEdit->newText += SnippetSuffix; // FIXME(kadircet): Do not even fill insertText after making sure textEdit is // compatible with most of the editors. Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp @@ -1140,7 +1140,7 @@ // For now we just return one of the doc strings arbitrarily. EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"), HasSubstr("Overload with bool"))); - EXPECT_EQ(A.SnippetSuffix, "(${0})"); + EXPECT_EQ(A.SnippetSuffix, "($0)"); } TEST(CompletionTest, DocumentationFromChangedFileCrash) { @@ -1648,55 +1648,35 @@ SigDoc("Doc from sema")))); } -TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) { +TEST(CompletionTest, CompletionFunctionArgsDisabled) { 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; + const std::string Header = + R"cpp( + void xfoo(); + void xfoo(int x, int y); + void xbar(); + void f() { + )cpp"; { - 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); + auto Results = completions(Header + "\nxfo^", {}, Opts); + EXPECT_THAT( + Results.Completions, + UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")), + AllOf(Named("xfoo"), SnippetSuffix("($0)")))); } - { - 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); + auto Results = completions(Header + "\nxba^", {}, Opts); + EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf( + Named("xbar"), SnippetSuffix("()")))); } - { - 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); + Opts.BundleOverloads = true; + auto Results = completions(Header + "\nxfo^", {}, Opts); + EXPECT_THAT( + Results.Completions, + UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)")))); } }