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