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