1 //===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Annotations.h" 10 #include "ClangdServer.h" 11 #include "CodeComplete.h" 12 #include "Compiler.h" 13 #include "Matchers.h" 14 #include "Protocol.h" 15 #include "Quality.h" 16 #include "SourceCode.h" 17 #include "SyncAPI.h" 18 #include "TestFS.h" 19 #include "TestIndex.h" 20 #include "TestTU.h" 21 #include "Threading.h" 22 #include "index/Index.h" 23 #include "index/MemIndex.h" 24 #include "clang/Sema/CodeCompleteConsumer.h" 25 #include "clang/Tooling/CompilationDatabase.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/Path.h" 28 #include "llvm/Testing/Support/Error.h" 29 #include "gmock/gmock.h" 30 #include "gtest/gtest.h" 31 #include <condition_variable> 32 #include <mutex> 33 34 namespace clang { 35 namespace clangd { 36 37 namespace { 38 using ::llvm::Failed; 39 using ::testing::AllOf; 40 using ::testing::Contains; 41 using ::testing::ElementsAre; 42 using ::testing::Field; 43 using ::testing::HasSubstr; 44 using ::testing::IsEmpty; 45 using ::testing::Not; 46 using ::testing::UnorderedElementsAre; 47 48 class IgnoreDiagnostics : public DiagnosticsConsumer { 49 void onDiagnosticsReady(PathRef File, 50 std::vector<Diag> Diagnostics) override {} 51 }; 52 53 // GMock helpers for matching completion items. 54 MATCHER_P(Named, Name, "") { return arg.Name == Name; } 55 MATCHER_P(NameStartsWith, Prefix, "") { 56 return llvm::StringRef(arg.Name).startswith(Prefix); 57 } 58 MATCHER_P(Scope, S, "") { return arg.Scope == S; } 59 MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; } 60 MATCHER_P(Labeled, Label, "") { 61 return arg.RequiredQualifier + arg.Name + arg.Signature == Label; 62 } 63 MATCHER_P(SigHelpLabeled, Label, "") { return arg.label == Label; } 64 MATCHER_P(Kind, K, "") { return arg.Kind == K; } 65 MATCHER_P(Doc, D, "") { return arg.Documentation == D; } 66 MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; } 67 MATCHER_P(HasInclude, IncludeHeader, "") { 68 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader; 69 } 70 MATCHER_P(InsertInclude, IncludeHeader, "") { 71 return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader && 72 bool(arg.Includes[0].Insertion); 73 } 74 MATCHER(InsertInclude, "") { 75 return !arg.Includes.empty() && bool(arg.Includes[0].Insertion); 76 } 77 MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; } 78 MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; } 79 MATCHER_P(Signature, S, "") { return arg.Signature == S; } 80 81 // Shorthand for Contains(Named(Name)). 82 Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) { 83 return Contains(Named(std::move(Name))); 84 } 85 Matcher<const std::vector<CodeCompletion> &> Has(std::string Name, 86 CompletionItemKind K) { 87 return Contains(AllOf(Named(std::move(Name)), Kind(K))); 88 } 89 MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); } 90 MATCHER(Deprecated, "") { return arg.Deprecated; } 91 92 std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) { 93 SymbolSlab::Builder Slab; 94 for (const auto &Sym : Symbols) 95 Slab.insert(Sym); 96 return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab()); 97 } 98 99 CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef TestCode, 100 Position Point, 101 std::vector<Symbol> IndexSymbols = {}, 102 clangd::CodeCompleteOptions Opts = {}) { 103 std::unique_ptr<SymbolIndex> OverrideIndex; 104 if (!IndexSymbols.empty()) { 105 assert(!Opts.Index && "both Index and IndexSymbols given!"); 106 OverrideIndex = memIndex(std::move(IndexSymbols)); 107 Opts.Index = OverrideIndex.get(); 108 } 109 110 auto File = testPath("foo.cpp"); 111 runAddDocument(Server, File, TestCode); 112 auto CompletionList = 113 llvm::cantFail(runCodeComplete(Server, File, Point, Opts)); 114 return CompletionList; 115 } 116 117 CodeCompleteResult completions(ClangdServer &Server, llvm::StringRef Text, 118 std::vector<Symbol> IndexSymbols = {}, 119 clangd::CodeCompleteOptions Opts = {}, 120 PathRef FilePath = "foo.cpp") { 121 std::unique_ptr<SymbolIndex> OverrideIndex; 122 if (!IndexSymbols.empty()) { 123 assert(!Opts.Index && "both Index and IndexSymbols given!"); 124 OverrideIndex = memIndex(std::move(IndexSymbols)); 125 Opts.Index = OverrideIndex.get(); 126 } 127 128 auto File = testPath(FilePath); 129 Annotations Test(Text); 130 runAddDocument(Server, File, Test.code()); 131 auto CompletionList = 132 llvm::cantFail(runCodeComplete(Server, File, Test.point(), Opts)); 133 return CompletionList; 134 } 135 136 // Builds a server and runs code completion. 137 // If IndexSymbols is non-empty, an index will be built and passed to opts. 138 CodeCompleteResult completions(llvm::StringRef Text, 139 std::vector<Symbol> IndexSymbols = {}, 140 clangd::CodeCompleteOptions Opts = {}, 141 PathRef FilePath = "foo.cpp") { 142 MockFSProvider FS; 143 MockCompilationDatabase CDB; 144 IgnoreDiagnostics DiagConsumer; 145 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 146 return completions(Server, Text, std::move(IndexSymbols), std::move(Opts), 147 FilePath); 148 } 149 150 // Builds a server and runs code completion. 151 // If IndexSymbols is non-empty, an index will be built and passed to opts. 152 CodeCompleteResult completionsNoCompile(llvm::StringRef Text, 153 std::vector<Symbol> IndexSymbols = {}, 154 clangd::CodeCompleteOptions Opts = {}, 155 PathRef FilePath = "foo.cpp") { 156 std::unique_ptr<SymbolIndex> OverrideIndex; 157 if (!IndexSymbols.empty()) { 158 assert(!Opts.Index && "both Index and IndexSymbols given!"); 159 OverrideIndex = memIndex(std::move(IndexSymbols)); 160 Opts.Index = OverrideIndex.get(); 161 } 162 163 MockFSProvider FS; 164 Annotations Test(Text); 165 return codeComplete(FilePath, tooling::CompileCommand(), /*Preamble=*/nullptr, 166 Test.code(), Test.point(), FS.getFileSystem(), Opts); 167 } 168 169 Symbol withReferences(int N, Symbol S) { 170 S.References = N; 171 return S; 172 } 173 174 TEST(CompletionTest, Limit) { 175 clangd::CodeCompleteOptions Opts; 176 Opts.Limit = 2; 177 auto Results = completions(R"cpp( 178 struct ClassWithMembers { 179 int AAA(); 180 int BBB(); 181 int CCC(); 182 }; 183 184 int main() { ClassWithMembers().^ } 185 )cpp", 186 /*IndexSymbols=*/{}, Opts); 187 188 EXPECT_TRUE(Results.HasMore); 189 EXPECT_THAT(Results.Completions, ElementsAre(Named("AAA"), Named("BBB"))); 190 } 191 192 TEST(CompletionTest, Filter) { 193 std::string Body = R"cpp( 194 #define MotorCar 195 int Car; 196 struct S { 197 int FooBar; 198 int FooBaz; 199 int Qux; 200 }; 201 )cpp"; 202 203 // Only items matching the fuzzy query are returned. 204 EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions, 205 AllOf(Has("FooBar"), Has("FooBaz"), Not(Has("Qux")))); 206 207 // Macros require prefix match. 208 EXPECT_THAT(completions(Body + "int main() { C^ }").Completions, 209 AllOf(Has("Car"), Not(Has("MotorCar")))); 210 } 211 212 void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) { 213 auto Results = completions( 214 R"cpp( 215 int global_var; 216 217 int global_func(); 218 219 // Make sure this is not in preamble. 220 #define MACRO X 221 222 struct GlobalClass {}; 223 224 struct ClassWithMembers { 225 /// Doc for method. 226 int method(); 227 228 int field; 229 private: 230 int private_field; 231 }; 232 233 int test() { 234 struct LocalClass {}; 235 236 /// Doc for local_var. 237 int local_var; 238 239 ClassWithMembers().^ 240 } 241 )cpp", 242 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts); 243 244 EXPECT_TRUE(Results.RanParser); 245 // Class members. The only items that must be present in after-dot 246 // completion. 247 EXPECT_THAT(Results.Completions, 248 AllOf(Has("method"), Has("field"), Not(Has("ClassWithMembers")), 249 Not(Has("operator=")), Not(Has("~ClassWithMembers")))); 250 EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions, 251 Has("private_field")); 252 // Global items. 253 EXPECT_THAT( 254 Results.Completions, 255 Not(AnyOf(Has("global_var"), Has("index_var"), Has("global_func"), 256 Has("global_func()"), Has("index_func"), Has("GlobalClass"), 257 Has("IndexClass"), Has("MACRO"), Has("LocalClass")))); 258 // There should be no code patterns (aka snippets) in after-dot 259 // completion. At least there aren't any we're aware of. 260 EXPECT_THAT(Results.Completions, 261 Not(Contains(Kind(CompletionItemKind::Snippet)))); 262 // Check documentation. 263 EXPECT_IFF(Opts.IncludeComments, Results.Completions, 264 Contains(IsDocumented())); 265 } 266 267 void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) { 268 auto Results = completions( 269 R"cpp( 270 int global_var; 271 int global_func(); 272 273 // Make sure this is not in preamble. 274 #define MACRO X 275 276 struct GlobalClass {}; 277 278 struct ClassWithMembers { 279 /// Doc for method. 280 int method(); 281 }; 282 283 int test() { 284 struct LocalClass {}; 285 286 /// Doc for local_var. 287 int local_var; 288 289 ^ 290 } 291 )cpp", 292 {cls("IndexClass"), var("index_var"), func("index_func")}, Opts); 293 294 EXPECT_TRUE(Results.RanParser); 295 // Class members. Should never be present in global completions. 296 EXPECT_THAT(Results.Completions, 297 Not(AnyOf(Has("method"), Has("method()"), Has("field")))); 298 // Global items. 299 EXPECT_THAT(Results.Completions, 300 AllOf(Has("global_var"), Has("index_var"), Has("global_func"), 301 Has("index_func" /* our fake symbol doesn't include () */), 302 Has("GlobalClass"), Has("IndexClass"))); 303 // A macro. 304 EXPECT_IFF(Opts.IncludeMacros, Results.Completions, Has("MACRO")); 305 // Local items. Must be present always. 306 EXPECT_THAT(Results.Completions, 307 AllOf(Has("local_var"), Has("LocalClass"), 308 Contains(Kind(CompletionItemKind::Snippet)))); 309 // Check documentation. 310 EXPECT_IFF(Opts.IncludeComments, Results.Completions, 311 Contains(IsDocumented())); 312 } 313 314 TEST(CompletionTest, CompletionOptions) { 315 auto Test = [&](const clangd::CodeCompleteOptions &Opts) { 316 testAfterDotCompletion(Opts); 317 testGlobalScopeCompletion(Opts); 318 }; 319 // We used to test every combination of options, but that got too slow (2^N). 320 auto Flags = { 321 &clangd::CodeCompleteOptions::IncludeMacros, 322 &clangd::CodeCompleteOptions::IncludeComments, 323 &clangd::CodeCompleteOptions::IncludeCodePatterns, 324 &clangd::CodeCompleteOptions::IncludeIneligibleResults, 325 }; 326 // Test default options. 327 Test({}); 328 // Test with one flag flipped. 329 for (auto &F : Flags) { 330 clangd::CodeCompleteOptions O; 331 O.*F ^= true; 332 Test(O); 333 } 334 } 335 336 TEST(CompletionTest, Accessible) { 337 auto Internal = completions(R"cpp( 338 class Foo { 339 public: void pub(); 340 protected: void prot(); 341 private: void priv(); 342 }; 343 void Foo::pub() { this->^ } 344 )cpp"); 345 EXPECT_THAT(Internal.Completions, 346 AllOf(Has("priv"), Has("prot"), Has("pub"))); 347 348 auto External = completions(R"cpp( 349 class Foo { 350 public: void pub(); 351 protected: void prot(); 352 private: void priv(); 353 }; 354 void test() { 355 Foo F; 356 F.^ 357 } 358 )cpp"); 359 EXPECT_THAT(External.Completions, 360 AllOf(Has("pub"), Not(Has("prot")), Not(Has("priv")))); 361 } 362 363 TEST(CompletionTest, Qualifiers) { 364 auto Results = completions(R"cpp( 365 class Foo { 366 public: int foo() const; 367 int bar() const; 368 }; 369 class Bar : public Foo { 370 int foo() const; 371 }; 372 void test() { Bar().^ } 373 )cpp"); 374 EXPECT_THAT(Results.Completions, 375 Contains(AllOf(Qualifier(""), Named("bar")))); 376 // Hidden members are not shown. 377 EXPECT_THAT(Results.Completions, 378 Not(Contains(AllOf(Qualifier("Foo::"), Named("foo"))))); 379 // Private members are not shown. 380 EXPECT_THAT(Results.Completions, 381 Not(Contains(AllOf(Qualifier(""), Named("foo"))))); 382 } 383 384 TEST(CompletionTest, InjectedTypename) { 385 // These are suppressed when accessed as a member... 386 EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions, 387 Not(Has("X"))); 388 EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions, 389 Not(Has("X"))); 390 // ...but accessible in other, more useful cases. 391 EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions, 392 Has("X")); 393 EXPECT_THAT( 394 completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions, 395 Has("Y")); 396 EXPECT_THAT( 397 completions( 398 "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };") 399 .Completions, 400 Has("Y")); 401 // This case is marginal (`using X::X` is useful), we allow it for now. 402 EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions, 403 Has("X")); 404 } 405 406 TEST(CompletionTest, SkipInjectedWhenUnqualified) { 407 EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions, 408 ElementsAre(Named("X"), Named("~X"))); 409 } 410 411 TEST(CompletionTest, Snippets) { 412 clangd::CodeCompleteOptions Opts; 413 auto Results = completions( 414 R"cpp( 415 struct fake { 416 int a; 417 int f(int i, const float f) const; 418 }; 419 int main() { 420 fake f; 421 f.^ 422 } 423 )cpp", 424 /*IndexSymbols=*/{}, Opts); 425 EXPECT_THAT( 426 Results.Completions, 427 HasSubsequence(Named("a"), 428 SnippetSuffix("(${1:int i}, ${2:const float f})"))); 429 } 430 431 TEST(CompletionTest, NoSnippetsInUsings) { 432 clangd::CodeCompleteOptions Opts; 433 Opts.EnableSnippets = true; 434 auto Results = completions( 435 R"cpp( 436 namespace ns { 437 int func(int a, int b); 438 } 439 440 using ns::^; 441 )cpp", 442 /*IndexSymbols=*/{}, Opts); 443 EXPECT_THAT(Results.Completions, 444 ElementsAre(AllOf(Named("func"), Labeled("func(int a, int b)"), 445 SnippetSuffix("")))); 446 447 // Check index completions too. 448 auto Func = func("ns::func"); 449 Func.CompletionSnippetSuffix = "(${1:int a}, ${2: int b})"; 450 Func.Signature = "(int a, int b)"; 451 Func.ReturnType = "void"; 452 453 Results = completions(R"cpp( 454 namespace ns {} 455 using ns::^; 456 )cpp", 457 /*IndexSymbols=*/{Func}, Opts); 458 EXPECT_THAT(Results.Completions, 459 ElementsAre(AllOf(Named("func"), Labeled("func(int a, int b)"), 460 SnippetSuffix("")))); 461 462 // Check all-scopes completions too. 463 Opts.AllScopes = true; 464 Results = completions(R"cpp( 465 using ^; 466 )cpp", 467 /*IndexSymbols=*/{Func}, Opts); 468 EXPECT_THAT(Results.Completions, 469 Contains(AllOf(Named("func"), Labeled("ns::func(int a, int b)"), 470 SnippetSuffix("")))); 471 } 472 473 TEST(CompletionTest, Kinds) { 474 auto Results = completions( 475 R"cpp( 476 int variable; 477 struct Struct {}; 478 int function(); 479 // make sure MACRO is not included in preamble. 480 #define MACRO 10 481 int X = ^ 482 )cpp", 483 {func("indexFunction"), var("indexVariable"), cls("indexClass")}); 484 EXPECT_THAT(Results.Completions, 485 AllOf(Has("function", CompletionItemKind::Function), 486 Has("variable", CompletionItemKind::Variable), 487 Has("int", CompletionItemKind::Keyword), 488 Has("Struct", CompletionItemKind::Class), 489 Has("MACRO", CompletionItemKind::Text), 490 Has("indexFunction", CompletionItemKind::Function), 491 Has("indexVariable", CompletionItemKind::Variable), 492 Has("indexClass", CompletionItemKind::Class))); 493 494 Results = completions("nam^"); 495 EXPECT_THAT(Results.Completions, 496 Has("namespace", CompletionItemKind::Snippet)); 497 498 // Members of anonymous unions are of kind 'field'. 499 Results = completions( 500 R"cpp( 501 struct X{ 502 union { 503 void *a; 504 }; 505 }; 506 auto u = X().^ 507 )cpp"); 508 EXPECT_THAT( 509 Results.Completions, 510 UnorderedElementsAre(AllOf(Named("a"), Kind(CompletionItemKind::Field)))); 511 512 // Completion kinds for templates should not be unknown. 513 Results = completions( 514 R"cpp( 515 template <class T> struct complete_class {}; 516 template <class T> void complete_function(); 517 template <class T> using complete_type_alias = int; 518 template <class T> int complete_variable = 10; 519 520 struct X { 521 template <class T> static int complete_static_member = 10; 522 523 static auto x = complete_^ 524 } 525 )cpp"); 526 EXPECT_THAT( 527 Results.Completions, 528 UnorderedElementsAre( 529 AllOf(Named("complete_class"), Kind(CompletionItemKind::Class)), 530 AllOf(Named("complete_function"), Kind(CompletionItemKind::Function)), 531 AllOf(Named("complete_type_alias"), 532 Kind(CompletionItemKind::Interface)), 533 AllOf(Named("complete_variable"), Kind(CompletionItemKind::Variable)), 534 AllOf(Named("complete_static_member"), 535 Kind(CompletionItemKind::Property)))); 536 } 537 538 TEST(CompletionTest, NoDuplicates) { 539 auto Results = completions( 540 R"cpp( 541 class Adapter { 542 }; 543 544 void f() { 545 Adapter^ 546 } 547 )cpp", 548 {cls("Adapter")}); 549 550 // Make sure there are no duplicate entries of 'Adapter'. 551 EXPECT_THAT(Results.Completions, ElementsAre(Named("Adapter"))); 552 } 553 554 TEST(CompletionTest, ScopedNoIndex) { 555 auto Results = completions( 556 R"cpp( 557 namespace fake { int BigBang, Babble, Box; }; 558 int main() { fake::ba^ } 559 ")cpp"); 560 // Babble is a better match than BigBang. Box doesn't match at all. 561 EXPECT_THAT(Results.Completions, 562 ElementsAre(Named("Babble"), Named("BigBang"))); 563 } 564 565 TEST(CompletionTest, Scoped) { 566 auto Results = completions( 567 R"cpp( 568 namespace fake { int Babble, Box; }; 569 int main() { fake::ba^ } 570 ")cpp", 571 {var("fake::BigBang")}); 572 EXPECT_THAT(Results.Completions, 573 ElementsAre(Named("Babble"), Named("BigBang"))); 574 } 575 576 TEST(CompletionTest, ScopedWithFilter) { 577 auto Results = completions( 578 R"cpp( 579 void f() { ns::x^ } 580 )cpp", 581 {cls("ns::XYZ"), func("ns::foo")}); 582 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("XYZ"))); 583 } 584 585 TEST(CompletionTest, ReferencesAffectRanking) { 586 auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")}); 587 EXPECT_THAT(Results.Completions, 588 HasSubsequence(Named("absb"), Named("absl"))); 589 Results = completions("int main() { abs^ }", 590 {withReferences(10000, ns("absl")), func("absb")}); 591 EXPECT_THAT(Results.Completions, 592 HasSubsequence(Named("absl"), Named("absb"))); 593 } 594 595 TEST(CompletionTest, ContextWords) { 596 auto Results = completions(R"cpp( 597 enum class Color { RED, YELLOW, BLUE }; 598 599 // (blank lines so the definition above isn't "context") 600 601 // "It was a yellow car," he said. "Big yellow car, new." 602 auto Finish = Color::^ 603 )cpp"); 604 // Yellow would normally sort last (alphabetic). 605 // But the recent mention shuold bump it up. 606 ASSERT_THAT(Results.Completions, 607 HasSubsequence(Named("YELLOW"), Named("BLUE"))); 608 } 609 610 TEST(CompletionTest, GlobalQualified) { 611 auto Results = completions( 612 R"cpp( 613 void f() { ::^ } 614 )cpp", 615 {cls("XYZ")}); 616 EXPECT_THAT(Results.Completions, 617 AllOf(Has("XYZ", CompletionItemKind::Class), 618 Has("f", CompletionItemKind::Function))); 619 } 620 621 TEST(CompletionTest, FullyQualified) { 622 auto Results = completions( 623 R"cpp( 624 namespace ns { void bar(); } 625 void f() { ::ns::^ } 626 )cpp", 627 {cls("ns::XYZ")}); 628 EXPECT_THAT(Results.Completions, 629 AllOf(Has("XYZ", CompletionItemKind::Class), 630 Has("bar", CompletionItemKind::Function))); 631 } 632 633 TEST(CompletionTest, SemaIndexMerge) { 634 auto Results = completions( 635 R"cpp( 636 namespace ns { int local; void both(); } 637 void f() { ::ns::^ } 638 )cpp", 639 {func("ns::both"), cls("ns::Index")}); 640 // We get results from both index and sema, with no duplicates. 641 EXPECT_THAT(Results.Completions, 642 UnorderedElementsAre( 643 AllOf(Named("local"), Origin(SymbolOrigin::AST)), 644 AllOf(Named("Index"), Origin(SymbolOrigin::Static)), 645 AllOf(Named("both"), 646 Origin(SymbolOrigin::AST | SymbolOrigin::Static)))); 647 } 648 649 TEST(CompletionTest, SemaIndexMergeWithLimit) { 650 clangd::CodeCompleteOptions Opts; 651 Opts.Limit = 1; 652 auto Results = completions( 653 R"cpp( 654 namespace ns { int local; void both(); } 655 void f() { ::ns::^ } 656 )cpp", 657 {func("ns::both"), cls("ns::Index")}, Opts); 658 EXPECT_EQ(Results.Completions.size(), Opts.Limit); 659 EXPECT_TRUE(Results.HasMore); 660 } 661 662 TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) { 663 MockFSProvider FS; 664 MockCompilationDatabase CDB; 665 std::string Subdir = testPath("sub"); 666 std::string SearchDirArg = (Twine("-I") + Subdir).str(); 667 CDB.ExtraClangFlags = {SearchDirArg.c_str()}; 668 std::string BarHeader = testPath("sub/bar.h"); 669 FS.Files[BarHeader] = ""; 670 671 IgnoreDiagnostics DiagConsumer; 672 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 673 auto BarURI = URI::create(BarHeader).toString(); 674 Symbol Sym = cls("ns::X"); 675 Sym.CanonicalDeclaration.FileURI = BarURI.c_str(); 676 Sym.IncludeHeaders.emplace_back(BarURI, 1); 677 // Shoten include path based on search dirctory and insert. 678 auto Results = completions(Server, 679 R"cpp( 680 int main() { ns::^ } 681 )cpp", 682 {Sym}); 683 EXPECT_THAT(Results.Completions, 684 ElementsAre(AllOf(Named("X"), InsertInclude("\"bar.h\"")))); 685 // Can be disabled via option. 686 CodeCompleteOptions NoInsertion; 687 NoInsertion.InsertIncludes = CodeCompleteOptions::NeverInsert; 688 Results = completions(Server, 689 R"cpp( 690 int main() { ns::^ } 691 )cpp", 692 {Sym}, NoInsertion); 693 EXPECT_THAT(Results.Completions, 694 ElementsAre(AllOf(Named("X"), Not(InsertInclude())))); 695 // Duplicate based on inclusions in preamble. 696 Results = completions(Server, 697 R"cpp( 698 #include "sub/bar.h" // not shortest, so should only match resolved. 699 int main() { ns::^ } 700 )cpp", 701 {Sym}); 702 EXPECT_THAT(Results.Completions, ElementsAre(AllOf(Named("X"), Labeled("X"), 703 Not(InsertInclude())))); 704 } 705 706 TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) { 707 MockFSProvider FS; 708 MockCompilationDatabase CDB; 709 710 IgnoreDiagnostics DiagConsumer; 711 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 712 Symbol SymX = cls("ns::X"); 713 Symbol SymY = cls("ns::Y"); 714 std::string BarHeader = testPath("bar.h"); 715 auto BarURI = URI::create(BarHeader).toString(); 716 SymX.CanonicalDeclaration.FileURI = BarURI.c_str(); 717 SymY.CanonicalDeclaration.FileURI = BarURI.c_str(); 718 SymX.IncludeHeaders.emplace_back("<bar>", 1); 719 SymY.IncludeHeaders.emplace_back("<bar>", 1); 720 // Shoten include path based on search dirctory and insert. 721 auto Results = completions(Server, 722 R"cpp( 723 namespace ns { 724 class X; 725 class Y {}; 726 } 727 int main() { ns::^ } 728 )cpp", 729 {SymX, SymY}); 730 EXPECT_THAT(Results.Completions, 731 ElementsAre(AllOf(Named("X"), Not(InsertInclude())), 732 AllOf(Named("Y"), Not(InsertInclude())))); 733 } 734 735 TEST(CompletionTest, IndexSuppressesPreambleCompletions) { 736 MockFSProvider FS; 737 MockCompilationDatabase CDB; 738 IgnoreDiagnostics DiagConsumer; 739 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 740 741 FS.Files[testPath("bar.h")] = 742 R"cpp(namespace ns { struct preamble { int member; }; })cpp"; 743 auto File = testPath("foo.cpp"); 744 Annotations Test(R"cpp( 745 #include "bar.h" 746 namespace ns { int local; } 747 void f() { ns::^; } 748 void f2() { ns::preamble().$2^; } 749 )cpp"); 750 runAddDocument(Server, File, Test.code()); 751 clangd::CodeCompleteOptions Opts = {}; 752 753 auto I = memIndex({var("ns::index")}); 754 Opts.Index = I.get(); 755 auto WithIndex = cantFail(runCodeComplete(Server, File, Test.point(), Opts)); 756 EXPECT_THAT(WithIndex.Completions, 757 UnorderedElementsAre(Named("local"), Named("index"))); 758 auto ClassFromPreamble = 759 cantFail(runCodeComplete(Server, File, Test.point("2"), Opts)); 760 EXPECT_THAT(ClassFromPreamble.Completions, Contains(Named("member"))); 761 762 Opts.Index = nullptr; 763 auto WithoutIndex = 764 cantFail(runCodeComplete(Server, File, Test.point(), Opts)); 765 EXPECT_THAT(WithoutIndex.Completions, 766 UnorderedElementsAre(Named("local"), Named("preamble"))); 767 } 768 769 // This verifies that we get normal preprocessor completions in the preamble. 770 // This is a regression test for an old bug: if we override the preamble and 771 // try to complete inside it, clang kicks our completion point just outside the 772 // preamble, resulting in always getting top-level completions. 773 TEST(CompletionTest, CompletionInPreamble) { 774 auto Results = completions(R"cpp( 775 #ifnd^ef FOO_H_ 776 #define BAR_H_ 777 #include <bar.h> 778 int foo() {} 779 #endif 780 )cpp") 781 .Completions; 782 EXPECT_THAT(Results, ElementsAre(Named("ifndef"))); 783 } 784 785 TEST(CompletionTest, DynamicIndexIncludeInsertion) { 786 MockFSProvider FS; 787 MockCompilationDatabase CDB; 788 IgnoreDiagnostics DiagConsumer; 789 ClangdServer::Options Opts = ClangdServer::optsForTest(); 790 Opts.BuildDynamicSymbolIndex = true; 791 ClangdServer Server(CDB, FS, DiagConsumer, Opts); 792 793 FS.Files[testPath("foo_header.h")] = R"cpp( 794 #pragma once 795 struct Foo { 796 // Member doc 797 int foo(); 798 }; 799 )cpp"; 800 const std::string FileContent(R"cpp( 801 #include "foo_header.h" 802 int Foo::foo() { 803 return 42; 804 } 805 )cpp"); 806 Server.addDocument(testPath("foo_impl.cpp"), FileContent); 807 // Wait for the dynamic index being built. 808 ASSERT_TRUE(Server.blockUntilIdleForTest()); 809 EXPECT_THAT(completions(Server, "Foo^ foo;").Completions, 810 ElementsAre(AllOf(Named("Foo"), HasInclude("\"foo_header.h\""), 811 InsertInclude()))); 812 } 813 814 TEST(CompletionTest, DynamicIndexMultiFile) { 815 MockFSProvider FS; 816 MockCompilationDatabase CDB; 817 IgnoreDiagnostics DiagConsumer; 818 auto Opts = ClangdServer::optsForTest(); 819 Opts.BuildDynamicSymbolIndex = true; 820 ClangdServer Server(CDB, FS, DiagConsumer, Opts); 821 822 FS.Files[testPath("foo.h")] = R"cpp( 823 namespace ns { class XYZ {}; void foo(int x) {} } 824 )cpp"; 825 runAddDocument(Server, testPath("foo.cpp"), R"cpp( 826 #include "foo.h" 827 )cpp"); 828 829 auto File = testPath("bar.cpp"); 830 Annotations Test(R"cpp( 831 namespace ns { 832 class XXX {}; 833 /// Doooc 834 void fooooo() {} 835 } 836 void f() { ns::^ } 837 )cpp"); 838 runAddDocument(Server, File, Test.code()); 839 840 auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {})); 841 // "XYZ" and "foo" are not included in the file being completed but are still 842 // visible through the index. 843 EXPECT_THAT(Results.Completions, Has("XYZ", CompletionItemKind::Class)); 844 EXPECT_THAT(Results.Completions, Has("foo", CompletionItemKind::Function)); 845 EXPECT_THAT(Results.Completions, Has("XXX", CompletionItemKind::Class)); 846 EXPECT_THAT(Results.Completions, 847 Contains((Named("fooooo"), Kind(CompletionItemKind::Function), 848 Doc("Doooc"), ReturnType("void")))); 849 } 850 851 TEST(CompletionTest, Documentation) { 852 auto Results = completions( 853 R"cpp( 854 // Non-doxygen comment. 855 int foo(); 856 /// Doxygen comment. 857 /// \param int a 858 int bar(int a); 859 /* Multi-line 860 block comment 861 */ 862 int baz(); 863 864 int x = ^ 865 )cpp"); 866 EXPECT_THAT(Results.Completions, 867 Contains(AllOf(Named("foo"), Doc("Non-doxygen comment.")))); 868 EXPECT_THAT( 869 Results.Completions, 870 Contains(AllOf(Named("bar"), Doc("Doxygen comment.\n\\param int a")))); 871 EXPECT_THAT(Results.Completions, 872 Contains(AllOf(Named("baz"), Doc("Multi-line\nblock comment")))); 873 } 874 875 TEST(CompletionTest, CommentsFromSystemHeaders) { 876 MockFSProvider FS; 877 MockCompilationDatabase CDB; 878 IgnoreDiagnostics DiagConsumer; 879 880 auto Opts = ClangdServer::optsForTest(); 881 Opts.BuildDynamicSymbolIndex = true; 882 883 ClangdServer Server(CDB, FS, DiagConsumer, Opts); 884 885 FS.Files[testPath("foo.h")] = R"cpp( 886 #pragma GCC system_header 887 888 // This comment should be retained! 889 int foo(); 890 )cpp"; 891 892 auto Results = completions(Server, 893 R"cpp( 894 #include "foo.h" 895 int x = foo^ 896 )cpp"); 897 EXPECT_THAT( 898 Results.Completions, 899 Contains(AllOf(Named("foo"), Doc("This comment should be retained!")))); 900 } 901 902 TEST(CompletionTest, GlobalCompletionFiltering) { 903 904 Symbol Class = cls("XYZ"); 905 Class.Flags = static_cast<Symbol::SymbolFlag>( 906 Class.Flags & ~(Symbol::IndexedForCodeCompletion)); 907 Symbol Func = func("XYZ::foooo"); 908 Func.Flags = static_cast<Symbol::SymbolFlag>( 909 Func.Flags & ~(Symbol::IndexedForCodeCompletion)); 910 911 auto Results = completions(R"(// void f() { 912 XYZ::foooo^ 913 })", 914 {Class, Func}); 915 EXPECT_THAT(Results.Completions, IsEmpty()); 916 } 917 918 TEST(CodeCompleteTest, DisableTypoCorrection) { 919 auto Results = completions(R"cpp( 920 namespace clang { int v; } 921 void f() { clangd::^ 922 )cpp"); 923 EXPECT_TRUE(Results.Completions.empty()); 924 } 925 926 TEST(CodeCompleteTest, NoColonColonAtTheEnd) { 927 auto Results = completions(R"cpp( 928 namespace clang { } 929 void f() { 930 clan^ 931 } 932 )cpp"); 933 934 EXPECT_THAT(Results.Completions, Contains(Labeled("clang"))); 935 EXPECT_THAT(Results.Completions, Not(Contains(Labeled("clang::")))); 936 } 937 938 TEST(CompletionTest, BacktrackCrashes) { 939 // Sema calls code completion callbacks twice in these cases. 940 auto Results = completions(R"cpp( 941 namespace ns { 942 struct FooBarBaz {}; 943 } // namespace ns 944 945 int foo(ns::FooBar^ 946 )cpp"); 947 948 EXPECT_THAT(Results.Completions, ElementsAre(Labeled("FooBarBaz"))); 949 950 // Check we don't crash in that case too. 951 completions(R"cpp( 952 struct FooBarBaz {}; 953 void test() { 954 if (FooBarBaz * x^) {} 955 } 956 )cpp"); 957 } 958 959 TEST(CompletionTest, CompleteInMacroWithStringification) { 960 auto Results = completions(R"cpp( 961 void f(const char *, int x); 962 #define F(x) f(#x, x) 963 964 namespace ns { 965 int X; 966 int Y; 967 } // namespace ns 968 969 int f(int input_num) { 970 F(ns::^) 971 } 972 )cpp"); 973 974 EXPECT_THAT(Results.Completions, 975 UnorderedElementsAre(Named("X"), Named("Y"))); 976 } 977 978 TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) { 979 auto Results = completions(R"cpp( 980 void f(const char *, int x); 981 #define F(x) f(#x, x) 982 983 namespace ns { 984 int X; 985 986 int f(int input_num) { 987 F(^) 988 } 989 } // namespace ns 990 )cpp"); 991 992 EXPECT_THAT(Results.Completions, Contains(Named("X"))); 993 } 994 995 TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) { 996 auto Results = completions(R"cpp( 997 int bar(int param_in_bar) { 998 } 999 1000 int foo(int param_in_foo) { 1001 #if 0 1002 // In recorvery mode, "param_in_foo" will also be suggested among many other 1003 // unrelated symbols; however, this is really a special case where this works. 1004 // If the #if block is outside of the function, "param_in_foo" is still 1005 // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't 1006 // really provide useful results in excluded branches. 1007 par^ 1008 #endif 1009 } 1010 )cpp"); 1011 1012 EXPECT_TRUE(Results.Completions.empty()); 1013 } 1014 1015 TEST(CompletionTest, DefaultArgs) { 1016 clangd::CodeCompleteOptions Opts; 1017 std::string Context = R"cpp( 1018 int X(int A = 0); 1019 int Y(int A, int B = 0); 1020 int Z(int A, int B = 0, int C = 0, int D = 0); 1021 )cpp"; 1022 EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions, 1023 UnorderedElementsAre(Labeled("X(int A = 0)"))); 1024 EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions, 1025 UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"), 1026 SnippetSuffix("(${1:int A})")))); 1027 EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions, 1028 UnorderedElementsAre( 1029 AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"), 1030 SnippetSuffix("(${1:int A})")))); 1031 } 1032 1033 SignatureHelp signatures(llvm::StringRef Text, Position Point, 1034 std::vector<Symbol> IndexSymbols = {}) { 1035 std::unique_ptr<SymbolIndex> Index; 1036 if (!IndexSymbols.empty()) 1037 Index = memIndex(IndexSymbols); 1038 1039 MockFSProvider FS; 1040 MockCompilationDatabase CDB; 1041 IgnoreDiagnostics DiagConsumer; 1042 ClangdServer::Options Opts = ClangdServer::optsForTest(); 1043 Opts.StaticIndex = Index.get(); 1044 1045 ClangdServer Server(CDB, FS, DiagConsumer, Opts); 1046 auto File = testPath("foo.cpp"); 1047 runAddDocument(Server, File, Text); 1048 return llvm::cantFail(runSignatureHelp(Server, File, Point)); 1049 } 1050 1051 SignatureHelp signatures(llvm::StringRef Text, 1052 std::vector<Symbol> IndexSymbols = {}) { 1053 Annotations Test(Text); 1054 return signatures(Test.code(), Test.point(), std::move(IndexSymbols)); 1055 } 1056 1057 struct ExpectedParameter { 1058 std::string Text; 1059 std::pair<unsigned, unsigned> Offsets; 1060 }; 1061 MATCHER_P(ParamsAre, P, "") { 1062 if (P.size() != arg.parameters.size()) 1063 return false; 1064 for (unsigned I = 0; I < P.size(); ++I) { 1065 if (P[I].Text != arg.parameters[I].labelString || 1066 P[I].Offsets != arg.parameters[I].labelOffsets) 1067 return false; 1068 } 1069 return true; 1070 } 1071 MATCHER_P(SigDoc, Doc, "") { return arg.documentation == Doc; } 1072 1073 /// \p AnnotatedLabel is a signature label with ranges marking parameters, e.g. 1074 /// foo([[int p1]], [[double p2]]) -> void 1075 Matcher<SignatureInformation> Sig(llvm::StringRef AnnotatedLabel) { 1076 llvm::Annotations A(AnnotatedLabel); 1077 std::string Label = A.code(); 1078 std::vector<ExpectedParameter> Parameters; 1079 for (auto Range : A.ranges()) { 1080 Parameters.emplace_back(); 1081 1082 ExpectedParameter &P = Parameters.back(); 1083 P.Text = Label.substr(Range.Begin, Range.End - Range.Begin); 1084 P.Offsets.first = lspLength(llvm::StringRef(Label).substr(0, Range.Begin)); 1085 P.Offsets.second = lspLength(llvm::StringRef(Label).substr(1, Range.End)); 1086 } 1087 return AllOf(SigHelpLabeled(Label), ParamsAre(Parameters)); 1088 } 1089 1090 TEST(SignatureHelpTest, Overloads) { 1091 auto Results = signatures(R"cpp( 1092 void foo(int x, int y); 1093 void foo(int x, float y); 1094 void foo(float x, int y); 1095 void foo(float x, float y); 1096 void bar(int x, int y = 0); 1097 int main() { foo(^); } 1098 )cpp"); 1099 EXPECT_THAT(Results.signatures, 1100 UnorderedElementsAre(Sig("foo([[float x]], [[float y]]) -> void"), 1101 Sig("foo([[float x]], [[int y]]) -> void"), 1102 Sig("foo([[int x]], [[float y]]) -> void"), 1103 Sig("foo([[int x]], [[int y]]) -> void"))); 1104 // We always prefer the first signature. 1105 EXPECT_EQ(0, Results.activeSignature); 1106 EXPECT_EQ(0, Results.activeParameter); 1107 } 1108 1109 TEST(SignatureHelpTest, DefaultArgs) { 1110 auto Results = signatures(R"cpp( 1111 void bar(int x, int y = 0); 1112 void bar(float x = 0, int y = 42); 1113 int main() { bar(^ 1114 )cpp"); 1115 EXPECT_THAT(Results.signatures, 1116 UnorderedElementsAre( 1117 Sig("bar([[int x]], [[int y = 0]]) -> void"), 1118 Sig("bar([[float x = 0]], [[int y = 42]]) -> void"))); 1119 EXPECT_EQ(0, Results.activeSignature); 1120 EXPECT_EQ(0, Results.activeParameter); 1121 } 1122 1123 TEST(SignatureHelpTest, ActiveArg) { 1124 auto Results = signatures(R"cpp( 1125 int baz(int a, int b, int c); 1126 int main() { baz(baz(1,2,3), ^); } 1127 )cpp"); 1128 EXPECT_THAT(Results.signatures, 1129 ElementsAre(Sig("baz([[int a]], [[int b]], [[int c]]) -> int"))); 1130 EXPECT_EQ(0, Results.activeSignature); 1131 EXPECT_EQ(1, Results.activeParameter); 1132 } 1133 1134 TEST(SignatureHelpTest, OpeningParen) { 1135 llvm::StringLiteral Tests[] = {// Recursive function call. 1136 R"cpp( 1137 int foo(int a, int b, int c); 1138 int main() { 1139 foo(foo $p^( foo(10, 10, 10), ^ ))); 1140 })cpp", 1141 // Functional type cast. 1142 R"cpp( 1143 struct Foo { 1144 Foo(int a, int b, int c); 1145 }; 1146 int main() { 1147 Foo $p^( 10, ^ ); 1148 })cpp", 1149 // New expression. 1150 R"cpp( 1151 struct Foo { 1152 Foo(int a, int b, int c); 1153 }; 1154 int main() { 1155 new Foo $p^( 10, ^ ); 1156 })cpp", 1157 // Macro expansion. 1158 R"cpp( 1159 int foo(int a, int b, int c); 1160 #define FOO foo( 1161 1162 int main() { 1163 // Macro expansions. 1164 $p^FOO 10, ^ ); 1165 })cpp", 1166 // Macro arguments. 1167 R"cpp( 1168 int foo(int a, int b, int c); 1169 int main() { 1170 #define ID(X) X 1171 ID(foo $p^( foo(10), ^ )) 1172 })cpp"}; 1173 1174 for (auto Test : Tests) { 1175 Annotations Code(Test); 1176 EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart, 1177 Code.point("p")) 1178 << "Test source:" << Test; 1179 } 1180 } 1181 1182 class IndexRequestCollector : public SymbolIndex { 1183 public: 1184 bool 1185 fuzzyFind(const FuzzyFindRequest &Req, 1186 llvm::function_ref<void(const Symbol &)> Callback) const override { 1187 std::unique_lock<std::mutex> Lock(Mut); 1188 Requests.push_back(Req); 1189 ReceivedRequestCV.notify_one(); 1190 return true; 1191 } 1192 1193 void lookup(const LookupRequest &, 1194 llvm::function_ref<void(const Symbol &)>) const override {} 1195 1196 bool refs(const RefsRequest &, 1197 llvm::function_ref<void(const Ref &)>) const override { 1198 return false; 1199 } 1200 1201 void relations(const RelationsRequest &, 1202 llvm::function_ref<void(const SymbolID &, const Symbol &)>) 1203 const override {} 1204 1205 // This is incorrect, but IndexRequestCollector is not an actual index and it 1206 // isn't used in production code. 1207 size_t estimateMemoryUsage() const override { return 0; } 1208 1209 const std::vector<FuzzyFindRequest> consumeRequests(size_t Num) const { 1210 std::unique_lock<std::mutex> Lock(Mut); 1211 EXPECT_TRUE(wait(Lock, ReceivedRequestCV, timeoutSeconds(30), 1212 [this, Num] { return Requests.size() == Num; })); 1213 auto Reqs = std::move(Requests); 1214 Requests = {}; 1215 return Reqs; 1216 } 1217 1218 private: 1219 // We need a mutex to handle async fuzzy find requests. 1220 mutable std::condition_variable ReceivedRequestCV; 1221 mutable std::mutex Mut; 1222 mutable std::vector<FuzzyFindRequest> Requests; 1223 }; 1224 1225 // Clients have to consume exactly Num requests. 1226 std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code, 1227 size_t Num = 1) { 1228 clangd::CodeCompleteOptions Opts; 1229 IndexRequestCollector Requests; 1230 Opts.Index = &Requests; 1231 completions(Code, {}, Opts); 1232 const auto Reqs = Requests.consumeRequests(Num); 1233 EXPECT_EQ(Reqs.size(), Num); 1234 return Reqs; 1235 } 1236 1237 TEST(CompletionTest, UnqualifiedIdQuery) { 1238 auto Requests = captureIndexRequests(R"cpp( 1239 namespace std {} 1240 using namespace std; 1241 namespace ns { 1242 void f() { 1243 vec^ 1244 } 1245 } 1246 )cpp"); 1247 1248 EXPECT_THAT(Requests, 1249 ElementsAre(Field(&FuzzyFindRequest::Scopes, 1250 UnorderedElementsAre("", "ns::", "std::")))); 1251 } 1252 1253 TEST(CompletionTest, EnclosingScopeComesFirst) { 1254 auto Requests = captureIndexRequests(R"cpp( 1255 namespace std {} 1256 using namespace std; 1257 namespace nx { 1258 namespace ns { 1259 namespace { 1260 void f() { 1261 vec^ 1262 } 1263 } 1264 } 1265 } 1266 )cpp"); 1267 1268 EXPECT_THAT(Requests, 1269 ElementsAre(Field( 1270 &FuzzyFindRequest::Scopes, 1271 UnorderedElementsAre("", "std::", "nx::ns::", "nx::")))); 1272 EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::"); 1273 } 1274 1275 TEST(CompletionTest, ResolvedQualifiedIdQuery) { 1276 auto Requests = captureIndexRequests(R"cpp( 1277 namespace ns1 {} 1278 namespace ns2 {} // ignore 1279 namespace ns3 { namespace nns3 {} } 1280 namespace foo { 1281 using namespace ns1; 1282 using namespace ns3::nns3; 1283 } 1284 namespace ns { 1285 void f() { 1286 foo::^ 1287 } 1288 } 1289 )cpp"); 1290 1291 EXPECT_THAT(Requests, 1292 ElementsAre(Field( 1293 &FuzzyFindRequest::Scopes, 1294 UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::")))); 1295 } 1296 1297 TEST(CompletionTest, UnresolvedQualifierIdQuery) { 1298 auto Requests = captureIndexRequests(R"cpp( 1299 namespace a {} 1300 using namespace a; 1301 namespace ns { 1302 void f() { 1303 bar::^ 1304 } 1305 } // namespace ns 1306 )cpp"); 1307 1308 EXPECT_THAT(Requests, 1309 ElementsAre(Field( 1310 &FuzzyFindRequest::Scopes, 1311 UnorderedElementsAre("a::bar::", "ns::bar::", "bar::")))); 1312 } 1313 1314 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) { 1315 auto Requests = captureIndexRequests(R"cpp( 1316 namespace a {} 1317 using namespace a; 1318 namespace ns { 1319 void f() { 1320 ::a::bar::^ 1321 } 1322 } // namespace ns 1323 )cpp"); 1324 1325 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes, 1326 UnorderedElementsAre("a::bar::")))); 1327 } 1328 1329 TEST(CompletionTest, EmptyQualifiedQuery) { 1330 auto Requests = captureIndexRequests(R"cpp( 1331 namespace ns { 1332 void f() { 1333 ^ 1334 } 1335 } // namespace ns 1336 )cpp"); 1337 1338 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes, 1339 UnorderedElementsAre("", "ns::")))); 1340 } 1341 1342 TEST(CompletionTest, GlobalQualifiedQuery) { 1343 auto Requests = captureIndexRequests(R"cpp( 1344 namespace ns { 1345 void f() { 1346 ::^ 1347 } 1348 } // namespace ns 1349 )cpp"); 1350 1351 EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes, 1352 UnorderedElementsAre("")))); 1353 } 1354 1355 TEST(CompletionTest, NoDuplicatedQueryScopes) { 1356 auto Requests = captureIndexRequests(R"cpp( 1357 namespace {} 1358 1359 namespace na { 1360 namespace {} 1361 namespace nb { 1362 ^ 1363 } // namespace nb 1364 } // namespace na 1365 )cpp"); 1366 1367 EXPECT_THAT(Requests, 1368 ElementsAre(Field(&FuzzyFindRequest::Scopes, 1369 UnorderedElementsAre("na::", "na::nb::", "")))); 1370 } 1371 1372 TEST(CompletionTest, NoIndexCompletionsInsideClasses) { 1373 auto Completions = completions( 1374 R"cpp( 1375 struct Foo { 1376 int SomeNameOfField; 1377 typedef int SomeNameOfTypedefField; 1378 }; 1379 1380 Foo::^)cpp", 1381 {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")}); 1382 1383 EXPECT_THAT(Completions.Completions, 1384 AllOf(Contains(Labeled("SomeNameOfField")), 1385 Contains(Labeled("SomeNameOfTypedefField")), 1386 Not(Contains(Labeled("SomeNameInTheIndex"))))); 1387 } 1388 1389 TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) { 1390 { 1391 auto Completions = completions( 1392 R"cpp( 1393 template <class T> 1394 void foo() { 1395 T::^ 1396 } 1397 )cpp", 1398 {func("::SomeNameInTheIndex")}); 1399 1400 EXPECT_THAT(Completions.Completions, 1401 Not(Contains(Labeled("SomeNameInTheIndex")))); 1402 } 1403 1404 { 1405 auto Completions = completions( 1406 R"cpp( 1407 template <class T> 1408 void foo() { 1409 T::template Y<int>::^ 1410 } 1411 )cpp", 1412 {func("::SomeNameInTheIndex")}); 1413 1414 EXPECT_THAT(Completions.Completions, 1415 Not(Contains(Labeled("SomeNameInTheIndex")))); 1416 } 1417 1418 { 1419 auto Completions = completions( 1420 R"cpp( 1421 template <class T> 1422 void foo() { 1423 T::foo::^ 1424 } 1425 )cpp", 1426 {func("::SomeNameInTheIndex")}); 1427 1428 EXPECT_THAT(Completions.Completions, 1429 Not(Contains(Labeled("SomeNameInTheIndex")))); 1430 } 1431 } 1432 1433 TEST(CompletionTest, OverloadBundling) { 1434 clangd::CodeCompleteOptions Opts; 1435 Opts.BundleOverloads = true; 1436 1437 std::string Context = R"cpp( 1438 struct X { 1439 // Overload with int 1440 int a(int); 1441 // Overload with bool 1442 int a(bool); 1443 int b(float); 1444 }; 1445 int GFuncC(int); 1446 int GFuncD(int); 1447 )cpp"; 1448 1449 // Member completions are bundled. 1450 EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions, 1451 UnorderedElementsAre(Labeled("a(…)"), Labeled("b(float)"))); 1452 1453 // Non-member completions are bundled, including index+sema. 1454 Symbol NoArgsGFunc = func("GFuncC"); 1455 EXPECT_THAT( 1456 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions, 1457 UnorderedElementsAre(Labeled("GFuncC(…)"), Labeled("GFuncD(int)"))); 1458 1459 // Differences in header-to-insert suppress bundling. 1460 std::string DeclFile = URI::create(testPath("foo")).toString(); 1461 NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str(); 1462 NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1); 1463 EXPECT_THAT( 1464 completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions, 1465 UnorderedElementsAre(AllOf(Named("GFuncC"), InsertInclude("<foo>")), 1466 Labeled("GFuncC(int)"), Labeled("GFuncD(int)"))); 1467 1468 // Examine a bundled completion in detail. 1469 auto A = 1470 completions(Context + "int y = X().a^", {}, Opts).Completions.front(); 1471 EXPECT_EQ(A.Name, "a"); 1472 EXPECT_EQ(A.Signature, "(…)"); 1473 EXPECT_EQ(A.BundleSize, 2u); 1474 EXPECT_EQ(A.Kind, CompletionItemKind::Method); 1475 EXPECT_EQ(A.ReturnType, "int"); // All overloads return int. 1476 // For now we just return one of the doc strings arbitrarily. 1477 EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"), 1478 HasSubstr("Overload with bool"))); 1479 EXPECT_EQ(A.SnippetSuffix, "($0)"); 1480 } 1481 1482 TEST(CompletionTest, DocumentationFromChangedFileCrash) { 1483 MockFSProvider FS; 1484 auto FooH = testPath("foo.h"); 1485 auto FooCpp = testPath("foo.cpp"); 1486 FS.Files[FooH] = R"cpp( 1487 // this is my documentation comment. 1488 int func(); 1489 )cpp"; 1490 FS.Files[FooCpp] = ""; 1491 1492 MockCompilationDatabase CDB; 1493 IgnoreDiagnostics DiagConsumer; 1494 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 1495 1496 Annotations Source(R"cpp( 1497 #include "foo.h" 1498 int func() { 1499 // This makes sure we have func from header in the AST. 1500 } 1501 int a = fun^ 1502 )cpp"); 1503 Server.addDocument(FooCpp, Source.code(), WantDiagnostics::Yes); 1504 // We need to wait for preamble to build. 1505 ASSERT_TRUE(Server.blockUntilIdleForTest()); 1506 1507 // Change the header file. Completion will reuse the old preamble! 1508 FS.Files[FooH] = R"cpp( 1509 int func(); 1510 )cpp"; 1511 1512 clangd::CodeCompleteOptions Opts; 1513 Opts.IncludeComments = true; 1514 CodeCompleteResult Completions = 1515 cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts)); 1516 // We shouldn't crash. Unfortunately, current workaround is to not produce 1517 // comments for symbols from headers. 1518 EXPECT_THAT(Completions.Completions, 1519 Contains(AllOf(Not(IsDocumented()), Named("func")))); 1520 } 1521 1522 TEST(CompletionTest, NonDocComments) { 1523 MockFSProvider FS; 1524 auto FooCpp = testPath("foo.cpp"); 1525 FS.Files[FooCpp] = ""; 1526 1527 MockCompilationDatabase CDB; 1528 IgnoreDiagnostics DiagConsumer; 1529 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 1530 1531 Annotations Source(R"cpp( 1532 // We ignore namespace comments, for rationale see CodeCompletionStrings.h. 1533 namespace comments_ns { 1534 } 1535 1536 // ------------------ 1537 int comments_foo(); 1538 1539 // A comment and a decl are separated by newlines. 1540 // Therefore, the comment shouldn't show up as doc comment. 1541 1542 int comments_bar(); 1543 1544 // this comment should be in the results. 1545 int comments_baz(); 1546 1547 1548 template <class T> 1549 struct Struct { 1550 int comments_qux(); 1551 int comments_quux(); 1552 }; 1553 1554 1555 // This comment should not be there. 1556 1557 template <class T> 1558 int Struct<T>::comments_qux() { 1559 } 1560 1561 // This comment **should** be in results. 1562 template <class T> 1563 int Struct<T>::comments_quux() { 1564 int a = comments^; 1565 } 1566 )cpp"); 1567 // FIXME: Auto-completion in a template requires disabling delayed template 1568 // parsing. 1569 CDB.ExtraClangFlags.push_back("-fno-delayed-template-parsing"); 1570 runAddDocument(Server, FooCpp, Source.code(), WantDiagnostics::Yes); 1571 CodeCompleteResult Completions = cantFail(runCodeComplete( 1572 Server, FooCpp, Source.point(), clangd::CodeCompleteOptions())); 1573 1574 // We should not get any of those comments in completion. 1575 EXPECT_THAT( 1576 Completions.Completions, 1577 UnorderedElementsAre(AllOf(Not(IsDocumented()), Named("comments_foo")), 1578 AllOf(IsDocumented(), Named("comments_baz")), 1579 AllOf(IsDocumented(), Named("comments_quux")), 1580 AllOf(Not(IsDocumented()), Named("comments_ns")), 1581 // FIXME(ibiryukov): the following items should have 1582 // empty documentation, since they are separated from 1583 // a comment with an empty line. Unfortunately, I 1584 // couldn't make Sema tests pass if we ignore those. 1585 AllOf(IsDocumented(), Named("comments_bar")), 1586 AllOf(IsDocumented(), Named("comments_qux")))); 1587 } 1588 1589 TEST(CompletionTest, CompleteOnInvalidLine) { 1590 auto FooCpp = testPath("foo.cpp"); 1591 1592 MockCompilationDatabase CDB; 1593 IgnoreDiagnostics DiagConsumer; 1594 MockFSProvider FS; 1595 FS.Files[FooCpp] = "// empty file"; 1596 1597 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 1598 // Run completion outside the file range. 1599 Position Pos; 1600 Pos.line = 100; 1601 Pos.character = 0; 1602 EXPECT_THAT_EXPECTED( 1603 runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()), 1604 Failed()); 1605 } 1606 1607 TEST(CompletionTest, QualifiedNames) { 1608 auto Results = completions( 1609 R"cpp( 1610 namespace ns { int local; void both(); } 1611 void f() { ::ns::^ } 1612 )cpp", 1613 {func("ns::both"), cls("ns::Index")}); 1614 // We get results from both index and sema, with no duplicates. 1615 EXPECT_THAT( 1616 Results.Completions, 1617 UnorderedElementsAre(Scope("ns::"), Scope("ns::"), Scope("ns::"))); 1618 } 1619 1620 TEST(CompletionTest, Render) { 1621 CodeCompletion C; 1622 C.Name = "x"; 1623 C.Signature = "(bool) const"; 1624 C.SnippetSuffix = "(${0:bool})"; 1625 C.ReturnType = "int"; 1626 C.RequiredQualifier = "Foo::"; 1627 C.Scope = "ns::Foo::"; 1628 C.Documentation = "This is x()."; 1629 C.Includes.emplace_back(); 1630 auto &Include = C.Includes.back(); 1631 Include.Header = "\"foo.h\""; 1632 C.Kind = CompletionItemKind::Method; 1633 C.Score.Total = 1.0; 1634 C.Origin = SymbolOrigin::AST | SymbolOrigin::Static; 1635 1636 CodeCompleteOptions Opts; 1637 Opts.IncludeIndicator.Insert = "^"; 1638 Opts.IncludeIndicator.NoInsert = ""; 1639 Opts.EnableSnippets = false; 1640 1641 auto R = C.render(Opts); 1642 EXPECT_EQ(R.label, "Foo::x(bool) const"); 1643 EXPECT_EQ(R.insertText, "Foo::x"); 1644 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText); 1645 EXPECT_EQ(R.filterText, "x"); 1646 EXPECT_EQ(R.detail, "int\n\"foo.h\""); 1647 EXPECT_EQ(R.documentation, "This is x()."); 1648 EXPECT_THAT(R.additionalTextEdits, IsEmpty()); 1649 EXPECT_EQ(R.sortText, sortText(1.0, "x")); 1650 EXPECT_FALSE(R.deprecated); 1651 1652 Opts.EnableSnippets = true; 1653 R = C.render(Opts); 1654 EXPECT_EQ(R.insertText, "Foo::x(${0:bool})"); 1655 EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet); 1656 1657 Include.Insertion.emplace(); 1658 R = C.render(Opts); 1659 EXPECT_EQ(R.label, "^Foo::x(bool) const"); 1660 EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty())); 1661 1662 Opts.ShowOrigins = true; 1663 R = C.render(Opts); 1664 EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const"); 1665 1666 C.BundleSize = 2; 1667 R = C.render(Opts); 1668 EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\""); 1669 1670 C.Deprecated = true; 1671 R = C.render(Opts); 1672 EXPECT_TRUE(R.deprecated); 1673 } 1674 1675 TEST(CompletionTest, IgnoreRecoveryResults) { 1676 auto Results = completions( 1677 R"cpp( 1678 namespace ns { int NotRecovered() { return 0; } } 1679 void f() { 1680 // Sema enters recovery mode first and then normal mode. 1681 if (auto x = ns::NotRecover^) 1682 } 1683 )cpp"); 1684 EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("NotRecovered"))); 1685 } 1686 1687 TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) { 1688 auto Results = completions( 1689 R"cpp( 1690 namespace ns { 1691 class X { public: X(); int x_; }; 1692 X::X() : x_^(0) {} 1693 } 1694 )cpp"); 1695 EXPECT_THAT(Results.Completions, 1696 UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_")))); 1697 } 1698 1699 TEST(CompletionTest, CodeCompletionContext) { 1700 auto Results = completions( 1701 R"cpp( 1702 namespace ns { 1703 class X { public: X(); int x_; }; 1704 void f() { 1705 X x; 1706 x.^; 1707 } 1708 } 1709 )cpp"); 1710 1711 EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess); 1712 } 1713 1714 TEST(CompletionTest, FixItForArrowToDot) { 1715 MockFSProvider FS; 1716 MockCompilationDatabase CDB; 1717 IgnoreDiagnostics DiagConsumer; 1718 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 1719 1720 CodeCompleteOptions Opts; 1721 Opts.IncludeFixIts = true; 1722 Annotations TestCode( 1723 R"cpp( 1724 class Auxilary { 1725 public: 1726 void AuxFunction(); 1727 }; 1728 class ClassWithPtr { 1729 public: 1730 void MemberFunction(); 1731 Auxilary* operator->() const; 1732 Auxilary* Aux; 1733 }; 1734 void f() { 1735 ClassWithPtr x; 1736 x[[->]]^; 1737 } 1738 )cpp"); 1739 auto Results = 1740 completions(Server, TestCode.code(), TestCode.point(), {}, Opts); 1741 EXPECT_EQ(Results.Completions.size(), 3u); 1742 1743 TextEdit ReplacementEdit; 1744 ReplacementEdit.range = TestCode.range(); 1745 ReplacementEdit.newText = "."; 1746 for (const auto &C : Results.Completions) { 1747 EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction"); 1748 if (!C.FixIts.empty()) { 1749 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit)); 1750 } 1751 } 1752 } 1753 1754 TEST(CompletionTest, FixItForDotToArrow) { 1755 MockFSProvider FS; 1756 MockCompilationDatabase CDB; 1757 IgnoreDiagnostics DiagConsumer; 1758 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 1759 1760 CodeCompleteOptions Opts; 1761 Opts.IncludeFixIts = true; 1762 Annotations TestCode( 1763 R"cpp( 1764 class Auxilary { 1765 public: 1766 void AuxFunction(); 1767 }; 1768 class ClassWithPtr { 1769 public: 1770 void MemberFunction(); 1771 Auxilary* operator->() const; 1772 Auxilary* Aux; 1773 }; 1774 void f() { 1775 ClassWithPtr x; 1776 x[[.]]^; 1777 } 1778 )cpp"); 1779 auto Results = 1780 completions(Server, TestCode.code(), TestCode.point(), {}, Opts); 1781 EXPECT_EQ(Results.Completions.size(), 3u); 1782 1783 TextEdit ReplacementEdit; 1784 ReplacementEdit.range = TestCode.range(); 1785 ReplacementEdit.newText = "->"; 1786 for (const auto &C : Results.Completions) { 1787 EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction"); 1788 if (!C.FixIts.empty()) { 1789 EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit)); 1790 } 1791 } 1792 } 1793 1794 TEST(CompletionTest, RenderWithFixItMerged) { 1795 TextEdit FixIt; 1796 FixIt.range.end.character = 5; 1797 FixIt.newText = "->"; 1798 1799 CodeCompletion C; 1800 C.Name = "x"; 1801 C.RequiredQualifier = "Foo::"; 1802 C.FixIts = {FixIt}; 1803 C.CompletionTokenRange.start.character = 5; 1804 1805 CodeCompleteOptions Opts; 1806 Opts.IncludeFixIts = true; 1807 1808 auto R = C.render(Opts); 1809 EXPECT_TRUE(R.textEdit); 1810 EXPECT_EQ(R.textEdit->newText, "->Foo::x"); 1811 EXPECT_TRUE(R.additionalTextEdits.empty()); 1812 } 1813 1814 TEST(CompletionTest, RenderWithFixItNonMerged) { 1815 TextEdit FixIt; 1816 FixIt.range.end.character = 4; 1817 FixIt.newText = "->"; 1818 1819 CodeCompletion C; 1820 C.Name = "x"; 1821 C.RequiredQualifier = "Foo::"; 1822 C.FixIts = {FixIt}; 1823 C.CompletionTokenRange.start.character = 5; 1824 1825 CodeCompleteOptions Opts; 1826 Opts.IncludeFixIts = true; 1827 1828 auto R = C.render(Opts); 1829 EXPECT_TRUE(R.textEdit); 1830 EXPECT_EQ(R.textEdit->newText, "Foo::x"); 1831 EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt)); 1832 } 1833 1834 TEST(CompletionTest, CompletionTokenRange) { 1835 MockFSProvider FS; 1836 MockCompilationDatabase CDB; 1837 IgnoreDiagnostics DiagConsumer; 1838 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 1839 1840 constexpr const char *TestCodes[] = { 1841 R"cpp( 1842 class Auxilary { 1843 public: 1844 void AuxFunction(); 1845 }; 1846 void f() { 1847 Auxilary x; 1848 x.[[Aux]]^; 1849 } 1850 )cpp", 1851 R"cpp( 1852 class Auxilary { 1853 public: 1854 void AuxFunction(); 1855 }; 1856 void f() { 1857 Auxilary x; 1858 x.[[]]^; 1859 } 1860 )cpp"}; 1861 for (const auto &Text : TestCodes) { 1862 Annotations TestCode(Text); 1863 auto Results = completions(Server, TestCode.code(), TestCode.point()); 1864 1865 EXPECT_EQ(Results.Completions.size(), 1u); 1866 EXPECT_THAT(Results.Completions.front().CompletionTokenRange, 1867 TestCode.range()); 1868 } 1869 } 1870 1871 TEST(SignatureHelpTest, OverloadsOrdering) { 1872 const auto Results = signatures(R"cpp( 1873 void foo(int x); 1874 void foo(int x, float y); 1875 void foo(float x, int y); 1876 void foo(float x, float y); 1877 void foo(int x, int y = 0); 1878 int main() { foo(^); } 1879 )cpp"); 1880 EXPECT_THAT(Results.signatures, 1881 ElementsAre(Sig("foo([[int x]]) -> void"), 1882 Sig("foo([[int x]], [[int y = 0]]) -> void"), 1883 Sig("foo([[float x]], [[int y]]) -> void"), 1884 Sig("foo([[int x]], [[float y]]) -> void"), 1885 Sig("foo([[float x]], [[float y]]) -> void"))); 1886 // We always prefer the first signature. 1887 EXPECT_EQ(0, Results.activeSignature); 1888 EXPECT_EQ(0, Results.activeParameter); 1889 } 1890 1891 TEST(SignatureHelpTest, InstantiatedSignatures) { 1892 StringRef Sig0 = R"cpp( 1893 template <class T> 1894 void foo(T, T, T); 1895 1896 int main() { 1897 foo<int>(^); 1898 } 1899 )cpp"; 1900 1901 EXPECT_THAT(signatures(Sig0).signatures, 1902 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void"))); 1903 1904 StringRef Sig1 = R"cpp( 1905 template <class T> 1906 void foo(T, T, T); 1907 1908 int main() { 1909 foo(10, ^); 1910 })cpp"; 1911 1912 EXPECT_THAT(signatures(Sig1).signatures, 1913 ElementsAre(Sig("foo([[T]], [[T]], [[T]]) -> void"))); 1914 1915 StringRef Sig2 = R"cpp( 1916 template <class ...T> 1917 void foo(T...); 1918 1919 int main() { 1920 foo<int>(^); 1921 } 1922 )cpp"; 1923 1924 EXPECT_THAT(signatures(Sig2).signatures, 1925 ElementsAre(Sig("foo([[T...]]) -> void"))); 1926 1927 // It is debatable whether we should substitute the outer template parameter 1928 // ('T') in that case. Currently we don't substitute it in signature help, but 1929 // do substitute in code complete. 1930 // FIXME: make code complete and signature help consistent, figure out which 1931 // way is better. 1932 StringRef Sig3 = R"cpp( 1933 template <class T> 1934 struct X { 1935 template <class U> 1936 void foo(T, U); 1937 }; 1938 1939 int main() { 1940 X<int>().foo<double>(^) 1941 } 1942 )cpp"; 1943 1944 EXPECT_THAT(signatures(Sig3).signatures, 1945 ElementsAre(Sig("foo([[T]], [[U]]) -> void"))); 1946 } 1947 1948 TEST(SignatureHelpTest, IndexDocumentation) { 1949 Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#"); 1950 Foo0.Documentation = "Doc from the index"; 1951 Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#"); 1952 Foo1.Documentation = "Doc from the index"; 1953 Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#"); 1954 1955 StringRef Sig0 = R"cpp( 1956 int foo(); 1957 int foo(double); 1958 1959 void test() { 1960 foo(^); 1961 } 1962 )cpp"; 1963 1964 EXPECT_THAT( 1965 signatures(Sig0, {Foo0}).signatures, 1966 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc("Doc from the index")), 1967 AllOf(Sig("foo([[double]]) -> int"), SigDoc("")))); 1968 1969 StringRef Sig1 = R"cpp( 1970 int foo(); 1971 // Overriden doc from sema 1972 int foo(int); 1973 // Doc from sema 1974 int foo(int, int); 1975 1976 void test() { 1977 foo(^); 1978 } 1979 )cpp"; 1980 1981 EXPECT_THAT( 1982 signatures(Sig1, {Foo0, Foo1, Foo2}).signatures, 1983 ElementsAre( 1984 AllOf(Sig("foo() -> int"), SigDoc("Doc from the index")), 1985 AllOf(Sig("foo([[int]]) -> int"), SigDoc("Overriden doc from sema")), 1986 AllOf(Sig("foo([[int]], [[int]]) -> int"), SigDoc("Doc from sema")))); 1987 } 1988 1989 TEST(SignatureHelpTest, DynamicIndexDocumentation) { 1990 MockFSProvider FS; 1991 MockCompilationDatabase CDB; 1992 IgnoreDiagnostics DiagConsumer; 1993 ClangdServer::Options Opts = ClangdServer::optsForTest(); 1994 Opts.BuildDynamicSymbolIndex = true; 1995 ClangdServer Server(CDB, FS, DiagConsumer, Opts); 1996 1997 FS.Files[testPath("foo.h")] = R"cpp( 1998 struct Foo { 1999 // Member doc 2000 int foo(); 2001 }; 2002 )cpp"; 2003 Annotations FileContent(R"cpp( 2004 #include "foo.h" 2005 void test() { 2006 Foo f; 2007 f.foo(^); 2008 } 2009 )cpp"); 2010 auto File = testPath("test.cpp"); 2011 Server.addDocument(File, FileContent.code()); 2012 // Wait for the dynamic index being built. 2013 ASSERT_TRUE(Server.blockUntilIdleForTest()); 2014 EXPECT_THAT( 2015 llvm::cantFail(runSignatureHelp(Server, File, FileContent.point())) 2016 .signatures, 2017 ElementsAre(AllOf(Sig("foo() -> int"), SigDoc("Member doc")))); 2018 } 2019 2020 TEST(CompletionTest, CompletionFunctionArgsDisabled) { 2021 CodeCompleteOptions Opts; 2022 Opts.EnableSnippets = true; 2023 Opts.EnableFunctionArgSnippets = false; 2024 2025 { 2026 auto Results = completions( 2027 R"cpp( 2028 void xfoo(); 2029 void xfoo(int x, int y); 2030 void f() { xfo^ })cpp", 2031 {}, Opts); 2032 EXPECT_THAT( 2033 Results.Completions, 2034 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")), 2035 AllOf(Named("xfoo"), SnippetSuffix("($0)")))); 2036 } 2037 { 2038 auto Results = completions( 2039 R"cpp( 2040 void xbar(); 2041 void f() { xba^ })cpp", 2042 {}, Opts); 2043 EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf( 2044 Named("xbar"), SnippetSuffix("()")))); 2045 } 2046 { 2047 Opts.BundleOverloads = true; 2048 auto Results = completions( 2049 R"cpp( 2050 void xfoo(); 2051 void xfoo(int x, int y); 2052 void f() { xfo^ })cpp", 2053 {}, Opts); 2054 EXPECT_THAT( 2055 Results.Completions, 2056 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)")))); 2057 } 2058 { 2059 auto Results = completions( 2060 R"cpp( 2061 template <class T, class U> 2062 void xfoo(int a, U b); 2063 void f() { xfo^ })cpp", 2064 {}, Opts); 2065 EXPECT_THAT( 2066 Results.Completions, 2067 UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("<$1>($0)")))); 2068 } 2069 { 2070 auto Results = completions( 2071 R"cpp( 2072 template <class T> 2073 class foo_class{}; 2074 template <class T> 2075 using foo_alias = T**; 2076 void f() { foo_^ })cpp", 2077 {}, Opts); 2078 EXPECT_THAT( 2079 Results.Completions, 2080 UnorderedElementsAre(AllOf(Named("foo_class"), SnippetSuffix("<$0>")), 2081 AllOf(Named("foo_alias"), SnippetSuffix("<$0>")))); 2082 } 2083 } 2084 2085 TEST(CompletionTest, SuggestOverrides) { 2086 constexpr const char *const Text(R"cpp( 2087 class A { 2088 public: 2089 virtual void vfunc(bool param); 2090 virtual void vfunc(bool param, int p); 2091 void func(bool param); 2092 }; 2093 class B : public A { 2094 virtual void ttt(bool param) const; 2095 void vfunc(bool param, int p) override; 2096 }; 2097 class C : public B { 2098 public: 2099 void vfunc(bool param) override; 2100 ^ 2101 }; 2102 )cpp"); 2103 const auto Results = completions(Text); 2104 EXPECT_THAT( 2105 Results.Completions, 2106 AllOf(Contains(AllOf(Labeled("void vfunc(bool param, int p) override"), 2107 NameStartsWith("vfunc"))), 2108 Contains(AllOf(Labeled("void ttt(bool param) const override"), 2109 NameStartsWith("ttt"))), 2110 Not(Contains(Labeled("void vfunc(bool param) override"))))); 2111 } 2112 2113 TEST(CompletionTest, OverridesNonIdentName) { 2114 // Check the completions call does not crash. 2115 completions(R"cpp( 2116 struct Base { 2117 virtual ~Base() = 0; 2118 virtual operator int() = 0; 2119 virtual Base& operator+(Base&) = 0; 2120 }; 2121 2122 struct Derived : Base { 2123 ^ 2124 }; 2125 )cpp"); 2126 } 2127 2128 TEST(GuessCompletionPrefix, Filters) { 2129 for (llvm::StringRef Case : { 2130 "[[scope::]][[ident]]^", 2131 "[[]][[]]^", 2132 "\n[[]][[]]^", 2133 "[[]][[ab]]^", 2134 "x.[[]][[ab]]^", 2135 "x.[[]][[]]^", 2136 "[[x::]][[ab]]^", 2137 "[[x::]][[]]^", 2138 "[[::x::]][[ab]]^", 2139 "some text [[scope::more::]][[identif]]^ier", 2140 "some text [[scope::]][[mor]]^e::identifier", 2141 "weird case foo::[[::bar::]][[baz]]^", 2142 }) { 2143 Annotations F(Case); 2144 auto Offset = cantFail(positionToOffset(F.code(), F.point())); 2145 auto ToStringRef = [&](Range R) { 2146 return F.code().slice(cantFail(positionToOffset(F.code(), R.start)), 2147 cantFail(positionToOffset(F.code(), R.end))); 2148 }; 2149 auto WantQualifier = ToStringRef(F.ranges()[0]), 2150 WantName = ToStringRef(F.ranges()[1]); 2151 2152 auto Prefix = guessCompletionPrefix(F.code(), Offset); 2153 // Even when components are empty, check their offsets are correct. 2154 EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case; 2155 EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case; 2156 EXPECT_EQ(WantName, Prefix.Name) << Case; 2157 EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case; 2158 } 2159 } 2160 2161 TEST(CompletionTest, EnableSpeculativeIndexRequest) { 2162 MockFSProvider FS; 2163 MockCompilationDatabase CDB; 2164 IgnoreDiagnostics DiagConsumer; 2165 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 2166 2167 auto File = testPath("foo.cpp"); 2168 Annotations Test(R"cpp( 2169 namespace ns1 { int abc; } 2170 namespace ns2 { int abc; } 2171 void f() { ns1::ab$1^; ns1::ab$2^; } 2172 void f2() { ns2::ab$3^; } 2173 )cpp"); 2174 runAddDocument(Server, File, Test.code()); 2175 clangd::CodeCompleteOptions Opts = {}; 2176 2177 IndexRequestCollector Requests; 2178 Opts.Index = &Requests; 2179 Opts.SpeculativeIndexRequest = true; 2180 2181 auto CompleteAtPoint = [&](StringRef P) { 2182 cantFail(runCodeComplete(Server, File, Test.point(P), Opts)); 2183 }; 2184 2185 CompleteAtPoint("1"); 2186 auto Reqs1 = Requests.consumeRequests(1); 2187 ASSERT_EQ(Reqs1.size(), 1u); 2188 EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::")); 2189 2190 CompleteAtPoint("2"); 2191 auto Reqs2 = Requests.consumeRequests(1); 2192 // Speculation succeeded. Used speculative index result. 2193 ASSERT_EQ(Reqs2.size(), 1u); 2194 EXPECT_EQ(Reqs2[0], Reqs1[0]); 2195 2196 CompleteAtPoint("3"); 2197 // Speculation failed. Sent speculative index request and the new index 2198 // request after sema. 2199 auto Reqs3 = Requests.consumeRequests(2); 2200 ASSERT_EQ(Reqs3.size(), 2u); 2201 } 2202 2203 TEST(CompletionTest, InsertTheMostPopularHeader) { 2204 std::string DeclFile = URI::create(testPath("foo")).toString(); 2205 Symbol Sym = func("Func"); 2206 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str(); 2207 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2); 2208 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000); 2209 2210 auto Results = completions("Fun^", {Sym}).Completions; 2211 assert(!Results.empty()); 2212 EXPECT_THAT(Results[0], AllOf(Named("Func"), InsertInclude("\"bar.h\""))); 2213 EXPECT_EQ(Results[0].Includes.size(), 2u); 2214 } 2215 2216 TEST(CompletionTest, NoInsertIncludeIfOnePresent) { 2217 MockFSProvider FS; 2218 MockCompilationDatabase CDB; 2219 2220 std::string FooHeader = testPath("foo.h"); 2221 FS.Files[FooHeader] = ""; 2222 2223 IgnoreDiagnostics DiagConsumer; 2224 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 2225 2226 std::string DeclFile = URI::create(testPath("foo")).toString(); 2227 Symbol Sym = func("Func"); 2228 Sym.CanonicalDeclaration.FileURI = DeclFile.c_str(); 2229 Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2); 2230 Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000); 2231 2232 EXPECT_THAT( 2233 completions(Server, "#include \"foo.h\"\nFun^", {Sym}).Completions, 2234 UnorderedElementsAre( 2235 AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude())))); 2236 } 2237 2238 TEST(CompletionTest, MergeMacrosFromIndexAndSema) { 2239 Symbol Sym; 2240 Sym.Name = "Clangd_Macro_Test"; 2241 Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test"); 2242 Sym.SymInfo.Kind = index::SymbolKind::Macro; 2243 Sym.Flags |= Symbol::IndexedForCodeCompletion; 2244 EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym}) 2245 .Completions, 2246 UnorderedElementsAre(Named("Clangd_Macro_Test"))); 2247 } 2248 2249 TEST(CompletionTest, MacroFromPreamble) { 2250 MockFSProvider FS; 2251 MockCompilationDatabase CDB; 2252 std::string FooHeader = testPath("foo.h"); 2253 FS.Files[FooHeader] = "#define CLANGD_PREAMBLE_HEADER x\n"; 2254 IgnoreDiagnostics DiagConsumer; 2255 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 2256 auto Results = completions( 2257 R"cpp(#include "foo.h" 2258 #define CLANGD_PREAMBLE_MAIN x 2259 2260 int x = 0; 2261 #define CLANGD_MAIN x 2262 void f() { CLANGD_^ } 2263 )cpp", 2264 {func("CLANGD_INDEX")}); 2265 // We should get results from the main file, including the preamble section. 2266 // However no results from included files (the index should cover them). 2267 EXPECT_THAT(Results.Completions, 2268 UnorderedElementsAre(Named("CLANGD_PREAMBLE_MAIN"), 2269 Named("CLANGD_MAIN"), 2270 Named("CLANGD_INDEX"))); 2271 } 2272 2273 TEST(CompletionTest, DeprecatedResults) { 2274 std::string Body = R"cpp( 2275 void TestClangd(); 2276 void TestClangc() __attribute__((deprecated("", ""))); 2277 )cpp"; 2278 2279 EXPECT_THAT( 2280 completions(Body + "int main() { TestClang^ }").Completions, 2281 UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())), 2282 AllOf(Named("TestClangc"), Deprecated()))); 2283 } 2284 2285 TEST(SignatureHelpTest, InsideArgument) { 2286 { 2287 const auto Results = signatures(R"cpp( 2288 void foo(int x); 2289 void foo(int x, int y); 2290 int main() { foo(1+^); } 2291 )cpp"); 2292 EXPECT_THAT(Results.signatures, 2293 ElementsAre(Sig("foo([[int x]]) -> void"), 2294 Sig("foo([[int x]], [[int y]]) -> void"))); 2295 EXPECT_EQ(0, Results.activeParameter); 2296 } 2297 { 2298 const auto Results = signatures(R"cpp( 2299 void foo(int x); 2300 void foo(int x, int y); 2301 int main() { foo(1^); } 2302 )cpp"); 2303 EXPECT_THAT(Results.signatures, 2304 ElementsAre(Sig("foo([[int x]]) -> void"), 2305 Sig("foo([[int x]], [[int y]]) -> void"))); 2306 EXPECT_EQ(0, Results.activeParameter); 2307 } 2308 { 2309 const auto Results = signatures(R"cpp( 2310 void foo(int x); 2311 void foo(int x, int y); 2312 int main() { foo(1^0); } 2313 )cpp"); 2314 EXPECT_THAT(Results.signatures, 2315 ElementsAre(Sig("foo([[int x]]) -> void"), 2316 Sig("foo([[int x]], [[int y]]) -> void"))); 2317 EXPECT_EQ(0, Results.activeParameter); 2318 } 2319 { 2320 const auto Results = signatures(R"cpp( 2321 void foo(int x); 2322 void foo(int x, int y); 2323 int bar(int x, int y); 2324 int main() { bar(foo(2, 3^)); } 2325 )cpp"); 2326 EXPECT_THAT(Results.signatures, 2327 ElementsAre(Sig("foo([[int x]], [[int y]]) -> void"))); 2328 EXPECT_EQ(1, Results.activeParameter); 2329 } 2330 } 2331 2332 TEST(SignatureHelpTest, ConstructorInitializeFields) { 2333 { 2334 const auto Results = signatures(R"cpp( 2335 struct A { 2336 A(int); 2337 }; 2338 struct B { 2339 B() : a_elem(^) {} 2340 A a_elem; 2341 }; 2342 )cpp"); 2343 EXPECT_THAT(Results.signatures, 2344 UnorderedElementsAre(Sig("A([[int]])"), Sig("A([[A &&]])"), 2345 Sig("A([[const A &]])"))); 2346 } 2347 { 2348 const auto Results = signatures(R"cpp( 2349 struct A { 2350 A(int); 2351 }; 2352 struct C { 2353 C(int); 2354 C(A); 2355 }; 2356 struct B { 2357 B() : c_elem(A(1^)) {} 2358 C c_elem; 2359 }; 2360 )cpp"); 2361 EXPECT_THAT(Results.signatures, 2362 UnorderedElementsAre(Sig("A([[int]])"), Sig("A([[A &&]])"), 2363 Sig("A([[const A &]])"))); 2364 } 2365 } 2366 2367 TEST(CompletionTest, IncludedCompletionKinds) { 2368 MockFSProvider FS; 2369 MockCompilationDatabase CDB; 2370 std::string Subdir = testPath("sub"); 2371 std::string SearchDirArg = (Twine("-I") + Subdir).str(); 2372 CDB.ExtraClangFlags = {SearchDirArg.c_str()}; 2373 std::string BarHeader = testPath("sub/bar.h"); 2374 FS.Files[BarHeader] = ""; 2375 IgnoreDiagnostics DiagConsumer; 2376 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); 2377 auto Results = completions(Server, 2378 R"cpp( 2379 #include "^" 2380 )cpp"); 2381 EXPECT_THAT(Results.Completions, 2382 AllOf(Has("sub/", CompletionItemKind::Folder), 2383 Has("bar.h\"", CompletionItemKind::File))); 2384 } 2385 2386 TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) { 2387 auto Results = completions( 2388 R"cpp( 2389 #include "./^" 2390 )cpp"); 2391 EXPECT_TRUE(Results.Completions.empty()); 2392 } 2393 2394 TEST(CompletionTest, NoAllScopesCompletionWhenQualified) { 2395 clangd::CodeCompleteOptions Opts = {}; 2396 Opts.AllScopes = true; 2397 2398 auto Results = completions( 2399 R"cpp( 2400 void f() { na::Clangd^ } 2401 )cpp", 2402 {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts); 2403 EXPECT_THAT(Results.Completions, 2404 UnorderedElementsAre( 2405 AllOf(Qualifier(""), Scope("na::"), Named("ClangdA")))); 2406 } 2407 2408 TEST(CompletionTest, AllScopesCompletion) { 2409 clangd::CodeCompleteOptions Opts = {}; 2410 Opts.AllScopes = true; 2411 2412 auto Results = completions( 2413 R"cpp( 2414 namespace na { 2415 void f() { Clangd^ } 2416 } 2417 )cpp", 2418 {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"), 2419 cls("na::nb::Clangd4")}, 2420 Opts); 2421 EXPECT_THAT( 2422 Results.Completions, 2423 UnorderedElementsAre(AllOf(Qualifier("nx::"), Named("Clangd1")), 2424 AllOf(Qualifier("ny::"), Named("Clangd2")), 2425 AllOf(Qualifier(""), Scope(""), Named("Clangd3")), 2426 AllOf(Qualifier("nb::"), Named("Clangd4")))); 2427 } 2428 2429 TEST(CompletionTest, NoQualifierIfShadowed) { 2430 clangd::CodeCompleteOptions Opts = {}; 2431 Opts.AllScopes = true; 2432 2433 auto Results = completions(R"cpp( 2434 namespace nx { class Clangd1 {}; } 2435 using nx::Clangd1; 2436 void f() { Clangd^ } 2437 )cpp", 2438 {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts); 2439 // Although Clangd1 is from another namespace, Sema tells us it's in-scope and 2440 // needs no qualifier. 2441 EXPECT_THAT(Results.Completions, 2442 UnorderedElementsAre(AllOf(Qualifier(""), Named("Clangd1")), 2443 AllOf(Qualifier("nx::"), Named("Clangd2")))); 2444 } 2445 2446 TEST(CompletionTest, NoCompletionsForNewNames) { 2447 clangd::CodeCompleteOptions Opts; 2448 Opts.AllScopes = true; 2449 auto Results = completions(R"cpp( 2450 void f() { int n^ } 2451 )cpp", 2452 {cls("naber"), cls("nx::naber")}, Opts); 2453 EXPECT_THAT(Results.Completions, UnorderedElementsAre()); 2454 } 2455 2456 TEST(CompletionTest, ObjectiveCMethodNoArguments) { 2457 auto Results = completions(R"objc( 2458 @interface Foo 2459 @property(nonatomic, setter=setXToIgnoreComplete:) int value; 2460 @end 2461 Foo *foo = [Foo new]; int y = [foo v^] 2462 )objc", 2463 /*IndexSymbols=*/{}, 2464 /*Opts=*/{}, "Foo.m"); 2465 2466 auto C = Results.Completions; 2467 EXPECT_THAT(C, ElementsAre(Named("value"))); 2468 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method))); 2469 EXPECT_THAT(C, ElementsAre(ReturnType("int"))); 2470 EXPECT_THAT(C, ElementsAre(Signature(""))); 2471 EXPECT_THAT(C, ElementsAre(SnippetSuffix(""))); 2472 } 2473 2474 TEST(CompletionTest, ObjectiveCMethodOneArgument) { 2475 auto Results = completions(R"objc( 2476 @interface Foo 2477 - (int)valueForCharacter:(char)c; 2478 @end 2479 Foo *foo = [Foo new]; int y = [foo v^] 2480 )objc", 2481 /*IndexSymbols=*/{}, 2482 /*Opts=*/{}, "Foo.m"); 2483 2484 auto C = Results.Completions; 2485 EXPECT_THAT(C, ElementsAre(Named("valueForCharacter:"))); 2486 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method))); 2487 EXPECT_THAT(C, ElementsAre(ReturnType("int"))); 2488 EXPECT_THAT(C, ElementsAre(Signature("(char)"))); 2489 EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(char)}"))); 2490 } 2491 2492 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) { 2493 auto Results = completions(R"objc( 2494 @interface Foo 2495 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2496 @end 2497 id val = [Foo foo^] 2498 )objc", 2499 /*IndexSymbols=*/{}, 2500 /*Opts=*/{}, "Foo.m"); 2501 2502 auto C = Results.Completions; 2503 EXPECT_THAT(C, ElementsAre(Named("fooWithValue:"))); 2504 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method))); 2505 EXPECT_THAT(C, ElementsAre(ReturnType("id"))); 2506 EXPECT_THAT(C, ElementsAre(Signature("(int) fooey:(unsigned int)"))); 2507 EXPECT_THAT( 2508 C, ElementsAre(SnippetSuffix("${1:(int)} fooey:${2:(unsigned int)}"))); 2509 } 2510 2511 TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) { 2512 auto Results = completions(R"objc( 2513 @interface Foo 2514 + (id)fooWithValue:(int)value fooey:(unsigned int)fooey; 2515 @end 2516 id val = [Foo fooWithValue:10 f^] 2517 )objc", 2518 /*IndexSymbols=*/{}, 2519 /*Opts=*/{}, "Foo.m"); 2520 2521 auto C = Results.Completions; 2522 EXPECT_THAT(C, ElementsAre(Named("fooey:"))); 2523 EXPECT_THAT(C, ElementsAre(Kind(CompletionItemKind::Method))); 2524 EXPECT_THAT(C, ElementsAre(ReturnType("id"))); 2525 EXPECT_THAT(C, ElementsAre(Signature("(unsigned int)"))); 2526 EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(unsigned int)}"))); 2527 } 2528 2529 TEST(CompletionTest, CursorInSnippets) { 2530 clangd::CodeCompleteOptions Options; 2531 Options.EnableSnippets = true; 2532 auto Results = completions( 2533 R"cpp( 2534 void while_foo(int a, int b); 2535 void test() { 2536 whil^ 2537 })cpp", 2538 /*IndexSymbols=*/{}, Options); 2539 2540 // Last placeholder in code patterns should be $0 to put the cursor there. 2541 EXPECT_THAT(Results.Completions, 2542 Contains(AllOf( 2543 Named("while"), 2544 SnippetSuffix(" (${1:condition}) {\n${0:statements}\n}")))); 2545 // However, snippets for functions must *not* end with $0. 2546 EXPECT_THAT(Results.Completions, 2547 Contains(AllOf(Named("while_foo"), 2548 SnippetSuffix("(${1:int a}, ${2:int b})")))); 2549 } 2550 2551 TEST(CompletionTest, WorksWithNullType) { 2552 auto R = completions(R"cpp( 2553 int main() { 2554 for (auto [loopVar] : y ) { // y has to be unresolved. 2555 int z = loopV^; 2556 } 2557 } 2558 )cpp"); 2559 EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar"))); 2560 } 2561 2562 TEST(CompletionTest, UsingDecl) { 2563 const char *Header(R"cpp( 2564 void foo(int); 2565 namespace std { 2566 using ::foo; 2567 })cpp"); 2568 const char *Source(R"cpp( 2569 void bar() { 2570 std::^; 2571 })cpp"); 2572 auto Index = TestTU::withHeaderCode(Header).index(); 2573 clangd::CodeCompleteOptions Opts; 2574 Opts.Index = Index.get(); 2575 Opts.AllScopes = true; 2576 auto R = completions(Source, {}, Opts); 2577 EXPECT_THAT(R.Completions, 2578 ElementsAre(AllOf(Scope("std::"), Named("foo"), 2579 Kind(CompletionItemKind::Reference)))); 2580 } 2581 2582 TEST(CompletionTest, ScopeIsUnresolved) { 2583 clangd::CodeCompleteOptions Opts = {}; 2584 Opts.AllScopes = true; 2585 2586 auto Results = completions(R"cpp( 2587 namespace a { 2588 void f() { b::X^ } 2589 } 2590 )cpp", 2591 {cls("a::b::XYZ")}, Opts); 2592 EXPECT_THAT(Results.Completions, 2593 UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ")))); 2594 } 2595 2596 TEST(CompletionTest, NestedScopeIsUnresolved) { 2597 clangd::CodeCompleteOptions Opts = {}; 2598 Opts.AllScopes = true; 2599 2600 auto Results = completions(R"cpp( 2601 namespace a { 2602 namespace b {} 2603 void f() { b::c::X^ } 2604 } 2605 )cpp", 2606 {cls("a::b::c::XYZ")}, Opts); 2607 EXPECT_THAT(Results.Completions, 2608 UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ")))); 2609 } 2610 2611 // Clang parser gets confused here and doesn't report the ns:: prefix. 2612 // Naive behavior is to insert it again. We examine the source and recover. 2613 TEST(CompletionTest, NamespaceDoubleInsertion) { 2614 clangd::CodeCompleteOptions Opts = {}; 2615 2616 auto Results = completions(R"cpp( 2617 namespace foo { 2618 namespace ns {} 2619 #define M(X) < X 2620 M(ns::ABC^ 2621 } 2622 )cpp", 2623 {cls("foo::ns::ABCDE")}, Opts); 2624 EXPECT_THAT(Results.Completions, 2625 UnorderedElementsAre(AllOf(Qualifier(""), Named("ABCDE")))); 2626 } 2627 2628 TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) { 2629 // Despite the fact that base method matches the ref-qualifier better, 2630 // completion results should only include the derived method. 2631 auto Completions = completions(R"cpp( 2632 struct deque_base { 2633 float size(); 2634 double size() const; 2635 }; 2636 struct deque : deque_base { 2637 int size() const; 2638 }; 2639 2640 auto x = deque().^ 2641 )cpp") 2642 .Completions; 2643 EXPECT_THAT(Completions, 2644 ElementsAre(AllOf(ReturnType("int"), Named("size")))); 2645 } 2646 2647 TEST(NoCompileCompletionTest, Basic) { 2648 auto Results = completionsNoCompile(R"cpp( 2649 void func() { 2650 int xyz; 2651 int abc; 2652 ^ 2653 } 2654 )cpp"); 2655 EXPECT_FALSE(Results.RanParser); 2656 EXPECT_THAT(Results.Completions, 2657 UnorderedElementsAre(Named("void"), Named("func"), Named("int"), 2658 Named("xyz"), Named("abc"))); 2659 } 2660 2661 TEST(NoCompileCompletionTest, WithFilter) { 2662 auto Results = completionsNoCompile(R"cpp( 2663 void func() { 2664 int sym1; 2665 int sym2; 2666 int xyz1; 2667 int xyz2; 2668 sy^ 2669 } 2670 )cpp"); 2671 EXPECT_THAT(Results.Completions, 2672 UnorderedElementsAre(Named("sym1"), Named("sym2"))); 2673 } 2674 2675 TEST(NoCompileCompletionTest, WithIndex) { 2676 std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"), 2677 func("c::xxx"), func("ns::d::xxx")}; 2678 auto Results = completionsNoCompile( 2679 R"cpp( 2680 // Current-scopes, unqualified completion. 2681 using namespace a; 2682 namespace ns { 2683 using namespace b; 2684 void foo() { 2685 xx^ 2686 } 2687 } 2688 )cpp", 2689 Syms); 2690 EXPECT_THAT(Results.Completions, 2691 UnorderedElementsAre(AllOf(Qualifier(""), Scope("")), 2692 AllOf(Qualifier(""), Scope("a::")), 2693 AllOf(Qualifier(""), Scope("ns::b::")))); 2694 CodeCompleteOptions Opts; 2695 Opts.AllScopes = true; 2696 Results = completionsNoCompile( 2697 R"cpp( 2698 // All-scopes unqualified completion. 2699 using namespace a; 2700 namespace ns { 2701 using namespace b; 2702 void foo() { 2703 xx^ 2704 } 2705 } 2706 )cpp", 2707 Syms, Opts); 2708 EXPECT_THAT(Results.Completions, 2709 UnorderedElementsAre(AllOf(Qualifier(""), Scope("")), 2710 AllOf(Qualifier(""), Scope("a::")), 2711 AllOf(Qualifier(""), Scope("ns::b::")), 2712 AllOf(Qualifier("c::"), Scope("c::")), 2713 AllOf(Qualifier("d::"), Scope("ns::d::")))); 2714 Results = completionsNoCompile( 2715 R"cpp( 2716 // Qualified completion. 2717 using namespace a; 2718 namespace ns { 2719 using namespace b; 2720 void foo() { 2721 b::xx^ 2722 } 2723 } 2724 )cpp", 2725 Syms, Opts); 2726 EXPECT_THAT(Results.Completions, 2727 ElementsAre(AllOf(Qualifier(""), Scope("ns::b::")))); 2728 Results = completionsNoCompile( 2729 R"cpp( 2730 // Absolutely qualified completion. 2731 using namespace a; 2732 namespace ns { 2733 using namespace b; 2734 void foo() { 2735 ::a::xx^ 2736 } 2737 } 2738 )cpp", 2739 Syms, Opts); 2740 EXPECT_THAT(Results.Completions, 2741 ElementsAre(AllOf(Qualifier(""), Scope("a::")))); 2742 } 2743 2744 } // namespace 2745 } // namespace clangd 2746 } // namespace clang 2747