1 //===-- XRefsTests.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 #include "Annotations.h" 9 #include "AST.h" 10 #include "ParsedAST.h" 11 #include "Protocol.h" 12 #include "SourceCode.h" 13 #include "SyncAPI.h" 14 #include "TestFS.h" 15 #include "TestTU.h" 16 #include "XRefs.h" 17 #include "index/MemIndex.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/Basic/SourceLocation.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/Path.h" 24 #include "llvm/Support/ScopedPrinter.h" 25 #include "gmock/gmock.h" 26 #include "gtest/gtest.h" 27 #include <optional> 28 #include <string> 29 #include <vector> 30 31 namespace clang { 32 namespace clangd { 33 namespace { 34 35 using ::testing::AllOf; 36 using ::testing::ElementsAre; 37 using ::testing::Eq; 38 using ::testing::IsEmpty; 39 using ::testing::Matcher; 40 using ::testing::UnorderedElementsAre; 41 using ::testing::UnorderedElementsAreArray; 42 using ::testing::UnorderedPointwise; 43 44 std::string guard(llvm::StringRef Code) { 45 return "#pragma once\n" + Code.str(); 46 } 47 48 MATCHER_P2(FileRange, File, Range, "") { 49 return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg; 50 } 51 MATCHER(declRange, "") { 52 const LocatedSymbol &Sym = ::testing::get<0>(arg); 53 const Range &Range = ::testing::get<1>(arg); 54 return Sym.PreferredDeclaration.range == Range; 55 } 56 57 // Extracts ranges from an annotated example, and constructs a matcher for a 58 // highlight set. Ranges should be named $read/$write as appropriate. 59 Matcher<const std::vector<DocumentHighlight> &> 60 highlightsFrom(const Annotations &Test) { 61 std::vector<DocumentHighlight> Expected; 62 auto Add = [&](const Range &R, DocumentHighlightKind K) { 63 Expected.emplace_back(); 64 Expected.back().range = R; 65 Expected.back().kind = K; 66 }; 67 for (const auto &Range : Test.ranges()) 68 Add(Range, DocumentHighlightKind::Text); 69 for (const auto &Range : Test.ranges("read")) 70 Add(Range, DocumentHighlightKind::Read); 71 for (const auto &Range : Test.ranges("write")) 72 Add(Range, DocumentHighlightKind::Write); 73 return UnorderedElementsAreArray(Expected); 74 } 75 76 TEST(HighlightsTest, All) { 77 const char *Tests[] = { 78 R"cpp(// Local variable 79 int main() { 80 int [[bonjour]]; 81 $write[[^bonjour]] = 2; 82 int test1 = $read[[bonjour]]; 83 } 84 )cpp", 85 86 R"cpp(// Struct 87 namespace ns1 { 88 struct [[MyClass]] { 89 static void foo([[MyClass]]*) {} 90 }; 91 } // namespace ns1 92 int main() { 93 ns1::[[My^Class]]* Params; 94 } 95 )cpp", 96 97 R"cpp(// Function 98 int [[^foo]](int) {} 99 int main() { 100 [[foo]]([[foo]](42)); 101 auto *X = &[[foo]]; 102 } 103 )cpp", 104 105 R"cpp(// Function parameter in decl 106 void foo(int [[^bar]]); 107 )cpp", 108 R"cpp(// Not touching any identifiers. 109 struct Foo { 110 [[~]]Foo() {}; 111 }; 112 void foo() { 113 Foo f; 114 f.[[^~]]Foo(); 115 } 116 )cpp", 117 R"cpp(// ObjC methods with split selectors. 118 @interface Foo 119 +(void) [[x]]:(int)a [[y]]:(int)b; 120 @end 121 @implementation Foo 122 +(void) [[x]]:(int)a [[y]]:(int)b {} 123 @end 124 void go() { 125 [Foo [[x]]:2 [[^y]]:4]; 126 } 127 )cpp", 128 R"cpp( // Label 129 int main() { 130 goto [[^theLabel]]; 131 [[theLabel]]: 132 return 1; 133 } 134 )cpp", 135 }; 136 for (const char *Test : Tests) { 137 Annotations T(Test); 138 auto TU = TestTU::withCode(T.code()); 139 TU.ExtraArgs.push_back("-xobjective-c++"); 140 auto AST = TU.build(); 141 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T)) 142 << Test; 143 } 144 } 145 146 TEST(HighlightsTest, ControlFlow) { 147 const char *Tests[] = { 148 R"cpp( 149 // Highlight same-function returns. 150 int fib(unsigned n) { 151 if (n <= 1) [[ret^urn]] 1; 152 [[return]] fib(n - 1) + fib(n - 2); 153 154 // Returns from other functions not highlighted. 155 auto Lambda = [] { return; }; 156 class LocalClass { void x() { return; } }; 157 } 158 )cpp", 159 160 R"cpp( 161 #define FAIL() return false 162 #define DO(x) { x; } 163 bool foo(int n) { 164 if (n < 0) [[FAIL]](); 165 DO([[re^turn]] true) 166 } 167 )cpp", 168 169 R"cpp( 170 // Highlight loop control flow 171 int magic() { 172 int counter = 0; 173 [[^for]] (char c : "fruit loops!") { 174 if (c == ' ') [[continue]]; 175 counter += c; 176 if (c == '!') [[break]]; 177 if (c == '?') [[return]] -1; 178 } 179 return counter; 180 } 181 )cpp", 182 183 R"cpp( 184 // Highlight loop and same-loop control flow 185 void nonsense() { 186 [[while]] (true) { 187 if (false) [[bre^ak]]; 188 switch (1) break; 189 [[continue]]; 190 } 191 } 192 )cpp", 193 194 R"cpp( 195 // Highlight switch for break (but not other breaks). 196 void describe(unsigned n) { 197 [[switch]](n) { 198 case 0: 199 break; 200 [[default]]: 201 [[^break]]; 202 } 203 } 204 )cpp", 205 206 R"cpp( 207 // Highlight case and exits for switch-break (but not other cases). 208 void describe(unsigned n) { 209 [[switch]](n) { 210 case 0: 211 break; 212 [[case]] 1: 213 [[default]]: 214 [[return]]; 215 [[^break]]; 216 } 217 } 218 )cpp", 219 220 R"cpp( 221 // Highlight exits and switch for case 222 void describe(unsigned n) { 223 [[switch]](n) { 224 case 0: 225 break; 226 [[case]] 1: 227 [[d^efault]]: 228 [[return]]; 229 [[break]]; 230 } 231 } 232 )cpp", 233 234 R"cpp( 235 // Highlight nothing for switch. 236 void describe(unsigned n) { 237 s^witch(n) { 238 case 0: 239 break; 240 case 1: 241 default: 242 return; 243 break; 244 } 245 } 246 )cpp", 247 248 R"cpp( 249 // FIXME: match exception type against catch blocks 250 int catchy() { 251 try { // wrong: highlight try with matching catch 252 try { // correct: has no matching catch 253 [[thr^ow]] "oh no!"; 254 } catch (int) { } // correct: catch doesn't match type 255 [[return]] -1; // correct: exits the matching catch 256 } catch (const char*) { } // wrong: highlight matching catch 257 [[return]] 42; // wrong: throw doesn't exit function 258 } 259 )cpp", 260 261 R"cpp( 262 // Loop highlights goto exiting the loop, but not jumping within it. 263 void jumpy() { 264 [[wh^ile]](1) { 265 up: 266 if (0) [[goto]] out; 267 goto up; 268 } 269 out: return; 270 } 271 )cpp", 272 }; 273 for (const char *Test : Tests) { 274 Annotations T(Test); 275 auto TU = TestTU::withCode(T.code()); 276 TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4. 277 auto AST = TU.build(); 278 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T)) 279 << Test; 280 } 281 } 282 283 MATCHER_P3(sym, Name, Decl, DefOrNone, "") { 284 std::optional<Range> Def = DefOrNone; 285 if (Name != arg.Name) { 286 *result_listener << "Name is " << arg.Name; 287 return false; 288 } 289 if (Decl != arg.PreferredDeclaration.range) { 290 *result_listener << "Declaration is " 291 << llvm::to_string(arg.PreferredDeclaration); 292 return false; 293 } 294 if (!Def && !arg.Definition) 295 return true; 296 if (Def && !arg.Definition) { 297 *result_listener << "Has no definition"; 298 return false; 299 } 300 if (!Def && arg.Definition) { 301 *result_listener << "Definition is " << llvm::to_string(*arg.Definition); 302 return false; 303 } 304 if (arg.Definition->range != *Def) { 305 *result_listener << "Definition is " << llvm::to_string(*arg.Definition); 306 return false; 307 } 308 return true; 309 } 310 311 MATCHER_P(sym, Name, "") { return arg.Name == Name; } 312 313 MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; } 314 MATCHER_P(containerIs, C, "") { 315 return arg.Loc.containerName.value_or("") == C; 316 } 317 MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; } 318 MATCHER_P(hasID, ID, "") { return arg.ID == ID; } 319 320 TEST(LocateSymbol, WithIndex) { 321 Annotations SymbolHeader(R"cpp( 322 class $forward[[Forward]]; 323 class $foo[[Foo]] {}; 324 325 void $f1[[f1]](); 326 327 inline void $f2[[f2]]() {} 328 )cpp"); 329 Annotations SymbolCpp(R"cpp( 330 class $forward[[forward]] {}; 331 void $f1[[f1]]() {} 332 )cpp"); 333 334 TestTU TU; 335 TU.Code = std::string(SymbolCpp.code()); 336 TU.HeaderCode = std::string(SymbolHeader.code()); 337 auto Index = TU.index(); 338 auto LocateWithIndex = [&Index](const Annotations &Main) { 339 auto AST = TestTU::withCode(Main.code()).build(); 340 return clangd::locateSymbolAt(AST, Main.point(), Index.get()); 341 }; 342 343 Annotations Test(R"cpp(// only declaration in AST. 344 void [[f1]](); 345 int main() { 346 ^f1(); 347 } 348 )cpp"); 349 EXPECT_THAT(LocateWithIndex(Test), 350 ElementsAre(sym("f1", Test.range(), SymbolCpp.range("f1")))); 351 352 Test = Annotations(R"cpp(// definition in AST. 353 void [[f1]]() {} 354 int main() { 355 ^f1(); 356 } 357 )cpp"); 358 EXPECT_THAT(LocateWithIndex(Test), 359 ElementsAre(sym("f1", SymbolHeader.range("f1"), Test.range()))); 360 361 Test = Annotations(R"cpp(// forward declaration in AST. 362 class [[Foo]]; 363 F^oo* create(); 364 )cpp"); 365 EXPECT_THAT(LocateWithIndex(Test), 366 ElementsAre(sym("Foo", Test.range(), SymbolHeader.range("foo")))); 367 368 Test = Annotations(R"cpp(// definition in AST. 369 class [[Forward]] {}; 370 F^orward create(); 371 )cpp"); 372 EXPECT_THAT( 373 LocateWithIndex(Test), 374 ElementsAre(sym("Forward", SymbolHeader.range("forward"), Test.range()))); 375 } 376 377 TEST(LocateSymbol, AnonymousStructFields) { 378 auto Code = Annotations(R"cpp( 379 struct $2[[Foo]] { 380 struct { int $1[[x]]; }; 381 void foo() { 382 // Make sure the implicit base is skipped. 383 $1^x = 42; 384 } 385 }; 386 // Check that we don't skip explicit bases. 387 int a = $2^Foo{}.x; 388 )cpp"); 389 TestTU TU = TestTU::withCode(Code.code()); 390 auto AST = TU.build(); 391 EXPECT_THAT(locateSymbolAt(AST, Code.point("1"), TU.index().get()), 392 UnorderedElementsAre(sym("x", Code.range("1"), Code.range("1")))); 393 EXPECT_THAT( 394 locateSymbolAt(AST, Code.point("2"), TU.index().get()), 395 UnorderedElementsAre(sym("Foo", Code.range("2"), Code.range("2")))); 396 } 397 398 TEST(LocateSymbol, FindOverrides) { 399 auto Code = Annotations(R"cpp( 400 class Foo { 401 virtual void $1[[fo^o]]() = 0; 402 }; 403 class Bar : public Foo { 404 void $2[[foo]]() override; 405 }; 406 )cpp"); 407 TestTU TU = TestTU::withCode(Code.code()); 408 auto AST = TU.build(); 409 EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()), 410 UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt), 411 sym("foo", Code.range("2"), std::nullopt))); 412 } 413 414 TEST(LocateSymbol, WithIndexPreferredLocation) { 415 Annotations SymbolHeader(R"cpp( 416 class $p[[Proto]] {}; 417 void $f[[func]]() {}; 418 )cpp"); 419 TestTU TU; 420 TU.HeaderCode = std::string(SymbolHeader.code()); 421 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files. 422 auto Index = TU.index(); 423 424 Annotations Test(R"cpp(// only declaration in AST. 425 // Shift to make range different. 426 class Proto; 427 void func() {} 428 P$p^roto* create() { 429 fu$f^nc(); 430 return nullptr; 431 } 432 )cpp"); 433 434 auto AST = TestTU::withCode(Test.code()).build(); 435 { 436 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get()); 437 auto CodeGenLoc = SymbolHeader.range("p"); 438 EXPECT_THAT(Locs, ElementsAre(sym("Proto", CodeGenLoc, CodeGenLoc))); 439 } 440 { 441 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get()); 442 auto CodeGenLoc = SymbolHeader.range("f"); 443 EXPECT_THAT(Locs, ElementsAre(sym("func", CodeGenLoc, CodeGenLoc))); 444 } 445 } 446 447 TEST(LocateSymbol, All) { 448 // Ranges in tests: 449 // $decl is the declaration location (if absent, no symbol is located) 450 // $def is the definition location (if absent, symbol has no definition) 451 // unnamed range becomes both $decl and $def. 452 const char *Tests[] = { 453 R"cpp( 454 struct X { 455 union { 456 int [[a]]; 457 float b; 458 }; 459 }; 460 int test(X &x) { 461 return x.^a; 462 } 463 )cpp", 464 465 R"cpp(// Local variable 466 int main() { 467 int [[bonjour]]; 468 ^bonjour = 2; 469 int test1 = bonjour; 470 } 471 )cpp", 472 473 R"cpp(// Struct 474 namespace ns1 { 475 struct [[MyClass]] {}; 476 } // namespace ns1 477 int main() { 478 ns1::My^Class* Params; 479 } 480 )cpp", 481 482 R"cpp(// Function definition via pointer 483 void [[foo]](int) {} 484 int main() { 485 auto *X = &^foo; 486 } 487 )cpp", 488 489 R"cpp(// Function declaration via call 490 int $decl[[foo]](int); 491 int main() { 492 return ^foo(42); 493 } 494 )cpp", 495 496 R"cpp(// Field 497 struct Foo { int [[x]]; }; 498 int main() { 499 Foo bar; 500 (void)bar.^x; 501 } 502 )cpp", 503 504 R"cpp(// Field, member initializer 505 struct Foo { 506 int [[x]]; 507 Foo() : ^x(0) {} 508 }; 509 )cpp", 510 511 R"cpp(// Field, field designator 512 struct Foo { int [[x]]; }; 513 int main() { 514 Foo bar = { .^x = 2 }; 515 } 516 )cpp", 517 518 R"cpp(// Method call 519 struct Foo { int $decl[[x]](); }; 520 int main() { 521 Foo bar; 522 bar.^x(); 523 } 524 )cpp", 525 526 R"cpp(// Typedef 527 typedef int $decl[[Foo]]; 528 int main() { 529 ^Foo bar; 530 } 531 )cpp", 532 533 R"cpp(// Template type parameter 534 template <typename [[T]]> 535 void foo() { ^T t; } 536 )cpp", 537 538 R"cpp(// Template template type parameter 539 template <template<typename> class [[T]]> 540 void foo() { ^T<int> t; } 541 )cpp", 542 543 R"cpp(// Namespace 544 namespace $decl[[ns]] { 545 struct Foo { static void bar(); }; 546 } // namespace ns 547 int main() { ^ns::Foo::bar(); } 548 )cpp", 549 550 R"cpp(// Macro 551 class TTT { public: int a; }; 552 #define [[FF]](S) if (int b = S.a) {} 553 void f() { 554 TTT t; 555 F^F(t); 556 } 557 )cpp", 558 559 R"cpp(// Macro argument 560 int [[i]]; 561 #define ADDRESSOF(X) &X; 562 int *j = ADDRESSOF(^i); 563 )cpp", 564 R"cpp(// Macro argument appearing multiple times in expansion 565 #define VALIDATE_TYPE(x) (void)x; 566 #define ASSERT(expr) \ 567 do { \ 568 VALIDATE_TYPE(expr); \ 569 if (!expr); \ 570 } while (false) 571 bool [[waldo]]() { return true; } 572 void foo() { 573 ASSERT(wa^ldo()); 574 } 575 )cpp", 576 R"cpp(// Symbol concatenated inside macro (not supported) 577 int *pi; 578 #define POINTER(X) p ## X; 579 int x = *POINTER(^i); 580 )cpp", 581 582 R"cpp(// Forward class declaration 583 class $decl[[Foo]]; 584 class $def[[Foo]] {}; 585 F^oo* foo(); 586 )cpp", 587 588 R"cpp(// Function declaration 589 void $decl[[foo]](); 590 void g() { f^oo(); } 591 void $def[[foo]]() {} 592 )cpp", 593 594 R"cpp( 595 #define FF(name) class name##_Test {}; 596 [[FF]](my); 597 void f() { my^_Test a; } 598 )cpp", 599 600 R"cpp( 601 #define FF() class [[Test]] {}; 602 FF(); 603 void f() { T^est a; } 604 )cpp", 605 606 R"cpp(// explicit template specialization 607 template <typename T> 608 struct Foo { void bar() {} }; 609 610 template <> 611 struct [[Foo]]<int> { void bar() {} }; 612 613 void foo() { 614 Foo<char> abc; 615 Fo^o<int> b; 616 } 617 )cpp", 618 619 R"cpp(// implicit template specialization 620 template <typename T> 621 struct [[Foo]] { void bar() {} }; 622 template <> 623 struct Foo<int> { void bar() {} }; 624 void foo() { 625 Fo^o<char> abc; 626 Foo<int> b; 627 } 628 )cpp", 629 630 R"cpp(// partial template specialization 631 template <typename T> 632 struct Foo { void bar() {} }; 633 template <typename T> 634 struct [[Foo]]<T*> { void bar() {} }; 635 ^Foo<int*> x; 636 )cpp", 637 638 R"cpp(// function template specializations 639 template <class T> 640 void foo(T) {} 641 template <> 642 void [[foo]](int) {} 643 void bar() { 644 fo^o(10); 645 } 646 )cpp", 647 648 R"cpp(// variable template decls 649 template <class T> 650 T var = T(); 651 652 template <> 653 double [[var]]<int> = 10; 654 655 double y = va^r<int>; 656 )cpp", 657 658 R"cpp(// No implicit constructors 659 struct X { 660 X(X&& x) = default; 661 }; 662 X $decl[[makeX]](); 663 void foo() { 664 auto x = m^akeX(); 665 } 666 )cpp", 667 668 R"cpp( 669 struct X { 670 X& $decl[[operator]]++(); 671 }; 672 void foo(X& x) { 673 +^+x; 674 } 675 )cpp", 676 677 R"cpp( 678 struct S1 { void f(); }; 679 struct S2 { S1 * $decl[[operator]]->(); }; 680 void test(S2 s2) { 681 s2-^>f(); 682 } 683 )cpp", 684 685 R"cpp(// Declaration of explicit template specialization 686 template <typename T> 687 struct $decl[[$def[[Foo]]]] {}; 688 689 template <> 690 struct Fo^o<int> {}; 691 )cpp", 692 693 R"cpp(// Declaration of partial template specialization 694 template <typename T> 695 struct $decl[[$def[[Foo]]]] {}; 696 697 template <typename T> 698 struct Fo^o<T*> {}; 699 )cpp", 700 701 R"cpp(// Definition on ClassTemplateDecl 702 namespace ns { 703 // Forward declaration. 704 template<typename T> 705 struct $decl[[Foo]]; 706 707 template <typename T> 708 struct $def[[Foo]] {}; 709 } 710 711 using ::ns::Fo^o; 712 )cpp", 713 714 R"cpp(// auto builtin type (not supported) 715 ^auto x = 42; 716 )cpp", 717 718 R"cpp(// auto on lambda 719 auto x = [[[]]]{}; 720 ^auto y = x; 721 )cpp", 722 723 R"cpp(// auto on struct 724 namespace ns1 { 725 struct [[S1]] {}; 726 } // namespace ns1 727 728 ^auto x = ns1::S1{}; 729 )cpp", 730 731 R"cpp(// decltype on struct 732 namespace ns1 { 733 struct [[S1]] {}; 734 } // namespace ns1 735 736 ns1::S1 i; 737 ^decltype(i) j; 738 )cpp", 739 740 R"cpp(// decltype(auto) on struct 741 namespace ns1 { 742 struct [[S1]] {}; 743 } // namespace ns1 744 745 ns1::S1 i; 746 ns1::S1& j = i; 747 ^decltype(auto) k = j; 748 )cpp", 749 750 R"cpp(// auto on template class 751 template<typename T> class [[Foo]] {}; 752 753 ^auto x = Foo<int>(); 754 )cpp", 755 756 R"cpp(// auto on template class with forward declared class 757 template<typename T> class [[Foo]] {}; 758 class X; 759 760 ^auto x = Foo<X>(); 761 )cpp", 762 763 R"cpp(// auto on specialized template class 764 template<typename T> class Foo {}; 765 template<> class [[Foo]]<int> {}; 766 767 ^auto x = Foo<int>(); 768 )cpp", 769 770 R"cpp(// auto on initializer list. 771 namespace std 772 { 773 template<class _E> 774 class [[initializer_list]] { const _E *a, *b; }; 775 } 776 777 ^auto i = {1,2}; 778 )cpp", 779 780 R"cpp(// auto function return with trailing type 781 struct [[Bar]] {}; 782 ^auto test() -> decltype(Bar()) { 783 return Bar(); 784 } 785 )cpp", 786 787 R"cpp(// decltype in trailing return type 788 struct [[Bar]] {}; 789 auto test() -> ^decltype(Bar()) { 790 return Bar(); 791 } 792 )cpp", 793 794 R"cpp(// auto in function return 795 struct [[Bar]] {}; 796 ^auto test() { 797 return Bar(); 798 } 799 )cpp", 800 801 R"cpp(// auto& in function return 802 struct [[Bar]] {}; 803 ^auto& test() { 804 static Bar x; 805 return x; 806 } 807 )cpp", 808 809 R"cpp(// auto* in function return 810 struct [[Bar]] {}; 811 ^auto* test() { 812 Bar* x; 813 return x; 814 } 815 )cpp", 816 817 R"cpp(// const auto& in function return 818 struct [[Bar]] {}; 819 const ^auto& test() { 820 static Bar x; 821 return x; 822 } 823 )cpp", 824 825 R"cpp(// auto lambda param where there's a single instantiation 826 struct [[Bar]] {}; 827 auto Lambda = [](^auto){ return 0; }; 828 int x = Lambda(Bar{}); 829 )cpp", 830 831 R"cpp(// decltype(auto) in function return 832 struct [[Bar]] {}; 833 ^decltype(auto) test() { 834 return Bar(); 835 } 836 )cpp", 837 838 R"cpp(// decltype of function with trailing return type. 839 struct [[Bar]] {}; 840 auto test() -> decltype(Bar()) { 841 return Bar(); 842 } 843 void foo() { 844 ^decltype(test()) i = test(); 845 } 846 )cpp", 847 848 R"cpp(// Override specifier jumps to overridden method 849 class Y { virtual void $decl[[a]]() = 0; }; 850 class X : Y { void a() ^override {} }; 851 )cpp", 852 853 R"cpp(// Final specifier jumps to overridden method 854 class Y { virtual void $decl[[a]]() = 0; }; 855 class X : Y { void a() ^final {} }; 856 )cpp", 857 858 R"cpp(// Heuristic resolution of dependent method 859 template <typename T> 860 struct S { 861 void [[bar]]() {} 862 }; 863 864 template <typename T> 865 void foo(S<T> arg) { 866 arg.ba^r(); 867 } 868 )cpp", 869 870 R"cpp(// Heuristic resolution of dependent method via this-> 871 template <typename T> 872 struct S { 873 void [[foo]]() { 874 this->fo^o(); 875 } 876 }; 877 )cpp", 878 879 R"cpp(// Heuristic resolution of dependent static method 880 template <typename T> 881 struct S { 882 static void [[bar]]() {} 883 }; 884 885 template <typename T> 886 void foo() { 887 S<T>::ba^r(); 888 } 889 )cpp", 890 891 R"cpp(// Heuristic resolution of dependent method 892 // invoked via smart pointer 893 template <typename> struct S { void [[foo]]() {} }; 894 template <typename T> struct unique_ptr { 895 T* operator->(); 896 }; 897 template <typename T> 898 void test(unique_ptr<S<T>>& V) { 899 V->fo^o(); 900 } 901 )cpp", 902 903 R"cpp(// Heuristic resolution of dependent enumerator 904 template <typename T> 905 struct Foo { 906 enum class E { [[A]], B }; 907 E e = E::A^; 908 }; 909 )cpp", 910 911 R"cpp(// Enum base 912 typedef int $decl[[MyTypeDef]]; 913 enum Foo : My^TypeDef {}; 914 )cpp", 915 R"cpp(// Enum base 916 typedef int $decl[[MyTypeDef]]; 917 enum Foo : My^TypeDef; 918 )cpp", 919 R"cpp(// Enum base 920 using $decl[[MyTypeDef]] = int; 921 enum Foo : My^TypeDef {}; 922 )cpp", 923 924 R"objc( 925 @protocol Dog; 926 @protocol $decl[[Dog]] 927 - (void)bark; 928 @end 929 id<Do^g> getDoggo() { 930 return 0; 931 } 932 )objc", 933 934 R"objc( 935 @interface Cat 936 @end 937 @implementation Cat 938 @end 939 @interface $decl[[Cat]] (Exte^nsion) 940 - (void)meow; 941 @end 942 @implementation $def[[Cat]] (Extension) 943 - (void)meow {} 944 @end 945 )objc", 946 947 R"objc( 948 @class $decl[[Foo]]; 949 Fo^o * getFoo() { 950 return 0; 951 } 952 )objc", 953 954 R"objc(// Prefer interface definition over forward declaration 955 @class Foo; 956 @interface $decl[[Foo]] 957 @end 958 Fo^o * getFoo() { 959 return 0; 960 } 961 )objc", 962 963 R"objc( 964 @class Foo; 965 @interface $decl[[Foo]] 966 @end 967 @implementation $def[[Foo]] 968 @end 969 Fo^o * getFoo() { 970 return 0; 971 } 972 )objc", 973 974 R"objc(// Method decl and definition for ObjC class. 975 @interface Cat 976 - (void)$decl[[meow]]; 977 @end 978 @implementation Cat 979 - (void)$def[[meow]] {} 980 @end 981 void makeNoise(Cat *kitty) { 982 [kitty me^ow]; 983 } 984 )objc", 985 986 R"objc(// Method decl and definition for ObjC category. 987 @interface Dog 988 @end 989 @interface Dog (Play) 990 - (void)$decl[[runAround]]; 991 @end 992 @implementation Dog (Play) 993 - (void)$def[[runAround]] {} 994 @end 995 void play(Dog *dog) { 996 [dog run^Around]; 997 } 998 )objc", 999 1000 R"objc(// Method decl and definition for ObjC class extension. 1001 @interface Dog 1002 @end 1003 @interface Dog () 1004 - (void)$decl[[howl]]; 1005 @end 1006 @implementation Dog 1007 - (void)$def[[howl]] {} 1008 @end 1009 void play(Dog *dog) { 1010 [dog ho^wl]; 1011 } 1012 )objc", 1013 R"cpp( 1014 struct PointerIntPairInfo { 1015 static void *getPointer(void *Value); 1016 }; 1017 1018 template <typename Info = PointerIntPairInfo> struct PointerIntPair { 1019 void *Value; 1020 void *getPointer() const { return Info::get^Pointer(Value); } 1021 }; 1022 )cpp", 1023 R"cpp(// Deducing this 1024 struct S { 1025 int bar(this S&); 1026 }; 1027 void foo() { 1028 S [[waldo]]; 1029 int x = wa^ldo.bar(); 1030 } 1031 )cpp"}; 1032 for (const char *Test : Tests) { 1033 Annotations T(Test); 1034 std::optional<Range> WantDecl; 1035 std::optional<Range> WantDef; 1036 if (!T.ranges().empty()) 1037 WantDecl = WantDef = T.range(); 1038 if (!T.ranges("decl").empty()) 1039 WantDecl = T.range("decl"); 1040 if (!T.ranges("def").empty()) 1041 WantDef = T.range("def"); 1042 1043 TestTU TU; 1044 TU.Code = std::string(T.code()); 1045 1046 TU.ExtraArgs.push_back("-xobjective-c++"); 1047 TU.ExtraArgs.push_back("-std=c++23"); 1048 1049 auto AST = TU.build(); 1050 auto Results = locateSymbolAt(AST, T.point()); 1051 1052 if (!WantDecl) { 1053 EXPECT_THAT(Results, IsEmpty()) << Test; 1054 } else { 1055 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test; 1056 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test; 1057 EXPECT_TRUE(Results[0].ID) << Test; 1058 std::optional<Range> GotDef; 1059 if (Results[0].Definition) 1060 GotDef = Results[0].Definition->range; 1061 EXPECT_EQ(WantDef, GotDef) << Test; 1062 } 1063 } 1064 } 1065 TEST(LocateSymbol, ValidSymbolID) { 1066 auto T = Annotations(R"cpp( 1067 #define MACRO(x, y) ((x) + (y)) 1068 int add(int x, int y) { return $MACRO^MACRO(x, y); } 1069 int sum = $add^add(1, 2); 1070 )cpp"); 1071 1072 TestTU TU = TestTU::withCode(T.code()); 1073 auto AST = TU.build(); 1074 auto Index = TU.index(); 1075 EXPECT_THAT(locateSymbolAt(AST, T.point("add"), Index.get()), 1076 ElementsAre(AllOf(sym("add"), 1077 hasID(getSymbolID(&findDecl(AST, "add")))))); 1078 EXPECT_THAT( 1079 locateSymbolAt(AST, T.point("MACRO"), Index.get()), 1080 ElementsAre(AllOf(sym("MACRO"), 1081 hasID(findSymbol(TU.headerSymbols(), "MACRO").ID)))); 1082 } 1083 1084 TEST(LocateSymbol, AllMulti) { 1085 // Ranges in tests: 1086 // $declN is the declaration location 1087 // $defN is the definition location (if absent, symbol has no definition) 1088 // 1089 // NOTE: 1090 // N starts at 0. 1091 struct ExpectedRanges { 1092 Range WantDecl; 1093 std::optional<Range> WantDef; 1094 }; 1095 const char *Tests[] = { 1096 R"objc( 1097 @interface $decl0[[Cat]] 1098 @end 1099 @implementation $def0[[Cat]] 1100 @end 1101 @interface $decl1[[Ca^t]] (Extension) 1102 - (void)meow; 1103 @end 1104 @implementation $def1[[Cat]] (Extension) 1105 - (void)meow {} 1106 @end 1107 )objc", 1108 1109 R"objc( 1110 @interface $decl0[[Cat]] 1111 @end 1112 @implementation $def0[[Cat]] 1113 @end 1114 @interface $decl1[[Cat]] (Extension) 1115 - (void)meow; 1116 @end 1117 @implementation $def1[[Ca^t]] (Extension) 1118 - (void)meow {} 1119 @end 1120 )objc", 1121 1122 R"objc( 1123 @interface $decl0[[Cat]] 1124 @end 1125 @interface $decl1[[Ca^t]] () 1126 - (void)meow; 1127 @end 1128 @implementation $def0[[$def1[[Cat]]]] 1129 - (void)meow {} 1130 @end 1131 )objc", 1132 }; 1133 for (const char *Test : Tests) { 1134 Annotations T(Test); 1135 std::vector<ExpectedRanges> Ranges; 1136 for (int Idx = 0; true; Idx++) { 1137 bool HasDecl = !T.ranges("decl" + std::to_string(Idx)).empty(); 1138 bool HasDef = !T.ranges("def" + std::to_string(Idx)).empty(); 1139 if (!HasDecl && !HasDef) 1140 break; 1141 ExpectedRanges Range; 1142 if (HasDecl) 1143 Range.WantDecl = T.range("decl" + std::to_string(Idx)); 1144 if (HasDef) 1145 Range.WantDef = T.range("def" + std::to_string(Idx)); 1146 Ranges.push_back(Range); 1147 } 1148 1149 TestTU TU; 1150 TU.Code = std::string(T.code()); 1151 TU.ExtraArgs.push_back("-xobjective-c++"); 1152 1153 auto AST = TU.build(); 1154 auto Results = locateSymbolAt(AST, T.point()); 1155 1156 ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test; 1157 for (size_t Idx = 0; Idx < Ranges.size(); Idx++) { 1158 EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl) 1159 << "($decl" << Idx << ")" << Test; 1160 std::optional<Range> GotDef; 1161 if (Results[Idx].Definition) 1162 GotDef = Results[Idx].Definition->range; 1163 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) << "($def" << Idx << ")" << Test; 1164 } 1165 } 1166 } 1167 1168 // LocateSymbol test cases that produce warnings. 1169 // These are separated out from All so that in All we can assert 1170 // that there are no diagnostics. 1171 TEST(LocateSymbol, Warnings) { 1172 const char *Tests[] = { 1173 R"cpp(// Field, GNU old-style field designator 1174 struct Foo { int [[x]]; }; 1175 int main() { 1176 Foo bar = { ^x : 1 }; 1177 } 1178 )cpp", 1179 1180 R"cpp(// Macro 1181 #define MACRO 0 1182 #define [[MACRO]] 1 1183 int main() { return ^MACRO; } 1184 #define MACRO 2 1185 #undef macro 1186 )cpp", 1187 }; 1188 1189 for (const char *Test : Tests) { 1190 Annotations T(Test); 1191 std::optional<Range> WantDecl; 1192 std::optional<Range> WantDef; 1193 if (!T.ranges().empty()) 1194 WantDecl = WantDef = T.range(); 1195 if (!T.ranges("decl").empty()) 1196 WantDecl = T.range("decl"); 1197 if (!T.ranges("def").empty()) 1198 WantDef = T.range("def"); 1199 1200 TestTU TU; 1201 TU.Code = std::string(T.code()); 1202 1203 auto AST = TU.build(); 1204 auto Results = locateSymbolAt(AST, T.point()); 1205 1206 if (!WantDecl) { 1207 EXPECT_THAT(Results, IsEmpty()) << Test; 1208 } else { 1209 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test; 1210 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test; 1211 std::optional<Range> GotDef; 1212 if (Results[0].Definition) 1213 GotDef = Results[0].Definition->range; 1214 EXPECT_EQ(WantDef, GotDef) << Test; 1215 } 1216 } 1217 } 1218 1219 TEST(LocateSymbol, TextualSmoke) { 1220 auto T = Annotations( 1221 R"cpp( 1222 struct [[MyClass]] {}; 1223 // Comment mentioning M^yClass 1224 )cpp"); 1225 1226 auto TU = TestTU::withCode(T.code()); 1227 auto AST = TU.build(); 1228 auto Index = TU.index(); 1229 EXPECT_THAT( 1230 locateSymbolAt(AST, T.point(), Index.get()), 1231 ElementsAre(AllOf(sym("MyClass", T.range(), T.range()), 1232 hasID(getSymbolID(&findDecl(AST, "MyClass")))))); 1233 } 1234 1235 TEST(LocateSymbol, Textual) { 1236 const char *Tests[] = { 1237 R"cpp(// Comment 1238 struct [[MyClass]] {}; 1239 // Comment mentioning M^yClass 1240 )cpp", 1241 R"cpp(// String 1242 struct MyClass {}; 1243 // Not triggered for string literal tokens. 1244 const char* s = "String literal mentioning M^yClass"; 1245 )cpp", 1246 R"cpp(// Ifdef'ed out code 1247 struct [[MyClass]] {}; 1248 #ifdef WALDO 1249 M^yClass var; 1250 #endif 1251 )cpp", 1252 R"cpp(// Macro definition 1253 struct [[MyClass]] {}; 1254 #define DECLARE_MYCLASS_OBJ(name) M^yClass name; 1255 )cpp", 1256 R"cpp(// Invalid code 1257 /*error-ok*/ 1258 int myFunction(int); 1259 // Not triggered for token which survived preprocessing. 1260 int var = m^yFunction(); 1261 )cpp"}; 1262 1263 for (const char *Test : Tests) { 1264 Annotations T(Test); 1265 std::optional<Range> WantDecl; 1266 if (!T.ranges().empty()) 1267 WantDecl = T.range(); 1268 1269 auto TU = TestTU::withCode(T.code()); 1270 1271 auto AST = TU.build(); 1272 auto Index = TU.index(); 1273 auto Word = SpelledWord::touching( 1274 cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())), 1275 AST.getTokens(), AST.getLangOpts()); 1276 if (!Word) { 1277 ADD_FAILURE() << "No word touching point!" << Test; 1278 continue; 1279 } 1280 auto Results = locateSymbolTextually(*Word, AST, Index.get(), 1281 testPath(TU.Filename), ASTNodeKind()); 1282 1283 if (!WantDecl) { 1284 EXPECT_THAT(Results, IsEmpty()) << Test; 1285 } else { 1286 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test; 1287 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test; 1288 } 1289 } 1290 } // namespace 1291 1292 TEST(LocateSymbol, Ambiguous) { 1293 auto T = Annotations(R"cpp( 1294 struct Foo { 1295 Foo(); 1296 Foo(Foo&&); 1297 $ConstructorLoc[[Foo]](const char*); 1298 }; 1299 1300 Foo f(); 1301 1302 void g(Foo foo); 1303 1304 void call() { 1305 const char* str = "123"; 1306 Foo a = $1^str; 1307 Foo b = Foo($2^str); 1308 Foo c = $3^f(); 1309 $4^g($5^f()); 1310 g($6^str); 1311 Foo ab$7^c; 1312 Foo ab$8^cd("asdf"); 1313 Foo foox = Fo$9^o("asdf"); 1314 Foo abcde$10^("asdf"); 1315 Foo foox2 = Foo$11^("asdf"); 1316 } 1317 1318 template <typename T> 1319 struct S { 1320 void $NonstaticOverload1[[bar]](int); 1321 void $NonstaticOverload2[[bar]](float); 1322 1323 static void $StaticOverload1[[baz]](int); 1324 static void $StaticOverload2[[baz]](float); 1325 }; 1326 1327 template <typename T, typename U> 1328 void dependent_call(S<T> s, U u) { 1329 s.ba$12^r(u); 1330 S<T>::ba$13^z(u); 1331 } 1332 )cpp"); 1333 auto TU = TestTU::withCode(T.code()); 1334 // FIXME: Go-to-definition in a template requires disabling delayed template 1335 // parsing. 1336 TU.ExtraArgs.push_back("-fno-delayed-template-parsing"); 1337 auto AST = TU.build(); 1338 // Ordered assertions are deliberate: we expect a predictable order. 1339 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(sym("str"))); 1340 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(sym("str"))); 1341 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(sym("f"))); 1342 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(sym("g"))); 1343 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(sym("f"))); 1344 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(sym("str"))); 1345 // FIXME: Target the constructor as well. 1346 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(sym("abc"))); 1347 // FIXME: Target the constructor as well. 1348 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(sym("abcd"))); 1349 // FIXME: Target the constructor as well. 1350 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(sym("Foo"))); 1351 EXPECT_THAT(locateSymbolAt(AST, T.point("10")), 1352 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt))); 1353 EXPECT_THAT(locateSymbolAt(AST, T.point("11")), 1354 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt))); 1355 // These assertions are unordered because the order comes from 1356 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide 1357 // an order guarantee. 1358 EXPECT_THAT(locateSymbolAt(AST, T.point("12")), 1359 UnorderedElementsAre( 1360 sym("bar", T.range("NonstaticOverload1"), std::nullopt), 1361 sym("bar", T.range("NonstaticOverload2"), std::nullopt))); 1362 EXPECT_THAT(locateSymbolAt(AST, T.point("13")), 1363 UnorderedElementsAre( 1364 sym("baz", T.range("StaticOverload1"), std::nullopt), 1365 sym("baz", T.range("StaticOverload2"), std::nullopt))); 1366 } 1367 1368 TEST(LocateSymbol, TextualDependent) { 1369 // Put the declarations in the header to make sure we are 1370 // finding them via the index heuristic and not the 1371 // nearby-ident heuristic. 1372 Annotations Header(R"cpp( 1373 struct Foo { 1374 void $FooLoc[[uniqueMethodName]](); 1375 }; 1376 struct Bar { 1377 void $BarLoc[[uniqueMethodName]](); 1378 }; 1379 )cpp"); 1380 Annotations Source(R"cpp( 1381 template <typename T> 1382 void f(T t) { 1383 t.u^niqueMethodName(); 1384 } 1385 )cpp"); 1386 TestTU TU; 1387 TU.Code = std::string(Source.code()); 1388 TU.HeaderCode = std::string(Header.code()); 1389 auto AST = TU.build(); 1390 auto Index = TU.index(); 1391 // Need to use locateSymbolAt() since we are testing an 1392 // interaction between locateASTReferent() and 1393 // locateSymbolNamedTextuallyAt(). 1394 auto Results = locateSymbolAt(AST, Source.point(), Index.get()); 1395 EXPECT_THAT( 1396 Results, 1397 UnorderedElementsAre( 1398 sym("uniqueMethodName", Header.range("FooLoc"), std::nullopt), 1399 sym("uniqueMethodName", Header.range("BarLoc"), std::nullopt))); 1400 } 1401 1402 TEST(LocateSymbol, Alias) { 1403 const char *Tests[] = { 1404 R"cpp( 1405 template <class T> struct function {}; 1406 template <class T> using [[callback]] = function<T()>; 1407 1408 c^allback<int> foo; 1409 )cpp", 1410 1411 // triggered on non-definition of a renaming alias: should not give any 1412 // underlying decls. 1413 R"cpp( 1414 class Foo {}; 1415 typedef Foo [[Bar]]; 1416 1417 B^ar b; 1418 )cpp", 1419 R"cpp( 1420 class Foo {}; 1421 using [[Bar]] = Foo; // definition 1422 Ba^r b; 1423 )cpp", 1424 1425 // triggered on the underlying decl of a renaming alias. 1426 R"cpp( 1427 class [[Foo]]; 1428 using Bar = Fo^o; 1429 )cpp", 1430 1431 // triggered on definition of a non-renaming alias: should give underlying 1432 // decls. 1433 R"cpp( 1434 namespace ns { class [[Foo]] {}; } 1435 using ns::F^oo; 1436 )cpp", 1437 1438 R"cpp( 1439 namespace ns { int [[x]](char); int [[x]](double); } 1440 using ns::^x; 1441 )cpp", 1442 1443 R"cpp( 1444 namespace ns { int [[x]](char); int x(double); } 1445 using ns::[[x]]; 1446 int y = ^x('a'); 1447 )cpp", 1448 1449 R"cpp( 1450 namespace ns { class [[Foo]] {}; } 1451 using ns::[[Foo]]; 1452 F^oo f; 1453 )cpp", 1454 1455 // other cases that don't matter much. 1456 R"cpp( 1457 class Foo {}; 1458 typedef Foo [[Ba^r]]; 1459 )cpp", 1460 R"cpp( 1461 class Foo {}; 1462 using [[B^ar]] = Foo; 1463 )cpp", 1464 1465 // Member of dependent base 1466 R"cpp( 1467 template <typename T> 1468 struct Base { 1469 void [[waldo]]() {} 1470 }; 1471 template <typename T> 1472 struct Derived : Base<T> { 1473 using Base<T>::w^aldo; 1474 }; 1475 )cpp", 1476 }; 1477 1478 for (const auto *Case : Tests) { 1479 SCOPED_TRACE(Case); 1480 auto T = Annotations(Case); 1481 auto AST = TestTU::withCode(T.code()).build(); 1482 EXPECT_THAT(locateSymbolAt(AST, T.point()), 1483 UnorderedPointwise(declRange(), T.ranges())); 1484 } 1485 } 1486 1487 TEST(LocateSymbol, RelPathsInCompileCommand) { 1488 // The source is in "/clangd-test/src". 1489 // We build in "/clangd-test/build". 1490 1491 Annotations SourceAnnotations(R"cpp( 1492 #include "header_in_preamble.h" 1493 int [[foo]]; 1494 #include "header_not_in_preamble.h" 1495 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble; 1496 )cpp"); 1497 1498 Annotations HeaderInPreambleAnnotations(R"cpp( 1499 int [[bar_preamble]]; 1500 )cpp"); 1501 1502 Annotations HeaderNotInPreambleAnnotations(R"cpp( 1503 int [[bar_not_preamble]]; 1504 )cpp"); 1505 1506 // Make the compilation paths appear as ../src/foo.cpp in the compile 1507 // commands. 1508 SmallString<32> RelPathPrefix(".."); 1509 llvm::sys::path::append(RelPathPrefix, "src"); 1510 std::string BuildDir = testPath("build"); 1511 MockCompilationDatabase CDB(BuildDir, RelPathPrefix); 1512 1513 MockFS FS; 1514 ClangdServer Server(CDB, FS, ClangdServer::optsForTest()); 1515 1516 // Fill the filesystem. 1517 auto FooCpp = testPath("src/foo.cpp"); 1518 FS.Files[FooCpp] = ""; 1519 auto HeaderInPreambleH = testPath("src/header_in_preamble.h"); 1520 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code()); 1521 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h"); 1522 FS.Files[HeaderNotInPreambleH] = 1523 std::string(HeaderNotInPreambleAnnotations.code()); 1524 1525 runAddDocument(Server, FooCpp, SourceAnnotations.code()); 1526 1527 // Go to a definition in main source file. 1528 auto Locations = 1529 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1")); 1530 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error"; 1531 EXPECT_THAT(*Locations, ElementsAre(sym("foo", SourceAnnotations.range(), 1532 SourceAnnotations.range()))); 1533 1534 // Go to a definition in header_in_preamble.h. 1535 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2")); 1536 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error"; 1537 EXPECT_THAT( 1538 *Locations, 1539 ElementsAre(sym("bar_preamble", HeaderInPreambleAnnotations.range(), 1540 HeaderInPreambleAnnotations.range()))); 1541 1542 // Go to a definition in header_not_in_preamble.h. 1543 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3")); 1544 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error"; 1545 EXPECT_THAT(*Locations, 1546 ElementsAre(sym("bar_not_preamble", 1547 HeaderNotInPreambleAnnotations.range(), 1548 HeaderNotInPreambleAnnotations.range()))); 1549 } 1550 1551 TEST(GoToInclude, All) { 1552 MockFS FS; 1553 MockCompilationDatabase CDB; 1554 ClangdServer Server(CDB, FS, ClangdServer::optsForTest()); 1555 1556 auto FooCpp = testPath("foo.cpp"); 1557 const char *SourceContents = R"cpp( 1558 #include ^"$2^foo.h$3^" 1559 #include "$4^invalid.h" 1560 int b = a; 1561 // test 1562 int foo; 1563 #in$5^clude "$6^foo.h"$7^ 1564 )cpp"; 1565 Annotations SourceAnnotations(SourceContents); 1566 FS.Files[FooCpp] = std::string(SourceAnnotations.code()); 1567 auto FooH = testPath("foo.h"); 1568 1569 const char *HeaderContents = R"cpp([[]]#pragma once 1570 int a; 1571 )cpp"; 1572 Annotations HeaderAnnotations(HeaderContents); 1573 FS.Files[FooH] = std::string(HeaderAnnotations.code()); 1574 1575 runAddDocument(Server, FooH, HeaderAnnotations.code()); 1576 runAddDocument(Server, FooCpp, SourceAnnotations.code()); 1577 1578 // Test include in preamble. 1579 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point()); 1580 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1581 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1582 HeaderAnnotations.range()))); 1583 1584 // Test include in preamble, last char. 1585 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2")); 1586 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1587 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1588 HeaderAnnotations.range()))); 1589 1590 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3")); 1591 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1592 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1593 HeaderAnnotations.range()))); 1594 1595 // Test include outside of preamble. 1596 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6")); 1597 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1598 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1599 HeaderAnnotations.range()))); 1600 1601 // Test a few positions that do not result in Locations. 1602 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4")); 1603 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1604 EXPECT_THAT(*Locations, IsEmpty()); 1605 1606 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5")); 1607 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1608 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1609 HeaderAnnotations.range()))); 1610 1611 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7")); 1612 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1613 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1614 HeaderAnnotations.range()))); 1615 1616 // Objective C #import directive. 1617 Annotations ObjC(R"objc( 1618 #import "^foo.h" 1619 )objc"); 1620 auto FooM = testPath("foo.m"); 1621 FS.Files[FooM] = std::string(ObjC.code()); 1622 1623 runAddDocument(Server, FooM, ObjC.code()); 1624 Locations = runLocateSymbolAt(Server, FooM, ObjC.point()); 1625 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error"; 1626 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(), 1627 HeaderAnnotations.range()))); 1628 } 1629 1630 TEST(LocateSymbol, WithPreamble) { 1631 // Test stragety: AST should always use the latest preamble instead of last 1632 // good preamble. 1633 MockFS FS; 1634 MockCompilationDatabase CDB; 1635 ClangdServer Server(CDB, FS, ClangdServer::optsForTest()); 1636 1637 auto FooCpp = testPath("foo.cpp"); 1638 // The trigger locations must be the same. 1639 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp"); 1640 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp"); 1641 1642 FS.Files[FooCpp] = std::string(FooWithHeader.code()); 1643 1644 auto FooH = testPath("foo.h"); 1645 Annotations FooHeader(R"cpp([[]])cpp"); 1646 FS.Files[FooH] = std::string(FooHeader.code()); 1647 1648 runAddDocument(Server, FooCpp, FooWithHeader.code()); 1649 // LocateSymbol goes to a #include file: the result comes from the preamble. 1650 EXPECT_THAT( 1651 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())), 1652 ElementsAre(sym("foo.h", FooHeader.range(), FooHeader.range()))); 1653 1654 // Only preamble is built, and no AST is built in this request. 1655 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null", 1656 WantDiagnostics::No); 1657 // We build AST here, and it should use the latest preamble rather than the 1658 // stale one. 1659 EXPECT_THAT( 1660 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())), 1661 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt))); 1662 1663 // Reset test environment. 1664 runAddDocument(Server, FooCpp, FooWithHeader.code()); 1665 // Both preamble and AST are built in this request. 1666 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null", 1667 WantDiagnostics::Yes); 1668 // Use the AST being built in above request. 1669 EXPECT_THAT( 1670 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())), 1671 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt))); 1672 } 1673 1674 TEST(LocateSymbol, NearbyTokenSmoke) { 1675 auto T = Annotations(R"cpp( 1676 // prints e^rr and crashes 1677 void die(const char* [[err]]); 1678 )cpp"); 1679 auto AST = TestTU::withCode(T.code()).build(); 1680 // We don't pass an index, so can't hit index-based fallback. 1681 EXPECT_THAT(locateSymbolAt(AST, T.point()), 1682 ElementsAre(sym("err", T.range(), T.range()))); 1683 } 1684 1685 TEST(LocateSymbol, NearbyIdentifier) { 1686 const char *Tests[] = { 1687 R"cpp( 1688 // regular identifiers (won't trigger) 1689 int hello; 1690 int y = he^llo; 1691 )cpp", 1692 R"cpp( 1693 // disabled preprocessor sections 1694 int [[hello]]; 1695 #if 0 1696 int y = ^hello; 1697 #endif 1698 )cpp", 1699 R"cpp( 1700 // comments 1701 // he^llo, world 1702 int [[hello]]; 1703 )cpp", 1704 R"cpp( 1705 // not triggered by string literals 1706 int hello; 1707 const char* greeting = "h^ello, world"; 1708 )cpp", 1709 1710 R"cpp( 1711 // can refer to macro invocations 1712 #define INT int 1713 [[INT]] x; 1714 // I^NT 1715 )cpp", 1716 1717 R"cpp( 1718 // can refer to macro invocations (even if they expand to nothing) 1719 #define EMPTY 1720 [[EMPTY]] int x; 1721 // E^MPTY 1722 )cpp", 1723 1724 R"cpp( 1725 // prefer nearest occurrence, backwards is worse than forwards 1726 int hello; 1727 int x = hello; 1728 // h^ello 1729 int y = [[hello]]; 1730 int z = hello; 1731 )cpp", 1732 1733 R"cpp( 1734 // short identifiers find near results 1735 int [[hi]]; 1736 // h^i 1737 )cpp", 1738 R"cpp( 1739 // short identifiers don't find far results 1740 int hi; 1741 1742 1743 1744 // h^i 1745 1746 1747 1748 1749 int x = hi; 1750 )cpp", 1751 R"cpp( 1752 // prefer nearest occurrence even if several matched tokens 1753 // have the same value of `floor(log2(<token line> - <word line>))`. 1754 int hello; 1755 int x = hello, y = hello; 1756 int z = [[hello]]; 1757 // h^ello 1758 )cpp"}; 1759 for (const char *Test : Tests) { 1760 Annotations T(Test); 1761 auto AST = TestTU::withCode(T.code()).build(); 1762 const auto &SM = AST.getSourceManager(); 1763 std::optional<Range> Nearby; 1764 auto Word = 1765 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())), 1766 AST.getTokens(), AST.getLangOpts()); 1767 if (!Word) { 1768 ADD_FAILURE() << "No word at point! " << Test; 1769 continue; 1770 } 1771 if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens())) 1772 Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange( 1773 Tok->location(), Tok->endLocation())); 1774 if (T.ranges().empty()) 1775 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test; 1776 else 1777 EXPECT_EQ(Nearby, T.range()) << Test; 1778 } 1779 } 1780 1781 TEST(FindImplementations, Inheritance) { 1782 llvm::StringRef Test = R"cpp( 1783 struct $0^Base { 1784 virtual void F$1^oo(); 1785 void C$4^oncrete(); 1786 }; 1787 struct $0[[Child1]] : Base { 1788 void $1[[Fo$3^o]]() override; 1789 virtual void B$2^ar(); 1790 void Concrete(); // No implementations for concrete methods. 1791 }; 1792 struct Child2 : Child1 { 1793 void $3[[Foo]]() override; 1794 void $2[[Bar]]() override; 1795 }; 1796 void FromReference() { 1797 $0^Base* B; 1798 B->Fo$1^o(); 1799 B->C$4^oncrete(); 1800 &Base::Fo$1^o; 1801 Child1 * C1; 1802 C1->B$2^ar(); 1803 C1->Fo$3^o(); 1804 } 1805 // CRTP should work. 1806 template<typename T> 1807 struct $5^TemplateBase {}; 1808 struct $5[[Child3]] : public TemplateBase<Child3> {}; 1809 1810 // Local classes. 1811 void LocationFunction() { 1812 struct $0[[LocalClass1]] : Base { 1813 void $1[[Foo]]() override; 1814 }; 1815 struct $6^LocalBase { 1816 virtual void $7^Bar(); 1817 }; 1818 struct $6[[LocalClass2]]: LocalBase { 1819 void $7[[Bar]]() override; 1820 }; 1821 } 1822 )cpp"; 1823 1824 Annotations Code(Test); 1825 auto TU = TestTU::withCode(Code.code()); 1826 auto AST = TU.build(); 1827 auto Index = TU.index(); 1828 for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) { 1829 for (const auto &Point : Code.points(Label)) { 1830 EXPECT_THAT(findImplementations(AST, Point, Index.get()), 1831 UnorderedPointwise(declRange(), Code.ranges(Label))) 1832 << Code.code() << " at " << Point << " for Label " << Label; 1833 } 1834 } 1835 } 1836 1837 TEST(FindImplementations, CaptureDefinition) { 1838 llvm::StringRef Test = R"cpp( 1839 struct Base { 1840 virtual void F^oo(); 1841 }; 1842 struct Child1 : Base { 1843 void $Decl[[Foo]]() override; 1844 }; 1845 struct Child2 : Base { 1846 void $Child2[[Foo]]() override; 1847 }; 1848 void Child1::$Def[[Foo]]() { /* Definition */ } 1849 )cpp"; 1850 Annotations Code(Test); 1851 auto TU = TestTU::withCode(Code.code()); 1852 auto AST = TU.build(); 1853 EXPECT_THAT( 1854 findImplementations(AST, Code.point(), TU.index().get()), 1855 UnorderedElementsAre(sym("Foo", Code.range("Decl"), Code.range("Def")), 1856 sym("Foo", Code.range("Child2"), std::nullopt))) 1857 << Test; 1858 } 1859 1860 TEST(FindType, All) { 1861 Annotations HeaderA(R"cpp( 1862 struct $Target[[Target]] { operator int() const; }; 1863 struct Aggregate { Target a, b; }; 1864 Target t; 1865 Target make(); 1866 1867 template <typename T> struct $smart_ptr[[smart_ptr]] { 1868 T& operator*(); 1869 T* operator->(); 1870 T* get(); 1871 }; 1872 )cpp"); 1873 auto TU = TestTU::withHeaderCode(HeaderA.code()); 1874 for (const llvm::StringRef Case : { 1875 "str^uct Target;", 1876 "T^arget x;", 1877 "Target ^x;", 1878 "a^uto x = Target{};", 1879 "namespace m { Target tgt; } auto x = m^::tgt;", 1880 "Target funcCall(); auto x = ^funcCall();", 1881 "Aggregate a = { {}, ^{} };", 1882 "Aggregate a = { ^.a=t, };", 1883 "struct X { Target a; X() : ^a() {} };", 1884 "^using T = Target; ^T foo();", 1885 "^template <int> Target foo();", 1886 "void x() { try {} ^catch(Target e) {} }", 1887 "void x() { ^throw t; }", 1888 "int x() { ^return t; }", 1889 "void x() { ^switch(t) {} }", 1890 "void x() { ^delete (Target*)nullptr; }", 1891 "Target& ^tref = t;", 1892 "void x() { ^if (t) {} }", 1893 "void x() { ^while (t) {} }", 1894 "void x() { ^do { } while (t); }", 1895 "void x() { ^make(); }", 1896 "void x(smart_ptr<Target> &t) { t.^get(); }", 1897 "^auto x = []() { return t; };", 1898 "Target* ^tptr = &t;", 1899 "Target ^tarray[3];", 1900 }) { 1901 Annotations A(Case); 1902 TU.Code = A.code().str(); 1903 ParsedAST AST = TU.build(); 1904 1905 ASSERT_GT(A.points().size(), 0u) << Case; 1906 for (auto Pos : A.points()) 1907 EXPECT_THAT(findType(AST, Pos, nullptr), 1908 ElementsAre( 1909 sym("Target", HeaderA.range("Target"), HeaderA.range("Target")))) 1910 << Case; 1911 } 1912 1913 for (const llvm::StringRef Case : { 1914 "smart_ptr<Target> ^tsmart;", 1915 }) { 1916 Annotations A(Case); 1917 TU.Code = A.code().str(); 1918 ParsedAST AST = TU.build(); 1919 1920 EXPECT_THAT(findType(AST, A.point(), nullptr), 1921 UnorderedElementsAre( 1922 sym("Target", HeaderA.range("Target"), HeaderA.range("Target")), 1923 sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr")) 1924 )) 1925 << Case; 1926 } 1927 } 1928 1929 TEST(FindType, Definition) { 1930 Annotations A(R"cpp( 1931 class $decl[[X]]; 1932 X *^x; 1933 class $def[[X]] {}; 1934 )cpp"); 1935 auto TU = TestTU::withCode(A.code().str()); 1936 ParsedAST AST = TU.build(); 1937 1938 EXPECT_THAT(findType(AST, A.point(), nullptr), 1939 ElementsAre(sym("X", A.range("decl"), A.range("def")))); 1940 } 1941 1942 TEST(FindType, Index) { 1943 Annotations Def(R"cpp( 1944 // This definition is only available through the index. 1945 class [[X]] {}; 1946 )cpp"); 1947 TestTU DefTU = TestTU::withHeaderCode(Def.code()); 1948 DefTU.HeaderFilename = "def.h"; 1949 auto DefIdx = DefTU.index(); 1950 1951 Annotations A(R"cpp( 1952 class [[X]]; 1953 X *^x; 1954 )cpp"); 1955 auto TU = TestTU::withCode(A.code().str()); 1956 ParsedAST AST = TU.build(); 1957 1958 EXPECT_THAT(findType(AST, A.point(), DefIdx.get()), 1959 ElementsAre(sym("X", A.range(), Def.range()))); 1960 } 1961 1962 void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) { 1963 Annotations T(Test); 1964 auto TU = TestTU::withCode(T.code()); 1965 TU.ExtraArgs.push_back("-std=c++20"); 1966 1967 auto AST = TU.build(); 1968 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations; 1969 for (const auto &[R, Context] : T.rangesWithPayload()) 1970 ExpectedLocations.push_back( 1971 AllOf(rangeIs(R), containerIs(Context), attrsAre(0u))); 1972 // $def is actually shorthand for both definition and declaration. 1973 // If we have cases that are definition-only, we should change this. 1974 for (const auto &[R, Context] : T.rangesWithPayload("def")) 1975 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context), 1976 attrsAre(ReferencesResult::Definition | 1977 ReferencesResult::Declaration))); 1978 for (const auto &[R, Context] : T.rangesWithPayload("decl")) 1979 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context), 1980 attrsAre(ReferencesResult::Declaration))); 1981 for (const auto &[R, Context] : T.rangesWithPayload("overridedecl")) 1982 ExpectedLocations.push_back(AllOf( 1983 rangeIs(R), containerIs(Context), 1984 attrsAre(ReferencesResult::Declaration | ReferencesResult::Override))); 1985 for (const auto &[R, Context] : T.rangesWithPayload("overridedef")) 1986 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context), 1987 attrsAre(ReferencesResult::Declaration | 1988 ReferencesResult::Definition | 1989 ReferencesResult::Override))); 1990 for (const auto &P : T.points()) { 1991 EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr, 1992 /*AddContext*/ true) 1993 .References, 1994 UnorderedElementsAreArray(ExpectedLocations)) 1995 << "Failed for Refs at " << P << "\n" 1996 << Test; 1997 } 1998 } 1999 2000 TEST(FindReferences, WithinAST) { 2001 const char *Tests[] = { 2002 R"cpp(// Local variable 2003 int main() { 2004 int $def(main)[[foo]]; 2005 $(main)[[^foo]] = 2; 2006 int test1 = $(main)[[foo]]; 2007 } 2008 )cpp", 2009 2010 R"cpp(// Struct 2011 namespace ns1 { 2012 struct $def(ns1)[[Foo]] {}; 2013 } // namespace ns1 2014 int main() { 2015 ns1::$(main)[[Fo^o]]* Params; 2016 } 2017 )cpp", 2018 2019 R"cpp(// Forward declaration 2020 class $decl[[Foo]]; 2021 class $def[[Foo]] {}; 2022 int main() { 2023 $(main)[[Fo^o]] foo; 2024 } 2025 )cpp", 2026 2027 R"cpp(// Function 2028 int $def[[foo]](int) {} 2029 int main() { 2030 auto *X = &$(main)[[^foo]]; 2031 $(main)[[foo]](42); 2032 } 2033 )cpp", 2034 2035 R"cpp(// Field 2036 struct Foo { 2037 int $def(Foo)[[foo]]; 2038 Foo() : $(Foo::Foo)[[foo]](0) {} 2039 }; 2040 int main() { 2041 Foo f; 2042 f.$(main)[[f^oo]] = 1; 2043 } 2044 )cpp", 2045 2046 R"cpp(// Method call 2047 struct Foo { int $decl(Foo)[[foo]](); }; 2048 int Foo::$def(Foo)[[foo]]() {} 2049 int main() { 2050 Foo f; 2051 f.$(main)[[^foo]](); 2052 } 2053 )cpp", 2054 2055 R"cpp(// Constructor 2056 struct Foo { 2057 $decl(Foo)[[F^oo]](int); 2058 }; 2059 void foo() { 2060 Foo f = $(foo)[[Foo]](42); 2061 } 2062 )cpp", 2063 2064 R"cpp(// Typedef 2065 typedef int $def[[Foo]]; 2066 int main() { 2067 $(main)[[^Foo]] bar; 2068 } 2069 )cpp", 2070 2071 R"cpp(// Namespace 2072 namespace $decl[[ns]] { // FIXME: def? 2073 struct Foo {}; 2074 } // namespace ns 2075 int main() { $(main)[[^ns]]::Foo foo; } 2076 )cpp", 2077 2078 R"cpp(// Macros 2079 #define TYPE(X) X 2080 #define FOO Foo 2081 #define CAT(X, Y) X##Y 2082 class $def[[Fo^o]] {}; 2083 void test() { 2084 TYPE($(test)[[Foo]]) foo; 2085 $(test)[[FOO]] foo2; 2086 TYPE(TYPE($(test)[[Foo]])) foo3; 2087 $(test)[[CAT]](Fo, o) foo4; 2088 } 2089 )cpp", 2090 2091 R"cpp(// Macros 2092 #define $def[[MA^CRO]](X) (X+1) 2093 void test() { 2094 int x = $[[MACRO]]($[[MACRO]](1)); 2095 } 2096 )cpp", 2097 2098 R"cpp(// Macro outside preamble 2099 int breakPreamble; 2100 #define $def[[MA^CRO]](X) (X+1) 2101 void test() { 2102 int x = $[[MACRO]]($[[MACRO]](1)); 2103 } 2104 )cpp", 2105 2106 R"cpp( 2107 int $def[[v^ar]] = 0; 2108 void foo(int s = $(foo)[[var]]); 2109 )cpp", 2110 2111 R"cpp( 2112 template <typename T> 2113 class $def[[Fo^o]] {}; 2114 void func($(func)[[Foo]]<int>); 2115 )cpp", 2116 2117 R"cpp( 2118 template <typename T> 2119 class $def[[Foo]] {}; 2120 void func($(func)[[Fo^o]]<int>); 2121 )cpp", 2122 R"cpp(// Not touching any identifiers. 2123 struct Foo { 2124 $def(Foo)[[~]]Foo() {}; 2125 }; 2126 void foo() { 2127 Foo f; 2128 f.$(foo)[[^~]]Foo(); 2129 } 2130 )cpp", 2131 R"cpp(// Lambda capture initializer 2132 void foo() { 2133 int $def(foo)[[w^aldo]] = 42; 2134 auto lambda = [x = $(foo)[[waldo]]](){}; 2135 } 2136 )cpp", 2137 R"cpp(// Renaming alias 2138 template <typename> class Vector {}; 2139 using $def[[^X]] = Vector<int>; 2140 $(x1)[[X]] x1; 2141 Vector<int> x2; 2142 Vector<double> y; 2143 )cpp", 2144 R"cpp(// Dependent code 2145 template <typename T> void $decl[[foo]](T t); 2146 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated. 2147 void baz(int x) { $(baz)[[f^oo]](x); } 2148 )cpp", 2149 R"cpp( 2150 namespace ns { 2151 struct S{}; 2152 void $decl(ns)[[foo]](S s); 2153 } // namespace ns 2154 template <typename T> void foo(T t); 2155 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL) 2156 // when bar<ns::S> is instantiated? 2157 template <typename T> void bar(T t) { foo(t); } 2158 void baz(int x) { 2159 ns::S s; 2160 bar<ns::S>(s); 2161 $(baz)[[f^oo]](s); 2162 } 2163 )cpp", 2164 R"cpp(// unresolved member expression 2165 struct Foo { 2166 template <typename T> void $decl(Foo)[[b^ar]](T t); 2167 }; 2168 template <typename T> void test(Foo F, T t) { 2169 F.$(test)[[bar]](t); 2170 } 2171 )cpp", 2172 2173 // Enum base 2174 R"cpp( 2175 typedef int $def[[MyTypeD^ef]]; 2176 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { }; 2177 )cpp", 2178 R"cpp( 2179 typedef int $def[[MyType^Def]]; 2180 enum MyEnum : $(MyEnum)[[MyTypeD^ef]]; 2181 )cpp", 2182 R"cpp( 2183 using $def[[MyTypeD^ef]] = int; 2184 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { }; 2185 )cpp", 2186 // UDL 2187 R"cpp( 2188 bool $decl[[operator]]"" _u^dl(unsigned long long value); 2189 bool x = $(x)[[1_udl]]; 2190 )cpp", 2191 }; 2192 for (const char *Test : Tests) 2193 checkFindRefs(Test); 2194 } 2195 2196 TEST(FindReferences, ConceptsWithinAST) { 2197 constexpr llvm::StringLiteral Code = R"cpp( 2198 template <class T> 2199 concept $def[[IsSmal^l]] = sizeof(T) <= 8; 2200 2201 template <class T> 2202 concept IsSmallPtr = requires(T x) { 2203 { *x } -> $(IsSmallPtr)[[IsSmal^l]]; 2204 }; 2205 2206 $(i)[[IsSmall]] auto i = 'c'; 2207 template<$(foo)[[IsSmal^l]] U> void foo(); 2208 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>; 2209 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz(); 2210 static_assert([[IsSma^ll]]<char>); 2211 )cpp"; 2212 checkFindRefs(Code); 2213 } 2214 2215 TEST(FindReferences, ConceptReq) { 2216 constexpr llvm::StringLiteral Code = R"cpp( 2217 template <class T> 2218 concept $def[[IsSmal^l]] = sizeof(T) <= 8; 2219 2220 template <class T> 2221 concept IsSmallPtr = requires(T x) { 2222 { *x } -> $(IsSmallPtr)[[IsSmal^l]]; 2223 }; 2224 )cpp"; 2225 checkFindRefs(Code); 2226 } 2227 2228 TEST(FindReferences, RequiresExprParameters) { 2229 constexpr llvm::StringLiteral Code = R"cpp( 2230 template <class T> 2231 concept IsSmall = sizeof(T) <= 8; 2232 2233 template <class T> 2234 concept IsSmallPtr = requires(T $def[[^x]]) { 2235 { *$(IsSmallPtr)[[^x]] } -> IsSmall; 2236 }; 2237 )cpp"; 2238 checkFindRefs(Code); 2239 } 2240 2241 TEST(FindReferences, IncludeOverrides) { 2242 llvm::StringRef Test = 2243 R"cpp( 2244 class Base { 2245 public: 2246 virtu^al void $decl(Base)[[f^unc]]() ^= ^0; 2247 }; 2248 class Derived : public Base { 2249 public: 2250 void $overridedecl(Derived::func)[[func]]() override; 2251 }; 2252 void Derived::$overridedef[[func]]() {} 2253 class Derived2 : public Base { 2254 void $overridedef(Derived2::func)[[func]]() override {} 2255 }; 2256 void test(Derived* D, Base* B) { 2257 D->func(); // No references to the overrides. 2258 B->$(test)[[func]](); 2259 })cpp"; 2260 checkFindRefs(Test, /*UseIndex=*/true); 2261 } 2262 2263 TEST(FindReferences, RefsToBaseMethod) { 2264 llvm::StringRef Test = 2265 R"cpp( 2266 class BaseBase { 2267 public: 2268 virtual void $(BaseBase)[[func]](); 2269 }; 2270 class Base : public BaseBase { 2271 public: 2272 void $(Base)[[func]]() override; 2273 }; 2274 class Derived : public Base { 2275 public: 2276 void $decl(Derived)[[fu^nc]]() over^ride; 2277 }; 2278 void test(BaseBase* BB, Base* B, Derived* D) { 2279 // refs to overridden methods in complete type hierarchy are reported. 2280 BB->$(test)[[func]](); 2281 B->$(test)[[func]](); 2282 D->$(test)[[fu^nc]](); 2283 })cpp"; 2284 checkFindRefs(Test, /*UseIndex=*/true); 2285 } 2286 2287 TEST(FindReferences, MainFileReferencesOnly) { 2288 llvm::StringRef Test = 2289 R"cpp( 2290 void test() { 2291 int [[fo^o]] = 1; 2292 // refs not from main file should not be included. 2293 #include "foo.inc" 2294 })cpp"; 2295 2296 Annotations Code(Test); 2297 auto TU = TestTU::withCode(Code.code()); 2298 TU.AdditionalFiles["foo.inc"] = R"cpp( 2299 foo = 3; 2300 )cpp"; 2301 auto AST = TU.build(); 2302 2303 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations; 2304 for (const auto &R : Code.ranges()) 2305 ExpectedLocations.push_back(rangeIs(R)); 2306 EXPECT_THAT(findReferences(AST, Code.point(), 0).References, 2307 ElementsAreArray(ExpectedLocations)) 2308 << Test; 2309 } 2310 2311 TEST(FindReferences, ExplicitSymbols) { 2312 const char *Tests[] = { 2313 R"cpp( 2314 struct Foo { Foo* $decl(Foo)[[self]]() const; }; 2315 void f() { 2316 Foo foo; 2317 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr. 2318 } 2319 )cpp", 2320 2321 R"cpp( 2322 struct Foo { Foo(int); }; 2323 Foo f() { 2324 int $def(f)[[b]]; 2325 return $(f)[[^b]]; // Foo constructor expr. 2326 } 2327 )cpp", 2328 2329 R"cpp( 2330 struct Foo {}; 2331 void g(Foo); 2332 Foo $decl[[f]](); 2333 void call() { 2334 g($(call)[[^f]]()); // Foo constructor expr. 2335 } 2336 )cpp", 2337 2338 R"cpp( 2339 void $decl[[foo]](int); 2340 void $decl[[foo]](double); 2341 2342 namespace ns { 2343 using ::$decl(ns)[[fo^o]]; 2344 } 2345 )cpp", 2346 2347 R"cpp( 2348 struct X { 2349 operator bool(); 2350 }; 2351 2352 int test() { 2353 X $def(test)[[a]]; 2354 $(test)[[a]].operator bool(); 2355 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node 2356 } 2357 )cpp", 2358 }; 2359 for (const char *Test : Tests) 2360 checkFindRefs(Test); 2361 } 2362 2363 TEST(FindReferences, UsedSymbolsFromInclude) { 2364 const char *Tests[] = { 2365 R"cpp( [[#include ^"bar.h"]] 2366 #include <vector> 2367 int fstBar = [[bar1]](); 2368 int sndBar = [[bar2]](); 2369 [[Bar]] bar; 2370 int macroBar = [[BAR]]; 2371 std::vector<int> vec; 2372 )cpp", 2373 2374 R"cpp([[#in^clude <vector>]] 2375 std::[[vector]]<int> vec; 2376 )cpp", 2377 2378 R"cpp( 2379 [[#include ^"udl_header.h"]] 2380 auto x = [[1_b]]; 2381 )cpp", 2382 }; 2383 for (const char *Test : Tests) { 2384 Annotations T(Test); 2385 auto TU = TestTU::withCode(T.code()); 2386 TU.ExtraArgs.push_back("-std=c++20"); 2387 TU.AdditionalFiles["bar.h"] = guard(R"cpp( 2388 #define BAR 5 2389 int bar1(); 2390 int bar2(); 2391 class Bar {}; 2392 )cpp"); 2393 TU.AdditionalFiles["system/vector"] = guard(R"cpp( 2394 namespace std { 2395 template<typename> 2396 class vector{}; 2397 } 2398 )cpp"); 2399 TU.AdditionalFiles["udl_header.h"] = guard(R"cpp( 2400 bool operator"" _b(unsigned long long value); 2401 )cpp"); 2402 TU.ExtraArgs.push_back("-isystem" + testPath("system")); 2403 2404 auto AST = TU.build(); 2405 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations; 2406 for (const auto &R : T.ranges()) 2407 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u))); 2408 for (const auto &P : T.points()) 2409 EXPECT_THAT(findReferences(AST, P, 0).References, 2410 UnorderedElementsAreArray(ExpectedLocations)) 2411 << "Failed for Refs at " << P << "\n" 2412 << Test; 2413 } 2414 } 2415 2416 TEST(FindReferences, NeedsIndexForSymbols) { 2417 const char *Header = "int foo();"; 2418 Annotations Main("int main() { [[f^oo]](); }"); 2419 TestTU TU; 2420 TU.Code = std::string(Main.code()); 2421 TU.HeaderCode = Header; 2422 auto AST = TU.build(); 2423 2424 // References in main file are returned without index. 2425 EXPECT_THAT( 2426 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References, 2427 ElementsAre(rangeIs(Main.range()))); 2428 Annotations IndexedMain(R"cpp( 2429 int $decl[[foo]]() { return 42; } 2430 void bar() { $bar(bar)[[foo]](); } 2431 struct S { void bar() { $S(S::bar)[[foo]](); } }; 2432 namespace N { void bar() { $N(N::bar)[[foo]](); } } 2433 )cpp"); 2434 2435 // References from indexed files are included. 2436 TestTU IndexedTU; 2437 IndexedTU.Code = std::string(IndexedMain.code()); 2438 IndexedTU.Filename = "Indexed.cpp"; 2439 IndexedTU.HeaderCode = Header; 2440 EXPECT_THAT( 2441 findReferences(AST, Main.point(), 0, IndexedTU.index().get(), 2442 /*AddContext*/ true) 2443 .References, 2444 ElementsAre( 2445 rangeIs(Main.range()), 2446 AllOf(rangeIs(IndexedMain.range("decl")), 2447 attrsAre(ReferencesResult::Declaration | 2448 ReferencesResult::Definition)), 2449 AllOf(rangeIs(IndexedMain.range("bar")), containerIs("bar")), 2450 AllOf(rangeIs(IndexedMain.range("S")), containerIs("S::bar")), 2451 AllOf(rangeIs(IndexedMain.range("N")), containerIs("N::bar")))); 2452 auto LimitRefs = 2453 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get()); 2454 EXPECT_EQ(1u, LimitRefs.References.size()); 2455 EXPECT_TRUE(LimitRefs.HasMore); 2456 2457 // Avoid indexed results for the main file. Use AST for the mainfile. 2458 TU.Code = ("\n\n" + Main.code()).str(); 2459 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References, 2460 ElementsAre(rangeIs(Main.range()))); 2461 } 2462 2463 TEST(FindReferences, NeedsIndexForMacro) { 2464 const char *Header = "#define MACRO(X) (X+1)"; 2465 Annotations Main(R"cpp( 2466 int main() { 2467 int a = [[MA^CRO]](1); 2468 } 2469 )cpp"); 2470 TestTU TU; 2471 TU.Code = std::string(Main.code()); 2472 TU.HeaderCode = Header; 2473 auto AST = TU.build(); 2474 2475 // References in main file are returned without index. 2476 EXPECT_THAT( 2477 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References, 2478 ElementsAre(rangeIs(Main.range()))); 2479 2480 Annotations IndexedMain(R"cpp( 2481 int indexed_main() { 2482 int a = [[MACRO]](1); 2483 } 2484 )cpp"); 2485 2486 // References from indexed files are included. 2487 TestTU IndexedTU; 2488 IndexedTU.Code = std::string(IndexedMain.code()); 2489 IndexedTU.Filename = "Indexed.cpp"; 2490 IndexedTU.HeaderCode = Header; 2491 EXPECT_THAT( 2492 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References, 2493 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range()))); 2494 auto LimitRefs = 2495 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get()); 2496 EXPECT_EQ(1u, LimitRefs.References.size()); 2497 EXPECT_TRUE(LimitRefs.HasMore); 2498 } 2499 2500 TEST(FindReferences, NoQueryForLocalSymbols) { 2501 struct RecordingIndex : public MemIndex { 2502 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs; 2503 bool refs(const RefsRequest &Req, 2504 llvm::function_ref<void(const Ref &)>) const override { 2505 RefIDs = Req.IDs; 2506 return false; 2507 } 2508 }; 2509 2510 struct Test { 2511 StringRef AnnotatedCode; 2512 bool WantQuery; 2513 } Tests[] = { 2514 {"int ^x;", true}, 2515 // For now we don't assume header structure which would allow skipping. 2516 {"namespace { int ^x; }", true}, 2517 {"static int ^x;", true}, 2518 // Anything in a function certainly can't be referenced though. 2519 {"void foo() { int ^x; }", false}, 2520 {"void foo() { struct ^x{}; }", false}, 2521 {"auto lambda = []{ int ^x; };", false}, 2522 }; 2523 for (Test T : Tests) { 2524 Annotations File(T.AnnotatedCode); 2525 RecordingIndex Rec; 2526 auto AST = TestTU::withCode(File.code()).build(); 2527 findReferences(AST, File.point(), 0, &Rec); 2528 if (T.WantQuery) 2529 EXPECT_NE(Rec.RefIDs, std::nullopt) << T.AnnotatedCode; 2530 else 2531 EXPECT_EQ(Rec.RefIDs, std::nullopt) << T.AnnotatedCode; 2532 } 2533 } 2534 2535 TEST(GetNonLocalDeclRefs, All) { 2536 struct Case { 2537 llvm::StringRef AnnotatedCode; 2538 std::vector<std::string> ExpectedDecls; 2539 } Cases[] = { 2540 { 2541 // VarDecl and ParamVarDecl 2542 R"cpp( 2543 void bar(); 2544 void ^foo(int baz) { 2545 int x = 10; 2546 bar(); 2547 })cpp", 2548 {"bar"}, 2549 }, 2550 { 2551 // Method from class 2552 R"cpp( 2553 class Foo { public: void foo(); }; 2554 class Bar { 2555 void foo(); 2556 void bar(); 2557 }; 2558 void Bar::^foo() { 2559 Foo f; 2560 bar(); 2561 f.foo(); 2562 })cpp", 2563 {"Bar", "Bar::bar", "Foo", "Foo::foo"}, 2564 }, 2565 { 2566 // Local types 2567 R"cpp( 2568 void ^foo() { 2569 class Foo { public: void foo() {} }; 2570 class Bar { public: void bar() {} }; 2571 Foo f; 2572 Bar b; 2573 b.bar(); 2574 f.foo(); 2575 })cpp", 2576 {}, 2577 }, 2578 { 2579 // Template params 2580 R"cpp( 2581 template <typename T, template<typename> class Q> 2582 void ^foo() { 2583 T x; 2584 Q<T> y; 2585 })cpp", 2586 {}, 2587 }, 2588 }; 2589 for (const Case &C : Cases) { 2590 Annotations File(C.AnnotatedCode); 2591 auto AST = TestTU::withCode(File.code()).build(); 2592 SourceLocation SL = llvm::cantFail( 2593 sourceLocationInMainFile(AST.getSourceManager(), File.point())); 2594 2595 const FunctionDecl *FD = 2596 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) { 2597 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND); 2598 })); 2599 ASSERT_NE(FD, nullptr); 2600 2601 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD); 2602 std::vector<std::string> Names; 2603 for (const Decl *D : NonLocalDeclRefs) { 2604 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) 2605 Names.push_back(ND->getQualifiedNameAsString()); 2606 } 2607 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls)) 2608 << File.code(); 2609 } 2610 } 2611 2612 TEST(DocumentLinks, All) { 2613 Annotations MainCpp(R"cpp( 2614 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments 2615 int end_of_preamble = 0; 2616 #include $bar[[<bar.h>]] 2617 )cpp"); 2618 2619 TestTU TU; 2620 TU.Code = std::string(MainCpp.code()); 2621 TU.AdditionalFiles = {{"foo.h", ""}, {"bar.h", ""}}; 2622 TU.ExtraArgs = {"-isystem."}; 2623 auto AST = TU.build(); 2624 2625 EXPECT_THAT( 2626 clangd::getDocumentLinks(AST), 2627 ElementsAre( 2628 DocumentLink({MainCpp.range("foo"), 2629 URIForFile::canonicalize(testPath("foo.h"), "")}), 2630 DocumentLink({MainCpp.range("bar"), 2631 URIForFile::canonicalize(testPath("bar.h"), "")}))); 2632 } 2633 2634 } // namespace 2635 } // namespace clangd 2636 } // namespace clang 2637