1 //===-- HoverTests.cpp ----------------------------------------------------===// 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 "AST.h" 10 #include "Annotations.h" 11 #include "Config.h" 12 #include "Hover.h" 13 #include "TestFS.h" 14 #include "TestIndex.h" 15 #include "TestTU.h" 16 #include "index/MemIndex.h" 17 #include "clang/AST/Attr.h" 18 #include "clang/Format/Format.h" 19 #include "clang/Index/IndexSymbol.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/ADT/Twine.h" 22 23 #include "gtest/gtest.h" 24 #include <functional> 25 #include <optional> 26 #include <string> 27 #include <vector> 28 29 namespace clang { 30 namespace clangd { 31 namespace { 32 33 using PassMode = HoverInfo::PassType::PassMode; 34 35 std::string guard(llvm::StringRef Code) { 36 return "#pragma once\n" + Code.str(); 37 } 38 39 TEST(Hover, Structured) { 40 struct { 41 const char *const Code; 42 const std::function<void(HoverInfo &)> ExpectedBuilder; 43 } Cases[] = { 44 // Global scope. 45 {R"cpp( 46 // Best foo ever. 47 void [[fo^o]]() {} 48 )cpp", 49 [](HoverInfo &HI) { 50 HI.NamespaceScope = ""; 51 HI.Name = "foo"; 52 HI.Kind = index::SymbolKind::Function; 53 HI.Documentation = "Best foo ever."; 54 HI.Definition = "void foo()"; 55 HI.ReturnType = "void"; 56 HI.Type = "void ()"; 57 HI.Parameters.emplace(); 58 }}, 59 // Inside namespace 60 {R"cpp( 61 namespace ns1 { namespace ns2 { 62 /// Best foo ever. 63 void [[fo^o]]() {} 64 }} 65 )cpp", 66 [](HoverInfo &HI) { 67 HI.NamespaceScope = "ns1::ns2::"; 68 HI.Name = "foo"; 69 HI.Kind = index::SymbolKind::Function; 70 HI.Documentation = "Best foo ever."; 71 HI.Definition = "void foo()"; 72 HI.ReturnType = "void"; 73 HI.Type = "void ()"; 74 HI.Parameters.emplace(); 75 }}, 76 // Field 77 {R"cpp( 78 namespace ns1 { namespace ns2 { 79 class Foo { 80 char [[b^ar]]; 81 double y[2]; 82 }; 83 }} 84 )cpp", 85 [](HoverInfo &HI) { 86 HI.NamespaceScope = "ns1::ns2::"; 87 HI.LocalScope = "Foo::"; 88 HI.Name = "bar"; 89 HI.Kind = index::SymbolKind::Field; 90 HI.Definition = "char bar"; 91 HI.Type = "char"; 92 HI.Offset = 0; 93 HI.Size = 8; 94 HI.Padding = 56; 95 HI.Align = 8; 96 HI.AccessSpecifier = "private"; 97 }}, 98 // Union field 99 {R"cpp( 100 union Foo { 101 char [[b^ar]]; 102 double y[2]; 103 }; 104 )cpp", 105 [](HoverInfo &HI) { 106 HI.NamespaceScope = ""; 107 HI.LocalScope = "Foo::"; 108 HI.Name = "bar"; 109 HI.Kind = index::SymbolKind::Field; 110 HI.Definition = "char bar"; 111 HI.Type = "char"; 112 HI.Size = 8; 113 HI.Padding = 120; 114 HI.Align = 8; 115 HI.AccessSpecifier = "public"; 116 }}, 117 // Bitfield 118 {R"cpp( 119 struct Foo { 120 int [[^x]] : 1; 121 int y : 1; 122 }; 123 )cpp", 124 [](HoverInfo &HI) { 125 HI.NamespaceScope = ""; 126 HI.LocalScope = "Foo::"; 127 HI.Name = "x"; 128 HI.Kind = index::SymbolKind::Field; 129 HI.Definition = "int x : 1"; 130 HI.Type = "int"; 131 HI.Offset = 0; 132 HI.Size = 1; 133 HI.Align = 32; 134 HI.AccessSpecifier = "public"; 135 }}, 136 // Local to class method. 137 {R"cpp( 138 namespace ns1 { namespace ns2 { 139 struct Foo { 140 void foo() { 141 int [[b^ar]]; 142 } 143 }; 144 }} 145 )cpp", 146 [](HoverInfo &HI) { 147 HI.NamespaceScope = "ns1::ns2::"; 148 HI.LocalScope = "Foo::foo::"; 149 HI.Name = "bar"; 150 HI.Kind = index::SymbolKind::Variable; 151 HI.Definition = "int bar"; 152 HI.Type = "int"; 153 }}, 154 // Predefined variable 155 {R"cpp( 156 void foo() { 157 [[__f^unc__]]; 158 } 159 )cpp", 160 [](HoverInfo &HI) { 161 HI.Name = "__func__"; 162 HI.Kind = index::SymbolKind::Variable; 163 HI.Documentation = 164 "Name of the current function (predefined variable)"; 165 HI.Value = "\"foo\""; 166 HI.Type = "const char[4]"; 167 }}, 168 // Predefined variable (dependent) 169 {R"cpp( 170 template<int> void foo() { 171 [[__f^unc__]]; 172 } 173 )cpp", 174 [](HoverInfo &HI) { 175 HI.Name = "__func__"; 176 HI.Kind = index::SymbolKind::Variable; 177 HI.Documentation = 178 "Name of the current function (predefined variable)"; 179 HI.Type = "const char[]"; 180 }}, 181 // Anon namespace and local scope. 182 {R"cpp( 183 namespace ns1 { namespace { 184 struct { 185 char [[b^ar]]; 186 } T; 187 }} 188 )cpp", 189 [](HoverInfo &HI) { 190 HI.NamespaceScope = "ns1::"; 191 HI.LocalScope = "(anonymous struct)::"; 192 HI.Name = "bar"; 193 HI.Kind = index::SymbolKind::Field; 194 HI.Definition = "char bar"; 195 HI.Type = "char"; 196 HI.Offset = 0; 197 HI.Size = 8; 198 HI.Align = 8; 199 HI.AccessSpecifier = "public"; 200 }}, 201 // Struct definition shows size. 202 {R"cpp( 203 struct [[^X]]{}; 204 )cpp", 205 [](HoverInfo &HI) { 206 HI.NamespaceScope = ""; 207 HI.Name = "X"; 208 HI.Kind = index::SymbolKind::Struct; 209 HI.Definition = "struct X {}"; 210 HI.Size = 8; 211 HI.Align = 8; 212 }}, 213 // Variable with template type 214 {R"cpp( 215 template <typename T, class... Ts> class Foo { public: Foo(int); }; 216 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5); 217 )cpp", 218 [](HoverInfo &HI) { 219 HI.NamespaceScope = ""; 220 HI.Name = "foo"; 221 HI.Kind = index::SymbolKind::Variable; 222 HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)"; 223 HI.Type = "Foo<int, char, bool>"; 224 }}, 225 // Implicit template instantiation 226 {R"cpp( 227 template <typename T> class vector{}; 228 [[vec^tor]]<int> foo; 229 )cpp", 230 [](HoverInfo &HI) { 231 HI.NamespaceScope = ""; 232 HI.Name = "vector<int>"; 233 HI.Kind = index::SymbolKind::Class; 234 HI.Definition = "template <> class vector<int> {}"; 235 }}, 236 // Class template 237 {R"cpp( 238 template <template<typename, bool...> class C, 239 typename = char, 240 int = 0, 241 bool Q = false, 242 class... Ts> class Foo final {}; 243 template <template<typename, bool...> class T> 244 [[F^oo]]<T> foo; 245 )cpp", 246 [](HoverInfo &HI) { 247 HI.NamespaceScope = ""; 248 HI.Name = "Foo"; 249 HI.Kind = index::SymbolKind::Class; 250 HI.Definition = 251 R"cpp(template <template <typename, bool...> class C, typename = char, int = 0, 252 bool Q = false, class... Ts> 253 class Foo final {})cpp"; 254 HI.TemplateParameters = { 255 {{"template <typename, bool...> class"}, 256 std::string("C"), 257 std::nullopt}, 258 {{"typename"}, std::nullopt, std::string("char")}, 259 {{"int"}, std::nullopt, std::string("0")}, 260 {{"bool"}, std::string("Q"), std::string("false")}, 261 {{"class..."}, std::string("Ts"), std::nullopt}, 262 }; 263 }}, 264 // Function template 265 {R"cpp( 266 template <template<typename, bool...> class C, 267 typename = char, 268 int = 0, 269 bool Q = false, 270 class... Ts> void foo(); 271 template<typename, bool...> class Foo; 272 273 void bar() { 274 [[fo^o]]<Foo>(); 275 } 276 )cpp", 277 [](HoverInfo &HI) { 278 HI.NamespaceScope = ""; 279 HI.Name = "foo"; 280 HI.Kind = index::SymbolKind::Function; 281 HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()"; 282 HI.ReturnType = "void"; 283 HI.Type = "void ()"; 284 HI.Parameters.emplace(); 285 }}, 286 // Function decl 287 {R"cpp( 288 template<typename, bool...> class Foo {}; 289 Foo<bool, true, false> foo(int, bool T = false); 290 291 void bar() { 292 [[fo^o]](3); 293 } 294 )cpp", 295 [](HoverInfo &HI) { 296 HI.NamespaceScope = ""; 297 HI.Name = "foo"; 298 HI.Kind = index::SymbolKind::Function; 299 HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)"; 300 HI.ReturnType = "Foo<bool, true, false>"; 301 HI.Type = "Foo<bool, true, false> (int, bool)"; 302 HI.Parameters = { 303 {{"int"}, std::nullopt, std::nullopt}, 304 {{"bool"}, std::string("T"), std::string("false")}, 305 }; 306 }}, 307 // Pointers to lambdas 308 {R"cpp( 309 void foo() { 310 auto lamb = [](int T, bool B) -> bool { return T && B; }; 311 auto *b = &lamb; 312 auto *[[^c]] = &b; 313 } 314 )cpp", 315 [](HoverInfo &HI) { 316 HI.NamespaceScope = ""; 317 HI.LocalScope = "foo::"; 318 HI.Name = "c"; 319 HI.Kind = index::SymbolKind::Variable; 320 HI.Definition = "auto *c = &b"; 321 HI.Type = "(lambda) **"; 322 HI.ReturnType = "bool"; 323 HI.Parameters = { 324 {{"int"}, std::string("T"), std::nullopt}, 325 {{"bool"}, std::string("B"), std::nullopt}, 326 }; 327 return HI; 328 }}, 329 // Lambda parameter with decltype reference 330 {R"cpp( 331 auto lamb = [](int T, bool B) -> bool { return T && B; }; 332 void foo(decltype(lamb)& bar) { 333 [[ba^r]](0, false); 334 } 335 )cpp", 336 [](HoverInfo &HI) { 337 HI.NamespaceScope = ""; 338 HI.LocalScope = "foo::"; 339 HI.Name = "bar"; 340 HI.Kind = index::SymbolKind::Parameter; 341 HI.Definition = "decltype(lamb) &bar"; 342 HI.Type = {"decltype(lamb) &", "(lambda) &"}; 343 HI.ReturnType = "bool"; 344 HI.Parameters = { 345 {{"int"}, std::string("T"), std::nullopt}, 346 {{"bool"}, std::string("B"), std::nullopt}, 347 }; 348 return HI; 349 }}, 350 // Lambda parameter with decltype 351 {R"cpp( 352 auto lamb = [](int T, bool B) -> bool { return T && B; }; 353 void foo(decltype(lamb) bar) { 354 [[ba^r]](0, false); 355 } 356 )cpp", 357 [](HoverInfo &HI) { 358 HI.NamespaceScope = ""; 359 HI.LocalScope = "foo::"; 360 HI.Name = "bar"; 361 HI.Kind = index::SymbolKind::Parameter; 362 HI.Definition = "decltype(lamb) bar"; 363 HI.Type = "class (lambda)"; 364 HI.ReturnType = "bool"; 365 HI.Parameters = { 366 {{"int"}, std::string("T"), std::nullopt}, 367 {{"bool"}, std::string("B"), std::nullopt}, 368 }; 369 HI.Value = "false"; 370 return HI; 371 }}, 372 // Lambda variable 373 {R"cpp( 374 void foo() { 375 int bar = 5; 376 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; }; 377 bool res = [[lam^b]](bar, false); 378 } 379 )cpp", 380 [](HoverInfo &HI) { 381 HI.NamespaceScope = ""; 382 HI.LocalScope = "foo::"; 383 HI.Name = "lamb"; 384 HI.Kind = index::SymbolKind::Variable; 385 HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}"; 386 HI.Type = "class (lambda)"; 387 HI.ReturnType = "bool"; 388 HI.Parameters = { 389 {{"int"}, std::string("T"), std::nullopt}, 390 {{"bool"}, std::string("B"), std::nullopt}, 391 }; 392 return HI; 393 }}, 394 // Local variable in lambda 395 {R"cpp( 396 void foo() { 397 auto lamb = []{int [[te^st]];}; 398 } 399 )cpp", 400 [](HoverInfo &HI) { 401 HI.NamespaceScope = ""; 402 HI.LocalScope = "foo::(anonymous class)::operator()::"; 403 HI.Name = "test"; 404 HI.Kind = index::SymbolKind::Variable; 405 HI.Definition = "int test"; 406 HI.Type = "int"; 407 }}, 408 // Partially-specialized class template. (formerly type-parameter-0-0) 409 {R"cpp( 410 template <typename T> class X; 411 template <typename T> class [[^X]]<T*> {}; 412 )cpp", 413 [](HoverInfo &HI) { 414 HI.Name = "X<T *>"; 415 HI.NamespaceScope = ""; 416 HI.Kind = index::SymbolKind::Class; 417 HI.Definition = "template <typename T> class X<T *> {}"; 418 }}, 419 // Constructor of partially-specialized class template 420 {R"cpp( 421 template<typename, typename=void> struct X; 422 template<typename T> struct X<T*>{ [[^X]](); }; 423 )cpp", 424 [](HoverInfo &HI) { 425 HI.NamespaceScope = ""; 426 HI.Name = "X"; 427 HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>:: 428 HI.Kind = index::SymbolKind::Constructor; 429 HI.Definition = "X()"; 430 HI.Parameters.emplace(); 431 HI.AccessSpecifier = "public"; 432 }}, 433 {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]() 434 [](HoverInfo &HI) { 435 HI.NamespaceScope = ""; 436 HI.Name = "~X"; 437 HI.LocalScope = "X::"; 438 HI.Kind = index::SymbolKind::Destructor; 439 HI.Definition = "~X()"; 440 HI.Parameters.emplace(); 441 HI.AccessSpecifier = "private"; 442 }}, 443 {"class X { [[op^erator]] int(); };", 444 [](HoverInfo &HI) { 445 HI.NamespaceScope = ""; 446 HI.Name = "operator int"; 447 HI.LocalScope = "X::"; 448 HI.Kind = index::SymbolKind::ConversionFunction; 449 HI.Definition = "operator int()"; 450 HI.Parameters.emplace(); 451 HI.AccessSpecifier = "private"; 452 }}, 453 {"class X { operator [[^X]](); };", 454 [](HoverInfo &HI) { 455 HI.NamespaceScope = ""; 456 HI.Name = "X"; 457 HI.Kind = index::SymbolKind::Class; 458 HI.Definition = "class X {}"; 459 }}, 460 461 // auto on structured bindings 462 {R"cpp( 463 void foo() { 464 struct S { int x; float y; }; 465 [[au^to]] [x, y] = S(); 466 } 467 )cpp", 468 [](HoverInfo &HI) { 469 HI.Name = "auto"; 470 HI.Kind = index::SymbolKind::TypeAlias; 471 HI.Definition = "S"; 472 }}, 473 // undeduced auto 474 {R"cpp( 475 template<typename T> 476 void foo() { 477 [[au^to]] x = T{}; 478 } 479 )cpp", 480 [](HoverInfo &HI) { 481 HI.Name = "auto"; 482 HI.Kind = index::SymbolKind::TypeAlias; 483 HI.Definition = "/* not deduced */"; 484 }}, 485 // constrained auto 486 {R"cpp( 487 template <class T> concept F = true; 488 F [[au^to]] x = 1; 489 )cpp", 490 [](HoverInfo &HI) { 491 HI.Name = "auto"; 492 HI.Kind = index::SymbolKind::TypeAlias; 493 HI.Definition = "int"; 494 }}, 495 {R"cpp( 496 template <class T> concept F = true; 497 [[^F]] auto x = 1; 498 )cpp", 499 [](HoverInfo &HI) { 500 HI.NamespaceScope = ""; 501 HI.Name = "F"; 502 HI.Kind = index::SymbolKind::Concept; 503 HI.Definition = "template <class T>\nconcept F = true"; 504 }}, 505 // auto on lambda 506 {R"cpp( 507 void foo() { 508 [[au^to]] lamb = []{}; 509 } 510 )cpp", 511 [](HoverInfo &HI) { 512 HI.Name = "auto"; 513 HI.Kind = index::SymbolKind::TypeAlias; 514 HI.Definition = "class(lambda)"; 515 }}, 516 // auto on template instantiation 517 {R"cpp( 518 template<typename T> class Foo{}; 519 void foo() { 520 [[au^to]] x = Foo<int>(); 521 } 522 )cpp", 523 [](HoverInfo &HI) { 524 HI.Name = "auto"; 525 HI.Kind = index::SymbolKind::TypeAlias; 526 HI.Definition = "Foo<int>"; 527 }}, 528 // auto on specialized template 529 {R"cpp( 530 template<typename T> class Foo{}; 531 template<> class Foo<int>{}; 532 void foo() { 533 [[au^to]] x = Foo<int>(); 534 } 535 )cpp", 536 [](HoverInfo &HI) { 537 HI.Name = "auto"; 538 HI.Kind = index::SymbolKind::TypeAlias; 539 HI.Definition = "Foo<int>"; 540 }}, 541 // constrained template parameter 542 {R"cpp( 543 template<class T> concept Fooable = true; 544 template<[[Foo^able]] T> 545 void bar(T t) {} 546 )cpp", 547 [](HoverInfo &HI) { 548 HI.NamespaceScope = ""; 549 HI.Name = "Fooable"; 550 HI.Kind = index::SymbolKind::Concept; 551 HI.Definition = "template <class T>\nconcept Fooable = true"; 552 }}, 553 {R"cpp( 554 template<class T> concept Fooable = true; 555 template<Fooable [[T^T]]> 556 void bar(TT t) {} 557 )cpp", 558 [](HoverInfo &HI) { 559 HI.Name = "TT"; 560 HI.Type = "class"; 561 HI.AccessSpecifier = "public"; 562 HI.NamespaceScope = ""; 563 HI.LocalScope = "bar::"; 564 HI.Kind = index::SymbolKind::TemplateTypeParm; 565 HI.Definition = "Fooable TT"; 566 }}, 567 {R"cpp( 568 template<class T> concept Fooable = true; 569 void bar([[Foo^able]] auto t) {} 570 )cpp", 571 [](HoverInfo &HI) { 572 HI.NamespaceScope = ""; 573 HI.Name = "Fooable"; 574 HI.Kind = index::SymbolKind::Concept; 575 HI.Definition = "template <class T>\nconcept Fooable = true"; 576 }}, 577 // concept reference 578 {R"cpp( 579 template<class T> concept Fooable = true; 580 auto X = [[Fooa^ble]]<int>; 581 )cpp", 582 [](HoverInfo &HI) { 583 HI.NamespaceScope = ""; 584 HI.Name = "Fooable"; 585 HI.Kind = index::SymbolKind::Concept; 586 HI.Definition = "template <class T>\nconcept Fooable = true"; 587 HI.Value = "true"; 588 }}, 589 590 // empty macro 591 {R"cpp( 592 #define MACRO 593 [[MAC^RO]] 594 )cpp", 595 [](HoverInfo &HI) { 596 HI.Name = "MACRO"; 597 HI.Kind = index::SymbolKind::Macro; 598 HI.Definition = "#define MACRO"; 599 }}, 600 601 // object-like macro 602 {R"cpp( 603 #define MACRO 41 604 int x = [[MAC^RO]]; 605 )cpp", 606 [](HoverInfo &HI) { 607 HI.Name = "MACRO"; 608 HI.Kind = index::SymbolKind::Macro; 609 HI.Value = "41 (0x29)"; 610 HI.Type = "int"; 611 HI.Definition = "#define MACRO 41\n\n" 612 "// Expands to\n" 613 "41"; 614 }}, 615 616 // function-like macro 617 {R"cpp( 618 // Best MACRO ever. 619 #define MACRO(x,y,z) void foo(x, y, z) 620 [[MAC^RO]](int, double d, bool z = false); 621 )cpp", 622 [](HoverInfo &HI) { 623 HI.Name = "MACRO"; 624 HI.Kind = index::SymbolKind::Macro; 625 HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z)\n\n" 626 "// Expands to\n" 627 "void foo(int, double d, bool z = false)"; 628 }}, 629 630 // nested macro 631 {R"cpp( 632 #define STRINGIFY_AUX(s) #s 633 #define STRINGIFY(s) STRINGIFY_AUX(s) 634 #define DECL_STR(NAME, VALUE) const char *v_##NAME = STRINGIFY(VALUE) 635 #define FOO 41 636 637 [[DECL^_STR]](foo, FOO); 638 )cpp", 639 [](HoverInfo &HI) { 640 HI.Name = "DECL_STR"; 641 HI.Kind = index::SymbolKind::Macro; 642 HI.Type = HoverInfo::PrintedType("const char *"); 643 HI.Definition = "#define DECL_STR(NAME, VALUE) const char *v_##NAME = " 644 "STRINGIFY(VALUE)\n\n" 645 "// Expands to\n" 646 "const char *v_foo = \"41\""; 647 }}, 648 649 // constexprs 650 {R"cpp( 651 constexpr int add(int a, int b) { return a + b; } 652 int [[b^ar]] = add(1, 2); 653 )cpp", 654 [](HoverInfo &HI) { 655 HI.Name = "bar"; 656 HI.Definition = "int bar = add(1, 2)"; 657 HI.Kind = index::SymbolKind::Variable; 658 HI.Type = "int"; 659 HI.NamespaceScope = ""; 660 HI.Value = "3"; 661 }}, 662 {R"cpp( 663 int [[b^ar]] = sizeof(char); 664 )cpp", 665 [](HoverInfo &HI) { 666 HI.Name = "bar"; 667 HI.Definition = "int bar = sizeof(char)"; 668 HI.Kind = index::SymbolKind::Variable; 669 HI.Type = "int"; 670 HI.NamespaceScope = ""; 671 HI.Value = "1"; 672 }}, 673 {R"cpp( 674 template<int a, int b> struct Add { 675 static constexpr int result = a + b; 676 }; 677 int [[ba^r]] = Add<1, 2>::result; 678 )cpp", 679 [](HoverInfo &HI) { 680 HI.Name = "bar"; 681 HI.Definition = "int bar = Add<1, 2>::result"; 682 HI.Kind = index::SymbolKind::Variable; 683 HI.Type = "int"; 684 HI.NamespaceScope = ""; 685 HI.Value = "3"; 686 }}, 687 {R"cpp( 688 enum Color { RED = -123, GREEN = 5, }; 689 Color x = [[GR^EEN]]; 690 )cpp", 691 [](HoverInfo &HI) { 692 HI.Name = "GREEN"; 693 HI.NamespaceScope = ""; 694 HI.LocalScope = "Color::"; 695 HI.Definition = "GREEN = 5"; 696 HI.Kind = index::SymbolKind::EnumConstant; 697 HI.Type = "enum Color"; 698 HI.Value = "5"; // Numeric on the enumerator name, no hex as small. 699 }}, 700 {R"cpp( 701 enum Color { RED = -123, GREEN = 5, }; 702 Color x = RED; 703 Color y = [[^x]]; 704 )cpp", 705 [](HoverInfo &HI) { 706 HI.Name = "x"; 707 HI.NamespaceScope = ""; 708 HI.Definition = "Color x = RED"; 709 HI.Kind = index::SymbolKind::Variable; 710 HI.Type = "Color"; 711 HI.Value = "RED (0xffffff85)"; // Symbolic on an expression. 712 }}, 713 {R"cpp( 714 template<int a, int b> struct Add { 715 static constexpr int result = a + b; 716 }; 717 int bar = Add<1, 2>::[[resu^lt]]; 718 )cpp", 719 [](HoverInfo &HI) { 720 HI.Name = "result"; 721 HI.Definition = "static constexpr int result = a + b"; 722 HI.Kind = index::SymbolKind::StaticProperty; 723 HI.Type = "const int"; 724 HI.NamespaceScope = ""; 725 HI.LocalScope = "Add<1, 2>::"; 726 HI.Value = "3"; 727 HI.AccessSpecifier = "public"; 728 }}, 729 {R"cpp( 730 using my_int = int; 731 constexpr my_int answer() { return 40 + 2; } 732 int x = [[ans^wer]](); 733 )cpp", 734 [](HoverInfo &HI) { 735 HI.Name = "answer"; 736 HI.Definition = "constexpr my_int answer()"; 737 HI.Kind = index::SymbolKind::Function; 738 HI.Type = {"my_int ()", "int ()"}; 739 HI.ReturnType = {"my_int", "int"}; 740 HI.Parameters.emplace(); 741 HI.NamespaceScope = ""; 742 HI.Value = "42 (0x2a)"; 743 }}, 744 {R"cpp( 745 const char *[[ba^r]] = "1234"; 746 )cpp", 747 [](HoverInfo &HI) { 748 HI.Name = "bar"; 749 HI.Definition = "const char *bar = \"1234\""; 750 HI.Kind = index::SymbolKind::Variable; 751 HI.Type = "const char *"; 752 HI.NamespaceScope = ""; 753 HI.Value = "&\"1234\"[0]"; 754 }}, 755 {R"cpp(// Should not crash 756 template <typename T> 757 struct Tmpl { 758 Tmpl(int name); 759 }; 760 761 template <typename A> 762 void boom(int name) { 763 new Tmpl<A>([[na^me]]); 764 })cpp", 765 [](HoverInfo &HI) { 766 HI.Name = "name"; 767 HI.Definition = "int name"; 768 HI.Kind = index::SymbolKind::Parameter; 769 HI.Type = "int"; 770 HI.NamespaceScope = ""; 771 HI.LocalScope = "boom::"; 772 }}, 773 { 774 R"cpp(// Should not print inline or anon namespaces. 775 namespace ns { 776 inline namespace in_ns { 777 namespace a { 778 namespace { 779 namespace b { 780 inline namespace in_ns2 { 781 class Foo {}; 782 } // in_ns2 783 } // b 784 } // anon 785 } // a 786 } // in_ns 787 } // ns 788 void foo() { 789 ns::a::b::[[F^oo]] x; 790 (void)x; 791 } 792 )cpp", 793 [](HoverInfo &HI) { 794 HI.Name = "Foo"; 795 HI.Kind = index::SymbolKind::Class; 796 HI.NamespaceScope = "ns::a::b::"; 797 HI.Definition = "class Foo {}"; 798 }}, 799 { 800 R"cpp( 801 template <typename T> class Foo {}; 802 class X; 803 void foo() { 804 [[^auto]] x = Foo<X>(); 805 } 806 )cpp", 807 [](HoverInfo &HI) { 808 HI.Name = "auto"; 809 HI.Kind = index::SymbolKind::TypeAlias; 810 HI.Definition = "Foo<X>"; 811 }}, 812 {// Falls back to primary template, when the type is not instantiated. 813 R"cpp( 814 // comment from primary 815 template <typename T> class Foo {}; 816 // comment from specialization 817 template <typename T> class Foo<T*> {}; 818 void foo() { 819 [[Fo^o]]<int*> *x = nullptr; 820 } 821 )cpp", 822 [](HoverInfo &HI) { 823 HI.Name = "Foo<int *>"; 824 HI.Kind = index::SymbolKind::Class; 825 HI.NamespaceScope = ""; 826 HI.Definition = "template <> class Foo<int *>"; 827 // FIXME: Maybe force instantiation to make use of real template 828 // pattern. 829 HI.Documentation = "comment from primary"; 830 }}, 831 {// Template Type Parameter 832 R"cpp( 833 template <typename [[^T]] = int> void foo(); 834 )cpp", 835 [](HoverInfo &HI) { 836 HI.Name = "T"; 837 HI.Kind = index::SymbolKind::TemplateTypeParm; 838 HI.NamespaceScope = ""; 839 HI.Definition = "typename T = int"; 840 HI.LocalScope = "foo::"; 841 HI.Type = "typename"; 842 HI.AccessSpecifier = "public"; 843 }}, 844 {// TemplateTemplate Type Parameter 845 R"cpp( 846 template <template<typename> class [[^T]]> void foo(); 847 )cpp", 848 [](HoverInfo &HI) { 849 HI.Name = "T"; 850 HI.Kind = index::SymbolKind::TemplateTemplateParm; 851 HI.NamespaceScope = ""; 852 HI.Definition = "template <typename> class T"; 853 HI.LocalScope = "foo::"; 854 HI.Type = "template <typename> class"; 855 HI.AccessSpecifier = "public"; 856 }}, 857 {// NonType Template Parameter 858 R"cpp( 859 template <int [[^T]] = 5> void foo(); 860 )cpp", 861 [](HoverInfo &HI) { 862 HI.Name = "T"; 863 HI.Kind = index::SymbolKind::NonTypeTemplateParm; 864 HI.NamespaceScope = ""; 865 HI.Definition = "int T = 5"; 866 HI.LocalScope = "foo::"; 867 HI.Type = "int"; 868 HI.AccessSpecifier = "public"; 869 }}, 870 871 {// Getter 872 R"cpp( 873 struct X { int Y; float [[^y]]() { return Y; } }; 874 )cpp", 875 [](HoverInfo &HI) { 876 HI.Name = "y"; 877 HI.Kind = index::SymbolKind::InstanceMethod; 878 HI.NamespaceScope = ""; 879 HI.Definition = "float y()"; 880 HI.LocalScope = "X::"; 881 HI.Documentation = "Trivial accessor for `Y`."; 882 HI.Type = "float ()"; 883 HI.ReturnType = "float"; 884 HI.Parameters.emplace(); 885 HI.AccessSpecifier = "public"; 886 }}, 887 {// Setter 888 R"cpp( 889 struct X { int Y; void [[^setY]](float v) { Y = v; } }; 890 )cpp", 891 [](HoverInfo &HI) { 892 HI.Name = "setY"; 893 HI.Kind = index::SymbolKind::InstanceMethod; 894 HI.NamespaceScope = ""; 895 HI.Definition = "void setY(float v)"; 896 HI.LocalScope = "X::"; 897 HI.Documentation = "Trivial setter for `Y`."; 898 HI.Type = "void (float)"; 899 HI.ReturnType = "void"; 900 HI.Parameters.emplace(); 901 HI.Parameters->emplace_back(); 902 HI.Parameters->back().Type = "float"; 903 HI.Parameters->back().Name = "v"; 904 HI.AccessSpecifier = "public"; 905 }}, 906 {// Setter (builder) 907 R"cpp( 908 struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } }; 909 )cpp", 910 [](HoverInfo &HI) { 911 HI.Name = "setY"; 912 HI.Kind = index::SymbolKind::InstanceMethod; 913 HI.NamespaceScope = ""; 914 HI.Definition = "X &setY(float v)"; 915 HI.LocalScope = "X::"; 916 HI.Documentation = "Trivial setter for `Y`."; 917 HI.Type = "X &(float)"; 918 HI.ReturnType = "X &"; 919 HI.Parameters.emplace(); 920 HI.Parameters->emplace_back(); 921 HI.Parameters->back().Type = "float"; 922 HI.Parameters->back().Name = "v"; 923 HI.AccessSpecifier = "public"; 924 }}, 925 {// Setter (move) 926 R"cpp( 927 namespace std { template<typename T> T&& move(T&& t); } 928 struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } }; 929 )cpp", 930 [](HoverInfo &HI) { 931 HI.Name = "setY"; 932 HI.Kind = index::SymbolKind::InstanceMethod; 933 HI.NamespaceScope = ""; 934 HI.Definition = "void setY(float v)"; 935 HI.LocalScope = "X::"; 936 HI.Documentation = "Trivial setter for `Y`."; 937 HI.Type = "void (float)"; 938 HI.ReturnType = "void"; 939 HI.Parameters.emplace(); 940 HI.Parameters->emplace_back(); 941 HI.Parameters->back().Type = "float"; 942 HI.Parameters->back().Name = "v"; 943 HI.AccessSpecifier = "public"; 944 }}, 945 {// Field type initializer. 946 R"cpp( 947 struct X { int x = 2; }; 948 X ^[[x]]; 949 )cpp", 950 [](HoverInfo &HI) { 951 HI.Name = "x"; 952 HI.Kind = index::SymbolKind::Variable; 953 HI.NamespaceScope = ""; 954 HI.Definition = "X x"; 955 HI.Type = "X"; 956 }}, 957 {// Don't crash on null types. 958 R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp", 959 [](HoverInfo &HI) { 960 HI.Name = "x"; 961 HI.Kind = index::SymbolKind::Variable; 962 HI.NamespaceScope = ""; 963 HI.Definition = ""; 964 HI.Type = "NULL TYPE"; 965 // Bindings are in theory public members of an anonymous struct. 966 HI.AccessSpecifier = "public"; 967 }}, 968 {// Don't crash on invalid decl with invalid init expr. 969 R"cpp( 970 Unknown [[^abc]] = invalid; 971 // error-ok 972 )cpp", 973 [](HoverInfo &HI) { 974 HI.Name = "abc"; 975 HI.Kind = index::SymbolKind::Variable; 976 HI.NamespaceScope = ""; 977 HI.Definition = "int abc = <recovery - expr>()"; 978 HI.Type = "int"; 979 HI.AccessSpecifier = "public"; 980 }}, 981 {// Extra info for function call. 982 R"cpp( 983 void fun(int arg_a, int &arg_b) {}; 984 void code() { 985 int a = 1, b = 2; 986 fun(a, [[^b]]); 987 } 988 )cpp", 989 [](HoverInfo &HI) { 990 HI.Name = "b"; 991 HI.Kind = index::SymbolKind::Variable; 992 HI.NamespaceScope = ""; 993 HI.Definition = "int b = 2"; 994 HI.LocalScope = "code::"; 995 HI.Value = "2"; 996 HI.Type = "int"; 997 HI.CalleeArgInfo.emplace(); 998 HI.CalleeArgInfo->Name = "arg_b"; 999 HI.CalleeArgInfo->Type = "int &"; 1000 HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false}; 1001 }}, 1002 {// make_unique-like function call 1003 R"cpp( 1004 struct Foo { 1005 explicit Foo(int arg_a) {} 1006 }; 1007 template<class T, class... Args> 1008 T make(Args&&... args) 1009 { 1010 return T(args...); 1011 } 1012 1013 void code() { 1014 int a = 1; 1015 auto foo = make<Foo>([[^a]]); 1016 } 1017 )cpp", 1018 [](HoverInfo &HI) { 1019 HI.Name = "a"; 1020 HI.Kind = index::SymbolKind::Variable; 1021 HI.NamespaceScope = ""; 1022 HI.Definition = "int a = 1"; 1023 HI.LocalScope = "code::"; 1024 HI.Value = "1"; 1025 HI.Type = "int"; 1026 HI.CalleeArgInfo.emplace(); 1027 HI.CalleeArgInfo->Name = "arg_a"; 1028 HI.CalleeArgInfo->Type = "int"; 1029 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; 1030 }}, 1031 { 1032 R"cpp( 1033 void foobar(const float &arg); 1034 int main() { 1035 int a = 0; 1036 foobar([[^a]]); 1037 } 1038 )cpp", 1039 [](HoverInfo &HI) { 1040 HI.Name = "a"; 1041 HI.Kind = index::SymbolKind::Variable; 1042 HI.NamespaceScope = ""; 1043 HI.Definition = "int a = 0"; 1044 HI.LocalScope = "main::"; 1045 HI.Value = "0"; 1046 HI.Type = "int"; 1047 HI.CalleeArgInfo.emplace(); 1048 HI.CalleeArgInfo->Name = "arg"; 1049 HI.CalleeArgInfo->Type = "const float &"; 1050 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true}; 1051 }}, 1052 { 1053 R"cpp( 1054 struct Foo { 1055 explicit Foo(const float& arg) {} 1056 }; 1057 int main() { 1058 int a = 0; 1059 Foo foo([[^a]]); 1060 } 1061 )cpp", 1062 [](HoverInfo &HI) { 1063 HI.Name = "a"; 1064 HI.Kind = index::SymbolKind::Variable; 1065 HI.NamespaceScope = ""; 1066 HI.Definition = "int a = 0"; 1067 HI.LocalScope = "main::"; 1068 HI.Value = "0"; 1069 HI.Type = "int"; 1070 HI.CalleeArgInfo.emplace(); 1071 HI.CalleeArgInfo->Name = "arg"; 1072 HI.CalleeArgInfo->Type = "const float &"; 1073 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true}; 1074 }}, 1075 {// Literal passed to function call 1076 R"cpp( 1077 void fun(int arg_a, const int &arg_b) {}; 1078 void code() { 1079 int a = 1; 1080 fun(a, [[^2]]); 1081 } 1082 )cpp", 1083 [](HoverInfo &HI) { 1084 HI.Name = "literal"; 1085 HI.Kind = index::SymbolKind::Unknown; 1086 HI.CalleeArgInfo.emplace(); 1087 HI.CalleeArgInfo->Name = "arg_b"; 1088 HI.CalleeArgInfo->Type = "const int &"; 1089 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false}; 1090 }}, 1091 {// Expression passed to function call 1092 R"cpp( 1093 void fun(int arg_a, const int &arg_b) {}; 1094 void code() { 1095 int a = 1; 1096 fun(a, 1 [[^+]] 2); 1097 } 1098 )cpp", 1099 [](HoverInfo &HI) { 1100 HI.Name = "expression"; 1101 HI.Kind = index::SymbolKind::Unknown; 1102 HI.Type = "int"; 1103 HI.Value = "3"; 1104 HI.CalleeArgInfo.emplace(); 1105 HI.CalleeArgInfo->Name = "arg_b"; 1106 HI.CalleeArgInfo->Type = "const int &"; 1107 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false}; 1108 }}, 1109 { 1110 R"cpp( 1111 int add(int lhs, int rhs); 1112 int main() { 1113 add(1 [[^+]] 2, 3); 1114 } 1115 )cpp", 1116 [](HoverInfo &HI) { 1117 HI.Name = "expression"; 1118 HI.Kind = index::SymbolKind::Unknown; 1119 HI.Type = "int"; 1120 HI.Value = "3"; 1121 HI.CalleeArgInfo.emplace(); 1122 HI.CalleeArgInfo->Name = "lhs"; 1123 HI.CalleeArgInfo->Type = "int"; 1124 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; 1125 }}, 1126 { 1127 R"cpp( 1128 void foobar(const float &arg); 1129 int main() { 1130 foobar([[^0]]); 1131 } 1132 )cpp", 1133 [](HoverInfo &HI) { 1134 HI.Name = "literal"; 1135 HI.Kind = index::SymbolKind::Unknown; 1136 HI.CalleeArgInfo.emplace(); 1137 HI.CalleeArgInfo->Name = "arg"; 1138 HI.CalleeArgInfo->Type = "const float &"; 1139 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true}; 1140 }}, 1141 {// Extra info for method call. 1142 R"cpp( 1143 class C { 1144 public: 1145 void fun(int arg_a = 3, int arg_b = 4) {} 1146 }; 1147 void code() { 1148 int a = 1, b = 2; 1149 C c; 1150 c.fun([[^a]], b); 1151 } 1152 )cpp", 1153 [](HoverInfo &HI) { 1154 HI.Name = "a"; 1155 HI.Kind = index::SymbolKind::Variable; 1156 HI.NamespaceScope = ""; 1157 HI.Definition = "int a = 1"; 1158 HI.LocalScope = "code::"; 1159 HI.Value = "1"; 1160 HI.Type = "int"; 1161 HI.CalleeArgInfo.emplace(); 1162 HI.CalleeArgInfo->Name = "arg_a"; 1163 HI.CalleeArgInfo->Type = "int"; 1164 HI.CalleeArgInfo->Default = "3"; 1165 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; 1166 }}, 1167 { 1168 R"cpp( 1169 struct Foo { 1170 Foo(const int &); 1171 }; 1172 void foo(Foo); 1173 void bar() { 1174 const int x = 0; 1175 foo([[^x]]); 1176 } 1177 )cpp", 1178 [](HoverInfo &HI) { 1179 HI.Name = "x"; 1180 HI.Kind = index::SymbolKind::Variable; 1181 HI.NamespaceScope = ""; 1182 HI.Definition = "const int x = 0"; 1183 HI.LocalScope = "bar::"; 1184 HI.Value = "0"; 1185 HI.Type = "const int"; 1186 HI.CalleeArgInfo.emplace(); 1187 HI.CalleeArgInfo->Type = "Foo"; 1188 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true}; 1189 }}, 1190 {// Dont crash on invalid decl 1191 R"cpp( 1192 // error-ok 1193 struct Foo { 1194 Bar [[x^x]]; 1195 };)cpp", 1196 [](HoverInfo &HI) { 1197 HI.Name = "xx"; 1198 HI.Kind = index::SymbolKind::Field; 1199 HI.NamespaceScope = ""; 1200 HI.Definition = "int xx"; 1201 HI.LocalScope = "Foo::"; 1202 HI.Type = "int"; 1203 HI.AccessSpecifier = "public"; 1204 }}, 1205 {R"cpp( 1206 // error-ok 1207 struct Foo { 1208 Bar xx; 1209 int [[y^y]]; 1210 };)cpp", 1211 [](HoverInfo &HI) { 1212 HI.Name = "yy"; 1213 HI.Kind = index::SymbolKind::Field; 1214 HI.NamespaceScope = ""; 1215 HI.Definition = "int yy"; 1216 HI.LocalScope = "Foo::"; 1217 HI.Type = "int"; 1218 HI.AccessSpecifier = "public"; 1219 }}, 1220 {// No crash on InitListExpr. 1221 R"cpp( 1222 struct Foo { 1223 int a[10]; 1224 }; 1225 constexpr Foo k2 = { 1226 ^[[{]]1} // FIXME: why the hover range is 1 character? 1227 }; 1228 )cpp", 1229 [](HoverInfo &HI) { 1230 HI.Name = "expression"; 1231 HI.Kind = index::SymbolKind::Unknown; 1232 HI.Type = "int[10]"; 1233 HI.Value = "{1}"; 1234 }}, 1235 {// Var template decl 1236 R"cpp( 1237 using m_int = int; 1238 1239 template <int Size> m_int ^[[arr]][Size]; 1240 )cpp", 1241 [](HoverInfo &HI) { 1242 HI.Name = "arr"; 1243 HI.Kind = index::SymbolKind::Variable; 1244 HI.Type = {"m_int[Size]", "int[Size]"}; 1245 HI.NamespaceScope = ""; 1246 HI.Definition = "template <int Size> m_int arr[Size]"; 1247 HI.TemplateParameters = {{{"int"}, {"Size"}, std::nullopt}}; 1248 }}, 1249 {// Var template decl specialization 1250 R"cpp( 1251 using m_int = int; 1252 1253 template <int Size> m_int arr[Size]; 1254 1255 template <> m_int ^[[arr]]<4>[4]; 1256 )cpp", 1257 [](HoverInfo &HI) { 1258 HI.Name = "arr<4>"; 1259 HI.Kind = index::SymbolKind::Variable; 1260 HI.Type = {"m_int[4]", "int[4]"}; 1261 HI.NamespaceScope = ""; 1262 HI.Definition = "m_int arr[4]"; 1263 }}, 1264 {// Canonical type 1265 R"cpp( 1266 template<typename T> 1267 struct TestHover { 1268 using Type = T; 1269 }; 1270 1271 void code() { 1272 TestHover<int>::Type ^[[a]]; 1273 } 1274 )cpp", 1275 [](HoverInfo &HI) { 1276 HI.Name = "a"; 1277 HI.NamespaceScope = ""; 1278 HI.LocalScope = "code::"; 1279 HI.Definition = "TestHover<int>::Type a"; 1280 HI.Kind = index::SymbolKind::Variable; 1281 HI.Type = {"TestHover<int>::Type", "int"}; 1282 }}, 1283 {// Canonical template type 1284 R"cpp( 1285 template<typename T> 1286 void ^[[foo]](T arg) {} 1287 )cpp", 1288 [](HoverInfo &HI) { 1289 HI.Name = "foo"; 1290 HI.Kind = index::SymbolKind::Function; 1291 HI.NamespaceScope = ""; 1292 HI.Definition = "template <typename T> void foo(T arg)"; 1293 HI.Type = "void (T)"; 1294 HI.ReturnType = "void"; 1295 HI.Parameters = {{{"T"}, std::string("arg"), std::nullopt}}; 1296 HI.TemplateParameters = { 1297 {{"typename"}, std::string("T"), std::nullopt}}; 1298 }}, 1299 {// TypeAlias Template 1300 R"cpp( 1301 template<typename T> 1302 using ^[[alias]] = T; 1303 )cpp", 1304 [](HoverInfo &HI) { 1305 HI.Name = "alias"; 1306 HI.NamespaceScope = ""; 1307 HI.LocalScope = ""; 1308 HI.Kind = index::SymbolKind::TypeAlias; 1309 HI.Definition = "template <typename T> using alias = T"; 1310 HI.Type = "T"; 1311 HI.TemplateParameters = { 1312 {{"typename"}, std::string("T"), std::nullopt}}; 1313 }}, 1314 {// TypeAlias Template 1315 R"cpp( 1316 template<typename T> 1317 using A = T; 1318 1319 template<typename T> 1320 using ^[[AA]] = A<T>; 1321 )cpp", 1322 [](HoverInfo &HI) { 1323 HI.Name = "AA"; 1324 HI.NamespaceScope = ""; 1325 HI.LocalScope = ""; 1326 HI.Kind = index::SymbolKind::TypeAlias; 1327 HI.Definition = "template <typename T> using AA = A<T>"; 1328 HI.Type = {"A<T>", "T"}; 1329 HI.TemplateParameters = { 1330 {{"typename"}, std::string("T"), std::nullopt}}; 1331 }}, 1332 {// Constant array 1333 R"cpp( 1334 using m_int = int; 1335 1336 m_int ^[[arr]][10]; 1337 )cpp", 1338 [](HoverInfo &HI) { 1339 HI.Name = "arr"; 1340 HI.NamespaceScope = ""; 1341 HI.LocalScope = ""; 1342 HI.Kind = index::SymbolKind::Variable; 1343 HI.Definition = "m_int arr[10]"; 1344 HI.Type = {"m_int[10]", "int[10]"}; 1345 }}, 1346 {// Incomplete array 1347 R"cpp( 1348 using m_int = int; 1349 1350 extern m_int ^[[arr]][]; 1351 )cpp", 1352 [](HoverInfo &HI) { 1353 HI.Name = "arr"; 1354 HI.NamespaceScope = ""; 1355 HI.LocalScope = ""; 1356 HI.Kind = index::SymbolKind::Variable; 1357 HI.Definition = "extern m_int arr[]"; 1358 HI.Type = {"m_int[]", "int[]"}; 1359 }}, 1360 {// Dependent size array 1361 R"cpp( 1362 using m_int = int; 1363 1364 template<int Size> 1365 struct Test { 1366 m_int ^[[arr]][Size]; 1367 }; 1368 )cpp", 1369 [](HoverInfo &HI) { 1370 HI.Name = "arr"; 1371 HI.NamespaceScope = ""; 1372 HI.LocalScope = "Test<Size>::"; 1373 HI.AccessSpecifier = "public"; 1374 HI.Kind = index::SymbolKind::Field; 1375 HI.Definition = "m_int arr[Size]"; 1376 HI.Type = {"m_int[Size]", "int[Size]"}; 1377 }}, 1378 {// Bitfield offset, size and padding 1379 R"cpp( 1380 struct Foo { 1381 char x; 1382 char [[^y]] : 1; 1383 int z; 1384 }; 1385 )cpp", 1386 [](HoverInfo &HI) { 1387 HI.NamespaceScope = ""; 1388 HI.LocalScope = "Foo::"; 1389 HI.Name = "y"; 1390 HI.Kind = index::SymbolKind::Field; 1391 HI.Definition = "char y : 1"; 1392 HI.Type = "char"; 1393 HI.Offset = 8; 1394 HI.Size = 1; 1395 HI.Padding = 23; 1396 HI.Align = 8; 1397 HI.AccessSpecifier = "public"; 1398 }}}; 1399 for (const auto &Case : Cases) { 1400 SCOPED_TRACE(Case.Code); 1401 1402 Annotations T(Case.Code); 1403 TestTU TU = TestTU::withCode(T.code()); 1404 TU.ExtraArgs.push_back("-std=c++20"); 1405 // Types might be different depending on the target triplet, we chose a 1406 // fixed one to make sure tests passes on different platform. 1407 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu"); 1408 auto AST = TU.build(); 1409 Config Cfg; 1410 Cfg.Hover.ShowAKA = true; 1411 WithContextValue WithCfg(Config::Key, std::move(Cfg)); 1412 1413 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 1414 ASSERT_TRUE(H); 1415 HoverInfo Expected; 1416 Expected.SymRange = T.range(); 1417 Case.ExpectedBuilder(Expected); 1418 1419 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope); 1420 EXPECT_EQ(H->LocalScope, Expected.LocalScope); 1421 EXPECT_EQ(H->Name, Expected.Name); 1422 EXPECT_EQ(H->Kind, Expected.Kind); 1423 EXPECT_EQ(H->Documentation, Expected.Documentation); 1424 EXPECT_EQ(H->Definition, Expected.Definition); 1425 EXPECT_EQ(H->Type, Expected.Type); 1426 EXPECT_EQ(H->ReturnType, Expected.ReturnType); 1427 EXPECT_EQ(H->Parameters, Expected.Parameters); 1428 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters); 1429 EXPECT_EQ(H->SymRange, Expected.SymRange); 1430 EXPECT_EQ(H->Value, Expected.Value); 1431 EXPECT_EQ(H->Size, Expected.Size); 1432 EXPECT_EQ(H->Offset, Expected.Offset); 1433 EXPECT_EQ(H->Align, Expected.Align); 1434 EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier); 1435 EXPECT_EQ(H->CalleeArgInfo, Expected.CalleeArgInfo); 1436 EXPECT_EQ(H->CallPassType, Expected.CallPassType); 1437 } 1438 } 1439 1440 TEST(Hover, DefinitionLanuage) { 1441 struct { 1442 const char *const Code; 1443 const std::string ClangLanguageFlag; 1444 const char *const ExpectedDefinitionLanguage; 1445 } Cases[] = {{R"cpp( 1446 void [[some^Global]]() {} 1447 )cpp", 1448 "", "cpp"}, 1449 {R"cpp( 1450 void [[some^Global]]() {} 1451 )cpp", 1452 "-xobjective-c++", "objective-cpp"}, 1453 {R"cpp( 1454 void [[some^Global]]() {} 1455 )cpp", 1456 "-xobjective-c", "objective-c"}}; 1457 for (const auto &Case : Cases) { 1458 SCOPED_TRACE(Case.Code); 1459 1460 Annotations T(Case.Code); 1461 TestTU TU = TestTU::withCode(T.code()); 1462 if (!Case.ClangLanguageFlag.empty()) 1463 TU.ExtraArgs.push_back(Case.ClangLanguageFlag); 1464 auto AST = TU.build(); 1465 1466 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 1467 ASSERT_TRUE(H); 1468 1469 EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage); 1470 } 1471 } 1472 1473 TEST(Hover, CallPassType) { 1474 const llvm::StringRef CodePrefix = R"cpp( 1475 class Base {}; 1476 class Derived : public Base {}; 1477 class CustomClass { 1478 public: 1479 CustomClass() {} 1480 CustomClass(const Base &x) {} 1481 CustomClass(int &x) {} 1482 CustomClass(float x) {} 1483 CustomClass(int x, int y) {} 1484 }; 1485 1486 void int_by_ref(int &x) {} 1487 void int_by_const_ref(const int &x) {} 1488 void int_by_value(int x) {} 1489 void base_by_ref(Base &x) {} 1490 void base_by_const_ref(const Base &x) {} 1491 void base_by_value(Base x) {} 1492 void float_by_value(float x) {} 1493 void custom_by_value(CustomClass x) {} 1494 1495 void fun() { 1496 int int_x; 1497 int &int_ref = int_x; 1498 const int &int_const_ref = int_x; 1499 Base base; 1500 const Base &base_const_ref = base; 1501 Derived derived; 1502 float float_x; 1503 )cpp"; 1504 const llvm::StringRef CodeSuffix = "}"; 1505 1506 struct { 1507 const char *const Code; 1508 HoverInfo::PassType::PassMode PassBy; 1509 bool Converted; 1510 } Tests[] = { 1511 // Integer tests 1512 {"int_by_value([[^int_x]]);", PassMode::Value, false}, 1513 {"int_by_value([[^123]]);", PassMode::Value, false}, 1514 {"int_by_ref([[^int_x]]);", PassMode::Ref, false}, 1515 {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false}, 1516 {"int_by_const_ref([[^123]]);", PassMode::ConstRef, false}, 1517 {"int_by_value([[^int_ref]]);", PassMode::Value, false}, 1518 {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false}, 1519 {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false}, 1520 {"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef, false}, 1521 // Custom class tests 1522 {"base_by_ref([[^base]]);", PassMode::Ref, false}, 1523 {"base_by_const_ref([[^base]]);", PassMode::ConstRef, false}, 1524 {"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef, false}, 1525 {"base_by_value([[^base]]);", PassMode::Value, false}, 1526 {"base_by_value([[^base_const_ref]]);", PassMode::Value, false}, 1527 {"base_by_ref([[^derived]]);", PassMode::Ref, false}, 1528 {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false}, 1529 {"base_by_value([[^derived]]);", PassMode::Value, false}, 1530 // Custom class constructor tests 1531 {"CustomClass c1([[^base]]);", PassMode::ConstRef, false}, 1532 {"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef, false}, 1533 {"CustomClass c3([[^int_x]]);", PassMode::Ref, false}, 1534 {"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value, false}, 1535 // Converted tests 1536 {"float_by_value([[^int_x]]);", PassMode::Value, true}, 1537 {"float_by_value([[^int_ref]]);", PassMode::Value, true}, 1538 {"float_by_value([[^int_const_ref]]);", PassMode::Value, true}, 1539 {"float_by_value([[^123.0f]]);", PassMode::Value, false}, 1540 {"float_by_value([[^123]]);", PassMode::Value, true}, 1541 {"custom_by_value([[^int_x]]);", PassMode::Ref, true}, 1542 {"custom_by_value([[^float_x]]);", PassMode::Value, true}, 1543 {"custom_by_value([[^base]]);", PassMode::ConstRef, true}, 1544 }; 1545 for (const auto &Test : Tests) { 1546 SCOPED_TRACE(Test.Code); 1547 1548 const auto Code = (CodePrefix + Test.Code + CodeSuffix).str(); 1549 Annotations T(Code); 1550 TestTU TU = TestTU::withCode(T.code()); 1551 TU.ExtraArgs.push_back("-std=c++17"); 1552 auto AST = TU.build(); 1553 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 1554 ASSERT_TRUE(H); 1555 EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy); 1556 EXPECT_EQ(H->CallPassType->Converted, Test.Converted); 1557 } 1558 } 1559 1560 TEST(Hover, NoHover) { 1561 llvm::StringRef Tests[] = { 1562 "^int main() {}", 1563 "void foo() {^}", 1564 // FIXME: "decltype(auto)" should be a single hover 1565 "decltype(au^to) x = 0;", 1566 // FIXME: not supported yet 1567 R"cpp(// Lambda auto parameter 1568 auto lamb = [](a^uto){}; 1569 )cpp", 1570 R"cpp(// non-named decls don't get hover. Don't crash! 1571 ^static_assert(1, ""); 1572 )cpp", 1573 R"cpp(// non-evaluatable expr 1574 template <typename T> void foo() { 1575 (void)[[size^of]](T); 1576 })cpp", 1577 R"cpp(// should not crash on invalid semantic form of init-list-expr. 1578 /*error-ok*/ 1579 struct Foo { 1580 int xyz = 0; 1581 }; 1582 class Bar {}; 1583 constexpr Foo s = ^{ 1584 .xyz = Bar(), 1585 }; 1586 )cpp", 1587 // literals 1588 "auto x = t^rue;", 1589 "auto x = ^(int){42};", 1590 "auto x = ^42.;", 1591 "auto x = ^42.0i;", 1592 "auto x = ^42;", 1593 "auto x = ^nullptr;", 1594 }; 1595 1596 for (const auto &Test : Tests) { 1597 SCOPED_TRACE(Test); 1598 1599 Annotations T(Test); 1600 TestTU TU = TestTU::withCode(T.code()); 1601 TU.ExtraArgs.push_back("-std=c++17"); 1602 auto AST = TU.build(); 1603 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 1604 ASSERT_FALSE(H); 1605 } 1606 } 1607 1608 TEST(Hover, All) { 1609 struct { 1610 const char *const Code; 1611 const std::function<void(HoverInfo &)> ExpectedBuilder; 1612 } Cases[] = { 1613 {"auto x = [['^A']]; // character literal", 1614 [](HoverInfo &HI) { 1615 HI.Name = "expression"; 1616 HI.Type = "char"; 1617 HI.Value = "65 (0x41)"; 1618 }}, 1619 {"auto s = ^[[\"Hello, world!\"]]; // string literal", 1620 [](HoverInfo &HI) { 1621 HI.Name = "string-literal"; 1622 HI.Size = 112; 1623 HI.Type = "const char[14]"; 1624 }}, 1625 { 1626 R"cpp(// Local variable 1627 int main() { 1628 int bonjour; 1629 ^[[bonjour]] = 2; 1630 int test1 = bonjour; 1631 } 1632 )cpp", 1633 [](HoverInfo &HI) { 1634 HI.Name = "bonjour"; 1635 HI.Kind = index::SymbolKind::Variable; 1636 HI.NamespaceScope = ""; 1637 HI.LocalScope = "main::"; 1638 HI.Type = "int"; 1639 HI.Definition = "int bonjour"; 1640 }}, 1641 { 1642 R"cpp(// Local variable in method 1643 struct s { 1644 void method() { 1645 int bonjour; 1646 ^[[bonjour]] = 2; 1647 } 1648 }; 1649 )cpp", 1650 [](HoverInfo &HI) { 1651 HI.Name = "bonjour"; 1652 HI.Kind = index::SymbolKind::Variable; 1653 HI.NamespaceScope = ""; 1654 HI.LocalScope = "s::method::"; 1655 HI.Type = "int"; 1656 HI.Definition = "int bonjour"; 1657 }}, 1658 { 1659 R"cpp(// Struct 1660 namespace ns1 { 1661 struct MyClass {}; 1662 } // namespace ns1 1663 int main() { 1664 ns1::[[My^Class]]* Params; 1665 } 1666 )cpp", 1667 [](HoverInfo &HI) { 1668 HI.Name = "MyClass"; 1669 HI.Kind = index::SymbolKind::Struct; 1670 HI.NamespaceScope = "ns1::"; 1671 HI.Definition = "struct MyClass {}"; 1672 }}, 1673 { 1674 R"cpp(// Class 1675 namespace ns1 { 1676 class MyClass {}; 1677 } // namespace ns1 1678 int main() { 1679 ns1::[[My^Class]]* Params; 1680 } 1681 )cpp", 1682 [](HoverInfo &HI) { 1683 HI.Name = "MyClass"; 1684 HI.Kind = index::SymbolKind::Class; 1685 HI.NamespaceScope = "ns1::"; 1686 HI.Definition = "class MyClass {}"; 1687 }}, 1688 { 1689 R"cpp(// Union 1690 namespace ns1 { 1691 union MyUnion { int x; int y; }; 1692 } // namespace ns1 1693 int main() { 1694 ns1::[[My^Union]] Params; 1695 } 1696 )cpp", 1697 [](HoverInfo &HI) { 1698 HI.Name = "MyUnion"; 1699 HI.Kind = index::SymbolKind::Union; 1700 HI.NamespaceScope = "ns1::"; 1701 HI.Definition = "union MyUnion {}"; 1702 }}, 1703 { 1704 R"cpp(// Function definition via pointer 1705 void foo(int) {} 1706 int main() { 1707 auto *X = &^[[foo]]; 1708 } 1709 )cpp", 1710 [](HoverInfo &HI) { 1711 HI.Name = "foo"; 1712 HI.Kind = index::SymbolKind::Function; 1713 HI.NamespaceScope = ""; 1714 HI.Type = "void (int)"; 1715 HI.Definition = "void foo(int)"; 1716 HI.Documentation = "Function definition via pointer"; 1717 HI.ReturnType = "void"; 1718 HI.Parameters = { 1719 {{"int"}, std::nullopt, std::nullopt}, 1720 }; 1721 }}, 1722 { 1723 R"cpp(// Function declaration via call 1724 int foo(int); 1725 int main() { 1726 return ^[[foo]](42); 1727 } 1728 )cpp", 1729 [](HoverInfo &HI) { 1730 HI.Name = "foo"; 1731 HI.Kind = index::SymbolKind::Function; 1732 HI.NamespaceScope = ""; 1733 HI.Type = "int (int)"; 1734 HI.Definition = "int foo(int)"; 1735 HI.Documentation = "Function declaration via call"; 1736 HI.ReturnType = "int"; 1737 HI.Parameters = { 1738 {{"int"}, std::nullopt, std::nullopt}, 1739 }; 1740 }}, 1741 { 1742 R"cpp(// Field 1743 struct Foo { int x; }; 1744 int main() { 1745 Foo bar; 1746 (void)bar.^[[x]]; 1747 } 1748 )cpp", 1749 [](HoverInfo &HI) { 1750 HI.Name = "x"; 1751 HI.Kind = index::SymbolKind::Field; 1752 HI.NamespaceScope = ""; 1753 HI.LocalScope = "Foo::"; 1754 HI.Type = "int"; 1755 HI.Definition = "int x"; 1756 }}, 1757 { 1758 R"cpp(// Field with initialization 1759 struct Foo { int x = 5; }; 1760 int main() { 1761 Foo bar; 1762 (void)bar.^[[x]]; 1763 } 1764 )cpp", 1765 [](HoverInfo &HI) { 1766 HI.Name = "x"; 1767 HI.Kind = index::SymbolKind::Field; 1768 HI.NamespaceScope = ""; 1769 HI.LocalScope = "Foo::"; 1770 HI.Type = "int"; 1771 HI.Definition = "int x = 5"; 1772 }}, 1773 { 1774 R"cpp(// Static field 1775 struct Foo { static int x; }; 1776 int main() { 1777 (void)Foo::^[[x]]; 1778 } 1779 )cpp", 1780 [](HoverInfo &HI) { 1781 HI.Name = "x"; 1782 HI.Kind = index::SymbolKind::StaticProperty; 1783 HI.NamespaceScope = ""; 1784 HI.LocalScope = "Foo::"; 1785 HI.Type = "int"; 1786 HI.Definition = "static int x"; 1787 }}, 1788 { 1789 R"cpp(// Field, member initializer 1790 struct Foo { 1791 int x; 1792 Foo() : ^[[x]](0) {} 1793 }; 1794 )cpp", 1795 [](HoverInfo &HI) { 1796 HI.Name = "x"; 1797 HI.Kind = index::SymbolKind::Field; 1798 HI.NamespaceScope = ""; 1799 HI.LocalScope = "Foo::"; 1800 HI.Type = "int"; 1801 HI.Definition = "int x"; 1802 }}, 1803 { 1804 R"cpp(// Field, GNU old-style field designator 1805 struct Foo { int x; }; 1806 int main() { 1807 Foo bar = { ^[[x]] : 1 }; 1808 } 1809 )cpp", 1810 [](HoverInfo &HI) { 1811 HI.Name = "x"; 1812 HI.Kind = index::SymbolKind::Field; 1813 HI.NamespaceScope = ""; 1814 HI.LocalScope = "Foo::"; 1815 HI.Type = "int"; 1816 HI.Definition = "int x"; 1817 // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is 1818 // of struct type and omitted. 1819 }}, 1820 { 1821 R"cpp(// Field, field designator 1822 struct Foo { int x; int y; }; 1823 int main() { 1824 Foo bar = { .^[[x]] = 2, .y = 2 }; 1825 } 1826 )cpp", 1827 [](HoverInfo &HI) { 1828 HI.Name = "x"; 1829 HI.Kind = index::SymbolKind::Field; 1830 HI.NamespaceScope = ""; 1831 HI.LocalScope = "Foo::"; 1832 HI.Type = "int"; 1833 HI.Definition = "int x"; 1834 }}, 1835 { 1836 R"cpp(// Method call 1837 struct Foo { int x(); }; 1838 int main() { 1839 Foo bar; 1840 bar.^[[x]](); 1841 } 1842 )cpp", 1843 [](HoverInfo &HI) { 1844 HI.Name = "x"; 1845 HI.Kind = index::SymbolKind::InstanceMethod; 1846 HI.NamespaceScope = ""; 1847 HI.LocalScope = "Foo::"; 1848 HI.Type = "int ()"; 1849 HI.Definition = "int x()"; 1850 HI.ReturnType = "int"; 1851 HI.Parameters = std::vector<HoverInfo::Param>{}; 1852 }}, 1853 { 1854 R"cpp(// Static method call 1855 struct Foo { static int x(); }; 1856 int main() { 1857 Foo::^[[x]](); 1858 } 1859 )cpp", 1860 [](HoverInfo &HI) { 1861 HI.Name = "x"; 1862 HI.Kind = index::SymbolKind::StaticMethod; 1863 HI.NamespaceScope = ""; 1864 HI.LocalScope = "Foo::"; 1865 HI.Type = "int ()"; 1866 HI.Definition = "static int x()"; 1867 HI.ReturnType = "int"; 1868 HI.Parameters = std::vector<HoverInfo::Param>{}; 1869 }}, 1870 { 1871 R"cpp(// Typedef 1872 typedef int Foo; 1873 int main() { 1874 ^[[Foo]] bar; 1875 } 1876 )cpp", 1877 [](HoverInfo &HI) { 1878 HI.Name = "Foo"; 1879 HI.Kind = index::SymbolKind::TypeAlias; 1880 HI.NamespaceScope = ""; 1881 HI.Definition = "typedef int Foo"; 1882 HI.Type = "int"; 1883 HI.Documentation = "Typedef"; 1884 }}, 1885 { 1886 R"cpp(// Typedef with embedded definition 1887 typedef struct Bar {} Foo; 1888 int main() { 1889 ^[[Foo]] bar; 1890 } 1891 )cpp", 1892 [](HoverInfo &HI) { 1893 HI.Name = "Foo"; 1894 HI.Kind = index::SymbolKind::TypeAlias; 1895 HI.NamespaceScope = ""; 1896 HI.Definition = "typedef struct Bar Foo"; 1897 HI.Type = "struct Bar"; 1898 HI.Documentation = "Typedef with embedded definition"; 1899 }}, 1900 { 1901 R"cpp(// Namespace 1902 namespace ns { 1903 struct Foo { static void bar(); }; 1904 } // namespace ns 1905 int main() { ^[[ns]]::Foo::bar(); } 1906 )cpp", 1907 [](HoverInfo &HI) { 1908 HI.Name = "ns"; 1909 HI.Kind = index::SymbolKind::Namespace; 1910 HI.NamespaceScope = ""; 1911 HI.Definition = "namespace ns {}"; 1912 }}, 1913 { 1914 R"cpp(// Anonymous namespace 1915 namespace ns { 1916 namespace { 1917 int foo; 1918 } // anonymous namespace 1919 } // namespace ns 1920 int main() { ns::[[f^oo]]++; } 1921 )cpp", 1922 [](HoverInfo &HI) { 1923 HI.Name = "foo"; 1924 HI.Kind = index::SymbolKind::Variable; 1925 HI.NamespaceScope = "ns::"; 1926 HI.Type = "int"; 1927 HI.Definition = "int foo"; 1928 }}, 1929 { 1930 R"cpp(// Function definition via using declaration 1931 namespace ns { 1932 void foo(); 1933 } 1934 int main() { 1935 using ns::foo; 1936 ^[[foo]](); 1937 } 1938 )cpp", 1939 [](HoverInfo &HI) { 1940 HI.Name = "foo"; 1941 HI.Kind = index::SymbolKind::Function; 1942 HI.NamespaceScope = "ns::"; 1943 HI.Type = "void ()"; 1944 HI.Definition = "void foo()"; 1945 HI.Documentation = ""; 1946 HI.ReturnType = "void"; 1947 HI.Parameters = std::vector<HoverInfo::Param>{}; 1948 }}, 1949 { 1950 R"cpp( // using declaration and two possible function declarations 1951 namespace ns { void foo(int); void foo(char); } 1952 using ns::foo; 1953 template <typename T> void bar() { [[f^oo]](T{}); } 1954 )cpp", 1955 [](HoverInfo &HI) { 1956 HI.Name = "foo"; 1957 HI.Kind = index::SymbolKind::Using; 1958 HI.NamespaceScope = ""; 1959 HI.Definition = "using ns::foo"; 1960 }}, 1961 { 1962 R"cpp(// Macro 1963 #define MACRO 0 1964 int main() { return ^[[MACRO]]; } 1965 )cpp", 1966 [](HoverInfo &HI) { 1967 HI.Name = "MACRO"; 1968 HI.Value = "0"; 1969 HI.Type = "int"; 1970 HI.Kind = index::SymbolKind::Macro; 1971 HI.Definition = "#define MACRO 0\n\n" 1972 "// Expands to\n" 1973 "0"; 1974 }}, 1975 { 1976 R"cpp(// Macro 1977 #define MACRO 0 1978 #define MACRO2 ^[[MACRO]] 1979 )cpp", 1980 [](HoverInfo &HI) { 1981 HI.Name = "MACRO"; 1982 HI.Kind = index::SymbolKind::Macro; 1983 HI.Definition = "#define MACRO 0"; 1984 // NOTE MACRO doesn't have expansion since it technically isn't 1985 // expanded here 1986 }}, 1987 { 1988 R"cpp(// Macro 1989 #define MACRO {\ 1990 return 0;\ 1991 } 1992 int main() ^[[MACRO]] 1993 )cpp", 1994 [](HoverInfo &HI) { 1995 HI.Name = "MACRO"; 1996 HI.Kind = index::SymbolKind::Macro; 1997 HI.Definition = 1998 R"cpp(#define MACRO \ 1999 { \ 2000 return 0; \ 2001 } 2002 2003 // Expands to 2004 { 2005 return 0; 2006 })cpp"; 2007 }}, 2008 { 2009 R"cpp(// Forward class declaration 2010 class Foo; 2011 class Foo {}; 2012 [[F^oo]]* foo(); 2013 )cpp", 2014 [](HoverInfo &HI) { 2015 HI.Name = "Foo"; 2016 HI.Kind = index::SymbolKind::Class; 2017 HI.NamespaceScope = ""; 2018 HI.Definition = "class Foo {}"; 2019 HI.Documentation = "Forward class declaration"; 2020 }}, 2021 { 2022 R"cpp(// Function declaration 2023 void foo(); 2024 void g() { [[f^oo]](); } 2025 void foo() {} 2026 )cpp", 2027 [](HoverInfo &HI) { 2028 HI.Name = "foo"; 2029 HI.Kind = index::SymbolKind::Function; 2030 HI.NamespaceScope = ""; 2031 HI.Type = "void ()"; 2032 HI.Definition = "void foo()"; 2033 HI.Documentation = "Function declaration"; 2034 HI.ReturnType = "void"; 2035 HI.Parameters = std::vector<HoverInfo::Param>{}; 2036 }}, 2037 { 2038 R"cpp(// Enum declaration 2039 enum Hello { 2040 ONE, TWO, THREE, 2041 }; 2042 void foo() { 2043 [[Hel^lo]] hello = ONE; 2044 } 2045 )cpp", 2046 [](HoverInfo &HI) { 2047 HI.Name = "Hello"; 2048 HI.Kind = index::SymbolKind::Enum; 2049 HI.NamespaceScope = ""; 2050 HI.Definition = "enum Hello {}"; 2051 HI.Documentation = "Enum declaration"; 2052 }}, 2053 { 2054 R"cpp(// Enumerator 2055 enum Hello { 2056 ONE, TWO, THREE, 2057 }; 2058 void foo() { 2059 Hello hello = [[O^NE]]; 2060 } 2061 )cpp", 2062 [](HoverInfo &HI) { 2063 HI.Name = "ONE"; 2064 HI.Kind = index::SymbolKind::EnumConstant; 2065 HI.NamespaceScope = ""; 2066 HI.LocalScope = "Hello::"; 2067 HI.Type = "enum Hello"; 2068 HI.Definition = "ONE"; 2069 HI.Value = "0"; 2070 }}, 2071 { 2072 R"cpp(// C++20's using enum 2073 enum class Hello { 2074 ONE, TWO, THREE, 2075 }; 2076 void foo() { 2077 using enum Hello; 2078 Hello hello = [[O^NE]]; 2079 } 2080 )cpp", 2081 [](HoverInfo &HI) { 2082 HI.Name = "ONE"; 2083 HI.Kind = index::SymbolKind::EnumConstant; 2084 HI.NamespaceScope = ""; 2085 HI.LocalScope = "Hello::"; 2086 HI.Type = "enum Hello"; 2087 HI.Definition = "ONE"; 2088 HI.Value = "0"; 2089 }}, 2090 { 2091 R"cpp(// Enumerator in anonymous enum 2092 enum { 2093 ONE, TWO, THREE, 2094 }; 2095 void foo() { 2096 int hello = [[O^NE]]; 2097 } 2098 )cpp", 2099 [](HoverInfo &HI) { 2100 HI.Name = "ONE"; 2101 HI.Kind = index::SymbolKind::EnumConstant; 2102 HI.NamespaceScope = ""; 2103 // FIXME: This should be `(anon enum)::` 2104 HI.LocalScope = ""; 2105 HI.Type = "enum (unnamed)"; 2106 HI.Definition = "ONE"; 2107 HI.Value = "0"; 2108 }}, 2109 { 2110 R"cpp(// Global variable 2111 static int hey = 10; 2112 void foo() { 2113 [[he^y]]++; 2114 } 2115 )cpp", 2116 [](HoverInfo &HI) { 2117 HI.Name = "hey"; 2118 HI.Kind = index::SymbolKind::Variable; 2119 HI.NamespaceScope = ""; 2120 HI.Type = "int"; 2121 HI.Definition = "static int hey = 10"; 2122 HI.Documentation = "Global variable"; 2123 // FIXME: Value shouldn't be set in this case 2124 HI.Value = "10 (0xa)"; 2125 }}, 2126 { 2127 R"cpp(// Global variable in namespace 2128 namespace ns1 { 2129 static long long hey = -36637162602497; 2130 } 2131 void foo() { 2132 ns1::[[he^y]]++; 2133 } 2134 )cpp", 2135 [](HoverInfo &HI) { 2136 HI.Name = "hey"; 2137 HI.Kind = index::SymbolKind::Variable; 2138 HI.NamespaceScope = "ns1::"; 2139 HI.Type = "long long"; 2140 HI.Definition = "static long long hey = -36637162602497"; 2141 HI.Value = "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits 2142 }}, 2143 { 2144 R"cpp(// Field in anonymous struct 2145 static struct { 2146 int hello; 2147 } s; 2148 void foo() { 2149 s.[[he^llo]]++; 2150 } 2151 )cpp", 2152 [](HoverInfo &HI) { 2153 HI.Name = "hello"; 2154 HI.Kind = index::SymbolKind::Field; 2155 HI.NamespaceScope = ""; 2156 HI.LocalScope = "(anonymous struct)::"; 2157 HI.Type = "int"; 2158 HI.Definition = "int hello"; 2159 }}, 2160 { 2161 R"cpp(// Templated function 2162 template <typename T> 2163 T foo() { 2164 return 17; 2165 } 2166 void g() { auto x = [[f^oo]]<int>(); } 2167 )cpp", 2168 [](HoverInfo &HI) { 2169 HI.Name = "foo"; 2170 HI.Kind = index::SymbolKind::Function; 2171 HI.NamespaceScope = ""; 2172 HI.Type = "int ()"; 2173 HI.Definition = "template <> int foo<int>()"; 2174 HI.Documentation = "Templated function"; 2175 HI.ReturnType = "int"; 2176 HI.Parameters = std::vector<HoverInfo::Param>{}; 2177 // FIXME: We should populate template parameters with arguments in 2178 // case of instantiations. 2179 }}, 2180 { 2181 R"cpp(// Anonymous union 2182 struct outer { 2183 union { 2184 int abc, def; 2185 } v; 2186 }; 2187 void g() { struct outer o; o.v.[[d^ef]]++; } 2188 )cpp", 2189 [](HoverInfo &HI) { 2190 HI.Name = "def"; 2191 HI.Kind = index::SymbolKind::Field; 2192 HI.NamespaceScope = ""; 2193 HI.LocalScope = "outer::(anonymous union)::"; 2194 HI.Type = "int"; 2195 HI.Definition = "int def"; 2196 }}, 2197 { 2198 R"cpp(// documentation from index 2199 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs; 2200 void indexSymbol(); 2201 void g() { [[ind^exSymbol]](); } 2202 )cpp", 2203 [](HoverInfo &HI) { 2204 HI.Name = "indexSymbol"; 2205 HI.Kind = index::SymbolKind::Function; 2206 HI.NamespaceScope = ""; 2207 HI.Type = "void ()"; 2208 HI.Definition = "void indexSymbol()"; 2209 HI.ReturnType = "void"; 2210 HI.Parameters = std::vector<HoverInfo::Param>{}; 2211 HI.Documentation = "comment from index"; 2212 }}, 2213 { 2214 R"cpp(// Simple initialization with auto 2215 void foo() { 2216 ^[[auto]] i = 1; 2217 } 2218 )cpp", 2219 [](HoverInfo &HI) { 2220 HI.Name = "auto"; 2221 HI.Kind = index::SymbolKind::TypeAlias; 2222 HI.Definition = "int"; 2223 }}, 2224 { 2225 R"cpp(// Simple initialization with const auto 2226 void foo() { 2227 const ^[[auto]] i = 1; 2228 } 2229 )cpp", 2230 [](HoverInfo &HI) { 2231 HI.Name = "auto"; 2232 HI.Kind = index::SymbolKind::TypeAlias; 2233 HI.Definition = "int"; 2234 }}, 2235 { 2236 R"cpp(// Simple initialization with const auto& 2237 void foo() { 2238 const ^[[auto]]& i = 1; 2239 } 2240 )cpp", 2241 [](HoverInfo &HI) { 2242 HI.Name = "auto"; 2243 HI.Kind = index::SymbolKind::TypeAlias; 2244 HI.Definition = "int"; 2245 }}, 2246 { 2247 R"cpp(// Simple initialization with auto& 2248 void foo() { 2249 int x; 2250 ^[[auto]]& i = x; 2251 } 2252 )cpp", 2253 [](HoverInfo &HI) { 2254 HI.Name = "auto"; 2255 HI.Kind = index::SymbolKind::TypeAlias; 2256 HI.Definition = "int"; 2257 }}, 2258 { 2259 R"cpp(// Simple initialization with auto* 2260 void foo() { 2261 int a = 1; 2262 ^[[auto]]* i = &a; 2263 } 2264 )cpp", 2265 [](HoverInfo &HI) { 2266 HI.Name = "auto"; 2267 HI.Kind = index::SymbolKind::TypeAlias; 2268 HI.Definition = "int"; 2269 }}, 2270 { 2271 R"cpp(// Simple initialization with auto from pointer 2272 void foo() { 2273 int a = 1; 2274 ^[[auto]] i = &a; 2275 } 2276 )cpp", 2277 [](HoverInfo &HI) { 2278 HI.Name = "auto"; 2279 HI.Kind = index::SymbolKind::TypeAlias; 2280 HI.Definition = "int *"; 2281 }}, 2282 { 2283 R"cpp(// Auto with initializer list. 2284 namespace std 2285 { 2286 template<class _E> 2287 class initializer_list { const _E *a, *b; }; 2288 } 2289 void foo() { 2290 ^[[auto]] i = {1,2}; 2291 } 2292 )cpp", 2293 [](HoverInfo &HI) { 2294 HI.Name = "auto"; 2295 HI.Kind = index::SymbolKind::TypeAlias; 2296 HI.Definition = "std::initializer_list<int>"; 2297 }}, 2298 { 2299 R"cpp(// User defined conversion to auto 2300 struct Bar { 2301 operator ^[[auto]]() const { return 10; } 2302 }; 2303 )cpp", 2304 [](HoverInfo &HI) { 2305 HI.Name = "auto"; 2306 HI.Kind = index::SymbolKind::TypeAlias; 2307 HI.Definition = "int"; 2308 }}, 2309 { 2310 R"cpp(// Simple initialization with decltype(auto) 2311 void foo() { 2312 ^[[decltype]](auto) i = 1; 2313 } 2314 )cpp", 2315 [](HoverInfo &HI) { 2316 HI.Name = "decltype"; 2317 HI.Kind = index::SymbolKind::TypeAlias; 2318 HI.Definition = "int"; 2319 }}, 2320 { 2321 R"cpp(// Simple initialization with const decltype(auto) 2322 void foo() { 2323 const int j = 0; 2324 ^[[decltype]](auto) i = j; 2325 } 2326 )cpp", 2327 [](HoverInfo &HI) { 2328 HI.Name = "decltype"; 2329 HI.Kind = index::SymbolKind::TypeAlias; 2330 HI.Definition = "const int"; 2331 }}, 2332 { 2333 R"cpp(// Simple initialization with const& decltype(auto) 2334 void foo() { 2335 int k = 0; 2336 const int& j = k; 2337 ^[[decltype]](auto) i = j; 2338 } 2339 )cpp", 2340 [](HoverInfo &HI) { 2341 HI.Name = "decltype"; 2342 HI.Kind = index::SymbolKind::TypeAlias; 2343 HI.Definition = "const int &"; 2344 }}, 2345 { 2346 R"cpp(// Simple initialization with & decltype(auto) 2347 void foo() { 2348 int k = 0; 2349 int& j = k; 2350 ^[[decltype]](auto) i = j; 2351 } 2352 )cpp", 2353 [](HoverInfo &HI) { 2354 HI.Name = "decltype"; 2355 HI.Kind = index::SymbolKind::TypeAlias; 2356 HI.Definition = "int &"; 2357 }}, 2358 { 2359 R"cpp(// simple trailing return type 2360 ^[[auto]] main() -> int { 2361 return 0; 2362 } 2363 )cpp", 2364 [](HoverInfo &HI) { 2365 HI.Name = "auto"; 2366 HI.Kind = index::SymbolKind::TypeAlias; 2367 HI.Definition = "int"; 2368 }}, 2369 { 2370 R"cpp(// auto function return with trailing type 2371 struct Bar {}; 2372 ^[[auto]] test() -> decltype(Bar()) { 2373 return Bar(); 2374 } 2375 )cpp", 2376 [](HoverInfo &HI) { 2377 HI.Name = "auto"; 2378 HI.Kind = index::SymbolKind::TypeAlias; 2379 HI.Definition = "Bar"; 2380 HI.Documentation = "auto function return with trailing type"; 2381 }}, 2382 { 2383 R"cpp(// trailing return type 2384 struct Bar {}; 2385 auto test() -> ^[[decltype]](Bar()) { 2386 return Bar(); 2387 } 2388 )cpp", 2389 [](HoverInfo &HI) { 2390 HI.Name = "decltype"; 2391 HI.Kind = index::SymbolKind::TypeAlias; 2392 HI.Definition = "Bar"; 2393 HI.Documentation = "trailing return type"; 2394 }}, 2395 { 2396 R"cpp(// auto in function return 2397 struct Bar {}; 2398 ^[[auto]] test() { 2399 return Bar(); 2400 } 2401 )cpp", 2402 [](HoverInfo &HI) { 2403 HI.Name = "auto"; 2404 HI.Kind = index::SymbolKind::TypeAlias; 2405 HI.Definition = "Bar"; 2406 HI.Documentation = "auto in function return"; 2407 }}, 2408 { 2409 R"cpp(// auto& in function return 2410 struct Bar {}; 2411 ^[[auto]]& test() { 2412 static Bar x; 2413 return x; 2414 } 2415 )cpp", 2416 [](HoverInfo &HI) { 2417 HI.Name = "auto"; 2418 HI.Kind = index::SymbolKind::TypeAlias; 2419 HI.Definition = "Bar"; 2420 HI.Documentation = "auto& in function return"; 2421 }}, 2422 { 2423 R"cpp(// auto* in function return 2424 struct Bar {}; 2425 ^[[auto]]* test() { 2426 Bar* bar; 2427 return bar; 2428 } 2429 )cpp", 2430 [](HoverInfo &HI) { 2431 HI.Name = "auto"; 2432 HI.Kind = index::SymbolKind::TypeAlias; 2433 HI.Definition = "Bar"; 2434 HI.Documentation = "auto* in function return"; 2435 }}, 2436 { 2437 R"cpp(// const auto& in function return 2438 struct Bar {}; 2439 const ^[[auto]]& test() { 2440 static Bar x; 2441 return x; 2442 } 2443 )cpp", 2444 [](HoverInfo &HI) { 2445 HI.Name = "auto"; 2446 HI.Kind = index::SymbolKind::TypeAlias; 2447 HI.Definition = "Bar"; 2448 HI.Documentation = "const auto& in function return"; 2449 }}, 2450 { 2451 R"cpp(// decltype(auto) in function return 2452 struct Bar {}; 2453 ^[[decltype]](auto) test() { 2454 return Bar(); 2455 } 2456 )cpp", 2457 [](HoverInfo &HI) { 2458 HI.Name = "decltype"; 2459 HI.Kind = index::SymbolKind::TypeAlias; 2460 HI.Definition = "Bar"; 2461 HI.Documentation = "decltype(auto) in function return"; 2462 }}, 2463 { 2464 R"cpp(// decltype(auto) reference in function return 2465 ^[[decltype]](auto) test() { 2466 static int a; 2467 return (a); 2468 } 2469 )cpp", 2470 [](HoverInfo &HI) { 2471 HI.Name = "decltype"; 2472 HI.Kind = index::SymbolKind::TypeAlias; 2473 HI.Definition = "int &"; 2474 }}, 2475 { 2476 R"cpp(// decltype lvalue reference 2477 void foo() { 2478 int I = 0; 2479 ^[[decltype]](I) J = I; 2480 } 2481 )cpp", 2482 [](HoverInfo &HI) { 2483 HI.Name = "decltype"; 2484 HI.Kind = index::SymbolKind::TypeAlias; 2485 HI.Definition = "int"; 2486 }}, 2487 { 2488 R"cpp(// decltype lvalue reference 2489 void foo() { 2490 int I= 0; 2491 int &K = I; 2492 ^[[decltype]](K) J = I; 2493 } 2494 )cpp", 2495 [](HoverInfo &HI) { 2496 HI.Name = "decltype"; 2497 HI.Kind = index::SymbolKind::TypeAlias; 2498 HI.Definition = "int &"; 2499 }}, 2500 { 2501 R"cpp(// decltype lvalue reference parenthesis 2502 void foo() { 2503 int I = 0; 2504 ^[[decltype]]((I)) J = I; 2505 } 2506 )cpp", 2507 [](HoverInfo &HI) { 2508 HI.Name = "decltype"; 2509 HI.Kind = index::SymbolKind::TypeAlias; 2510 HI.Definition = "int &"; 2511 }}, 2512 { 2513 R"cpp(// decltype rvalue reference 2514 void foo() { 2515 int I = 0; 2516 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I); 2517 } 2518 )cpp", 2519 [](HoverInfo &HI) { 2520 HI.Name = "decltype"; 2521 HI.Kind = index::SymbolKind::TypeAlias; 2522 HI.Definition = "int &&"; 2523 }}, 2524 { 2525 R"cpp(// decltype rvalue reference function call 2526 int && bar(); 2527 void foo() { 2528 int I = 0; 2529 ^[[decltype]](bar()) J = bar(); 2530 } 2531 )cpp", 2532 [](HoverInfo &HI) { 2533 HI.Name = "decltype"; 2534 HI.Kind = index::SymbolKind::TypeAlias; 2535 HI.Definition = "int &&"; 2536 }}, 2537 { 2538 R"cpp(// decltype of function with trailing return type. 2539 struct Bar {}; 2540 auto test() -> decltype(Bar()) { 2541 return Bar(); 2542 } 2543 void foo() { 2544 ^[[decltype]](test()) i = test(); 2545 } 2546 )cpp", 2547 [](HoverInfo &HI) { 2548 HI.Name = "decltype"; 2549 HI.Kind = index::SymbolKind::TypeAlias; 2550 HI.Definition = "Bar"; 2551 HI.Documentation = 2552 "decltype of function with trailing return type."; 2553 }}, 2554 { 2555 R"cpp(// decltype of var with decltype. 2556 void foo() { 2557 int I = 0; 2558 decltype(I) J = I; 2559 ^[[decltype]](J) K = J; 2560 } 2561 )cpp", 2562 [](HoverInfo &HI) { 2563 HI.Name = "decltype"; 2564 HI.Kind = index::SymbolKind::TypeAlias; 2565 HI.Definition = "int"; 2566 }}, 2567 { 2568 R"cpp(// decltype of dependent type 2569 template <typename T> 2570 struct X { 2571 using Y = ^[[decltype]](T::Z); 2572 }; 2573 )cpp", 2574 [](HoverInfo &HI) { 2575 HI.Name = "decltype"; 2576 HI.Kind = index::SymbolKind::TypeAlias; 2577 HI.Definition = "<dependent type>"; 2578 }}, 2579 { 2580 R"cpp(// More complicated structured types. 2581 int bar(); 2582 ^[[auto]] (*foo)() = bar; 2583 )cpp", 2584 [](HoverInfo &HI) { 2585 HI.Name = "auto"; 2586 HI.Kind = index::SymbolKind::TypeAlias; 2587 HI.Definition = "int"; 2588 }}, 2589 { 2590 R"cpp(// Should not crash when evaluating the initializer. 2591 struct Test {}; 2592 void test() { Test && [[te^st]] = {}; } 2593 )cpp", 2594 [](HoverInfo &HI) { 2595 HI.Name = "test"; 2596 HI.Kind = index::SymbolKind::Variable; 2597 HI.NamespaceScope = ""; 2598 HI.LocalScope = "test::"; 2599 HI.Type = "Test &&"; 2600 HI.Definition = "Test &&test = {}"; 2601 }}, 2602 { 2603 R"cpp(// Shouldn't crash when evaluating the initializer. 2604 struct Bar {}; // error-ok 2605 struct Foo { void foo(Bar x = y); } 2606 void Foo::foo(Bar [[^x]]) {})cpp", 2607 [](HoverInfo &HI) { 2608 HI.Name = "x"; 2609 HI.Kind = index::SymbolKind::Parameter; 2610 HI.NamespaceScope = ""; 2611 HI.LocalScope = "Foo::foo::"; 2612 HI.Type = "Bar"; 2613 HI.Definition = "Bar x = <recovery - expr>()"; 2614 }}, 2615 { 2616 R"cpp(// auto on alias 2617 typedef int int_type; 2618 ^[[auto]] x = int_type(); 2619 )cpp", 2620 [](HoverInfo &HI) { 2621 HI.Name = "auto"; 2622 HI.Kind = index::SymbolKind::TypeAlias; 2623 HI.Definition = "int_type // aka: int"; 2624 }}, 2625 { 2626 R"cpp(// auto on alias 2627 struct cls {}; 2628 typedef cls cls_type; 2629 ^[[auto]] y = cls_type(); 2630 )cpp", 2631 [](HoverInfo &HI) { 2632 HI.Name = "auto"; 2633 HI.Kind = index::SymbolKind::TypeAlias; 2634 HI.Definition = "cls_type // aka: cls"; 2635 HI.Documentation = "auto on alias"; 2636 }}, 2637 { 2638 R"cpp(// auto on alias 2639 template <class> 2640 struct templ {}; 2641 ^[[auto]] z = templ<int>(); 2642 )cpp", 2643 [](HoverInfo &HI) { 2644 HI.Name = "auto"; 2645 HI.Kind = index::SymbolKind::TypeAlias; 2646 HI.Definition = "templ<int>"; 2647 HI.Documentation = "auto on alias"; 2648 }}, 2649 { 2650 R"cpp(// Undeduced auto declaration 2651 template<typename T> 2652 void foo() { 2653 ^[[auto]] x = T(); 2654 } 2655 )cpp", 2656 [](HoverInfo &HI) { 2657 HI.Name = "auto"; 2658 HI.Kind = index::SymbolKind::TypeAlias; 2659 HI.Definition = "/* not deduced */"; 2660 }}, 2661 { 2662 R"cpp(// Undeduced auto return type 2663 template<typename T> 2664 ^[[auto]] foo() { 2665 return T(); 2666 } 2667 )cpp", 2668 [](HoverInfo &HI) { 2669 HI.Name = "auto"; 2670 HI.Kind = index::SymbolKind::TypeAlias; 2671 HI.Definition = "/* not deduced */"; 2672 }}, 2673 { 2674 R"cpp(// Template auto parameter 2675 template<[[a^uto]] T> 2676 void func() { 2677 } 2678 )cpp", 2679 [](HoverInfo &HI) { 2680 // FIXME: not sure this is what we want, but this 2681 // is what we currently get with getDeducedType 2682 HI.Name = "auto"; 2683 HI.Kind = index::SymbolKind::TypeAlias; 2684 HI.Definition = "/* not deduced */"; 2685 }}, 2686 { 2687 R"cpp(// Undeduced decltype(auto) return type 2688 template<typename T> 2689 ^[[decltype]](auto) foo() { 2690 return T(); 2691 } 2692 )cpp", 2693 [](HoverInfo &HI) { 2694 HI.Name = "decltype"; 2695 HI.Kind = index::SymbolKind::TypeAlias; 2696 HI.Definition = "/* not deduced */"; 2697 }}, 2698 { 2699 R"cpp(// should not crash. 2700 template <class T> struct cls { 2701 int method(); 2702 }; 2703 2704 auto test = cls<int>().[[m^ethod]](); 2705 )cpp", 2706 [](HoverInfo &HI) { 2707 HI.Definition = "int method()"; 2708 HI.Kind = index::SymbolKind::InstanceMethod; 2709 HI.NamespaceScope = ""; 2710 HI.LocalScope = "cls<int>::"; 2711 HI.Name = "method"; 2712 HI.Parameters.emplace(); 2713 HI.ReturnType = "int"; 2714 HI.Type = "int ()"; 2715 }}, 2716 { 2717 R"cpp(// type of nested templates. 2718 template <class T> struct cls {}; 2719 cls<cls<cls<int>>> [[fo^o]]; 2720 )cpp", 2721 [](HoverInfo &HI) { 2722 HI.Definition = "cls<cls<cls<int>>> foo"; 2723 HI.Kind = index::SymbolKind::Variable; 2724 HI.NamespaceScope = ""; 2725 HI.Name = "foo"; 2726 HI.Type = "cls<cls<cls<int>>>"; 2727 }}, 2728 { 2729 R"cpp(// type of nested templates. 2730 template <class T> struct cls {}; 2731 [[cl^s]]<cls<cls<int>>> foo; 2732 )cpp", 2733 [](HoverInfo &HI) { 2734 HI.Definition = "template <> struct cls<cls<cls<int>>> {}"; 2735 HI.Kind = index::SymbolKind::Struct; 2736 HI.NamespaceScope = ""; 2737 HI.Name = "cls<cls<cls<int>>>"; 2738 HI.Documentation = "type of nested templates."; 2739 }}, 2740 { 2741 R"cpp(// type with decltype 2742 int a; 2743 decltype(a) [[b^]] = a;)cpp", 2744 [](HoverInfo &HI) { 2745 HI.Definition = "decltype(a) b = a"; 2746 HI.Kind = index::SymbolKind::Variable; 2747 HI.NamespaceScope = ""; 2748 HI.Name = "b"; 2749 HI.Type = "int"; 2750 }}, 2751 { 2752 R"cpp(// type with decltype 2753 int a; 2754 decltype(a) c; 2755 decltype(c) [[b^]] = a;)cpp", 2756 [](HoverInfo &HI) { 2757 HI.Definition = "decltype(c) b = a"; 2758 HI.Kind = index::SymbolKind::Variable; 2759 HI.NamespaceScope = ""; 2760 HI.Name = "b"; 2761 HI.Type = "int"; 2762 }}, 2763 { 2764 R"cpp(// type with decltype 2765 int a; 2766 const decltype(a) [[b^]] = a;)cpp", 2767 [](HoverInfo &HI) { 2768 HI.Definition = "const decltype(a) b = a"; 2769 HI.Kind = index::SymbolKind::Variable; 2770 HI.NamespaceScope = ""; 2771 HI.Name = "b"; 2772 HI.Type = "int"; 2773 }}, 2774 { 2775 R"cpp(// type with decltype 2776 int a; 2777 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp", 2778 [](HoverInfo &HI) { 2779 HI.Definition = "auto foo(decltype(a) x) -> decltype(a)"; 2780 HI.Kind = index::SymbolKind::Function; 2781 HI.NamespaceScope = ""; 2782 HI.Name = "foo"; 2783 // FIXME: Handle composite types with decltype with a printing 2784 // policy. 2785 HI.Type = {"auto (decltype(a)) -> decltype(a)", 2786 "auto (int) -> int"}; 2787 HI.ReturnType = "int"; 2788 HI.Parameters = {{{"int"}, std::string("x"), std::nullopt}}; 2789 }}, 2790 { 2791 R"cpp(// sizeof expr 2792 void foo() { 2793 (void)[[size^of]](char); 2794 })cpp", 2795 [](HoverInfo &HI) { 2796 HI.Name = "expression"; 2797 HI.Type = "unsigned long"; 2798 HI.Value = "1"; 2799 }}, 2800 { 2801 R"cpp(// alignof expr 2802 void foo() { 2803 (void)[[align^of]](char); 2804 })cpp", 2805 [](HoverInfo &HI) { 2806 HI.Name = "expression"; 2807 HI.Type = "unsigned long"; 2808 HI.Value = "1"; 2809 }}, 2810 { 2811 R"cpp( 2812 template <typename T = int> 2813 void foo(const T& = T()) { 2814 [[f^oo]]<>(3); 2815 })cpp", 2816 [](HoverInfo &HI) { 2817 HI.Name = "foo"; 2818 HI.Kind = index::SymbolKind::Function; 2819 HI.Type = "void (const int &)"; 2820 HI.ReturnType = "void"; 2821 HI.Parameters = { 2822 {{"const int &"}, std::nullopt, std::string("T()")}}; 2823 HI.Definition = "template <> void foo<int>(const int &)"; 2824 HI.NamespaceScope = ""; 2825 }}, 2826 { 2827 R"cpp(// should not crash 2828 @interface ObjC { 2829 char [[da^ta]]; 2830 }@end 2831 )cpp", 2832 [](HoverInfo &HI) { 2833 HI.Name = "data"; 2834 HI.Type = "char"; 2835 HI.Kind = index::SymbolKind::Field; 2836 HI.LocalScope = "ObjC::"; 2837 HI.NamespaceScope = ""; 2838 HI.Definition = "char data"; 2839 }}, 2840 { 2841 R"cpp( 2842 @interface MYObject 2843 @end 2844 @interface Interface 2845 @property(retain) [[MYOb^ject]] *x; 2846 @end 2847 )cpp", 2848 [](HoverInfo &HI) { 2849 HI.Name = "MYObject"; 2850 HI.Kind = index::SymbolKind::Class; 2851 HI.NamespaceScope = ""; 2852 HI.Definition = "@interface MYObject\n@end"; 2853 }}, 2854 { 2855 R"cpp( 2856 @interface MYObject 2857 @end 2858 @interface Interface 2859 - (void)doWith:([[MYOb^ject]] *)object; 2860 @end 2861 )cpp", 2862 [](HoverInfo &HI) { 2863 HI.Name = "MYObject"; 2864 HI.Kind = index::SymbolKind::Class; 2865 HI.NamespaceScope = ""; 2866 HI.Definition = "@interface MYObject\n@end"; 2867 }}, 2868 { 2869 R"cpp(// this expr 2870 // comment 2871 namespace ns { 2872 class Foo { 2873 Foo* bar() { 2874 return [[t^his]]; 2875 } 2876 }; 2877 } 2878 )cpp", 2879 [](HoverInfo &HI) { 2880 HI.Name = "this"; 2881 HI.Definition = "ns::Foo *"; 2882 }}, 2883 { 2884 R"cpp(// this expr for template class 2885 namespace ns { 2886 template <typename T> 2887 class Foo { 2888 Foo* bar() const { 2889 return [[t^his]]; 2890 } 2891 }; 2892 } 2893 )cpp", 2894 [](HoverInfo &HI) { 2895 HI.Name = "this"; 2896 HI.Definition = "const Foo<T> *"; 2897 }}, 2898 { 2899 R"cpp(// this expr for specialization class 2900 namespace ns { 2901 template <typename T> class Foo {}; 2902 template <> 2903 struct Foo<int> { 2904 Foo* bar() { 2905 return [[thi^s]]; 2906 } 2907 }; 2908 } 2909 )cpp", 2910 [](HoverInfo &HI) { 2911 HI.Name = "this"; 2912 HI.Definition = "Foo<int> *"; 2913 }}, 2914 { 2915 R"cpp(// this expr for partial specialization struct 2916 namespace ns { 2917 template <typename T, typename F> struct Foo {}; 2918 template <typename F> 2919 struct Foo<int, F> { 2920 Foo* bar() const { 2921 return [[thi^s]]; 2922 } 2923 }; 2924 } 2925 )cpp", 2926 [](HoverInfo &HI) { 2927 HI.Name = "this"; 2928 HI.Definition = "const Foo<int, F> *"; 2929 }}, 2930 { 2931 R"cpp( 2932 @interface MYObject 2933 @end 2934 @interface MYObject (Private) 2935 @property(nonatomic, assign) int privateField; 2936 @end 2937 2938 int someFunction() { 2939 MYObject *obj = [MYObject sharedInstance]; 2940 return obj.[[private^Field]]; 2941 } 2942 )cpp", 2943 [](HoverInfo &HI) { 2944 HI.Name = "privateField"; 2945 HI.Kind = index::SymbolKind::InstanceProperty; 2946 HI.LocalScope = "MYObject(Private)::"; 2947 HI.NamespaceScope = ""; 2948 HI.Definition = "@property(nonatomic, assign, unsafe_unretained, " 2949 "readwrite) int privateField;"; 2950 }}, 2951 { 2952 R"cpp( 2953 @protocol MYProtocol 2954 @property(nonatomic, assign) int prop1; 2955 @end 2956 2957 int someFunction() { 2958 id<MYProtocol> obj = 0; 2959 return obj.[[pro^p1]]; 2960 } 2961 )cpp", 2962 [](HoverInfo &HI) { 2963 HI.Name = "prop1"; 2964 HI.Kind = index::SymbolKind::InstanceProperty; 2965 HI.LocalScope = "MYProtocol::"; 2966 HI.NamespaceScope = ""; 2967 HI.Definition = "@property(nonatomic, assign, unsafe_unretained, " 2968 "readwrite) int prop1;"; 2969 }}, 2970 { 2971 R"cpp( 2972 @protocol MYProtocol 2973 @end 2974 @interface MYObject 2975 @end 2976 2977 @interface MYObject (Ext) <[[MYProt^ocol]]> 2978 @end 2979 )cpp", 2980 [](HoverInfo &HI) { 2981 HI.Name = "MYProtocol"; 2982 HI.Kind = index::SymbolKind::Protocol; 2983 HI.NamespaceScope = ""; 2984 HI.Definition = "@protocol MYProtocol\n@end"; 2985 }}, 2986 {R"objc( 2987 @interface Foo 2988 @end 2989 2990 @implementation Foo(Private) 2991 + (int)somePrivateMethod { 2992 int [[res^ult]] = 2; 2993 return result; 2994 } 2995 @end 2996 )objc", 2997 [](HoverInfo &HI) { 2998 HI.Name = "result"; 2999 HI.Definition = "int result = 2"; 3000 HI.Kind = index::SymbolKind::Variable; 3001 HI.Type = "int"; 3002 HI.LocalScope = "+[Foo(Private) somePrivateMethod]::"; 3003 HI.NamespaceScope = ""; 3004 HI.Value = "2"; 3005 }}, 3006 {R"objc( 3007 @interface Foo 3008 @end 3009 3010 @implementation Foo 3011 - (int)variadicArgMethod:(id)first, ... { 3012 int [[res^ult]] = 0; 3013 return result; 3014 } 3015 @end 3016 )objc", 3017 [](HoverInfo &HI) { 3018 HI.Name = "result"; 3019 HI.Definition = "int result = 0"; 3020 HI.Kind = index::SymbolKind::Variable; 3021 HI.Type = "int"; 3022 HI.LocalScope = "-[Foo variadicArgMethod:, ...]::"; 3023 HI.NamespaceScope = ""; 3024 HI.Value = "0"; 3025 }}, 3026 // Should not crash. 3027 {R"objc( 3028 typedef struct MyRect {} MyRect; 3029 3030 @interface IFace 3031 @property(nonatomic) MyRect frame; 3032 @end 3033 3034 MyRect foobar() { 3035 MyRect mr; 3036 return mr; 3037 } 3038 void test() { 3039 IFace *v; 3040 v.frame = [[foo^bar]](); 3041 } 3042 )objc", 3043 [](HoverInfo &HI) { 3044 HI.Name = "foobar"; 3045 HI.Kind = index::SymbolKind::Function; 3046 HI.NamespaceScope = ""; 3047 HI.Definition = "MyRect foobar()"; 3048 HI.Type = {"MyRect ()", "MyRect ()"}; 3049 HI.ReturnType = {"MyRect", "MyRect"}; 3050 HI.Parameters.emplace(); 3051 }}, 3052 {R"cpp( 3053 void foo(int * __attribute__(([[non^null]], noescape)) ); 3054 )cpp", 3055 [](HoverInfo &HI) { 3056 HI.Name = "nonnull"; 3057 HI.Kind = index::SymbolKind::Unknown; // FIXME: no suitable value 3058 HI.Definition = "__attribute__((nonnull))"; 3059 HI.Documentation = Attr::getDocumentation(attr::NonNull).str(); 3060 }}, 3061 { 3062 R"cpp( 3063 namespace std { 3064 struct strong_ordering { 3065 int n; 3066 constexpr operator int() const { return n; } 3067 static const strong_ordering equal, greater, less; 3068 }; 3069 constexpr strong_ordering strong_ordering::equal = {0}; 3070 constexpr strong_ordering strong_ordering::greater = {1}; 3071 constexpr strong_ordering strong_ordering::less = {-1}; 3072 } 3073 3074 struct Foo 3075 { 3076 int x; 3077 // Foo spaceship 3078 auto operator<=>(const Foo&) const = default; 3079 }; 3080 3081 bool x = Foo(1) [[!^=]] Foo(2); 3082 )cpp", 3083 [](HoverInfo &HI) { 3084 HI.Type = "bool (const Foo &) const noexcept"; 3085 HI.Value = "true"; 3086 HI.Name = "operator=="; 3087 HI.Parameters = {{{"const Foo &"}, std::nullopt, std::nullopt}}; 3088 HI.ReturnType = "bool"; 3089 HI.Kind = index::SymbolKind::InstanceMethod; 3090 HI.LocalScope = "Foo::"; 3091 HI.NamespaceScope = ""; 3092 HI.Definition = 3093 "bool operator==(const Foo &) const noexcept = default"; 3094 HI.Documentation = ""; 3095 }}, 3096 }; 3097 3098 // Create a tiny index, so tests above can verify documentation is fetched. 3099 Symbol IndexSym = func("indexSymbol"); 3100 IndexSym.Documentation = "comment from index"; 3101 SymbolSlab::Builder Symbols; 3102 Symbols.insert(IndexSym); 3103 auto Index = 3104 MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab()); 3105 3106 for (const auto &Case : Cases) { 3107 SCOPED_TRACE(Case.Code); 3108 3109 Annotations T(Case.Code); 3110 TestTU TU = TestTU::withCode(T.code()); 3111 TU.ExtraArgs.push_back("-std=c++20"); 3112 TU.ExtraArgs.push_back("-xobjective-c++"); 3113 3114 TU.ExtraArgs.push_back("-Wno-gnu-designator"); 3115 // Types might be different depending on the target triplet, we chose a 3116 // fixed one to make sure tests passes on different platform. 3117 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu"); 3118 auto AST = TU.build(); 3119 Config Cfg; 3120 Cfg.Hover.ShowAKA = true; 3121 WithContextValue WithCfg(Config::Key, std::move(Cfg)); 3122 auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get()); 3123 ASSERT_TRUE(H); 3124 HoverInfo Expected; 3125 Expected.SymRange = T.range(); 3126 Case.ExpectedBuilder(Expected); 3127 3128 SCOPED_TRACE(H->present().asPlainText()); 3129 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope); 3130 EXPECT_EQ(H->LocalScope, Expected.LocalScope); 3131 EXPECT_EQ(H->Name, Expected.Name); 3132 EXPECT_EQ(H->Kind, Expected.Kind); 3133 EXPECT_EQ(H->Documentation, Expected.Documentation); 3134 EXPECT_EQ(H->Definition, Expected.Definition); 3135 EXPECT_EQ(H->Type, Expected.Type); 3136 EXPECT_EQ(H->ReturnType, Expected.ReturnType); 3137 EXPECT_EQ(H->Parameters, Expected.Parameters); 3138 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters); 3139 EXPECT_EQ(H->SymRange, Expected.SymRange); 3140 EXPECT_EQ(H->Value, Expected.Value); 3141 } 3142 } 3143 3144 TEST(Hover, Providers) { 3145 struct { 3146 const char *Code; 3147 const std::function<void(HoverInfo &)> ExpectedBuilder; 3148 } Cases[] = {{R"cpp( 3149 struct Foo {}; 3150 Foo F = Fo^o{}; 3151 )cpp", 3152 [](HoverInfo &HI) { HI.Provider = ""; }}, 3153 {R"cpp( 3154 #include "foo.h" 3155 Foo F = Fo^o{}; 3156 )cpp", 3157 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, 3158 {R"cpp( 3159 #include "all.h" 3160 Foo F = Fo^o{}; 3161 )cpp", 3162 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, 3163 {R"cpp( 3164 #define FOO 5 3165 int F = ^FOO; 3166 )cpp", 3167 [](HoverInfo &HI) { HI.Provider = ""; }}, 3168 {R"cpp( 3169 #include "foo.h" 3170 int F = ^FOO; 3171 )cpp", 3172 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, 3173 {R"cpp( 3174 #include "all.h" 3175 int F = ^FOO; 3176 )cpp", 3177 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, 3178 {R"cpp( 3179 #include "foo.h" 3180 Foo A; 3181 Foo B; 3182 Foo C = A ^+ B; 3183 )cpp", 3184 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, 3185 // Hover selects the underlying decl of the using decl 3186 {R"cpp( 3187 #include "foo.h" 3188 namespace ns { 3189 using ::Foo; 3190 } 3191 ns::F^oo d; 3192 )cpp", 3193 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }}, 3194 {R"cpp( 3195 namespace foo {}; 3196 using namespace fo^o; 3197 )cpp", 3198 [](HoverInfo &HI) { HI.Provider = ""; }}, 3199 }; 3200 3201 for (const auto &Case : Cases) { 3202 Annotations Code{Case.Code}; 3203 SCOPED_TRACE(Code.code()); 3204 3205 TestTU TU; 3206 TU.Filename = "foo.cpp"; 3207 TU.Code = Code.code(); 3208 TU.AdditionalFiles["foo.h"] = guard(R"cpp( 3209 #define FOO 1 3210 class Foo {}; 3211 Foo& operator+(const Foo, const Foo); 3212 )cpp"); 3213 TU.AdditionalFiles["all.h"] = guard("#include \"foo.h\""); 3214 3215 auto AST = TU.build(); 3216 auto H = getHover(AST, Code.point(), format::getLLVMStyle(), nullptr); 3217 ASSERT_TRUE(H); 3218 HoverInfo Expected; 3219 Case.ExpectedBuilder(Expected); 3220 SCOPED_TRACE(H->present().asMarkdown()); 3221 EXPECT_EQ(H->Provider, Expected.Provider); 3222 } 3223 } 3224 3225 TEST(Hover, ParseProviderInfo) { 3226 HoverInfo HIFoo; 3227 HIFoo.Name = "foo"; 3228 HIFoo.Provider = "\"foo.h\""; 3229 3230 HoverInfo HIFooBar; 3231 HIFooBar.Name = "foo"; 3232 HIFooBar.Provider = "<bar.h>"; 3233 struct Case { 3234 HoverInfo HI; 3235 llvm::StringRef ExpectedMarkdown; 3236 } Cases[] = {{HIFoo, "### `foo` \nprovided by `\"foo.h\"`"}, 3237 {HIFooBar, "### `foo` \nprovided by `<bar.h>`"}}; 3238 3239 for (const auto &Case : Cases) 3240 EXPECT_EQ(Case.HI.present().asMarkdown(), Case.ExpectedMarkdown); 3241 } 3242 3243 TEST(Hover, UsedSymbols) { 3244 struct { 3245 const char *Code; 3246 const std::function<void(HoverInfo &)> ExpectedBuilder; 3247 } Cases[] = {{R"cpp( 3248 #include ^"bar.h" 3249 int fstBar = bar1(); 3250 int another= bar1(0); 3251 int sndBar = bar2(); 3252 Bar bar; 3253 int macroBar = BAR; 3254 )cpp", 3255 [](HoverInfo &HI) { 3256 HI.UsedSymbolNames = {"BAR", "Bar", "bar1", "bar2"}; 3257 }}, 3258 {R"cpp( 3259 #in^clude <vector> 3260 std::vector<int> vec; 3261 )cpp", 3262 [](HoverInfo &HI) { HI.UsedSymbolNames = {"vector"}; }}}; 3263 for (const auto &Case : Cases) { 3264 Annotations Code{Case.Code}; 3265 SCOPED_TRACE(Code.code()); 3266 3267 TestTU TU; 3268 TU.Filename = "foo.cpp"; 3269 TU.Code = Code.code(); 3270 TU.AdditionalFiles["bar.h"] = guard(R"cpp( 3271 #define BAR 5 3272 int bar1(); 3273 int bar2(); 3274 int bar1(double); 3275 class Bar {}; 3276 )cpp"); 3277 TU.AdditionalFiles["system/vector"] = guard(R"cpp( 3278 namespace std { 3279 template<typename> 3280 class vector{}; 3281 } 3282 )cpp"); 3283 TU.ExtraArgs.push_back("-isystem" + testPath("system")); 3284 3285 auto AST = TU.build(); 3286 auto H = getHover(AST, Code.point(), format::getLLVMStyle(), nullptr); 3287 ASSERT_TRUE(H); 3288 HoverInfo Expected; 3289 Case.ExpectedBuilder(Expected); 3290 SCOPED_TRACE(H->present().asMarkdown()); 3291 EXPECT_EQ(H->UsedSymbolNames, Expected.UsedSymbolNames); 3292 } 3293 } 3294 3295 TEST(Hover, DocsFromIndex) { 3296 Annotations T(R"cpp( 3297 template <typename T> class X {}; 3298 void foo() { 3299 auto t = X<int>(); 3300 X^<int> w; 3301 (void)w; 3302 })cpp"); 3303 3304 TestTU TU = TestTU::withCode(T.code()); 3305 auto AST = TU.build(); 3306 Symbol IndexSym; 3307 IndexSym.ID = getSymbolID(&findDecl(AST, "X")); 3308 IndexSym.Documentation = "comment from index"; 3309 SymbolSlab::Builder Symbols; 3310 Symbols.insert(IndexSym); 3311 auto Index = 3312 MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab()); 3313 3314 for (const auto &P : T.points()) { 3315 auto H = getHover(AST, P, format::getLLVMStyle(), Index.get()); 3316 ASSERT_TRUE(H); 3317 EXPECT_EQ(H->Documentation, IndexSym.Documentation); 3318 } 3319 } 3320 3321 TEST(Hover, DocsFromAST) { 3322 Annotations T(R"cpp( 3323 // doc 3324 template <typename T> class X {}; 3325 // doc 3326 template <typename T> void bar() {} 3327 // doc 3328 template <typename T> T baz; 3329 void foo() { 3330 au^to t = X<int>(); 3331 X^<int>(); 3332 b^ar<int>(); 3333 au^to T = ba^z<X<int>>; 3334 ba^z<int> = 0; 3335 })cpp"); 3336 3337 TestTU TU = TestTU::withCode(T.code()); 3338 auto AST = TU.build(); 3339 for (const auto &P : T.points()) { 3340 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr); 3341 ASSERT_TRUE(H); 3342 EXPECT_EQ(H->Documentation, "doc"); 3343 } 3344 } 3345 3346 TEST(Hover, NoCrash) { 3347 Annotations T(R"cpp( 3348 /* error-ok */ 3349 template<typename T> T foo(T); 3350 3351 // Setter variable heuristic might fail if the callexpr is broken. 3352 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp"); 3353 3354 TestTU TU = TestTU::withCode(T.code()); 3355 auto AST = TU.build(); 3356 for (const auto &P : T.points()) 3357 getHover(AST, P, format::getLLVMStyle(), nullptr); 3358 } 3359 3360 TEST(Hover, NoCrashAPInt64) { 3361 Annotations T(R"cpp( 3362 constexpr unsigned long value = -1; // wrap around 3363 void foo() { va^lue; } 3364 )cpp"); 3365 auto AST = TestTU::withCode(T.code()).build(); 3366 getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3367 } 3368 3369 TEST(Hover, NoCrashInt128) { 3370 Annotations T(R"cpp( 3371 constexpr __int128_t value = -4; 3372 void foo() { va^lue; } 3373 )cpp"); 3374 auto TU = TestTU::withCode(T.code()); 3375 // Need a triple that support __int128_t. 3376 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu"); 3377 auto AST = TU.build(); 3378 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3379 ASSERT_TRUE(H); 3380 EXPECT_EQ(H->Value, "-4 (0xfffffffc)"); 3381 } 3382 3383 TEST(Hover, DocsFromMostSpecial) { 3384 Annotations T(R"cpp( 3385 // doc1 3386 template <typename T> class $doc1^X {}; 3387 // doc2 3388 template <> class $doc2^X<int> {}; 3389 // doc3 3390 template <typename T> class $doc3^X<T*> {}; 3391 void foo() { 3392 X$doc1^<char>(); 3393 X$doc2^<int>(); 3394 X$doc3^<int*>(); 3395 })cpp"); 3396 3397 TestTU TU = TestTU::withCode(T.code()); 3398 auto AST = TU.build(); 3399 for (const auto *Comment : {"doc1", "doc2", "doc3"}) { 3400 for (const auto &P : T.points(Comment)) { 3401 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr); 3402 ASSERT_TRUE(H); 3403 EXPECT_EQ(H->Documentation, Comment); 3404 } 3405 } 3406 } 3407 3408 TEST(Hover, Present) { 3409 struct { 3410 const std::function<void(HoverInfo &)> Builder; 3411 llvm::StringRef ExpectedRender; 3412 } Cases[] = { 3413 { 3414 [](HoverInfo &HI) { 3415 HI.Kind = index::SymbolKind::Unknown; 3416 HI.Name = "X"; 3417 }, 3418 R"(X)", 3419 }, 3420 { 3421 [](HoverInfo &HI) { 3422 HI.Kind = index::SymbolKind::NamespaceAlias; 3423 HI.Name = "foo"; 3424 }, 3425 R"(namespace-alias foo)", 3426 }, 3427 { 3428 [](HoverInfo &HI) { 3429 HI.Kind = index::SymbolKind::Class; 3430 HI.Size = 80; 3431 HI.TemplateParameters = { 3432 {{"typename"}, std::string("T"), std::nullopt}, 3433 {{"typename"}, std::string("C"), std::string("bool")}, 3434 }; 3435 HI.Documentation = "documentation"; 3436 HI.Definition = 3437 "template <typename T, typename C = bool> class Foo {}"; 3438 HI.Name = "foo"; 3439 HI.NamespaceScope.emplace(); 3440 }, 3441 R"(class foo 3442 3443 Size: 10 bytes 3444 documentation 3445 3446 template <typename T, typename C = bool> class Foo {})", 3447 }, 3448 { 3449 [](HoverInfo &HI) { 3450 HI.Kind = index::SymbolKind::Function; 3451 HI.Name = "foo"; 3452 HI.Type = {"type", "c_type"}; 3453 HI.ReturnType = {"ret_type", "can_ret_type"}; 3454 HI.Parameters.emplace(); 3455 HoverInfo::Param P; 3456 HI.Parameters->push_back(P); 3457 P.Type = {"type", "can_type"}; 3458 HI.Parameters->push_back(P); 3459 P.Name = "foo"; 3460 HI.Parameters->push_back(P); 3461 P.Default = "default"; 3462 HI.Parameters->push_back(P); 3463 HI.NamespaceScope = "ns::"; 3464 HI.Definition = "ret_type foo(params) {}"; 3465 }, 3466 "function foo\n" 3467 "\n" 3468 "→ ret_type (aka can_ret_type)\n" 3469 "Parameters:\n" 3470 "- \n" 3471 "- type (aka can_type)\n" 3472 "- type foo (aka can_type)\n" 3473 "- type foo = default (aka can_type)\n" 3474 "\n" 3475 "// In namespace ns\n" 3476 "ret_type foo(params) {}", 3477 }, 3478 { 3479 [](HoverInfo &HI) { 3480 HI.Kind = index::SymbolKind::Field; 3481 HI.LocalScope = "test::Bar::"; 3482 HI.Value = "value"; 3483 HI.Name = "foo"; 3484 HI.Type = {"type", "can_type"}; 3485 HI.Definition = "def"; 3486 HI.Size = 32; 3487 HI.Offset = 96; 3488 HI.Padding = 32; 3489 HI.Align = 32; 3490 }, 3491 R"(field foo 3492 3493 Type: type (aka can_type) 3494 Value = value 3495 Offset: 12 bytes 3496 Size: 4 bytes (+4 bytes padding), alignment 4 bytes 3497 3498 // In test::Bar 3499 def)", 3500 }, 3501 { 3502 [](HoverInfo &HI) { 3503 HI.Kind = index::SymbolKind::Field; 3504 HI.LocalScope = "test::Bar::"; 3505 HI.Value = "value"; 3506 HI.Name = "foo"; 3507 HI.Type = {"type", "can_type"}; 3508 HI.Definition = "def"; 3509 HI.Size = 25; 3510 HI.Offset = 35; 3511 HI.Padding = 4; 3512 HI.Align = 64; 3513 }, 3514 R"(field foo 3515 3516 Type: type (aka can_type) 3517 Value = value 3518 Offset: 4 bytes and 3 bits 3519 Size: 25 bits (+4 bits padding), alignment 8 bytes 3520 3521 // In test::Bar 3522 def)", 3523 }, 3524 { 3525 [](HoverInfo &HI) { 3526 HI.Kind = index::SymbolKind::Field; 3527 HI.AccessSpecifier = "public"; 3528 HI.Name = "foo"; 3529 HI.LocalScope = "test::Bar::"; 3530 HI.Definition = "def"; 3531 }, 3532 R"(field foo 3533 3534 // In test::Bar 3535 public: def)", 3536 }, 3537 { 3538 [](HoverInfo &HI) { 3539 HI.Definition = "size_t method()"; 3540 HI.AccessSpecifier = "protected"; 3541 HI.Kind = index::SymbolKind::InstanceMethod; 3542 HI.NamespaceScope = ""; 3543 HI.LocalScope = "cls<int>::"; 3544 HI.Name = "method"; 3545 HI.Parameters.emplace(); 3546 HI.ReturnType = {"size_t", "unsigned long"}; 3547 HI.Type = {"size_t ()", "unsigned long ()"}; 3548 }, 3549 R"(instance-method method 3550 3551 → size_t (aka unsigned long) 3552 3553 // In cls<int> 3554 protected: size_t method())", 3555 }, 3556 { 3557 [](HoverInfo &HI) { 3558 HI.Definition = "cls(int a, int b = 5)"; 3559 HI.AccessSpecifier = "public"; 3560 HI.Kind = index::SymbolKind::Constructor; 3561 HI.NamespaceScope = ""; 3562 HI.LocalScope = "cls"; 3563 HI.Name = "cls"; 3564 HI.Parameters.emplace(); 3565 HI.Parameters->emplace_back(); 3566 HI.Parameters->back().Type = "int"; 3567 HI.Parameters->back().Name = "a"; 3568 HI.Parameters->emplace_back(); 3569 HI.Parameters->back().Type = "int"; 3570 HI.Parameters->back().Name = "b"; 3571 HI.Parameters->back().Default = "5"; 3572 }, 3573 R"(constructor cls 3574 3575 Parameters: 3576 - int a 3577 - int b = 5 3578 3579 // In cls 3580 public: cls(int a, int b = 5))", 3581 }, 3582 { 3583 [](HoverInfo &HI) { 3584 HI.Kind = index::SymbolKind::Union; 3585 HI.AccessSpecifier = "private"; 3586 HI.Name = "foo"; 3587 HI.NamespaceScope = "ns1::"; 3588 HI.Definition = "union foo {}"; 3589 }, 3590 R"(union foo 3591 3592 // In namespace ns1 3593 private: union foo {})", 3594 }, 3595 { 3596 [](HoverInfo &HI) { 3597 HI.Kind = index::SymbolKind::Variable; 3598 HI.Name = "foo"; 3599 HI.Definition = "int foo = 3"; 3600 HI.LocalScope = "test::Bar::"; 3601 HI.Value = "3"; 3602 HI.Type = "int"; 3603 HI.CalleeArgInfo.emplace(); 3604 HI.CalleeArgInfo->Name = "arg_a"; 3605 HI.CalleeArgInfo->Type = "int"; 3606 HI.CalleeArgInfo->Default = "7"; 3607 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; 3608 }, 3609 R"(variable foo 3610 3611 Type: int 3612 Value = 3 3613 Passed as arg_a 3614 3615 // In test::Bar 3616 int foo = 3)", 3617 }, 3618 { 3619 [](HoverInfo &HI) { 3620 HI.Kind = index::SymbolKind::Variable; 3621 HI.Name = "foo"; 3622 HI.CalleeArgInfo.emplace(); 3623 HI.CalleeArgInfo->Type = "int"; 3624 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; 3625 }, 3626 R"(variable foo 3627 3628 Passed by value)", 3629 }, 3630 { 3631 [](HoverInfo &HI) { 3632 HI.Kind = index::SymbolKind::Variable; 3633 HI.Name = "foo"; 3634 HI.Definition = "int foo = 3"; 3635 HI.LocalScope = "test::Bar::"; 3636 HI.Value = "3"; 3637 HI.Type = "int"; 3638 HI.CalleeArgInfo.emplace(); 3639 HI.CalleeArgInfo->Name = "arg_a"; 3640 HI.CalleeArgInfo->Type = "int"; 3641 HI.CalleeArgInfo->Default = "7"; 3642 HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false}; 3643 }, 3644 R"(variable foo 3645 3646 Type: int 3647 Value = 3 3648 Passed by reference as arg_a 3649 3650 // In test::Bar 3651 int foo = 3)", 3652 }, 3653 { 3654 [](HoverInfo &HI) { 3655 HI.Kind = index::SymbolKind::Variable; 3656 HI.Name = "foo"; 3657 HI.Definition = "int foo = 3"; 3658 HI.LocalScope = "test::Bar::"; 3659 HI.Value = "3"; 3660 HI.Type = "int"; 3661 HI.CalleeArgInfo.emplace(); 3662 HI.CalleeArgInfo->Name = "arg_a"; 3663 HI.CalleeArgInfo->Type = {"alias_int", "int"}; 3664 HI.CalleeArgInfo->Default = "7"; 3665 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true}; 3666 }, 3667 R"(variable foo 3668 3669 Type: int 3670 Value = 3 3671 Passed as arg_a (converted to alias_int) 3672 3673 // In test::Bar 3674 int foo = 3)", 3675 }, 3676 { 3677 [](HoverInfo &HI) { 3678 HI.Kind = index::SymbolKind::Macro; 3679 HI.Name = "PLUS_ONE"; 3680 HI.Definition = "#define PLUS_ONE(X) (X+1)\n\n" 3681 "// Expands to\n" 3682 "(1 + 1)"; 3683 }, 3684 R"(macro PLUS_ONE 3685 3686 #define PLUS_ONE(X) (X+1) 3687 3688 // Expands to 3689 (1 + 1))", 3690 }, 3691 { 3692 [](HoverInfo &HI) { 3693 HI.Kind = index::SymbolKind::Variable; 3694 HI.Name = "foo"; 3695 HI.Definition = "int foo = 3"; 3696 HI.LocalScope = "test::Bar::"; 3697 HI.Value = "3"; 3698 HI.Type = "int"; 3699 HI.CalleeArgInfo.emplace(); 3700 HI.CalleeArgInfo->Name = "arg_a"; 3701 HI.CalleeArgInfo->Type = "int"; 3702 HI.CalleeArgInfo->Default = "7"; 3703 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true}; 3704 }, 3705 R"(variable foo 3706 3707 Type: int 3708 Value = 3 3709 Passed by const reference as arg_a (converted to int) 3710 3711 // In test::Bar 3712 int foo = 3)", 3713 }, 3714 { 3715 [](HoverInfo &HI) { 3716 HI.Name = "stdio.h"; 3717 HI.Definition = "/usr/include/stdio.h"; 3718 }, 3719 R"(stdio.h 3720 3721 /usr/include/stdio.h)", 3722 }, 3723 {[](HoverInfo &HI) { 3724 HI.Name = "foo.h"; 3725 HI.UsedSymbolNames = {"Foo", "Bar", "Bar"}; 3726 }, 3727 R"(foo.h 3728 3729 provides Foo, Bar, Bar)"}, 3730 {[](HoverInfo &HI) { 3731 HI.Name = "foo.h"; 3732 HI.UsedSymbolNames = {"Foo", "Bar", "Baz", "Foobar", "Qux", "Quux"}; 3733 }, 3734 R"(foo.h 3735 3736 provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}}; 3737 3738 for (const auto &C : Cases) { 3739 HoverInfo HI; 3740 C.Builder(HI); 3741 Config Cfg; 3742 Cfg.Hover.ShowAKA = true; 3743 WithContextValue WithCfg(Config::Key, std::move(Cfg)); 3744 EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender); 3745 } 3746 } 3747 3748 TEST(Hover, ParseDocumentation) { 3749 struct Case { 3750 llvm::StringRef Documentation; 3751 llvm::StringRef ExpectedRenderMarkdown; 3752 llvm::StringRef ExpectedRenderPlainText; 3753 } Cases[] = {{ 3754 " \n foo\nbar", 3755 "foo bar", 3756 "foo bar", 3757 }, 3758 { 3759 "foo\nbar \n ", 3760 "foo bar", 3761 "foo bar", 3762 }, 3763 { 3764 "foo \nbar", 3765 "foo bar", 3766 "foo bar", 3767 }, 3768 { 3769 "foo \nbar", 3770 "foo bar", 3771 "foo bar", 3772 }, 3773 { 3774 "foo\n\n\nbar", 3775 "foo \nbar", 3776 "foo\nbar", 3777 }, 3778 { 3779 "foo\n\n\n\tbar", 3780 "foo \nbar", 3781 "foo\nbar", 3782 }, 3783 { 3784 "foo\n\n\n bar", 3785 "foo \nbar", 3786 "foo\nbar", 3787 }, 3788 { 3789 "foo.\nbar", 3790 "foo. \nbar", 3791 "foo.\nbar", 3792 }, 3793 { 3794 "foo. \nbar", 3795 "foo. \nbar", 3796 "foo.\nbar", 3797 }, 3798 { 3799 "foo\n*bar", 3800 "foo \n\\*bar", 3801 "foo\n*bar", 3802 }, 3803 { 3804 "foo\nbar", 3805 "foo bar", 3806 "foo bar", 3807 }, 3808 { 3809 "Tests primality of `p`.", 3810 "Tests primality of `p`.", 3811 "Tests primality of `p`.", 3812 }, 3813 { 3814 "'`' should not occur in `Code`", 3815 "'\\`' should not occur in `Code`", 3816 "'`' should not occur in `Code`", 3817 }, 3818 { 3819 "`not\nparsed`", 3820 "\\`not parsed\\`", 3821 "`not parsed`", 3822 }}; 3823 3824 for (const auto &C : Cases) { 3825 markup::Document Output; 3826 parseDocumentation(C.Documentation, Output); 3827 3828 EXPECT_EQ(Output.asMarkdown(), C.ExpectedRenderMarkdown); 3829 EXPECT_EQ(Output.asPlainText(), C.ExpectedRenderPlainText); 3830 } 3831 } 3832 3833 // This is a separate test as headings don't create any differences in 3834 // plaintext mode. 3835 TEST(Hover, PresentHeadings) { 3836 HoverInfo HI; 3837 HI.Kind = index::SymbolKind::Variable; 3838 HI.Name = "foo"; 3839 3840 EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`"); 3841 } 3842 3843 // This is a separate test as rulers behave differently in markdown vs 3844 // plaintext. 3845 TEST(Hover, PresentRulers) { 3846 HoverInfo HI; 3847 HI.Kind = index::SymbolKind::Variable; 3848 HI.Name = "foo"; 3849 HI.Value = "val"; 3850 HI.Definition = "def"; 3851 3852 llvm::StringRef ExpectedMarkdown = // 3853 "### variable `foo` \n" 3854 "\n" 3855 "---\n" 3856 "Value = `val` \n" 3857 "\n" 3858 "---\n" 3859 "```cpp\n" 3860 "def\n" 3861 "```"; 3862 EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown); 3863 3864 llvm::StringRef ExpectedPlaintext = R"pt(variable foo 3865 3866 Value = val 3867 3868 def)pt"; 3869 EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext); 3870 } 3871 3872 TEST(Hover, SpaceshipTemplateNoCrash) { 3873 Annotations T(R"cpp( 3874 namespace std { 3875 struct strong_ordering { 3876 int n; 3877 constexpr operator int() const { return n; } 3878 static const strong_ordering equal, greater, less; 3879 }; 3880 constexpr strong_ordering strong_ordering::equal = {0}; 3881 constexpr strong_ordering strong_ordering::greater = {1}; 3882 constexpr strong_ordering strong_ordering::less = {-1}; 3883 } 3884 3885 template <typename T> 3886 struct S { 3887 // Foo bar baz 3888 friend auto operator<=>(S, S) = default; 3889 }; 3890 static_assert(S<void>() =^= S<void>()); 3891 )cpp"); 3892 3893 TestTU TU = TestTU::withCode(T.code()); 3894 TU.ExtraArgs.push_back("-std=c++20"); 3895 auto AST = TU.build(); 3896 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3897 EXPECT_EQ(HI->Documentation, ""); 3898 } 3899 3900 TEST(Hover, ForwardStructNoCrash) { 3901 Annotations T(R"cpp( 3902 struct Foo; 3903 int bar; 3904 auto baz = (Fo^o*)&bar; 3905 )cpp"); 3906 3907 TestTU TU = TestTU::withCode(T.code()); 3908 auto AST = TU.build(); 3909 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3910 ASSERT_TRUE(HI); 3911 EXPECT_EQ(*HI->Value, "&bar"); 3912 } 3913 3914 TEST(Hover, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls) { 3915 struct { 3916 const char *const Code; 3917 const std::optional<std::string> HoverValue; 3918 } Cases[] = { 3919 {R"cpp( 3920 // error-ok testing behavior on invalid decl 3921 class Foo {}; 3922 void foo(Foo p^aram = nullptr); 3923 )cpp", 3924 std::nullopt}, 3925 {R"cpp( 3926 class Foo {}; 3927 void foo(Foo *p^aram = nullptr); 3928 )cpp", 3929 "nullptr"}, 3930 }; 3931 3932 for (const auto &C : Cases) { 3933 Annotations T(C.Code); 3934 TestTU TU = TestTU::withCode(T.code()); 3935 auto AST = TU.build(); 3936 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3937 ASSERT_TRUE(HI); 3938 ASSERT_EQ(HI->Value, C.HoverValue); 3939 } 3940 } 3941 3942 TEST(Hover, DisableShowAKA) { 3943 Annotations T(R"cpp( 3944 using m_int = int; 3945 m_int ^[[a]]; 3946 )cpp"); 3947 3948 Config Cfg; 3949 Cfg.Hover.ShowAKA = false; 3950 WithContextValue WithCfg(Config::Key, std::move(Cfg)); 3951 3952 TestTU TU = TestTU::withCode(T.code()); 3953 TU.ExtraArgs.push_back("-std=c++17"); 3954 auto AST = TU.build(); 3955 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3956 3957 ASSERT_TRUE(H); 3958 EXPECT_EQ(H->Type, HoverInfo::PrintedType("m_int")); 3959 } 3960 3961 TEST(Hover, HideBigInitializers) { 3962 Annotations T(R"cpp( 3963 #define A(x) x, x, x, x 3964 #define B(x) A(A(A(A(x)))) 3965 int a^rr[] = {B(0)}; 3966 )cpp"); 3967 3968 TestTU TU = TestTU::withCode(T.code()); 3969 auto AST = TU.build(); 3970 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3971 3972 ASSERT_TRUE(H); 3973 EXPECT_EQ(H->Definition, "int arr[]"); 3974 } 3975 3976 #if defined(__aarch64__) 3977 // FIXME: AARCH64 sanitizer buildbots are broken after 72142fbac4. 3978 #define PREDEFINEMACROS_TEST(x) DISABLED_##x 3979 #else 3980 #define PREDEFINEMACROS_TEST(x) x 3981 #endif 3982 3983 TEST(Hover, PREDEFINEMACROS_TEST(GlobalVarEnumeralCastNoCrash)) { 3984 Annotations T(R"cpp( 3985 using uintptr_t = __UINTPTR_TYPE__; 3986 enum Test : uintptr_t {}; 3987 unsigned global_var; 3988 void foo() { 3989 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var)); 3990 } 3991 )cpp"); 3992 3993 TestTU TU = TestTU::withCode(T.code()); 3994 TU.PredefineMacros = true; 3995 auto AST = TU.build(); 3996 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 3997 ASSERT_TRUE(HI); 3998 EXPECT_EQ(*HI->Value, "&global_var"); 3999 } 4000 4001 TEST(Hover, PREDEFINEMACROS_TEST(GlobalVarIntCastNoCrash)) { 4002 Annotations T(R"cpp( 4003 using uintptr_t = __UINTPTR_TYPE__; 4004 unsigned global_var; 4005 void foo() { 4006 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var); 4007 } 4008 )cpp"); 4009 4010 TestTU TU = TestTU::withCode(T.code()); 4011 TU.PredefineMacros = true; 4012 auto AST = TU.build(); 4013 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 4014 ASSERT_TRUE(HI); 4015 EXPECT_EQ(*HI->Value, "&global_var"); 4016 } 4017 4018 TEST(Hover, Typedefs) { 4019 Annotations T(R"cpp( 4020 template <bool X, typename T, typename F> 4021 struct cond { using type = T; }; 4022 template <typename T, typename F> 4023 struct cond<false, T, F> { using type = F; }; 4024 4025 template <bool X, typename T, typename F> 4026 using type = typename cond<X, T, F>::type; 4027 4028 void foo() { 4029 using f^oo = type<true, int, double>; 4030 } 4031 )cpp"); 4032 4033 TestTU TU = TestTU::withCode(T.code()); 4034 auto AST = TU.build(); 4035 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); 4036 4037 ASSERT_TRUE(H && H->Type); 4038 EXPECT_EQ(H->Type->Type, "int"); 4039 EXPECT_EQ(H->Definition, "using foo = type<true, int, double>"); 4040 } 4041 4042 TEST(Hover, EvaluateMacros) { 4043 llvm::StringRef PredefinedCXX = R"cpp( 4044 #define X 42 4045 #define SizeOf sizeof 4046 #define AlignOf alignof 4047 #define PLUS_TWO +2 4048 #define TWO 2 4049 4050 using u64 = unsigned long long; 4051 // calculate (a ** b) % p 4052 constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) { 4053 u64 ret = 1; 4054 while (b) { 4055 if (b & 1) 4056 ret = (ret * a) % p; 4057 a = (a * a) % p; 4058 b >>= 1; 4059 } 4060 return ret; 4061 } 4062 #define last_n_digit(x, y, n) \ 4063 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647)) 4064 #define declare_struct(X, name, value) \ 4065 struct X { \ 4066 constexpr auto name() { return value; } \ 4067 } 4068 #define gnu_statement_expression(value) \ 4069 ({ \ 4070 declare_struct(Widget, getter, value); \ 4071 Widget().getter(); \ 4072 }) 4073 #define define_lambda_begin(lambda, ...) \ 4074 [&](__VA_ARGS__) { 4075 #define define_lambda_end() } 4076 4077 #define left_bracket [ 4078 #define right_bracket ] 4079 #define dg_left_bracket <: 4080 #define dg_right_bracket :> 4081 #define array_decl(type, name, size) type name left_bracket size right_bracket 4082 )cpp"; 4083 4084 struct { 4085 llvm::StringRef Code; 4086 const std::function<void(std::optional<HoverInfo>, size_t /*Id*/)> 4087 Validator; 4088 } Cases[] = { 4089 { 4090 /*Code=*/R"cpp( 4091 X^; 4092 )cpp", 4093 /*Validator=*/ 4094 [](std::optional<HoverInfo> HI, size_t) { 4095 EXPECT_EQ(HI->Value, "42 (0x2a)"); 4096 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("int")); 4097 }, 4098 }, 4099 { 4100 /*Code=*/R"cpp( 4101 Size^Of(int); 4102 )cpp", 4103 /*Validator=*/ 4104 [](std::optional<HoverInfo> HI, size_t) { 4105 EXPECT_TRUE(HI->Value); 4106 EXPECT_TRUE(HI->Type); 4107 // Don't validate type or value of `sizeof` and `alignof` as we're 4108 // getting different values or desugared types on different 4109 // platforms. Same as below. 4110 }, 4111 }, 4112 { 4113 /*Code=*/R"cpp( 4114 struct Y { 4115 int y; 4116 double z; 4117 }; 4118 Alig^nOf(Y); 4119 )cpp", 4120 /*Validator=*/ 4121 [](std::optional<HoverInfo> HI, size_t) { 4122 EXPECT_TRUE(HI->Value); 4123 EXPECT_TRUE(HI->Type); 4124 }, 4125 }, 4126 { 4127 /*Code=*/R"cpp( 4128 // 2**32 == 4294967296 4129 last_n_di^git(2, 32, 6); 4130 )cpp", 4131 /*Validator=*/ 4132 [](std::optional<HoverInfo> HI, size_t) { 4133 EXPECT_EQ(HI->Value, "967296 (0xec280)"); 4134 EXPECT_EQ(HI->Type, "u64"); 4135 }, 4136 }, 4137 { 4138 /*Code=*/R"cpp( 4139 gnu_statement_exp^ression(42); 4140 )cpp", 4141 /*Validator=*/ 4142 [](std::optional<HoverInfo> HI, size_t) { 4143 EXPECT_EQ(HI->Value, "42 (0x2a)"); 4144 EXPECT_EQ(HI->Type, "int"); 4145 }, 4146 }, 4147 { 4148 /*Code=*/R"cpp( 4149 40 + PLU^S_TWO; 4150 )cpp", 4151 /*Validator=*/ 4152 [](std::optional<HoverInfo> HI, size_t) { 4153 EXPECT_EQ(HI->Value, "2"); 4154 EXPECT_EQ(HI->Type, "int"); 4155 }, 4156 }, 4157 { 4158 /*Code=*/R"cpp( 4159 40 PLU^S_TWO; 4160 )cpp", 4161 /*Validator=*/ 4162 [](std::optional<HoverInfo> HI, size_t) { 4163 EXPECT_FALSE(HI->Value) << HI->Value; 4164 EXPECT_FALSE(HI->Type) << HI->Type; 4165 }, 4166 }, 4167 { 4168 /*Code=*/R"cpp( 4169 40 + TW^O; 4170 )cpp", 4171 /*Validator=*/ 4172 [](std::optional<HoverInfo> HI, size_t) { 4173 EXPECT_EQ(HI->Value, "2"); 4174 EXPECT_EQ(HI->Type, "int"); 4175 }, 4176 }, 4177 { 4178 /*Code=*/R"cpp( 4179 arra^y_decl(int, vector, 10); 4180 vector left_b^racket 3 right_b^racket; 4181 vector dg_le^ft_bracket 3 dg_righ^t_bracket; 4182 )cpp", 4183 /*Validator=*/ 4184 [](std::optional<HoverInfo> HI, size_t Id) { 4185 switch (Id) { 4186 case 0: 4187 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("int[10]")); 4188 break; 4189 case 1: 4190 case 2: 4191 case 3: 4192 case 4: 4193 EXPECT_FALSE(HI->Type) << HI->Type; 4194 EXPECT_FALSE(HI->Value) << HI->Value; 4195 break; 4196 default: 4197 ASSERT_TRUE(false) << "Unhandled id: " << Id; 4198 } 4199 }, 4200 }, 4201 { 4202 /*Code=*/R"cpp( 4203 constexpr auto value = define_lamb^da_begin(lambda, int, char) 4204 // Check if the expansion range is right. 4205 return ^last_n_digit(10, 3, 3)^; 4206 define_lam^bda_end(); 4207 )cpp", 4208 /*Validator=*/ 4209 [](std::optional<HoverInfo> HI, size_t Id) { 4210 switch (Id) { 4211 case 0: 4212 EXPECT_FALSE(HI->Value); 4213 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("const (lambda)")); 4214 break; 4215 case 1: 4216 EXPECT_EQ(HI->Value, "0"); 4217 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("u64")); 4218 break; 4219 case 2: 4220 EXPECT_FALSE(HI); 4221 break; 4222 case 3: 4223 EXPECT_FALSE(HI->Type) << HI->Type; 4224 EXPECT_FALSE(HI->Value) << HI->Value; 4225 break; 4226 default: 4227 ASSERT_TRUE(false) << "Unhandled id: " << Id; 4228 } 4229 }, 4230 }, 4231 }; 4232 4233 Config Cfg; 4234 Cfg.Hover.ShowAKA = false; 4235 WithContextValue WithCfg(Config::Key, std::move(Cfg)); 4236 for (const auto &C : Cases) { 4237 Annotations Code( 4238 (PredefinedCXX + "void function() {\n" + C.Code + "}\n").str()); 4239 auto TU = TestTU::withCode(Code.code()); 4240 TU.ExtraArgs.push_back("-std=c++17"); 4241 auto AST = TU.build(); 4242 for (auto [Index, Position] : llvm::enumerate(Code.points())) { 4243 C.Validator(getHover(AST, Position, format::getLLVMStyle(), nullptr), 4244 Index); 4245 } 4246 } 4247 4248 Annotations C(R"c( 4249 #define alignof _Alignof 4250 void foo() { 4251 al^ignof(struct { int x; char y[10]; }); 4252 } 4253 )c"); 4254 4255 auto TU = TestTU::withCode(C.code()); 4256 TU.Filename = "TestTU.c"; 4257 TU.ExtraArgs = { 4258 "-std=c17", 4259 }; 4260 auto AST = TU.build(); 4261 auto H = getHover(AST, C.point(), format::getLLVMStyle(), nullptr); 4262 4263 ASSERT_TRUE(H); 4264 EXPECT_TRUE(H->Value); 4265 EXPECT_TRUE(H->Type); 4266 } 4267 } // namespace 4268 } // namespace clangd 4269 } // namespace clang 4270