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