clang-tools 19.0.0git
HoverTests.cpp
Go to the documentation of this file.
1//===-- HoverTests.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AST.h"
10#include "Annotations.h"
11#include "Config.h"
12#include "Hover.h"
13#include "TestFS.h"
14#include "TestIndex.h"
15#include "TestTU.h"
16#include "index/MemIndex.h"
17#include "clang/AST/Attr.h"
18#include "clang/Format/Format.h"
19#include "clang/Index/IndexSymbol.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
22
23#include "gtest/gtest.h"
24#include <functional>
25#include <optional>
26#include <string>
27#include <vector>
28
29namespace clang {
30namespace clangd {
31namespace {
32
33using PassMode = HoverInfo::PassType::PassMode;
34
35std::string guard(llvm::StringRef Code) {
36 return "#pragma once\n" + Code.str();
37}
38
39TEST(Hover, Structured) {
40 struct {
41 const char *const Code;
42 const std::function<void(HoverInfo &)> ExpectedBuilder;
43 } Cases[] = {
44 // Global scope.
45 {R"cpp(
46 // Best foo ever.
47 void [[fo^o]]() {}
48 )cpp",
49 [](HoverInfo &HI) {
50 HI.NamespaceScope = "";
51 HI.Name = "foo";
52 HI.Kind = index::SymbolKind::Function;
53 HI.Documentation = "Best foo ever.";
54 HI.Definition = "void foo()";
55 HI.ReturnType = "void";
56 HI.Type = "void ()";
57 HI.Parameters.emplace();
58 }},
59 // Inside namespace
60 {R"cpp(
61 namespace ns1 { namespace ns2 {
62 /// Best foo ever.
63 void [[fo^o]]() {}
64 }}
65 )cpp",
66 [](HoverInfo &HI) {
67 HI.NamespaceScope = "ns1::ns2::";
68 HI.Name = "foo";
69 HI.Kind = index::SymbolKind::Function;
70 HI.Documentation = "Best foo ever.";
71 HI.Definition = "void foo()";
72 HI.ReturnType = "void";
73 HI.Type = "void ()";
74 HI.Parameters.emplace();
75 }},
76 // Field
77 {R"cpp(
78 namespace ns1 { namespace ns2 {
79 class Foo {
80 char [[b^ar]];
81 double y[2];
82 };
83 }}
84 )cpp",
85 [](HoverInfo &HI) {
86 HI.NamespaceScope = "ns1::ns2::";
87 HI.LocalScope = "Foo::";
88 HI.Name = "bar";
89 HI.Kind = index::SymbolKind::Field;
90 HI.Definition = "char bar";
91 HI.Type = "char";
92 HI.Offset = 0;
93 HI.Size = 8;
94 HI.Padding = 56;
95 HI.Align = 8;
96 HI.AccessSpecifier = "private";
97 }},
98 // Union field
99 {R"cpp(
100 union Foo {
101 char [[b^ar]];
102 double y[2];
103 };
104 )cpp",
105 [](HoverInfo &HI) {
106 HI.NamespaceScope = "";
107 HI.LocalScope = "Foo::";
108 HI.Name = "bar";
109 HI.Kind = index::SymbolKind::Field;
110 HI.Definition = "char bar";
111 HI.Type = "char";
112 HI.Size = 8;
113 HI.Padding = 120;
114 HI.Align = 8;
115 HI.AccessSpecifier = "public";
116 }},
117 // Bitfield
118 {R"cpp(
119 struct Foo {
120 int [[^x]] : 1;
121 int y : 1;
122 };
123 )cpp",
124 [](HoverInfo &HI) {
125 HI.NamespaceScope = "";
126 HI.LocalScope = "Foo::";
127 HI.Name = "x";
128 HI.Kind = index::SymbolKind::Field;
129 HI.Definition = "int x : 1";
130 HI.Type = "int";
131 HI.Offset = 0;
132 HI.Size = 1;
133 HI.Align = 32;
134 HI.AccessSpecifier = "public";
135 }},
136 // Local to class method.
137 {R"cpp(
138 namespace ns1 { namespace ns2 {
139 struct Foo {
140 void foo() {
141 int [[b^ar]];
142 }
143 };
144 }}
145 )cpp",
146 [](HoverInfo &HI) {
147 HI.NamespaceScope = "ns1::ns2::";
148 HI.LocalScope = "Foo::foo::";
149 HI.Name = "bar";
150 HI.Kind = index::SymbolKind::Variable;
151 HI.Definition = "int bar";
152 HI.Type = "int";
153 }},
154 // Predefined variable
155 {R"cpp(
156 void foo() {
157 [[__f^unc__]];
158 }
159 )cpp",
160 [](HoverInfo &HI) {
161 HI.Name = "__func__";
162 HI.Kind = index::SymbolKind::Variable;
163 HI.Documentation =
164 "Name of the current function (predefined variable)";
165 HI.Value = "\"foo\"";
166 HI.Type = "const char[4]";
167 }},
168 // Predefined variable (dependent)
169 {R"cpp(
170 template<int> void foo() {
171 [[__f^unc__]];
172 }
173 )cpp",
174 [](HoverInfo &HI) {
175 HI.Name = "__func__";
176 HI.Kind = index::SymbolKind::Variable;
177 HI.Documentation =
178 "Name of the current function (predefined variable)";
179 HI.Type = "const char[]";
180 }},
181 // Anon namespace and local scope.
182 {R"cpp(
183 namespace ns1 { namespace {
184 struct {
185 char [[b^ar]];
186 } T;
187 }}
188 )cpp",
189 [](HoverInfo &HI) {
190 HI.NamespaceScope = "ns1::";
191 HI.LocalScope = "(anonymous struct)::";
192 HI.Name = "bar";
193 HI.Kind = index::SymbolKind::Field;
194 HI.Definition = "char bar";
195 HI.Type = "char";
196 HI.Offset = 0;
197 HI.Size = 8;
198 HI.Align = 8;
199 HI.AccessSpecifier = "public";
200 }},
201 // Struct definition shows size.
202 {R"cpp(
203 struct [[^X]]{};
204 )cpp",
205 [](HoverInfo &HI) {
206 HI.NamespaceScope = "";
207 HI.Name = "X";
208 HI.Kind = index::SymbolKind::Struct;
209 HI.Definition = "struct X {}";
210 HI.Size = 8;
211 HI.Align = 8;
212 }},
213 // Variable with template type
214 {R"cpp(
215 template <typename T, class... Ts> class Foo { public: Foo(int); };
216 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
217 )cpp",
218 [](HoverInfo &HI) {
219 HI.NamespaceScope = "";
220 HI.Name = "foo";
221 HI.Kind = index::SymbolKind::Variable;
222 HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
223 HI.Type = "Foo<int, char, bool>";
224 }},
225 // Implicit template instantiation
226 {R"cpp(
227 template <typename T> class vector{};
228 [[vec^tor]]<int> foo;
229 )cpp",
230 [](HoverInfo &HI) {
231 HI.NamespaceScope = "";
232 HI.Name = "vector<int>";
233 HI.Kind = index::SymbolKind::Class;
234 HI.Definition = "template <> class vector<int> {}";
235 }},
236 // Class template
237 {R"cpp(
238 template <template<typename, bool...> class C,
239 typename = char,
240 int = 0,
241 bool Q = false,
242 class... Ts> class Foo final {};
243 template <template<typename, bool...> class T>
244 [[F^oo]]<T> foo;
245 )cpp",
246 [](HoverInfo &HI) {
247 HI.NamespaceScope = "";
248 HI.Name = "Foo";
249 HI.Kind = index::SymbolKind::Class;
250 HI.Definition =
251 R"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
252 bool Q = false, class... Ts>
253class Foo final {})cpp";
254 HI.TemplateParameters = {
255 {{"template <typename, bool...> class"},
256 std::string("C"),
257 std::nullopt},
258 {{"typename"}, std::nullopt, std::string("char")},
259 {{"int"}, std::nullopt, std::string("0")},
260 {{"bool"}, std::string("Q"), std::string("false")},
261 {{"class..."}, std::string("Ts"), std::nullopt},
262 };
263 }},
264 // Function template
265 {R"cpp(
266 template <template<typename, bool...> class C,
267 typename = char,
268 int = 0,
269 bool Q = false,
270 class... Ts> void foo();
271 template<typename, bool...> class Foo;
272
273 void bar() {
274 [[fo^o]]<Foo>();
275 }
276 )cpp",
277 [](HoverInfo &HI) {
278 HI.NamespaceScope = "";
279 HI.Name = "foo";
280 HI.Kind = index::SymbolKind::Function;
281 HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";
282 HI.ReturnType = "void";
283 HI.Type = "void ()";
284 HI.Parameters.emplace();
285 }},
286 // Function decl
287 {R"cpp(
288 template<typename, bool...> class Foo {};
289 Foo<bool, true, false> foo(int, bool T = false);
290
291 void bar() {
292 [[fo^o]](3);
293 }
294 )cpp",
295 [](HoverInfo &HI) {
296 HI.NamespaceScope = "";
297 HI.Name = "foo";
298 HI.Kind = index::SymbolKind::Function;
299 HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
300 HI.ReturnType = "Foo<bool, true, false>";
301 HI.Type = "Foo<bool, true, false> (int, bool)";
302 HI.Parameters = {
303 {{"int"}, std::nullopt, std::nullopt},
304 {{"bool"}, std::string("T"), std::string("false")},
305 };
306 }},
307 // Pointers to lambdas
308 {R"cpp(
309 void foo() {
310 auto lamb = [](int T, bool B) -> bool { return T && B; };
311 auto *b = &lamb;
312 auto *[[^c]] = &b;
313 }
314 )cpp",
315 [](HoverInfo &HI) {
316 HI.NamespaceScope = "";
317 HI.LocalScope = "foo::";
318 HI.Name = "c";
319 HI.Kind = index::SymbolKind::Variable;
320 HI.Definition = "auto *c = &b";
321 HI.Type = "(lambda) **";
322 HI.ReturnType = "bool";
323 HI.Parameters = {
324 {{"int"}, std::string("T"), std::nullopt},
325 {{"bool"}, std::string("B"), std::nullopt},
326 };
327 return HI;
328 }},
329 // Lambda parameter with decltype reference
330 {R"cpp(
331 auto lamb = [](int T, bool B) -> bool { return T && B; };
332 void foo(decltype(lamb)& bar) {
333 [[ba^r]](0, false);
334 }
335 )cpp",
336 [](HoverInfo &HI) {
337 HI.NamespaceScope = "";
338 HI.LocalScope = "foo::";
339 HI.Name = "bar";
340 HI.Kind = index::SymbolKind::Parameter;
341 HI.Definition = "decltype(lamb) &bar";
342 HI.Type = {"decltype(lamb) &", "(lambda) &"};
343 HI.ReturnType = "bool";
344 HI.Parameters = {
345 {{"int"}, std::string("T"), std::nullopt},
346 {{"bool"}, std::string("B"), std::nullopt},
347 };
348 return HI;
349 }},
350 // Lambda parameter with decltype
351 {R"cpp(
352 auto lamb = [](int T, bool B) -> bool { return T && B; };
353 void foo(decltype(lamb) bar) {
354 [[ba^r]](0, false);
355 }
356 )cpp",
357 [](HoverInfo &HI) {
358 HI.NamespaceScope = "";
359 HI.LocalScope = "foo::";
360 HI.Name = "bar";
361 HI.Kind = index::SymbolKind::Parameter;
362 HI.Definition = "decltype(lamb) bar";
363 HI.Type = "class (lambda)";
364 HI.ReturnType = "bool";
365 HI.Parameters = {
366 {{"int"}, std::string("T"), std::nullopt},
367 {{"bool"}, std::string("B"), std::nullopt},
368 };
369 HI.Value = "false";
370 return HI;
371 }},
372 // Lambda variable
373 {R"cpp(
374 void foo() {
375 int bar = 5;
376 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
377 bool res = [[lam^b]](bar, false);
378 }
379 )cpp",
380 [](HoverInfo &HI) {
381 HI.NamespaceScope = "";
382 HI.LocalScope = "foo::";
383 HI.Name = "lamb";
384 HI.Kind = index::SymbolKind::Variable;
385 HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
386 HI.Type = "class (lambda)";
387 HI.ReturnType = "bool";
388 HI.Parameters = {
389 {{"int"}, std::string("T"), std::nullopt},
390 {{"bool"}, std::string("B"), std::nullopt},
391 };
392 return HI;
393 }},
394 // Local variable in lambda
395 {R"cpp(
396 void foo() {
397 auto lamb = []{int [[te^st]];};
398 }
399 )cpp",
400 [](HoverInfo &HI) {
401 HI.NamespaceScope = "";
402 HI.LocalScope = "foo::(anonymous class)::operator()::";
403 HI.Name = "test";
404 HI.Kind = index::SymbolKind::Variable;
405 HI.Definition = "int test";
406 HI.Type = "int";
407 }},
408 // Partially-specialized class template. (formerly type-parameter-0-0)
409 {R"cpp(
410 template <typename T> class X;
411 template <typename T> class [[^X]]<T*> {};
412 )cpp",
413 [](HoverInfo &HI) {
414 HI.Name = "X<T *>";
415 HI.NamespaceScope = "";
416 HI.Kind = index::SymbolKind::Class;
417 HI.Definition = "template <typename T> class X<T *> {}";
418 }},
419 // Constructor of partially-specialized class template
420 {R"cpp(
421 template<typename, typename=void> struct X;
422 template<typename T> struct X<T*>{ [[^X]](); };
423 )cpp",
424 [](HoverInfo &HI) {
425 HI.NamespaceScope = "";
426 HI.Name = "X";
427 HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>::
428 HI.Kind = index::SymbolKind::Constructor;
429 HI.Definition = "X()";
430 HI.Parameters.emplace();
431 HI.AccessSpecifier = "public";
432 }},
433 {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
434 [](HoverInfo &HI) {
435 HI.NamespaceScope = "";
436 HI.Name = "~X";
437 HI.LocalScope = "X::";
438 HI.Kind = index::SymbolKind::Destructor;
439 HI.Definition = "~X()";
440 HI.Parameters.emplace();
441 HI.AccessSpecifier = "private";
442 }},
443 {"class X { [[op^erator]] int(); };",
444 [](HoverInfo &HI) {
445 HI.NamespaceScope = "";
446 HI.Name = "operator int";
447 HI.LocalScope = "X::";
448 HI.Kind = index::SymbolKind::ConversionFunction;
449 HI.Definition = "operator int()";
450 HI.Parameters.emplace();
451 HI.AccessSpecifier = "private";
452 }},
453 {"class X { operator [[^X]](); };",
454 [](HoverInfo &HI) {
455 HI.NamespaceScope = "";
456 HI.Name = "X";
457 HI.Kind = index::SymbolKind::Class;
458 HI.Definition = "class X {}";
459 }},
460
461 // auto on structured bindings
462 {R"cpp(
463 void foo() {
464 struct S { int x; float y; };
465 [[au^to]] [x, y] = S();
466 }
467 )cpp",
468 [](HoverInfo &HI) {
469 HI.Name = "auto";
470 HI.Kind = index::SymbolKind::TypeAlias;
471 HI.Definition = "S";
472 }},
473 // undeduced auto
474 {R"cpp(
475 template<typename T>
476 void foo() {
477 [[au^to]] x = T{};
478 }
479 )cpp",
480 [](HoverInfo &HI) {
481 HI.Name = "auto";
482 HI.Kind = index::SymbolKind::TypeAlias;
483 HI.Definition = "/* not deduced */";
484 }},
485 // constrained auto
486 {R"cpp(
487 template <class T> concept F = true;
488 F [[au^to]] x = 1;
489 )cpp",
490 [](HoverInfo &HI) {
491 HI.Name = "auto";
492 HI.Kind = index::SymbolKind::TypeAlias;
493 HI.Definition = "int";
494 }},
495 {R"cpp(
496 template <class T> concept F = true;
497 [[^F]] auto x = 1;
498 )cpp",
499 [](HoverInfo &HI) {
500 HI.NamespaceScope = "";
501 HI.Name = "F";
502 HI.Kind = index::SymbolKind::Concept;
503 HI.Definition = "template <class T>\nconcept F = true";
504 }},
505 // auto on lambda
506 {R"cpp(
507 void foo() {
508 [[au^to]] lamb = []{};
509 }
510 )cpp",
511 [](HoverInfo &HI) {
512 HI.Name = "auto";
513 HI.Kind = index::SymbolKind::TypeAlias;
514 HI.Definition = "class(lambda)";
515 }},
516 // auto on template instantiation
517 {R"cpp(
518 template<typename T> class Foo{};
519 void foo() {
520 [[au^to]] x = Foo<int>();
521 }
522 )cpp",
523 [](HoverInfo &HI) {
524 HI.Name = "auto";
525 HI.Kind = index::SymbolKind::TypeAlias;
526 HI.Definition = "Foo<int>";
527 }},
528 // auto on specialized template
529 {R"cpp(
530 template<typename T> class Foo{};
531 template<> class Foo<int>{};
532 void foo() {
533 [[au^to]] x = Foo<int>();
534 }
535 )cpp",
536 [](HoverInfo &HI) {
537 HI.Name = "auto";
538 HI.Kind = index::SymbolKind::TypeAlias;
539 HI.Definition = "Foo<int>";
540 }},
541 // constrained template parameter
542 {R"cpp(
543 template<class T> concept Fooable = true;
544 template<[[Foo^able]] T>
545 void bar(T t) {}
546 )cpp",
547 [](HoverInfo &HI) {
548 HI.NamespaceScope = "";
549 HI.Name = "Fooable";
550 HI.Kind = index::SymbolKind::Concept;
551 HI.Definition = "template <class T>\nconcept Fooable = true";
552 }},
553 {R"cpp(
554 template<class T> concept Fooable = true;
555 template<Fooable [[T^T]]>
556 void bar(TT t) {}
557 )cpp",
558 [](HoverInfo &HI) {
559 HI.Name = "TT";
560 HI.Type = "class";
561 HI.AccessSpecifier = "public";
562 HI.NamespaceScope = "";
563 HI.LocalScope = "bar::";
564 HI.Kind = index::SymbolKind::TemplateTypeParm;
565 HI.Definition = "Fooable TT";
566 }},
567 {R"cpp(
568 template<class T> concept Fooable = true;
569 void bar([[Foo^able]] auto t) {}
570 )cpp",
571 [](HoverInfo &HI) {
572 HI.NamespaceScope = "";
573 HI.Name = "Fooable";
574 HI.Kind = index::SymbolKind::Concept;
575 HI.Definition = "template <class T>\nconcept Fooable = true";
576 }},
577 // concept reference
578 {R"cpp(
579 template<class T> concept Fooable = true;
580 auto X = [[Fooa^ble]]<int>;
581 )cpp",
582 [](HoverInfo &HI) {
583 HI.NamespaceScope = "";
584 HI.Name = "Fooable";
585 HI.Kind = index::SymbolKind::Concept;
586 HI.Definition = "template <class T>\nconcept Fooable = true";
587 HI.Value = "true";
588 }},
589
590 // empty macro
591 {R"cpp(
592 #define MACRO
593 [[MAC^RO]]
594 )cpp",
595 [](HoverInfo &HI) {
596 HI.Name = "MACRO";
597 HI.Kind = index::SymbolKind::Macro;
598 HI.Definition = "#define MACRO";
599 }},
600
601 // object-like macro
602 {R"cpp(
603 #define MACRO 41
604 int x = [[MAC^RO]];
605 )cpp",
606 [](HoverInfo &HI) {
607 HI.Name = "MACRO";
608 HI.Kind = index::SymbolKind::Macro;
609 HI.Value = "41 (0x29)";
610 HI.Type = "int";
611 HI.Definition = "#define MACRO 41\n\n"
612 "// Expands to\n"
613 "41";
614 }},
615
616 // function-like macro
617 {R"cpp(
618 // Best MACRO ever.
619 #define MACRO(x,y,z) void foo(x, y, z)
620 [[MAC^RO]](int, double d, bool z = false);
621 )cpp",
622 [](HoverInfo &HI) {
623 HI.Name = "MACRO";
624 HI.Kind = index::SymbolKind::Macro;
625 HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z)\n\n"
626 "// Expands to\n"
627 "void foo(int, double d, bool z = false)";
628 }},
629
630 // nested macro
631 {R"cpp(
632 #define STRINGIFY_AUX(s) #s
633 #define STRINGIFY(s) STRINGIFY_AUX(s)
634 #define DECL_STR(NAME, VALUE) const char *v_##NAME = STRINGIFY(VALUE)
635 #define FOO 41
636
637 [[DECL^_STR]](foo, FOO);
638 )cpp",
639 [](HoverInfo &HI) {
640 HI.Name = "DECL_STR";
641 HI.Kind = index::SymbolKind::Macro;
642 HI.Type = HoverInfo::PrintedType("const char *");
643 HI.Definition = "#define DECL_STR(NAME, VALUE) const char *v_##NAME = "
644 "STRINGIFY(VALUE)\n\n"
645 "// Expands to\n"
646 "const char *v_foo = \"41\"";
647 }},
648
649 // constexprs
650 {R"cpp(
651 constexpr int add(int a, int b) { return a + b; }
652 int [[b^ar]] = add(1, 2);
653 )cpp",
654 [](HoverInfo &HI) {
655 HI.Name = "bar";
656 HI.Definition = "int bar = add(1, 2)";
657 HI.Kind = index::SymbolKind::Variable;
658 HI.Type = "int";
659 HI.NamespaceScope = "";
660 HI.Value = "3";
661 }},
662 {R"cpp(
663 int [[b^ar]] = sizeof(char);
664 )cpp",
665 [](HoverInfo &HI) {
666 HI.Name = "bar";
667 HI.Definition = "int bar = sizeof(char)";
668 HI.Kind = index::SymbolKind::Variable;
669 HI.Type = "int";
670 HI.NamespaceScope = "";
671 HI.Value = "1";
672 }},
673 {R"cpp(
674 template<int a, int b> struct Add {
675 static constexpr int result = a + b;
676 };
677 int [[ba^r]] = Add<1, 2>::result;
678 )cpp",
679 [](HoverInfo &HI) {
680 HI.Name = "bar";
681 HI.Definition = "int bar = Add<1, 2>::result";
682 HI.Kind = index::SymbolKind::Variable;
683 HI.Type = "int";
684 HI.NamespaceScope = "";
685 HI.Value = "3";
686 }},
687 {R"cpp(
688 enum Color { RED = -123, GREEN = 5, };
689 Color x = [[GR^EEN]];
690 )cpp",
691 [](HoverInfo &HI) {
692 HI.Name = "GREEN";
693 HI.NamespaceScope = "";
694 HI.LocalScope = "Color::";
695 HI.Definition = "GREEN = 5";
696 HI.Kind = index::SymbolKind::EnumConstant;
697 HI.Type = "enum Color";
698 HI.Value = "5"; // Numeric on the enumerator name, no hex as small.
699 }},
700 {R"cpp(
701 enum Color { RED = -123, GREEN = 5, };
702 Color x = RED;
703 Color y = [[^x]];
704 )cpp",
705 [](HoverInfo &HI) {
706 HI.Name = "x";
707 HI.NamespaceScope = "";
708 HI.Definition = "Color x = RED";
709 HI.Kind = index::SymbolKind::Variable;
710 HI.Type = "Color";
711 HI.Value = "RED (0xffffff85)"; // Symbolic on an expression.
712 }},
713 {R"cpp(
714 template<int a, int b> struct Add {
715 static constexpr int result = a + b;
716 };
717 int bar = Add<1, 2>::[[resu^lt]];
718 )cpp",
719 [](HoverInfo &HI) {
720 HI.Name = "result";
721 HI.Definition = "static constexpr int result = a + b";
722 HI.Kind = index::SymbolKind::StaticProperty;
723 HI.Type = "const int";
724 HI.NamespaceScope = "";
725 HI.LocalScope = "Add<1, 2>::";
726 HI.Value = "3";
727 HI.AccessSpecifier = "public";
728 }},
729 {R"cpp(
730 using my_int = int;
731 constexpr my_int answer() { return 40 + 2; }
732 int x = [[ans^wer]]();
733 )cpp",
734 [](HoverInfo &HI) {
735 HI.Name = "answer";
736 HI.Definition = "constexpr my_int answer()";
737 HI.Kind = index::SymbolKind::Function;
738 HI.Type = {"my_int ()", "int ()"};
739 HI.ReturnType = {"my_int", "int"};
740 HI.Parameters.emplace();
741 HI.NamespaceScope = "";
742 HI.Value = "42 (0x2a)";
743 }},
744 {R"cpp(
745 const char *[[ba^r]] = "1234";
746 )cpp",
747 [](HoverInfo &HI) {
748 HI.Name = "bar";
749 HI.Definition = "const char *bar = \"1234\"";
750 HI.Kind = index::SymbolKind::Variable;
751 HI.Type = "const char *";
752 HI.NamespaceScope = "";
753 HI.Value = "&\"1234\"[0]";
754 }},
755 {R"cpp(// Should not crash
756 template <typename T>
757 struct Tmpl {
758 Tmpl(int name);
759 };
760
761 template <typename A>
762 void boom(int name) {
763 new Tmpl<A>([[na^me]]);
764 })cpp",
765 [](HoverInfo &HI) {
766 HI.Name = "name";
767 HI.Definition = "int name";
768 HI.Kind = index::SymbolKind::Parameter;
769 HI.Type = "int";
770 HI.NamespaceScope = "";
771 HI.LocalScope = "boom::";
772 }},
773 {
774 R"cpp(// Should not print inline or anon namespaces.
775 namespace ns {
776 inline namespace in_ns {
777 namespace a {
778 namespace {
779 namespace b {
780 inline namespace in_ns2 {
781 class Foo {};
782 } // in_ns2
783 } // b
784 } // anon
785 } // a
786 } // in_ns
787 } // ns
788 void foo() {
789 ns::a::b::[[F^oo]] x;
790 (void)x;
791 }
792 )cpp",
793 [](HoverInfo &HI) {
794 HI.Name = "Foo";
795 HI.Kind = index::SymbolKind::Class;
796 HI.NamespaceScope = "ns::a::b::";
797 HI.Definition = "class Foo {}";
798 }},
799 {
800 R"cpp(
801 template <typename T> class Foo {};
802 class X;
803 void foo() {
804 [[^auto]] x = Foo<X>();
805 }
806 )cpp",
807 [](HoverInfo &HI) {
808 HI.Name = "auto";
809 HI.Kind = index::SymbolKind::TypeAlias;
810 HI.Definition = "Foo<X>";
811 }},
812 {// Falls back to primary template, when the type is not instantiated.
813 R"cpp(
814 // comment from primary
815 template <typename T> class Foo {};
816 // comment from specialization
817 template <typename T> class Foo<T*> {};
818 void foo() {
819 [[Fo^o]]<int*> *x = nullptr;
820 }
821 )cpp",
822 [](HoverInfo &HI) {
823 HI.Name = "Foo<int *>";
824 HI.Kind = index::SymbolKind::Class;
825 HI.NamespaceScope = "";
826 HI.Definition = "template <> class Foo<int *>";
827 // FIXME: Maybe force instantiation to make use of real template
828 // pattern.
829 HI.Documentation = "comment from primary";
830 }},
831 {// Template Type Parameter
832 R"cpp(
833 template <typename [[^T]] = int> void foo();
834 )cpp",
835 [](HoverInfo &HI) {
836 HI.Name = "T";
837 HI.Kind = index::SymbolKind::TemplateTypeParm;
838 HI.NamespaceScope = "";
839 HI.Definition = "typename T = int";
840 HI.LocalScope = "foo::";
841 HI.Type = "typename";
842 HI.AccessSpecifier = "public";
843 }},
844 {// TemplateTemplate Type Parameter
845 R"cpp(
846 template <template<typename> class [[^T]]> void foo();
847 )cpp",
848 [](HoverInfo &HI) {
849 HI.Name = "T";
850 HI.Kind = index::SymbolKind::TemplateTemplateParm;
851 HI.NamespaceScope = "";
852 HI.Definition = "template <typename> class T";
853 HI.LocalScope = "foo::";
854 HI.Type = "template <typename> class";
855 HI.AccessSpecifier = "public";
856 }},
857 {// NonType Template Parameter
858 R"cpp(
859 template <int [[^T]] = 5> void foo();
860 )cpp",
861 [](HoverInfo &HI) {
862 HI.Name = "T";
863 HI.Kind = index::SymbolKind::NonTypeTemplateParm;
864 HI.NamespaceScope = "";
865 HI.Definition = "int T = 5";
866 HI.LocalScope = "foo::";
867 HI.Type = "int";
868 HI.AccessSpecifier = "public";
869 }},
870
871 {// Getter
872 R"cpp(
873 struct X { int Y; float [[^y]]() { return Y; } };
874 )cpp",
875 [](HoverInfo &HI) {
876 HI.Name = "y";
877 HI.Kind = index::SymbolKind::InstanceMethod;
878 HI.NamespaceScope = "";
879 HI.Definition = "float y()";
880 HI.LocalScope = "X::";
881 HI.Documentation = "Trivial accessor for `Y`.";
882 HI.Type = "float ()";
883 HI.ReturnType = "float";
884 HI.Parameters.emplace();
885 HI.AccessSpecifier = "public";
886 }},
887 {// Setter
888 R"cpp(
889 struct X { int Y; void [[^setY]](float v) { Y = v; } };
890 )cpp",
891 [](HoverInfo &HI) {
892 HI.Name = "setY";
893 HI.Kind = index::SymbolKind::InstanceMethod;
894 HI.NamespaceScope = "";
895 HI.Definition = "void setY(float v)";
896 HI.LocalScope = "X::";
897 HI.Documentation = "Trivial setter for `Y`.";
898 HI.Type = "void (float)";
899 HI.ReturnType = "void";
900 HI.Parameters.emplace();
901 HI.Parameters->emplace_back();
902 HI.Parameters->back().Type = "float";
903 HI.Parameters->back().Name = "v";
904 HI.AccessSpecifier = "public";
905 }},
906 {// Setter (builder)
907 R"cpp(
908 struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };
909 )cpp",
910 [](HoverInfo &HI) {
911 HI.Name = "setY";
912 HI.Kind = index::SymbolKind::InstanceMethod;
913 HI.NamespaceScope = "";
914 HI.Definition = "X &setY(float v)";
915 HI.LocalScope = "X::";
916 HI.Documentation = "Trivial setter for `Y`.";
917 HI.Type = "X &(float)";
918 HI.ReturnType = "X &";
919 HI.Parameters.emplace();
920 HI.Parameters->emplace_back();
921 HI.Parameters->back().Type = "float";
922 HI.Parameters->back().Name = "v";
923 HI.AccessSpecifier = "public";
924 }},
925 {// Setter (move)
926 R"cpp(
927 namespace std { template<typename T> T&& move(T&& t); }
928 struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } };
929 )cpp",
930 [](HoverInfo &HI) {
931 HI.Name = "setY";
932 HI.Kind = index::SymbolKind::InstanceMethod;
933 HI.NamespaceScope = "";
934 HI.Definition = "void setY(float v)";
935 HI.LocalScope = "X::";
936 HI.Documentation = "Trivial setter for `Y`.";
937 HI.Type = "void (float)";
938 HI.ReturnType = "void";
939 HI.Parameters.emplace();
940 HI.Parameters->emplace_back();
941 HI.Parameters->back().Type = "float";
942 HI.Parameters->back().Name = "v";
943 HI.AccessSpecifier = "public";
944 }},
945 {// Field type initializer.
946 R"cpp(
947 struct X { int x = 2; };
948 X ^[[x]];
949 )cpp",
950 [](HoverInfo &HI) {
951 HI.Name = "x";
952 HI.Kind = index::SymbolKind::Variable;
953 HI.NamespaceScope = "";
954 HI.Definition = "X x";
955 HI.Type = "X";
956 }},
957 {// Don't crash on null types.
958 R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
959 [](HoverInfo &HI) {
960 HI.Name = "x";
961 HI.Kind = index::SymbolKind::Variable;
962 HI.NamespaceScope = "";
963 HI.Definition = "";
964 HI.Type = "NULL TYPE";
965 // Bindings are in theory public members of an anonymous struct.
966 HI.AccessSpecifier = "public";
967 }},
968 {// 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]]);
974 }
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};
988 }},
989 {// make_unique-like function call
990 R"cpp(
991 struct Foo {
992 explicit Foo(int arg_a) {}
993 };
994 template<class T, class... Args>
995 T make(Args&&... args)
996 {
997 return T(args...);
998 }
999
1000 void code() {
1001 int a = 1;
1002 auto foo = make<Foo>([[^a]]);
1003 }
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};
1017 }},
1018 {
1019 R"cpp(
1020 void foobar(const float &arg);
1021 int main() {
1022 int a = 0;
1023 foobar([[^a]]);
1024 }
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};
1038 }},
1039 {
1040 R"cpp(
1041 struct Foo {
1042 explicit Foo(const float& arg) {}
1043 };
1044 int main() {
1045 int a = 0;
1046 Foo foo([[^a]]);
1047 }
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};
1061 }},
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]]);
1068 }
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};
1077 }},
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);
1084 }
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};
1095 }},
1096 {
1097 R"cpp(
1098 int add(int lhs, int rhs);
1099 int main() {
1100 add(1 [[^+]] 2, 3);
1101 }
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};
1112 }},
1113 {
1114 R"cpp(
1115 void foobar(const float &arg);
1116 int main() {
1117 foobar([[^0]]);
1118 }
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};
1127 }},
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) {}
1133 };
1134 void code() {
1135 int a = 1, b = 2;
1136 C c;
1137 c.fun([[^a]], b);
1138 }
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};
1153 }},
1154 {
1155 R"cpp(
1156 struct Foo {
1157 Foo(const int &);
1158 };
1159 void foo(Foo);
1160 void bar() {
1161 const int x = 0;
1162 foo([[^x]]);
1163 }
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};
1176 }},
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";
1191 }},
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";
1206 }},
1207 {// No crash on InitListExpr.
1208 R"cpp(
1209 struct Foo {
1210 int a[10];
1211 };
1212 constexpr Foo k2 = {
1213 ^[[{]]1} // FIXME: why the hover range is 1 character?
1214 };
1215 )cpp",
1216 [](HoverInfo &HI) {
1217 HI.Name = "expression";
1218 HI.Kind = index::SymbolKind::Unknown;
1219 HI.Type = "int[10]";
1220 HI.Value = "{1}";
1221 }},
1222 {// Var template decl
1223 R"cpp(
1224 using m_int = int;
1225
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}};
1235 }},
1236 {// Var template decl specialization
1237 R"cpp(
1238 using m_int = int;
1239
1240 template <int Size> m_int arr[Size];
1241
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]";
1250 }},
1251 {// Canonical type
1252 R"cpp(
1253 template<typename T>
1254 struct TestHover {
1255 using Type = T;
1256 };
1257
1258 void code() {
1259 TestHover<int>::Type ^[[a]];
1260 }
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"};
1269 }},
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}};
1285 }},
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}};
1300 }},
1301 {// TypeAlias Template
1302 R"cpp(
1303 template<typename T>
1304 using A = T;
1305
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}};
1318 }},
1319 {// Constant array
1320 R"cpp(
1321 using m_int = int;
1322
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]"};
1332 }},
1333 {// Incomplete array
1334 R"cpp(
1335 using m_int = int;
1336
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[]"};
1346 }},
1347 {// Dependent size array
1348 R"cpp(
1349 using m_int = int;
1350
1351 template<int Size>
1352 struct Test {
1353 m_int ^[[arr]][Size];
1354 };
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]"};
1364 }},
1365 {// Bitfield offset, size and padding
1366 R"cpp(
1367 struct Foo {
1368 char x;
1369 char [[^y]] : 1;
1370 int z;
1371 };
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);
1388
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));
1399
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);
1405
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);
1424 }
1425}
1426
1427TEST(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);
1446
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();
1452
1453 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
1454 ASSERT_TRUE(H);
1455
1456 EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage);
1457 }
1458}
1459
1460TEST(Hover, CallPassType) {
1461 const llvm::StringRef CodePrefix = R"cpp(
1462class Base {};
1463class Derived : public Base {};
1464class CustomClass {
1465 public:
1466 CustomClass() {}
1467 CustomClass(const Base &x) {}
1468 CustomClass(int &x) {}
1469 CustomClass(float x) {}
1470 CustomClass(int x, int y) {}
1471};
1472
1473void int_by_ref(int &x) {}
1474void int_by_const_ref(const int &x) {}
1475void int_by_value(int x) {}
1476void base_by_ref(Base &x) {}
1477void base_by_const_ref(const Base &x) {}
1478void base_by_value(Base x) {}
1479void float_by_value(float x) {}
1480void custom_by_value(CustomClass x) {}
1481
1482void 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 = "}";
1492
1493 struct {
1494 const char *const Code;
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},
1531 };
1532 for (const auto &Test : Tests) {
1533 SCOPED_TRACE(Test.Code);
1534
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);
1544 }
1545}
1546
1547TEST(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;
1568 };
1569 class Bar {};
1570 constexpr Foo s = ^{
1571 .xyz = Bar(),
1572 };
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;",
1581 };
1582
1583 for (const auto &Test : Tests) {
1584 SCOPED_TRACE(Test);
1585
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);
1592 }
1593}
1594
1595TEST(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)";
1605 }},
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]";
1611 }},
1612 {
1613 R"cpp(// Local variable
1614 int main() {
1615 int bonjour;
1616 ^[[bonjour]] = 2;
1617 int test1 = bonjour;
1618 }
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";
1627 }},
1628 {
1629 R"cpp(// Local variable in method
1630 struct s {
1631 void method() {
1632 int bonjour;
1633 ^[[bonjour]] = 2;
1634 }
1635 };
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";
1644 }},
1645 {
1646 R"cpp(// Struct
1647 namespace ns1 {
1648 struct MyClass {};
1649 } // namespace ns1
1650 int main() {
1651 ns1::[[My^Class]]* Params;
1652 }
1653 )cpp",
1654 [](HoverInfo &HI) {
1655 HI.Name = "MyClass";
1656 HI.Kind = index::SymbolKind::Struct;
1657 HI.NamespaceScope = "ns1::";
1658 HI.Definition = "struct MyClass {}";
1659 }},
1660 {
1661 R"cpp(// Class
1662 namespace ns1 {
1663 class MyClass {};
1664 } // namespace ns1
1665 int main() {
1666 ns1::[[My^Class]]* Params;
1667 }
1668 )cpp",
1669 [](HoverInfo &HI) {
1670 HI.Name = "MyClass";
1671 HI.Kind = index::SymbolKind::Class;
1672 HI.NamespaceScope = "ns1::";
1673 HI.Definition = "class MyClass {}";
1674 }},
1675 {
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;
1682 }
1683 )cpp",
1684 [](HoverInfo &HI) {
1685 HI.Name = "MyUnion";
1686 HI.Kind = index::SymbolKind::Union;
1687 HI.NamespaceScope = "ns1::";
1688 HI.Definition = "union MyUnion {}";
1689 }},
1690 {
1691 R"cpp(// Function definition via pointer
1692 void foo(int) {}
1693 int main() {
1694 auto *X = &^[[foo]];
1695 }
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},
1707 };
1708 }},
1709 {
1710 R"cpp(// Function declaration via call
1711 int foo(int);
1712 int main() {
1713 return ^[[foo]](42);
1714 }
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},
1726 };
1727 }},
1728 {
1729 R"cpp(// Field
1730 struct Foo { int x; };
1731 int main() {
1732 Foo bar;
1733 (void)bar.^[[x]];
1734 }
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";
1743 }},
1744 {
1745 R"cpp(// Field with initialization
1746 struct Foo { int x = 5; };
1747 int main() {
1748 Foo bar;
1749 (void)bar.^[[x]];
1750 }
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";
1759 }},
1760 {
1761 R"cpp(// Static field
1762 struct Foo { static int x; };
1763 int main() {
1764 (void)Foo::^[[x]];
1765 }
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";
1774 }},
1775 {
1776 R"cpp(// Field, member initializer
1777 struct Foo {
1778 int x;
1779 Foo() : ^[[x]](0) {}
1780 };
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";
1789 }},
1790 {
1791 R"cpp(// Field, GNU old-style field designator
1792 struct Foo { int x; };
1793 int main() {
1794 Foo bar = { ^[[x]] : 1 };
1795 }
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.
1806 }},
1807 {
1808 R"cpp(// Field, field designator
1809 struct Foo { int x; int y; };
1810 int main() {
1811 Foo bar = { .^[[x]] = 2, .y = 2 };
1812 }
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";
1821 }},
1822 {
1823 R"cpp(// Method call
1824 struct Foo { int x(); };
1825 int main() {
1826 Foo bar;
1827 bar.^[[x]]();
1828 }
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>{};
1839 }},
1840 {
1841 R"cpp(// Static method call
1842 struct Foo { static int x(); };
1843 int main() {
1844 Foo::^[[x]]();
1845 }
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>{};
1856 }},
1857 {
1858 R"cpp(// Typedef
1859 typedef int Foo;
1860 int main() {
1861 ^[[Foo]] bar;
1862 }
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";
1871 }},
1872 {
1873 R"cpp(// Typedef with embedded definition
1874 typedef struct Bar {} Foo;
1875 int main() {
1876 ^[[Foo]] bar;
1877 }
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";
1886 }},
1887 {
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 {}";
1899 }},
1900 {
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";
1915 }},
1916 {
1917 R"cpp(// Function definition via using declaration
1918 namespace ns {
1919 void foo();
1920 }
1921 int main() {
1922 using ns::foo;
1923 ^[[foo]]();
1924 }
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>{};
1935 }},
1936 {
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";
1947 }},
1948 {
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";
1961 }},
1962 {
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
1973 }},
1974 {
1975 R"cpp(// Macro
1976 #define MACRO {\
1977 return 0;\
1978 }
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; }
1987
1988// Expands to
1989{ return 0; })cpp";
1990 }},
1991 {
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";
2003 }},
2004 {
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>{};
2019 }},
2020 {
2021 R"cpp(// Enum declaration
2022 enum Hello {
2023 ONE, TWO, THREE,
2024 };
2025 void foo() {
2026 [[Hel^lo]] hello = ONE;
2027 }
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";
2035 }},
2036 {
2037 R"cpp(// Enumerator
2038 enum Hello {
2039 ONE, TWO, THREE,
2040 };
2041 void foo() {
2042 Hello hello = [[O^NE]];
2043 }
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";
2053 }},
2054 {
2055 R"cpp(// C++20's using enum
2056 enum class Hello {
2057 ONE, TWO, THREE,
2058 };
2059 void foo() {
2060 using enum Hello;
2061 Hello hello = [[O^NE]];
2062 }
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";
2072 }},
2073 {
2074 R"cpp(// Enumerator in anonymous enum
2075 enum {
2076 ONE, TWO, THREE,
2077 };
2078 void foo() {
2079 int hello = [[O^NE]];
2080 }
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";
2091 }},
2092 {
2093 R"cpp(// Global variable
2094 static int hey = 10;
2095 void foo() {
2096 [[he^y]]++;
2097 }
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)";
2108 }},
2109 {
2110 R"cpp(// Global variable in namespace
2111 namespace ns1 {
2112 static long long hey = -36637162602497;
2113 }
2114 void foo() {
2115 ns1::[[he^y]]++;
2116 }
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
2125 }},
2126 {
2127 R"cpp(// Field in anonymous struct
2128 static struct {
2129 int hello;
2130 } s;
2131 void foo() {
2132 s.[[he^llo]]++;
2133 }
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";
2142 }},
2143 {
2144 R"cpp(// Templated function
2145 template <typename T>
2146 T foo() {
2147 return 17;
2148 }
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.
2162 }},
2163 {
2164 R"cpp(// Anonymous union
2165 struct outer {
2166 union {
2167 int abc, def;
2168 } v;
2169 };
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";
2179 }},
2180 {
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";
2195 }},
2196 {
2197 R"cpp(// Simple initialization with auto
2198 void foo() {
2199 ^[[auto]] i = 1;
2200 }
2201 )cpp",
2202 [](HoverInfo &HI) {
2203 HI.Name = "auto";
2204 HI.Kind = index::SymbolKind::TypeAlias;
2205 HI.Definition = "int";
2206 }},
2207 {
2208 R"cpp(// Simple initialization with const auto
2209 void foo() {
2210 const ^[[auto]] i = 1;
2211 }
2212 )cpp",
2213 [](HoverInfo &HI) {
2214 HI.Name = "auto";
2215 HI.Kind = index::SymbolKind::TypeAlias;
2216 HI.Definition = "int";
2217 }},
2218 {
2219 R"cpp(// Simple initialization with const auto&
2220 void foo() {
2221 const ^[[auto]]& i = 1;
2222 }
2223 )cpp",
2224 [](HoverInfo &HI) {
2225 HI.Name = "auto";
2226 HI.Kind = index::SymbolKind::TypeAlias;
2227 HI.Definition = "int";
2228 }},
2229 {
2230 R"cpp(// Simple initialization with auto&
2231 void foo() {
2232 int x;
2233 ^[[auto]]& i = x;
2234 }
2235 )cpp",
2236 [](HoverInfo &HI) {
2237 HI.Name = "auto";
2238 HI.Kind = index::SymbolKind::TypeAlias;
2239 HI.Definition = "int";
2240 }},
2241 {
2242 R"cpp(// Simple initialization with auto*
2243 void foo() {
2244 int a = 1;
2245 ^[[auto]]* i = &a;
2246 }
2247 )cpp",
2248 [](HoverInfo &HI) {
2249 HI.Name = "auto";
2250 HI.Kind = index::SymbolKind::TypeAlias;
2251 HI.Definition = "int";
2252 }},
2253 {
2254 R"cpp(// Simple initialization with auto from pointer
2255 void foo() {
2256 int a = 1;
2257 ^[[auto]] i = &a;
2258 }
2259 )cpp",
2260 [](HoverInfo &HI) {
2261 HI.Name = "auto";
2262 HI.Kind = index::SymbolKind::TypeAlias;
2263 HI.Definition = "int *";
2264 }},
2265 {
2266 R"cpp(// Auto with initializer list.
2267 namespace std
2268 {
2269 template<class _E>
2270 class initializer_list {};
2271 }
2272 void foo() {
2273 ^[[auto]] i = {1,2};
2274 }
2275 )cpp",
2276 [](HoverInfo &HI) {
2277 HI.Name = "auto";
2278 HI.Kind = index::SymbolKind::TypeAlias;
2279 HI.Definition = "std::initializer_list<int>";
2280 }},
2281 {
2282 R"cpp(// User defined conversion to auto
2283 struct Bar {
2284 operator ^[[auto]]() const { return 10; }
2285 };
2286 )cpp",
2287 [](HoverInfo &HI) {
2288 HI.Name = "auto";
2289 HI.Kind = index::SymbolKind::TypeAlias;
2290 HI.Definition = "int";
2291 }},
2292 {
2293 R"cpp(// Simple initialization with decltype(auto)
2294 void foo() {
2295 ^[[decltype]](auto) i = 1;
2296 }
2297 )cpp",
2298 [](HoverInfo &HI) {
2299 HI.Name = "decltype";
2300 HI.Kind = index::SymbolKind::TypeAlias;
2301 HI.Definition = "int";
2302 }},
2303 {
2304 R"cpp(// Simple initialization with const decltype(auto)
2305 void foo() {
2306 const int j = 0;
2307 ^[[decltype]](auto) i = j;
2308 }
2309 )cpp",
2310 [](HoverInfo &HI) {
2311 HI.Name = "decltype";
2312 HI.Kind = index::SymbolKind::TypeAlias;
2313 HI.Definition = "const int";
2314 }},
2315 {
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;
2321 }
2322 )cpp",
2323 [](HoverInfo &HI) {
2324 HI.Name = "decltype";
2325 HI.Kind = index::SymbolKind::TypeAlias;
2326 HI.Definition = "const int &";
2327 }},
2328 {
2329 R"cpp(// Simple initialization with & decltype(auto)
2330 void foo() {
2331 int k = 0;
2332 int& j = k;
2333 ^[[decltype]](auto) i = j;
2334 }
2335 )cpp",
2336 [](HoverInfo &HI) {
2337 HI.Name = "decltype";
2338 HI.Kind = index::SymbolKind::TypeAlias;
2339 HI.Definition = "int &";
2340 }},
2341 {
2342 R"cpp(// simple trailing return type
2343 ^[[auto]] main() -> int {
2344 return 0;
2345 }
2346 )cpp",
2347 [](HoverInfo &HI) {
2348 HI.Name = "auto";
2349 HI.Kind = index::SymbolKind::TypeAlias;
2350 HI.Definition = "int";
2351 }},
2352 {
2353 R"cpp(// auto function return with trailing type
2354 struct Bar {};
2355 ^[[auto]] test() -> decltype(Bar()) {
2356 return Bar();
2357 }
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";
2364 }},
2365 {
2366 R"cpp(// trailing return type
2367 struct Bar {};
2368 auto test() -> ^[[decltype]](Bar()) {
2369 return Bar();
2370 }
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";
2377 }},
2378 {
2379 R"cpp(// auto in function return
2380 struct Bar {};
2381 ^[[auto]] test() {
2382 return Bar();
2383 }
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";
2390 }},
2391 {
2392 R"cpp(// auto& in function return
2393 struct Bar {};
2394 ^[[auto]]& test() {
2395 static Bar x;
2396 return x;
2397 }
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";
2404 }},
2405 {
2406 R"cpp(// auto* in function return
2407 struct Bar {};
2408 ^[[auto]]* test() {
2409 Bar* bar;
2410 return bar;
2411 }
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";
2418 }},
2419 {
2420 R"cpp(// const auto& in function return
2421 struct Bar {};
2422 const ^[[auto]]& test() {
2423 static Bar x;
2424 return x;
2425 }
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";
2432 }},
2433 {
2434 R"cpp(// decltype(auto) in function return
2435 struct Bar {};
2436 ^[[decltype]](auto) test() {
2437 return Bar();
2438 }
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";
2445 }},
2446 {
2447 R"cpp(// decltype(auto) reference in function return
2448 ^[[decltype]](auto) test() {
2449 static int a;
2450 return (a);
2451 }
2452 )cpp",
2453 [](HoverInfo &HI) {
2454 HI.Name = "decltype";
2455 HI.Kind = index::SymbolKind::TypeAlias;
2456 HI.Definition = "int &";
2457 }},
2458 {
2459 R"cpp(// decltype lvalue reference
2460 void foo() {
2461 int I = 0;
2462 ^[[decltype]](I) J = I;
2463 }
2464 )cpp",
2465 [](HoverInfo &HI) {
2466 HI.Name = "decltype";
2467 HI.Kind = index::SymbolKind::TypeAlias;
2468 HI.Definition = "int";
2469 }},
2470 {
2471 R"cpp(// decltype lvalue reference
2472 void foo() {
2473 int I= 0;
2474 int &K = I;
2475 ^[[decltype]](K) J = I;
2476 }
2477 )cpp",
2478 [](HoverInfo &HI) {
2479 HI.Name = "decltype";
2480 HI.Kind = index::SymbolKind::TypeAlias;
2481 HI.Definition = "int &";
2482 }},
2483 {
2484 R"cpp(// decltype lvalue reference parenthesis
2485 void foo() {
2486 int I = 0;
2487 ^[[decltype]]((I)) J = I;
2488 }
2489 )cpp",
2490 [](HoverInfo &HI) {
2491 HI.Name = "decltype";
2492 HI.Kind = index::SymbolKind::TypeAlias;
2493 HI.Definition = "int &";
2494 }},
2495 {
2496 R"cpp(// decltype rvalue reference
2497 void foo() {
2498 int I = 0;
2499 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
2500 }
2501 )cpp",
2502 [](HoverInfo &HI) {
2503 HI.Name = "decltype";
2504 HI.Kind = index::SymbolKind::TypeAlias;
2505 HI.Definition = "int &&";
2506 }},
2507 {
2508 R"cpp(// decltype rvalue reference function call
2509 int && bar();
2510 void foo() {
2511 int I = 0;
2512 ^[[decltype]](bar()) J = bar();
2513 }
2514 )cpp",
2515 [](HoverInfo &HI) {
2516 HI.Name = "decltype";
2517 HI.Kind = index::SymbolKind::TypeAlias;
2518 HI.Definition = "int &&";
2519 }},
2520 {
2521 R"cpp(// decltype of function with trailing return type.
2522 struct Bar {};
2523 auto test() -> decltype(Bar()) {
2524 return Bar();
2525 }
2526 void foo() {
2527 ^[[decltype]](test()) i = test();
2528 }
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.";
2536 }},
2537 {
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;
2543 }
2544 )cpp",
2545 [](HoverInfo &HI) {
2546 HI.Name = "decltype";
2547 HI.Kind = index::SymbolKind::TypeAlias;
2548 HI.Definition = "int";
2549 }},
2550 {
2551 R"cpp(// decltype of dependent type
2552 template <typename T>
2553 struct X {
2554 using Y = ^[[decltype]](T::Z);
2555 };
2556 )cpp",
2557 [](HoverInfo &HI) {
2558 HI.Name = "decltype";
2559 HI.Kind = index::SymbolKind::TypeAlias;
2560 HI.Definition = "<dependent type>";
2561 }},
2562 {
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";
2571 }},
2572 {
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 = {}";
2584 }},
2585 {
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>()";
2597 }},
2598 {
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";
2607 }},
2608 {
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";
2619 }},
2620 {
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";
2631 }},
2632 {
2633 R"cpp(// Undeduced auto declaration
2634 template<typename T>
2635 void foo() {
2636 ^[[auto]] x = T();
2637 }
2638 )cpp",
2639 [](HoverInfo &HI) {
2640 HI.Name = "auto";
2641 HI.Kind = index::SymbolKind::TypeAlias;
2642 HI.Definition = "/* not deduced */";
2643 }},
2644 {
2645 R"cpp(// Undeduced auto return type
2646 template<typename T>
2647 ^[[auto]] foo() {
2648 return T();
2649 }
2650 )cpp",
2651 [](HoverInfo &HI) {
2652 HI.Name = "auto";
2653 HI.Kind = index::SymbolKind::TypeAlias;
2654 HI.Definition = "/* not deduced */";
2655 }},
2656 {
2657 R"cpp(// Template auto parameter
2658 template<[[a^uto]] T>
2659 void func() {
2660 }
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 */";
2668 }},
2669 {
2670 R"cpp(// Undeduced decltype(auto) return type
2671 template<typename T>
2672 ^[[decltype]](auto) foo() {
2673 return T();
2674 }
2675 )cpp",
2676 [](HoverInfo &HI) {
2677 HI.Name = "decltype";
2678 HI.Kind = index::SymbolKind::TypeAlias;
2679 HI.Definition = "/* not deduced */";
2680 }},
2681 {
2682 R"cpp(// should not crash.
2683 template <class T> struct cls {
2684 int method();
2685 };
2686
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 ()";
2698 }},
2699 {
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>>>";
2710 }},
2711 {
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.";
2722 }},
2723 {
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";
2733 }},
2734 {
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";
2745 }},
2746 {
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";
2756 }},
2757 {
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}};
2772 }},
2773 {
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";
2782 }},
2783 {
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";
2792 }},
2793 {
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 = "";
2808 }},
2809 {
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";
2822 }},
2823 {
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";
2836 }},
2837 {
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";
2850 }},
2851 {
2852 R"cpp(// this expr
2853 // comment
2854 namespace ns {
2855 class Foo {
2856 Foo* bar() {
2857 return [[t^his]];
2858 }
2859 };
2860 }
2861 )cpp",
2862 [](HoverInfo &HI) {
2863 HI.Name = "this";
2864 HI.Definition = "ns::Foo *";
2865 }},
2866 {
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]];
2873 }
2874 };
2875 }
2876 )cpp",
2877 [](HoverInfo &HI) {
2878 HI.Name = "this";
2879 HI.Definition = "const Foo<T> *";
2880 }},
2881 {
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]];
2889 }
2890 };
2891 }
2892 )cpp",
2893 [](HoverInfo &HI) {
2894 HI.Name = "this";
2895 HI.Definition = "Foo<int> *";
2896 }},
2897 {
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]];
2905 }
2906 };
2907 }
2908 )cpp",
2909 [](HoverInfo &HI) {
2910 HI.Name = "this";
2911 HI.Definition = "const Foo<int, F> *";
2912 }},
2913 {
2914 R"cpp(
2915 @interface MYObject
2916 @end
2917 @interface MYObject (Private)
2918 @property(nonatomic, assign) int privateField;
2919 @end
2920
2921 int someFunction() {
2922 MYObject *obj = [MYObject sharedInstance];
2923 return obj.[[private^Field]];
2924 }
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;";
2933 }},
2934 {
2935 R"cpp(
2936 @protocol MYProtocol
2937 @property(nonatomic, assign) int prop1;
2938 @end
2939
2940 int someFunction() {
2941 id<MYProtocol> obj = 0;
2942 return obj.[[pro^p1]];
2943 }
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;";
2952 }},
2953 {
2954 R"cpp(
2955 @protocol MYProtocol
2956 @end
2957 @interface MYObject
2958 @end
2959
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";
2968 }},
2969 {R"objc(
2970 @interface Foo
2971 @end
2972
2973 @implementation Foo(Private)
2974 + (int)somePrivateMethod {
2975 int [[res^ult]] = 2;
2976 return result;
2977 }
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";
2988 }},
2989 {R"objc(
2990 @interface Foo
2991 @end
2992
2993 @implementation Foo
2994 - (int)variadicArgMethod:(id)first, ... {
2995 int [[res^ult]] = 0;
2996 return result;
2997 }
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";
3008 }},
3009 // Should not crash.
3010 {R"objc(
3011 typedef struct MyRect {} MyRect;
3012
3013 @interface IFace
3014 @property(nonatomic) MyRect frame;
3015 @end
3016
3017 MyRect foobar() {
3018 MyRect mr;
3019 return mr;
3020 }
3021 void test() {
3022 IFace *v;
3023 v.frame = [[foo^bar]]();
3024 }
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();
3034 }},
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();
3043 }},
3044 {
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;
3051 };
3052 constexpr strong_ordering strong_ordering::equal = {0};
3053 constexpr strong_ordering strong_ordering::greater = {1};
3054 constexpr strong_ordering strong_ordering::less = {-1};
3055 }
3056
3057 struct Foo
3058 {
3059 int x;
3060 // Foo spaceship
3061 auto operator<=>(const Foo&) const = default;
3062 };
3063
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";
3078 }},
3079 };
3080
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());
3088
3089 for (const auto &Case : Cases) {
3090 SCOPED_TRACE(Case.Code);
3091
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++");
3096
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);
3110
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);
3124 }
3125}
3126
3127TEST(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;
3173 }
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 = ""; }},
3182 };
3183
3184 for (const auto &Case : Cases) {
3185 Annotations Code{Case.Code};
3186 SCOPED_TRACE(Code.code());
3187
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\"");
3197
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);
3205 }
3206}
3207
3208TEST(Hover, ParseProviderInfo) {
3209 HoverInfo HIFoo;
3210 HIFoo.Name = "foo";
3211 HIFoo.Provider = "\"foo.h\"";
3212
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>`"}};
3221
3222 for (const auto &Case : Cases)
3223 EXPECT_EQ(Case.HI.present().asMarkdown(), Case.ExpectedMarkdown);
3224}
3225
3226TEST(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"};
3240 }},
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());
3249
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{};
3264 }
3265 )cpp");
3266 TU.ExtraArgs.push_back("-isystem" + testPath("system"));
3267
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);
3275 }
3276}
3277
3278TEST(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");
3286
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());
3296
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);
3301 }
3302}
3303
3304TEST(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");
3319
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");
3326 }
3327}
3328
3329TEST(Hover, NoCrash) {
3330 Annotations T(R"cpp(
3331 /* error-ok */
3332 template<typename T> T foo(T);
3333
3334 // Setter variable heuristic might fail if the callexpr is broken.
3335 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");
3336
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);
3341}
3342
3343TEST(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);
3350}
3351
3352TEST(Hover, NoCrashInt128) {
3353 Annotations T(R"cpp(
3354 constexpr __int128_t value = -4;
3355 void foo() { va^lue; }
3356 )cpp");
3357 auto TU = TestTU::withCode(T.code());
3358 // Need a triple that support __int128_t.
3359 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
3360 auto AST = TU.build();
3361 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3362 ASSERT_TRUE(H);
3363 EXPECT_EQ(H->Value, "-4 (0xfffffffc)");
3364}
3365
3366TEST(Hover, DocsFromMostSpecial) {
3367 Annotations T(R"cpp(
3368 // doc1
3369 template <typename T> class $doc1^X {};
3370 // doc2
3371 template <> class $doc2^X<int> {};
3372 // doc3
3373 template <typename T> class $doc3^X<T*> {};
3374 void foo() {
3375 X$doc1^<char>();
3376 X$doc2^<int>();
3377 X$doc3^<int*>();
3378 })cpp");
3379
3380 TestTU TU = TestTU::withCode(T.code());
3381 auto AST = TU.build();
3382 for (const auto *Comment : {"doc1", "doc2", "doc3"}) {
3383 for (const auto &P : T.points(Comment)) {
3384 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
3385 ASSERT_TRUE(H);
3386 EXPECT_EQ(H->Documentation, Comment);
3387 }
3388 }
3389}
3390
3391TEST(Hover, Present) {
3392 struct {
3393 const std::function<void(HoverInfo &)> Builder;
3394 llvm::StringRef ExpectedRender;
3395 } Cases[] = {
3396 {
3397 [](HoverInfo &HI) {
3398 HI.Kind = index::SymbolKind::Unknown;
3399 HI.Name = "X";
3400 },
3401 R"(X)",
3402 },
3403 {
3404 [](HoverInfo &HI) {
3405 HI.Kind = index::SymbolKind::NamespaceAlias;
3406 HI.Name = "foo";
3407 },
3408 R"(namespace-alias foo)",
3409 },
3410 {
3411 [](HoverInfo &HI) {
3412 HI.Kind = index::SymbolKind::Class;
3413 HI.Size = 80;
3414 HI.TemplateParameters = {
3415 {{"typename"}, std::string("T"), std::nullopt},
3416 {{"typename"}, std::string("C"), std::string("bool")},
3417 };
3418 HI.Documentation = "documentation";
3419 HI.Definition =
3420 "template <typename T, typename C = bool> class Foo {}";
3421 HI.Name = "foo";
3422 HI.NamespaceScope.emplace();
3423 },
3424 R"(class foo
3425
3426Size: 10 bytes
3427documentation
3428
3429template <typename T, typename C = bool> class Foo {})",
3430 },
3431 {
3432 [](HoverInfo &HI) {
3433 HI.Kind = index::SymbolKind::Function;
3434 HI.Name = "foo";
3435 HI.Type = {"type", "c_type"};
3436 HI.ReturnType = {"ret_type", "can_ret_type"};
3437 HI.Parameters.emplace();
3438 HoverInfo::Param P;
3439 HI.Parameters->push_back(P);
3440 P.Type = {"type", "can_type"};
3441 HI.Parameters->push_back(P);
3442 P.Name = "foo";
3443 HI.Parameters->push_back(P);
3444 P.Default = "default";
3445 HI.Parameters->push_back(P);
3446 HI.NamespaceScope = "ns::";
3447 HI.Definition = "ret_type foo(params) {}";
3448 },
3449 "function foo\n"
3450 "\n"
3451 "→ ret_type (aka can_ret_type)\n"
3452 "Parameters:\n"
3453 "- \n"
3454 "- type (aka can_type)\n"
3455 "- type foo (aka can_type)\n"
3456 "- type foo = default (aka can_type)\n"
3457 "\n"
3458 "// In namespace ns\n"
3459 "ret_type foo(params) {}",
3460 },
3461 {
3462 [](HoverInfo &HI) {
3463 HI.Kind = index::SymbolKind::Field;
3464 HI.LocalScope = "test::Bar::";
3465 HI.Value = "value";
3466 HI.Name = "foo";
3467 HI.Type = {"type", "can_type"};
3468 HI.Definition = "def";
3469 HI.Size = 32;
3470 HI.Offset = 96;
3471 HI.Padding = 32;
3472 HI.Align = 32;
3473 },
3474 R"(field foo
3475
3476Type: type (aka can_type)
3477Value = value
3478Offset: 12 bytes
3479Size: 4 bytes (+4 bytes padding), alignment 4 bytes
3480
3481// In test::Bar
3482def)",
3483 },
3484 {
3485 [](HoverInfo &HI) {
3486 HI.Kind = index::SymbolKind::Field;
3487 HI.LocalScope = "test::Bar::";
3488 HI.Value = "value";
3489 HI.Name = "foo";
3490 HI.Type = {"type", "can_type"};
3491 HI.Definition = "def";
3492 HI.Size = 25;
3493 HI.Offset = 35;
3494 HI.Padding = 4;
3495 HI.Align = 64;
3496 },
3497 R"(field foo
3498
3499Type: type (aka can_type)
3500Value = value
3501Offset: 4 bytes and 3 bits
3502Size: 25 bits (+4 bits padding), alignment 8 bytes
3503
3504// In test::Bar
3505def)",
3506 },
3507 {
3508 [](HoverInfo &HI) {
3509 HI.Kind = index::SymbolKind::Field;
3510 HI.AccessSpecifier = "public";
3511 HI.Name = "foo";
3512 HI.LocalScope = "test::Bar::";
3513 HI.Definition = "def";
3514 },
3515 R"(field foo
3516
3517// In test::Bar
3518public: def)",
3519 },
3520 {
3521 [](HoverInfo &HI) {
3522 HI.Definition = "size_t method()";
3523 HI.AccessSpecifier = "protected";
3524 HI.Kind = index::SymbolKind::InstanceMethod;
3525 HI.NamespaceScope = "";
3526 HI.LocalScope = "cls<int>::";
3527 HI.Name = "method";
3528 HI.Parameters.emplace();
3529 HI.ReturnType = {"size_t", "unsigned long"};
3530 HI.Type = {"size_t ()", "unsigned long ()"};
3531 },
3532 R"(instance-method method
3533
3534→ size_t (aka unsigned long)
3535
3536// In cls<int>
3537protected: size_t method())",
3538 },
3539 {
3540 [](HoverInfo &HI) {
3541 HI.Definition = "cls(int a, int b = 5)";
3542 HI.AccessSpecifier = "public";
3543 HI.Kind = index::SymbolKind::Constructor;
3544 HI.NamespaceScope = "";
3545 HI.LocalScope = "cls";
3546 HI.Name = "cls";
3547 HI.Parameters.emplace();
3548 HI.Parameters->emplace_back();
3549 HI.Parameters->back().Type = "int";
3550 HI.Parameters->back().Name = "a";
3551 HI.Parameters->emplace_back();
3552 HI.Parameters->back().Type = "int";
3553 HI.Parameters->back().Name = "b";
3554 HI.Parameters->back().Default = "5";
3555 },
3556 R"(constructor cls
3557
3558Parameters:
3559- int a
3560- int b = 5
3561
3562// In cls
3563public: cls(int a, int b = 5))",
3564 },
3565 {
3566 [](HoverInfo &HI) {
3567 HI.Kind = index::SymbolKind::Union;
3568 HI.AccessSpecifier = "private";
3569 HI.Name = "foo";
3570 HI.NamespaceScope = "ns1::";
3571 HI.Definition = "union foo {}";
3572 },
3573 R"(union foo
3574
3575// In namespace ns1
3576private: union foo {})",
3577 },
3578 {
3579 [](HoverInfo &HI) {
3580 HI.Kind = index::SymbolKind::Variable;
3581 HI.Name = "foo";
3582 HI.Definition = "int foo = 3";
3583 HI.LocalScope = "test::Bar::";
3584 HI.Value = "3";
3585 HI.Type = "int";
3586 HI.CalleeArgInfo.emplace();
3587 HI.CalleeArgInfo->Name = "arg_a";
3588 HI.CalleeArgInfo->Type = "int";
3589 HI.CalleeArgInfo->Default = "7";
3590 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
3591 },
3592 R"(variable foo
3593
3594Type: int
3595Value = 3
3596Passed as arg_a
3597
3598// In test::Bar
3599int foo = 3)",
3600 },
3601 {
3602 [](HoverInfo &HI) {
3603 HI.Kind = index::SymbolKind::Variable;
3604 HI.Name = "foo";
3605 HI.CalleeArgInfo.emplace();
3606 HI.CalleeArgInfo->Type = "int";
3607 HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
3608 },
3609 R"(variable foo
3610
3611Passed by value)",
3612 },
3613 {
3614 [](HoverInfo &HI) {
3615 HI.Kind = index::SymbolKind::Variable;
3616 HI.Name = "foo";
3617 HI.Definition = "int foo = 3";
3618 HI.LocalScope = "test::Bar::";
3619 HI.Value = "3";
3620 HI.Type = "int";
3621 HI.CalleeArgInfo.emplace();
3622 HI.CalleeArgInfo->Name = "arg_a";
3623 HI.CalleeArgInfo->Type = "int";
3624 HI.CalleeArgInfo->Default = "7";
3625 HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
3626 },
3627 R"(variable foo
3628
3629Type: int
3630Value = 3
3631Passed by reference as arg_a
3632
3633// In test::Bar
3634int foo = 3)",
3635 },
3636 {
3637 [](HoverInfo &HI) {
3638 HI.Kind = index::SymbolKind::Variable;
3639 HI.Name = "foo";
3640 HI.Definition = "int foo = 3";
3641 HI.LocalScope = "test::Bar::";
3642 HI.Value = "3";
3643 HI.Type = "int";
3644 HI.CalleeArgInfo.emplace();
3645 HI.CalleeArgInfo->Name = "arg_a";
3646 HI.CalleeArgInfo->Type = {"alias_int", "int"};
3647 HI.CalleeArgInfo->Default = "7";
3648 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
3649 },
3650 R"(variable foo
3651
3652Type: int
3653Value = 3
3654Passed as arg_a (converted to alias_int)
3655
3656// In test::Bar
3657int foo = 3)",
3658 },
3659 {
3660 [](HoverInfo &HI) {
3661 HI.Kind = index::SymbolKind::Macro;
3662 HI.Name = "PLUS_ONE";
3663 HI.Definition = "#define PLUS_ONE(X) (X+1)\n\n"
3664 "// Expands to\n"
3665 "(1 + 1)";
3666 },
3667 R"(macro PLUS_ONE
3668
3669#define PLUS_ONE(X) (X+1)
3670
3671// Expands to
3672(1 + 1))",
3673 },
3674 {
3675 [](HoverInfo &HI) {
3676 HI.Kind = index::SymbolKind::Variable;
3677 HI.Name = "foo";
3678 HI.Definition = "int foo = 3";
3679 HI.LocalScope = "test::Bar::";
3680 HI.Value = "3";
3681 HI.Type = "int";
3682 HI.CalleeArgInfo.emplace();
3683 HI.CalleeArgInfo->Name = "arg_a";
3684 HI.CalleeArgInfo->Type = "int";
3685 HI.CalleeArgInfo->Default = "7";
3686 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true};
3687 },
3688 R"(variable foo
3689
3690Type: int
3691Value = 3
3692Passed by const reference as arg_a (converted to int)
3693
3694// In test::Bar
3695int foo = 3)",
3696 },
3697 {
3698 [](HoverInfo &HI) {
3699 HI.Name = "stdio.h";
3700 HI.Definition = "/usr/include/stdio.h";
3701 },
3702 R"(stdio.h
3703
3704/usr/include/stdio.h)",
3705 },
3706 {[](HoverInfo &HI) {
3707 HI.Name = "foo.h";
3708 HI.UsedSymbolNames = {"Foo", "Bar", "Bar"};
3709 },
3710 R"(foo.h
3711
3712provides Foo, Bar, Bar)"},
3713 {[](HoverInfo &HI) {
3714 HI.Name = "foo.h";
3715 HI.UsedSymbolNames = {"Foo", "Bar", "Baz", "Foobar", "Qux", "Quux"};
3716 },
3717 R"(foo.h
3718
3719provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}};
3720
3721 for (const auto &C : Cases) {
3722 HoverInfo HI;
3723 C.Builder(HI);
3724 Config Cfg;
3725 Cfg.Hover.ShowAKA = true;
3726 WithContextValue WithCfg(Config::Key, std::move(Cfg));
3727 EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
3728 }
3729}
3730
3731TEST(Hover, ParseDocumentation) {
3732 struct Case {
3733 llvm::StringRef Documentation;
3734 llvm::StringRef ExpectedRenderMarkdown;
3735 llvm::StringRef ExpectedRenderPlainText;
3736 } Cases[] = {{
3737 " \n foo\nbar",
3738 "foo bar",
3739 "foo bar",
3740 },
3741 {
3742 "foo\nbar \n ",
3743 "foo bar",
3744 "foo bar",
3745 },
3746 {
3747 "foo \nbar",
3748 "foo bar",
3749 "foo bar",
3750 },
3751 {
3752 "foo \nbar",
3753 "foo bar",
3754 "foo bar",
3755 },
3756 {
3757 "foo\n\n\nbar",
3758 "foo \nbar",
3759 "foo\nbar",
3760 },
3761 {
3762 "foo\n\n\n\tbar",
3763 "foo \nbar",
3764 "foo\nbar",
3765 },
3766 {
3767 "foo\n\n\n bar",
3768 "foo \nbar",
3769 "foo\nbar",
3770 },
3771 {
3772 "foo.\nbar",
3773 "foo. \nbar",
3774 "foo.\nbar",
3775 },
3776 {
3777 "foo. \nbar",
3778 "foo. \nbar",
3779 "foo.\nbar",
3780 },
3781 {
3782 "foo\n*bar",
3783 "foo \n\\*bar",
3784 "foo\n*bar",
3785 },
3786 {
3787 "foo\nbar",
3788 "foo bar",
3789 "foo bar",
3790 },
3791 {
3792 "Tests primality of `p`.",
3793 "Tests primality of `p`.",
3794 "Tests primality of `p`.",
3795 },
3796 {
3797 "'`' should not occur in `Code`",
3798 "'\\`' should not occur in `Code`",
3799 "'`' should not occur in `Code`",
3800 },
3801 {
3802 "`not\nparsed`",
3803 "\\`not parsed\\`",
3804 "`not parsed`",
3805 }};
3806
3807 for (const auto &C : Cases) {
3808 markup::Document Output;
3809 parseDocumentation(C.Documentation, Output);
3810
3811 EXPECT_EQ(Output.asMarkdown(), C.ExpectedRenderMarkdown);
3812 EXPECT_EQ(Output.asPlainText(), C.ExpectedRenderPlainText);
3813 }
3814}
3815
3816// This is a separate test as headings don't create any differences in
3817// plaintext mode.
3818TEST(Hover, PresentHeadings) {
3819 HoverInfo HI;
3820 HI.Kind = index::SymbolKind::Variable;
3821 HI.Name = "foo";
3822
3823 EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`");
3824}
3825
3826// This is a separate test as rulers behave differently in markdown vs
3827// plaintext.
3828TEST(Hover, PresentRulers) {
3829 HoverInfo HI;
3830 HI.Kind = index::SymbolKind::Variable;
3831 HI.Name = "foo";
3832 HI.Value = "val";
3833 HI.Definition = "def";
3834
3835 llvm::StringRef ExpectedMarkdown = //
3836 "### variable `foo` \n"
3837 "\n"
3838 "---\n"
3839 "Value = `val` \n"
3840 "\n"
3841 "---\n"
3842 "```cpp\n"
3843 "def\n"
3844 "```";
3845 EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
3846
3847 llvm::StringRef ExpectedPlaintext = R"pt(variable foo
3848
3849Value = val
3850
3851def)pt";
3852 EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
3853}
3854
3855TEST(Hover, SpaceshipTemplateNoCrash) {
3856 Annotations T(R"cpp(
3857 namespace std {
3858 struct strong_ordering {
3859 int n;
3860 constexpr operator int() const { return n; }
3861 static const strong_ordering equal, greater, less;
3862 };
3863 constexpr strong_ordering strong_ordering::equal = {0};
3864 constexpr strong_ordering strong_ordering::greater = {1};
3865 constexpr strong_ordering strong_ordering::less = {-1};
3866 }
3867
3868 template <typename T>
3869 struct S {
3870 // Foo bar baz
3871 friend auto operator<=>(S, S) = default;
3872 };
3873 static_assert(S<void>() =^= S<void>());
3874 )cpp");
3875
3876 TestTU TU = TestTU::withCode(T.code());
3877 TU.ExtraArgs.push_back("-std=c++20");
3878 auto AST = TU.build();
3879 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3880 EXPECT_EQ(HI->Documentation, "Foo bar baz");
3881}
3882
3883TEST(Hover, ForwardStructNoCrash) {
3884 Annotations T(R"cpp(
3885 struct Foo;
3886 int bar;
3887 auto baz = (Fo^o*)&bar;
3888 )cpp");
3889
3890 TestTU TU = TestTU::withCode(T.code());
3891 auto AST = TU.build();
3892 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3893 ASSERT_TRUE(HI);
3894 EXPECT_EQ(*HI->Value, "&bar");
3895}
3896
3897TEST(Hover, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls) {
3898 struct {
3899 const char *const Code;
3900 const std::optional<std::string> HoverValue;
3901 } Cases[] = {
3902 {R"cpp(
3903 // error-ok testing behavior on invalid decl
3904 class Foo {};
3905 void foo(Foo p^aram = nullptr);
3906 )cpp",
3907 std::nullopt},
3908 {R"cpp(
3909 class Foo {};
3910 void foo(Foo *p^aram = nullptr);
3911 )cpp",
3912 "nullptr"},
3913 };
3914
3915 for (const auto &C : Cases) {
3916 Annotations T(C.Code);
3917 TestTU TU = TestTU::withCode(T.code());
3918 auto AST = TU.build();
3919 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3920 ASSERT_TRUE(HI);
3921 ASSERT_EQ(HI->Value, C.HoverValue);
3922 }
3923}
3924
3925TEST(Hover, DisableShowAKA) {
3926 Annotations T(R"cpp(
3927 using m_int = int;
3928 m_int ^[[a]];
3929 )cpp");
3930
3931 Config Cfg;
3932 Cfg.Hover.ShowAKA = false;
3933 WithContextValue WithCfg(Config::Key, std::move(Cfg));
3934
3935 TestTU TU = TestTU::withCode(T.code());
3936 TU.ExtraArgs.push_back("-std=c++17");
3937 auto AST = TU.build();
3938 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3939
3940 ASSERT_TRUE(H);
3941 EXPECT_EQ(H->Type, HoverInfo::PrintedType("m_int"));
3942}
3943
3944TEST(Hover, HideBigInitializers) {
3945 Annotations T(R"cpp(
3946 #define A(x) x, x, x, x
3947 #define B(x) A(A(A(A(x))))
3948 int a^rr[] = {B(0)};
3949 )cpp");
3950
3951 TestTU TU = TestTU::withCode(T.code());
3952 auto AST = TU.build();
3953 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3954
3955 ASSERT_TRUE(H);
3956 EXPECT_EQ(H->Definition, "int arr[]");
3957}
3958
3959#if defined(__aarch64__)
3960// FIXME: AARCH64 sanitizer buildbots are broken after 72142fbac4.
3961#define PREDEFINEMACROS_TEST(x) DISABLED_##x
3962#else
3963#define PREDEFINEMACROS_TEST(x) x
3964#endif
3965
3966TEST(Hover, PREDEFINEMACROS_TEST(GlobalVarEnumeralCastNoCrash)) {
3967 Annotations T(R"cpp(
3968 using uintptr_t = __UINTPTR_TYPE__;
3969 enum Test : uintptr_t {};
3970 unsigned global_var;
3971 void foo() {
3972 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));
3973 }
3974 )cpp");
3975
3976 TestTU TU = TestTU::withCode(T.code());
3977 TU.PredefineMacros = true;
3978 auto AST = TU.build();
3979 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3980 ASSERT_TRUE(HI);
3981 EXPECT_EQ(*HI->Value, "&global_var");
3982}
3983
3984TEST(Hover, PREDEFINEMACROS_TEST(GlobalVarIntCastNoCrash)) {
3985 Annotations T(R"cpp(
3986 using uintptr_t = __UINTPTR_TYPE__;
3987 unsigned global_var;
3988 void foo() {
3989 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);
3990 }
3991 )cpp");
3992
3993 TestTU TU = TestTU::withCode(T.code());
3994 TU.PredefineMacros = true;
3995 auto AST = TU.build();
3996 auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
3997 ASSERT_TRUE(HI);
3998 EXPECT_EQ(*HI->Value, "&global_var");
3999}
4000
4001TEST(Hover, Typedefs) {
4002 Annotations T(R"cpp(
4003 template <bool X, typename T, typename F>
4004 struct cond { using type = T; };
4005 template <typename T, typename F>
4006 struct cond<false, T, F> { using type = F; };
4007
4008 template <bool X, typename T, typename F>
4009 using type = typename cond<X, T, F>::type;
4010
4011 void foo() {
4012 using f^oo = type<true, int, double>;
4013 }
4014 )cpp");
4015
4016 TestTU TU = TestTU::withCode(T.code());
4017 auto AST = TU.build();
4018 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
4019
4020 ASSERT_TRUE(H && H->Type);
4021 EXPECT_EQ(H->Type->Type, "int");
4022 EXPECT_EQ(H->Definition, "using foo = type<true, int, double>");
4023}
4024
4025TEST(Hover, EvaluateMacros) {
4026 llvm::StringRef PredefinedCXX = R"cpp(
4027#define X 42
4028#define SizeOf sizeof
4029#define AlignOf alignof
4030#define PLUS_TWO +2
4031#define TWO 2
4032
4033using u64 = unsigned long long;
4034// calculate (a ** b) % p
4035constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
4036 u64 ret = 1;
4037 while (b) {
4038 if (b & 1)
4039 ret = (ret * a) % p;
4040 a = (a * a) % p;
4041 b >>= 1;
4042 }
4043 return ret;
4044}
4045#define last_n_digit(x, y, n) \
4046 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))
4047#define declare_struct(X, name, value) \
4048 struct X { \
4049 constexpr auto name() { return value; } \
4050 }
4051#define gnu_statement_expression(value) \
4052 ({ \
4053 declare_struct(Widget, getter, value); \
4054 Widget().getter(); \
4055 })
4056#define define_lambda_begin(lambda, ...) \
4057 [&](__VA_ARGS__) {
4058#define define_lambda_end() }
4059
4060#define left_bracket [
4061#define right_bracket ]
4062#define dg_left_bracket <:
4063#define dg_right_bracket :>
4064#define array_decl(type, name, size) type name left_bracket size right_bracket
4065 )cpp";
4066
4067 struct {
4068 llvm::StringRef Code;
4069 const std::function<void(std::optional<HoverInfo>, size_t /*Id*/)>
4070 Validator;
4071 } Cases[] = {
4072 {
4073 /*Code=*/R"cpp(
4074 X^;
4075 )cpp",
4076 /*Validator=*/
4077 [](std::optional<HoverInfo> HI, size_t) {
4078 EXPECT_EQ(HI->Value, "42 (0x2a)");
4079 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("int"));
4080 },
4081 },
4082 {
4083 /*Code=*/R"cpp(
4084 Size^Of(int);
4085 )cpp",
4086 /*Validator=*/
4087 [](std::optional<HoverInfo> HI, size_t) {
4088 EXPECT_TRUE(HI->Value);
4089 EXPECT_TRUE(HI->Type);
4090 // Don't validate type or value of `sizeof` and `alignof` as we're
4091 // getting different values or desugared types on different
4092 // platforms. Same as below.
4093 },
4094 },
4095 {
4096 /*Code=*/R"cpp(
4097 struct Y {
4098 int y;
4099 double z;
4100 };
4101 Alig^nOf(Y);
4102 )cpp",
4103 /*Validator=*/
4104 [](std::optional<HoverInfo> HI, size_t) {
4105 EXPECT_TRUE(HI->Value);
4106 EXPECT_TRUE(HI->Type);
4107 },
4108 },
4109 {
4110 /*Code=*/R"cpp(
4111 // 2**32 == 4294967296
4112 last_n_di^git(2, 32, 6);
4113 )cpp",
4114 /*Validator=*/
4115 [](std::optional<HoverInfo> HI, size_t) {
4116 EXPECT_EQ(HI->Value, "967296 (0xec280)");
4117 EXPECT_EQ(HI->Type, "u64");
4118 },
4119 },
4120 {
4121 /*Code=*/R"cpp(
4122 gnu_statement_exp^ression(42);
4123 )cpp",
4124 /*Validator=*/
4125 [](std::optional<HoverInfo> HI, size_t) {
4126 EXPECT_EQ(HI->Value, "42 (0x2a)");
4127 EXPECT_EQ(HI->Type, "int");
4128 },
4129 },
4130 {
4131 /*Code=*/R"cpp(
4132 40 + PLU^S_TWO;
4133 )cpp",
4134 /*Validator=*/
4135 [](std::optional<HoverInfo> HI, size_t) {
4136 EXPECT_EQ(HI->Value, "2");
4137 EXPECT_EQ(HI->Type, "int");
4138 },
4139 },
4140 {
4141 /*Code=*/R"cpp(
4142 40 PLU^S_TWO;
4143 )cpp",
4144 /*Validator=*/
4145 [](std::optional<HoverInfo> HI, size_t) {
4146 EXPECT_FALSE(HI->Value) << HI->Value;
4147 EXPECT_FALSE(HI->Type) << HI->Type;
4148 },
4149 },
4150 {
4151 /*Code=*/R"cpp(
4152 40 + TW^O;
4153 )cpp",
4154 /*Validator=*/
4155 [](std::optional<HoverInfo> HI, size_t) {
4156 EXPECT_EQ(HI->Value, "2");
4157 EXPECT_EQ(HI->Type, "int");
4158 },
4159 },
4160 {
4161 /*Code=*/R"cpp(
4162 arra^y_decl(int, vector, 10);
4163 vector left_b^racket 3 right_b^racket;
4164 vector dg_le^ft_bracket 3 dg_righ^t_bracket;
4165 )cpp",
4166 /*Validator=*/
4167 [](std::optional<HoverInfo> HI, size_t Id) {
4168 switch (Id) {
4169 case 0:
4170 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("int[10]"));
4171 break;
4172 case 1:
4173 case 2:
4174 case 3:
4175 case 4:
4176 EXPECT_FALSE(HI->Type) << HI->Type;
4177 EXPECT_FALSE(HI->Value) << HI->Value;
4178 break;
4179 default:
4180 ASSERT_TRUE(false) << "Unhandled id: " << Id;
4181 }
4182 },
4183 },
4184 {
4185 /*Code=*/R"cpp(
4186 constexpr auto value = define_lamb^da_begin(lambda, int, char)
4187 // Check if the expansion range is right.
4188 return ^last_n_digit(10, 3, 3)^;
4189 define_lam^bda_end();
4190 )cpp",
4191 /*Validator=*/
4192 [](std::optional<HoverInfo> HI, size_t Id) {
4193 switch (Id) {
4194 case 0:
4195 EXPECT_FALSE(HI->Value);
4196 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("const (lambda)"));
4197 break;
4198 case 1:
4199 EXPECT_EQ(HI->Value, "0");
4200 EXPECT_EQ(HI->Type, HoverInfo::PrintedType("u64"));
4201 break;
4202 case 2:
4203 EXPECT_FALSE(HI);
4204 break;
4205 case 3:
4206 EXPECT_FALSE(HI->Type) << HI->Type;
4207 EXPECT_FALSE(HI->Value) << HI->Value;
4208 break;
4209 default:
4210 ASSERT_TRUE(false) << "Unhandled id: " << Id;
4211 }
4212 },
4213 },
4214 };
4215
4216 Config Cfg;
4217 Cfg.Hover.ShowAKA = false;
4218 WithContextValue WithCfg(Config::Key, std::move(Cfg));
4219 for (const auto &C : Cases) {
4220 Annotations Code(
4221 (PredefinedCXX + "void function() {\n" + C.Code + "}\n").str());
4222 auto TU = TestTU::withCode(Code.code());
4223 TU.ExtraArgs.push_back("-std=c++17");
4224 auto AST = TU.build();
4225 for (auto [Index, Position] : llvm::enumerate(Code.points())) {
4226 C.Validator(getHover(AST, Position, format::getLLVMStyle(), nullptr),
4227 Index);
4228 }
4229 }
4230
4231 Annotations C(R"c(
4232 #define alignof _Alignof
4233 void foo() {
4234 al^ignof(struct { int x; char y[10]; });
4235 }
4236 )c");
4237
4238 auto TU = TestTU::withCode(C.code());
4239 TU.Filename = "TestTU.c";
4240 TU.ExtraArgs = {
4241 "-std=c17",
4242 };
4243 auto AST = TU.build();
4244 auto H = getHover(AST, C.point(), format::getLLVMStyle(), nullptr);
4245
4246 ASSERT_TRUE(H);
4247 EXPECT_TRUE(H->Value);
4248 EXPECT_TRUE(H->Type);
4249}
4250} // namespace
4251} // namespace clangd
4252} // namespace clang
CodeCompletionBuilder Builder
std::string Code
const Criteria C
#define PREDEFINEMACROS_TEST(x)
std::vector< const char * > Expected
std::string Output
Definition: TraceTests.cpp:159
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
Definition: MemIndex.cpp:17
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition: AST.cpp:348
Symbol func(llvm::StringRef Name)
Definition: TestIndex.cpp:61
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:219
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition: TestFS.cpp:93
std::optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, const format::FormatStyle &Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition: Hover.cpp:1278
TEST(BackgroundQueueTest, Priority)
void parseDocumentation(llvm::StringRef Input, markup::Document &Output)
Definition: Hover.cpp:1618
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
Definition: Config.h:48
bool ShowAKA
Whether hover show a.k.a type.
Definition: Config.h:138
struct clang::clangd::Config::@7 Hover
Configures hover feature.
ParsedAST build() const
Definition: TestTU.cpp:114
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:36