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 "Hover.h"
12 #include "TestIndex.h"
13 #include "TestTU.h"
14 #include "index/MemIndex.h"
15 #include "clang/Index/IndexSymbol.h"
16 #include "llvm/ADT/None.h"
17 #include "llvm/ADT/StringRef.h"
18
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <string>
22 #include <vector>
23
24 namespace clang {
25 namespace clangd {
26 namespace {
27
TEST(Hover,Structured)28 TEST(Hover, Structured) {
29 struct {
30 const char *const Code;
31 const std::function<void(HoverInfo &)> ExpectedBuilder;
32 } Cases[] = {
33 // Global scope.
34 {R"cpp(
35 // Best foo ever.
36 void [[fo^o]]() {}
37 )cpp",
38 [](HoverInfo &HI) {
39 HI.NamespaceScope = "";
40 HI.Name = "foo";
41 HI.Kind = index::SymbolKind::Function;
42 HI.Documentation = "Best foo ever.";
43 HI.Definition = "void foo()";
44 HI.ReturnType = "void";
45 HI.Type = "void ()";
46 HI.Parameters.emplace();
47 }},
48 // Inside namespace
49 {R"cpp(
50 namespace ns1 { namespace ns2 {
51 /// Best foo ever.
52 void [[fo^o]]() {}
53 }}
54 )cpp",
55 [](HoverInfo &HI) {
56 HI.NamespaceScope = "ns1::ns2::";
57 HI.Name = "foo";
58 HI.Kind = index::SymbolKind::Function;
59 HI.Documentation = "Best foo ever.";
60 HI.Definition = "void foo()";
61 HI.ReturnType = "void";
62 HI.Type = "void ()";
63 HI.Parameters.emplace();
64 }},
65 // Field
66 {R"cpp(
67 namespace ns1 { namespace ns2 {
68 struct Foo {
69 int [[b^ar]];
70 };
71 }}
72 )cpp",
73 [](HoverInfo &HI) {
74 HI.NamespaceScope = "ns1::ns2::";
75 HI.LocalScope = "Foo::";
76 HI.Name = "bar";
77 HI.Kind = index::SymbolKind::Field;
78 HI.Definition = "int bar";
79 HI.Type = "int";
80 }},
81 // Local to class method.
82 {R"cpp(
83 namespace ns1 { namespace ns2 {
84 struct Foo {
85 void foo() {
86 int [[b^ar]];
87 }
88 };
89 }}
90 )cpp",
91 [](HoverInfo &HI) {
92 HI.NamespaceScope = "ns1::ns2::";
93 HI.LocalScope = "Foo::foo::";
94 HI.Name = "bar";
95 HI.Kind = index::SymbolKind::Variable;
96 HI.Definition = "int bar";
97 HI.Type = "int";
98 }},
99 // Anon namespace and local scope.
100 {R"cpp(
101 namespace ns1 { namespace {
102 struct {
103 int [[b^ar]];
104 } T;
105 }}
106 )cpp",
107 [](HoverInfo &HI) {
108 HI.NamespaceScope = "ns1::";
109 HI.LocalScope = "(anonymous struct)::";
110 HI.Name = "bar";
111 HI.Kind = index::SymbolKind::Field;
112 HI.Definition = "int bar";
113 HI.Type = "int";
114 }},
115 // Variable with template type
116 {R"cpp(
117 template <typename T, class... Ts> class Foo { public: Foo(int); };
118 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
119 )cpp",
120 [](HoverInfo &HI) {
121 HI.NamespaceScope = "";
122 HI.Name = "foo";
123 HI.Kind = index::SymbolKind::Variable;
124 HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
125 HI.Type = "Foo<int, char, bool>";
126 }},
127 // Implicit template instantiation
128 {R"cpp(
129 template <typename T> class vector{};
130 [[vec^tor]]<int> foo;
131 )cpp",
132 [](HoverInfo &HI) {
133 HI.NamespaceScope = "";
134 HI.Name = "vector<int>";
135 HI.Kind = index::SymbolKind::Class;
136 HI.Definition = "template <> class vector<int> {}";
137 }},
138 // Class template
139 {R"cpp(
140 template <template<typename, bool...> class C,
141 typename = char,
142 int = 0,
143 bool Q = false,
144 class... Ts> class Foo {};
145 template <template<typename, bool...> class T>
146 [[F^oo]]<T> foo;
147 )cpp",
148 [](HoverInfo &HI) {
149 HI.NamespaceScope = "";
150 HI.Name = "Foo";
151 HI.Kind = index::SymbolKind::Class;
152 HI.Definition =
153 R"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
154 bool Q = false, class... Ts>
155 class Foo {})cpp";
156 HI.TemplateParameters = {
157 {std::string("template <typename, bool...> class"),
158 std::string("C"), llvm::None},
159 {std::string("typename"), llvm::None, std::string("char")},
160 {std::string("int"), llvm::None, std::string("0")},
161 {std::string("bool"), std::string("Q"), std::string("false")},
162 {std::string("class..."), std::string("Ts"), llvm::None},
163 };
164 }},
165 // Function template
166 {R"cpp(
167 template <template<typename, bool...> class C,
168 typename = char,
169 int = 0,
170 bool Q = false,
171 class... Ts> void foo();
172 template<typename, bool...> class Foo;
173
174 void bar() {
175 [[fo^o]]<Foo>();
176 }
177 )cpp",
178 [](HoverInfo &HI) {
179 HI.NamespaceScope = "";
180 HI.Name = "foo";
181 HI.Kind = index::SymbolKind::Function;
182 HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";
183 HI.ReturnType = "void";
184 HI.Type = "void ()";
185 HI.Parameters.emplace();
186 }},
187 // Function decl
188 {R"cpp(
189 template<typename, bool...> class Foo {};
190 Foo<bool, true, false> foo(int, bool T = false);
191
192 void bar() {
193 [[fo^o]](3);
194 }
195 )cpp",
196 [](HoverInfo &HI) {
197 HI.NamespaceScope = "";
198 HI.Name = "foo";
199 HI.Kind = index::SymbolKind::Function;
200 HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
201 HI.ReturnType = "Foo<bool, true, false>";
202 HI.Type = "Foo<bool, true, false> (int, bool)";
203 HI.Parameters = {
204 {std::string("int"), llvm::None, llvm::None},
205 {std::string("bool"), std::string("T"), std::string("false")},
206 };
207 }},
208 // Pointers to lambdas
209 {R"cpp(
210 void foo() {
211 auto lamb = [](int T, bool B) -> bool { return T && B; };
212 auto *b = &lamb;
213 auto *[[^c]] = &b;
214 }
215 )cpp",
216 [](HoverInfo &HI) {
217 HI.NamespaceScope = "";
218 HI.LocalScope = "foo::";
219 HI.Name = "c";
220 HI.Kind = index::SymbolKind::Variable;
221 HI.Definition = "auto *c = &b";
222 HI.Type = "class (lambda) **";
223 HI.ReturnType = "bool";
224 HI.Parameters = {
225 {std::string("int"), std::string("T"), llvm::None},
226 {std::string("bool"), std::string("B"), llvm::None},
227 };
228 return HI;
229 }},
230 // Lambda parameter with decltype reference
231 {R"cpp(
232 auto lamb = [](int T, bool B) -> bool { return T && B; };
233 void foo(decltype(lamb)& bar) {
234 [[ba^r]](0, false);
235 }
236 )cpp",
237 [](HoverInfo &HI) {
238 HI.NamespaceScope = "";
239 HI.LocalScope = "foo::";
240 HI.Name = "bar";
241 HI.Kind = index::SymbolKind::Parameter;
242 HI.Definition = "decltype(lamb) &bar";
243 HI.Type = "decltype(lamb) &";
244 HI.ReturnType = "bool";
245 HI.Parameters = {
246 {std::string("int"), std::string("T"), llvm::None},
247 {std::string("bool"), std::string("B"), llvm::None},
248 };
249 return HI;
250 }},
251 // Lambda parameter with decltype
252 {R"cpp(
253 auto lamb = [](int T, bool B) -> bool { return T && B; };
254 void foo(decltype(lamb) bar) {
255 [[ba^r]](0, false);
256 }
257 )cpp",
258 [](HoverInfo &HI) {
259 HI.NamespaceScope = "";
260 HI.LocalScope = "foo::";
261 HI.Name = "bar";
262 HI.Kind = index::SymbolKind::Parameter;
263 HI.Definition = "decltype(lamb) bar";
264 HI.Type = "class (lambda)";
265 HI.ReturnType = "bool";
266 HI.Parameters = {
267 {std::string("int"), std::string("T"), llvm::None},
268 {std::string("bool"), std::string("B"), llvm::None},
269 };
270 HI.Value = "false";
271 return HI;
272 }},
273 // Lambda variable
274 {R"cpp(
275 void foo() {
276 int bar = 5;
277 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
278 bool res = [[lam^b]](bar, false);
279 }
280 )cpp",
281 [](HoverInfo &HI) {
282 HI.NamespaceScope = "";
283 HI.LocalScope = "foo::";
284 HI.Name = "lamb";
285 HI.Kind = index::SymbolKind::Variable;
286 HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
287 HI.Type = "class (lambda)";
288 HI.ReturnType = "bool";
289 HI.Parameters = {
290 {std::string("int"), std::string("T"), llvm::None},
291 {std::string("bool"), std::string("B"), llvm::None},
292 };
293 return HI;
294 }},
295 // Local variable in lambda
296 {R"cpp(
297 void foo() {
298 auto lamb = []{int [[te^st]];};
299 }
300 )cpp",
301 [](HoverInfo &HI) {
302 HI.NamespaceScope = "";
303 HI.LocalScope = "foo::(anonymous class)::operator()::";
304 HI.Name = "test";
305 HI.Kind = index::SymbolKind::Variable;
306 HI.Definition = "int test";
307 HI.Type = "int";
308 }},
309 // Partially-specialized class template. (formerly type-parameter-0-0)
310 {R"cpp(
311 template <typename T> class X;
312 template <typename T> class [[^X]]<T*> {};
313 )cpp",
314 [](HoverInfo &HI) {
315 HI.Name = "X<T *>";
316 HI.NamespaceScope = "";
317 HI.Kind = index::SymbolKind::Class;
318 HI.Definition = "template <typename T> class X<T *> {}";
319 }},
320 // Constructor of partially-specialized class template
321 {R"cpp(
322 template<typename, typename=void> struct X;
323 template<typename T> struct X<T*>{ [[^X]](); };
324 )cpp",
325 [](HoverInfo &HI) {
326 HI.NamespaceScope = "";
327 HI.Name = "X";
328 HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>::
329 HI.Kind = index::SymbolKind::Constructor;
330 HI.Definition = "X()";
331 HI.Parameters.emplace();
332 }},
333 {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
334 [](HoverInfo &HI) {
335 HI.NamespaceScope = "";
336 HI.Name = "~X";
337 HI.LocalScope = "X::";
338 HI.Kind = index::SymbolKind::Destructor;
339 HI.Definition = "~X()";
340 HI.Parameters.emplace();
341 }},
342 {"class X { [[op^erator]] int(); };",
343 [](HoverInfo &HI) {
344 HI.NamespaceScope = "";
345 HI.Name = "operator int";
346 HI.LocalScope = "X::";
347 HI.Kind = index::SymbolKind::ConversionFunction;
348 HI.Definition = "operator int()";
349 HI.Parameters.emplace();
350 }},
351 {"class X { operator [[^X]]*(); };",
352 [](HoverInfo &HI) {
353 HI.NamespaceScope = "";
354 HI.Name = "X";
355 HI.Kind = index::SymbolKind::Class;
356 HI.Definition = "class X {}";
357 }},
358
359 // auto on lambda
360 {R"cpp(
361 void foo() {
362 [[au^to]] lamb = []{};
363 }
364 )cpp",
365 [](HoverInfo &HI) {
366 HI.Name = "(lambda)";
367 HI.Kind = index::SymbolKind::Class;
368 }},
369 // auto on template instantiation
370 {R"cpp(
371 template<typename T> class Foo{};
372 void foo() {
373 [[au^to]] x = Foo<int>();
374 }
375 )cpp",
376 [](HoverInfo &HI) {
377 HI.Name = "Foo<int>";
378 HI.Kind = index::SymbolKind::Class;
379 }},
380 // auto on specialized template
381 {R"cpp(
382 template<typename T> class Foo{};
383 template<> class Foo<int>{};
384 void foo() {
385 [[au^to]] x = Foo<int>();
386 }
387 )cpp",
388 [](HoverInfo &HI) {
389 HI.Name = "Foo<int>";
390 HI.Kind = index::SymbolKind::Class;
391 }},
392
393 // macro
394 {R"cpp(
395 // Best MACRO ever.
396 #define MACRO(x,y,z) void foo(x, y, z);
397 [[MAC^RO]](int, double d, bool z = false);
398 )cpp",
399 [](HoverInfo &HI) {
400 HI.Name = "MACRO", HI.Kind = index::SymbolKind::Macro,
401 HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z);";
402 }},
403
404 // constexprs
405 {R"cpp(
406 constexpr int add(int a, int b) { return a + b; }
407 int [[b^ar]] = add(1, 2);
408 )cpp",
409 [](HoverInfo &HI) {
410 HI.Name = "bar";
411 HI.Definition = "int bar = add(1, 2)";
412 HI.Kind = index::SymbolKind::Variable;
413 HI.Type = "int";
414 HI.NamespaceScope = "";
415 HI.Value = "3";
416 }},
417 {R"cpp(
418 int [[b^ar]] = sizeof(char);
419 )cpp",
420 [](HoverInfo &HI) {
421 HI.Name = "bar";
422 HI.Definition = "int bar = sizeof(char)";
423 HI.Kind = index::SymbolKind::Variable;
424 HI.Type = "int";
425 HI.NamespaceScope = "";
426 HI.Value = "1";
427 }},
428 {R"cpp(
429 template<int a, int b> struct Add {
430 static constexpr int result = a + b;
431 };
432 int [[ba^r]] = Add<1, 2>::result;
433 )cpp",
434 [](HoverInfo &HI) {
435 HI.Name = "bar";
436 HI.Definition = "int bar = Add<1, 2>::result";
437 HI.Kind = index::SymbolKind::Variable;
438 HI.Type = "int";
439 HI.NamespaceScope = "";
440 HI.Value = "3";
441 }},
442 {R"cpp(
443 enum Color { RED, GREEN, };
444 Color x = [[GR^EEN]];
445 )cpp",
446 [](HoverInfo &HI) {
447 HI.Name = "GREEN";
448 HI.NamespaceScope = "";
449 HI.LocalScope = "Color::";
450 HI.Definition = "GREEN";
451 HI.Kind = index::SymbolKind::EnumConstant;
452 HI.Type = "enum Color";
453 HI.Value = "1"; // Numeric when hovering on the enumerator name.
454 }},
455 {R"cpp(
456 enum Color { RED, GREEN, };
457 Color x = GREEN;
458 Color y = [[^x]];
459 )cpp",
460 [](HoverInfo &HI) {
461 HI.Name = "x";
462 HI.NamespaceScope = "";
463 HI.Definition = "Color x = GREEN";
464 HI.Kind = index::SymbolKind::Variable;
465 HI.Type = "enum Color";
466 HI.Value = "GREEN (1)"; // Symbolic when hovering on an expression.
467 }},
468 {R"cpp(
469 template<int a, int b> struct Add {
470 static constexpr int result = a + b;
471 };
472 int bar = Add<1, 2>::[[resu^lt]];
473 )cpp",
474 [](HoverInfo &HI) {
475 HI.Name = "result";
476 HI.Definition = "static constexpr int result = 1 + 2";
477 HI.Kind = index::SymbolKind::StaticProperty;
478 HI.Type = "const int";
479 HI.NamespaceScope = "";
480 HI.LocalScope = "Add<1, 2>::";
481 HI.Value = "3";
482 }},
483 {R"cpp(
484 constexpr int answer() { return 40 + 2; }
485 int x = [[ans^wer]]();
486 )cpp",
487 [](HoverInfo &HI) {
488 HI.Name = "answer";
489 HI.Definition = "constexpr int answer()";
490 HI.Kind = index::SymbolKind::Function;
491 HI.Type = "int ()";
492 HI.ReturnType = "int";
493 HI.Parameters.emplace();
494 HI.NamespaceScope = "";
495 HI.Value = "42";
496 }},
497 {R"cpp(
498 const char *[[ba^r]] = "1234";
499 )cpp",
500 [](HoverInfo &HI) {
501 HI.Name = "bar";
502 HI.Definition = "const char *bar = \"1234\"";
503 HI.Kind = index::SymbolKind::Variable;
504 HI.Type = "const char *";
505 HI.NamespaceScope = "";
506 HI.Value = "&\"1234\"[0]";
507 }},
508 {R"cpp(// Should not crash
509 template <typename T>
510 struct Tmpl {
511 Tmpl(int name);
512 };
513
514 template <typename A>
515 void boom(int name) {
516 new Tmpl<A>([[na^me]]);
517 })cpp",
518 [](HoverInfo &HI) {
519 HI.Name = "name";
520 HI.Definition = "int name";
521 HI.Kind = index::SymbolKind::Parameter;
522 HI.Type = "int";
523 HI.NamespaceScope = "";
524 HI.LocalScope = "boom::";
525 }},
526 {
527 R"cpp(// Should not print inline or anon namespaces.
528 namespace ns {
529 inline namespace in_ns {
530 namespace a {
531 namespace {
532 namespace b {
533 inline namespace in_ns2 {
534 class Foo {};
535 } // in_ns2
536 } // b
537 } // anon
538 } // a
539 } // in_ns
540 } // ns
541 void foo() {
542 ns::a::b::[[F^oo]] x;
543 (void)x;
544 }
545 )cpp",
546 [](HoverInfo &HI) {
547 HI.Name = "Foo";
548 HI.Kind = index::SymbolKind::Class;
549 HI.NamespaceScope = "ns::a::b::";
550 HI.Definition = "class Foo {}";
551 }},
552 {
553 R"cpp(
554 template <typename T> class Foo {};
555 class X;
556 void foo() {
557 [[^auto]] x = Foo<X>();
558 }
559 )cpp",
560 [](HoverInfo &HI) {
561 HI.Name = "Foo<X>";
562 HI.Kind = index::SymbolKind::Class;
563 }},
564 {// Falls back to primary template, when the type is not instantiated.
565 R"cpp(
566 // comment from primary
567 template <typename T> class Foo {};
568 // comment from specialization
569 template <typename T> class Foo<T*> {};
570 void foo() {
571 [[Fo^o]]<int*> *x = nullptr;
572 }
573 )cpp",
574 [](HoverInfo &HI) {
575 HI.Name = "Foo<int *>";
576 HI.Kind = index::SymbolKind::Class;
577 HI.NamespaceScope = "";
578 HI.Definition = "template <> class Foo<int *>";
579 // FIXME: Maybe force instantiation to make use of real template
580 // pattern.
581 HI.Documentation = "comment from primary";
582 }},
583 };
584 for (const auto &Case : Cases) {
585 SCOPED_TRACE(Case.Code);
586
587 Annotations T(Case.Code);
588 TestTU TU = TestTU::withCode(T.code());
589 TU.ExtraArgs.push_back("-std=c++17");
590 // FIXME: This is no longer necessary, as the default behavior is no delayed
591 // parsing in the triplet below.
592 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
593 // Types might be different depending on the target triplet, we chose a
594 // fixed one to make sure tests passes on different platform.
595 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
596 auto AST = TU.build();
597 ASSERT_TRUE(AST.getDiagnostics().empty());
598
599 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
600 ASSERT_TRUE(H);
601 HoverInfo Expected;
602 Expected.SymRange = T.range();
603 Case.ExpectedBuilder(Expected);
604
605 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
606 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
607 EXPECT_EQ(H->Name, Expected.Name);
608 EXPECT_EQ(H->Kind, Expected.Kind);
609 EXPECT_EQ(H->Documentation, Expected.Documentation);
610 EXPECT_EQ(H->Definition, Expected.Definition);
611 EXPECT_EQ(H->Type, Expected.Type);
612 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
613 EXPECT_EQ(H->Parameters, Expected.Parameters);
614 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
615 EXPECT_EQ(H->SymRange, Expected.SymRange);
616 EXPECT_EQ(H->Value, Expected.Value);
617 }
618 }
619
TEST(Hover,NoHover)620 TEST(Hover, NoHover) {
621 llvm::StringRef Tests[] = {
622 "^int main() {}",
623 "void foo() {^}",
624 R"cpp(// structured binding. Not supported yet
625 struct Bar {};
626 void foo() {
627 Bar a[2];
628 ^auto [x,y] = a;
629 }
630 )cpp",
631 R"cpp(// Template auto parameter. Nothing (Not useful).
632 template<^auto T>
633 void func() {
634 }
635 void foo() {
636 func<1>();
637 }
638 )cpp",
639 R"cpp(// non-named decls don't get hover. Don't crash!
640 ^static_assert(1, "");
641 )cpp",
642 R"cpp(// non-evaluatable expr
643 template <typename T> void foo() {
644 (void)[[size^of]](T);
645 })cpp",
646 // literals
647 "auto x = t^rue;",
648 "auto x = '^A';",
649 "auto x = ^(int){42};",
650 "auto x = ^42.;",
651 "auto x = ^42.0i;",
652 "auto x = ^42;",
653 "auto x = ^nullptr;",
654 "auto x = ^\"asdf\";",
655 };
656
657 for (const auto &Test : Tests) {
658 SCOPED_TRACE(Test);
659
660 Annotations T(Test);
661 TestTU TU = TestTU::withCode(T.code());
662 TU.ExtraArgs.push_back("-std=c++17");
663 auto AST = TU.build();
664 ASSERT_TRUE(AST.getDiagnostics().empty());
665
666 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
667 ASSERT_FALSE(H);
668 }
669 }
670
TEST(Hover,All)671 TEST(Hover, All) {
672 struct {
673 const char *const Code;
674 const std::function<void(HoverInfo &)> ExpectedBuilder;
675 } Cases[] = {
676 {
677 R"cpp(// Local variable
678 int main() {
679 int bonjour;
680 ^[[bonjour]] = 2;
681 int test1 = bonjour;
682 }
683 )cpp",
684 [](HoverInfo &HI) {
685 HI.Name = "bonjour";
686 HI.Kind = index::SymbolKind::Variable;
687 HI.NamespaceScope = "";
688 HI.LocalScope = "main::";
689 HI.Type = "int";
690 HI.Definition = "int bonjour";
691 }},
692 {
693 R"cpp(// Local variable in method
694 struct s {
695 void method() {
696 int bonjour;
697 ^[[bonjour]] = 2;
698 }
699 };
700 )cpp",
701 [](HoverInfo &HI) {
702 HI.Name = "bonjour";
703 HI.Kind = index::SymbolKind::Variable;
704 HI.NamespaceScope = "";
705 HI.LocalScope = "s::method::";
706 HI.Type = "int";
707 HI.Definition = "int bonjour";
708 }},
709 {
710 R"cpp(// Struct
711 namespace ns1 {
712 struct MyClass {};
713 } // namespace ns1
714 int main() {
715 ns1::[[My^Class]]* Params;
716 }
717 )cpp",
718 [](HoverInfo &HI) {
719 HI.Name = "MyClass";
720 HI.Kind = index::SymbolKind::Struct;
721 HI.NamespaceScope = "ns1::";
722 HI.Definition = "struct MyClass {}";
723 }},
724 {
725 R"cpp(// Class
726 namespace ns1 {
727 class MyClass {};
728 } // namespace ns1
729 int main() {
730 ns1::[[My^Class]]* Params;
731 }
732 )cpp",
733 [](HoverInfo &HI) {
734 HI.Name = "MyClass";
735 HI.Kind = index::SymbolKind::Class;
736 HI.NamespaceScope = "ns1::";
737 HI.Definition = "class MyClass {}";
738 }},
739 {
740 R"cpp(// Union
741 namespace ns1 {
742 union MyUnion { int x; int y; };
743 } // namespace ns1
744 int main() {
745 ns1::[[My^Union]] Params;
746 }
747 )cpp",
748 [](HoverInfo &HI) {
749 HI.Name = "MyUnion";
750 HI.Kind = index::SymbolKind::Union;
751 HI.NamespaceScope = "ns1::";
752 HI.Definition = "union MyUnion {}";
753 }},
754 {
755 R"cpp(// Function definition via pointer
756 void foo(int) {}
757 int main() {
758 auto *X = &^[[foo]];
759 }
760 )cpp",
761 [](HoverInfo &HI) {
762 HI.Name = "foo";
763 HI.Kind = index::SymbolKind::Function;
764 HI.NamespaceScope = "";
765 HI.Type = "void (int)";
766 HI.Definition = "void foo(int)";
767 HI.Documentation = "Function definition via pointer";
768 HI.ReturnType = "void";
769 HI.Parameters = {
770 {std::string("int"), llvm::None, llvm::None},
771 };
772 }},
773 {
774 R"cpp(// Function declaration via call
775 int foo(int);
776 int main() {
777 return ^[[foo]](42);
778 }
779 )cpp",
780 [](HoverInfo &HI) {
781 HI.Name = "foo";
782 HI.Kind = index::SymbolKind::Function;
783 HI.NamespaceScope = "";
784 HI.Type = "int (int)";
785 HI.Definition = "int foo(int)";
786 HI.Documentation = "Function declaration via call";
787 HI.ReturnType = "int";
788 HI.Parameters = {
789 {std::string("int"), llvm::None, llvm::None},
790 };
791 }},
792 {
793 R"cpp(// Field
794 struct Foo { int x; };
795 int main() {
796 Foo bar;
797 (void)bar.^[[x]];
798 }
799 )cpp",
800 [](HoverInfo &HI) {
801 HI.Name = "x";
802 HI.Kind = index::SymbolKind::Field;
803 HI.NamespaceScope = "";
804 HI.LocalScope = "Foo::";
805 HI.Type = "int";
806 HI.Definition = "int x";
807 }},
808 {
809 R"cpp(// Field with initialization
810 struct Foo { int x = 5; };
811 int main() {
812 Foo bar;
813 (void)bar.^[[x]];
814 }
815 )cpp",
816 [](HoverInfo &HI) {
817 HI.Name = "x";
818 HI.Kind = index::SymbolKind::Field;
819 HI.NamespaceScope = "";
820 HI.LocalScope = "Foo::";
821 HI.Type = "int";
822 HI.Definition = "int x = 5";
823 }},
824 {
825 R"cpp(// Static field
826 struct Foo { static int x; };
827 int main() {
828 (void)Foo::^[[x]];
829 }
830 )cpp",
831 [](HoverInfo &HI) {
832 HI.Name = "x";
833 HI.Kind = index::SymbolKind::StaticProperty;
834 HI.NamespaceScope = "";
835 HI.LocalScope = "Foo::";
836 HI.Type = "int";
837 HI.Definition = "static int x";
838 }},
839 {
840 R"cpp(// Field, member initializer
841 struct Foo {
842 int x;
843 Foo() : ^[[x]](0) {}
844 };
845 )cpp",
846 [](HoverInfo &HI) {
847 HI.Name = "x";
848 HI.Kind = index::SymbolKind::Field;
849 HI.NamespaceScope = "";
850 HI.LocalScope = "Foo::";
851 HI.Type = "int";
852 HI.Definition = "int x";
853 }},
854 {
855 R"cpp(// Field, GNU old-style field designator
856 struct Foo { int x; };
857 int main() {
858 Foo bar = { ^[[x]] : 1 };
859 }
860 )cpp",
861 [](HoverInfo &HI) {
862 HI.Name = "x";
863 HI.Kind = index::SymbolKind::Field;
864 HI.NamespaceScope = "";
865 HI.LocalScope = "Foo::";
866 HI.Type = "int";
867 HI.Definition = "int x";
868 HI.Value = "{1}";
869 }},
870 {
871 R"cpp(// Field, field designator
872 struct Foo { int x; };
873 int main() {
874 Foo bar = { .^[[x]] = 2 };
875 }
876 )cpp",
877 [](HoverInfo &HI) {
878 HI.Name = "x";
879 HI.Kind = index::SymbolKind::Field;
880 HI.NamespaceScope = "";
881 HI.LocalScope = "Foo::";
882 HI.Type = "int";
883 HI.Definition = "int x";
884 HI.Value = "{2}";
885 }},
886 {
887 R"cpp(// Method call
888 struct Foo { int x(); };
889 int main() {
890 Foo bar;
891 bar.^[[x]]();
892 }
893 )cpp",
894 [](HoverInfo &HI) {
895 HI.Name = "x";
896 HI.Kind = index::SymbolKind::InstanceMethod;
897 HI.NamespaceScope = "";
898 HI.LocalScope = "Foo::";
899 HI.Type = "int ()";
900 HI.Definition = "int x()";
901 HI.ReturnType = "int";
902 HI.Parameters = std::vector<HoverInfo::Param>{};
903 }},
904 {
905 R"cpp(// Static method call
906 struct Foo { static int x(); };
907 int main() {
908 Foo::^[[x]]();
909 }
910 )cpp",
911 [](HoverInfo &HI) {
912 HI.Name = "x";
913 HI.Kind = index::SymbolKind::StaticMethod;
914 HI.NamespaceScope = "";
915 HI.LocalScope = "Foo::";
916 HI.Type = "int ()";
917 HI.Definition = "static int x()";
918 HI.ReturnType = "int";
919 HI.Parameters = std::vector<HoverInfo::Param>{};
920 }},
921 {
922 R"cpp(// Typedef
923 typedef int Foo;
924 int main() {
925 ^[[Foo]] bar;
926 }
927 )cpp",
928 [](HoverInfo &HI) {
929 HI.Name = "Foo";
930 HI.Kind = index::SymbolKind::TypeAlias;
931 HI.NamespaceScope = "";
932 HI.Definition = "typedef int Foo";
933 HI.Documentation = "Typedef";
934 // FIXME: Maybe put underlying type into HI.Type for aliases?
935 }},
936 {
937 R"cpp(// Typedef with embedded definition
938 typedef struct Bar {} Foo;
939 int main() {
940 ^[[Foo]] bar;
941 }
942 )cpp",
943 [](HoverInfo &HI) {
944 HI.Name = "Foo";
945 HI.Kind = index::SymbolKind::TypeAlias;
946 HI.NamespaceScope = "";
947 HI.Definition = "typedef struct Bar Foo";
948 HI.Documentation = "Typedef with embedded definition";
949 }},
950 {
951 R"cpp(// Namespace
952 namespace ns {
953 struct Foo { static void bar(); };
954 } // namespace ns
955 int main() { ^[[ns]]::Foo::bar(); }
956 )cpp",
957 [](HoverInfo &HI) {
958 HI.Name = "ns";
959 HI.Kind = index::SymbolKind::Namespace;
960 HI.NamespaceScope = "";
961 HI.Definition = "namespace ns {}";
962 }},
963 {
964 R"cpp(// Anonymous namespace
965 namespace ns {
966 namespace {
967 int foo;
968 } // anonymous namespace
969 } // namespace ns
970 int main() { ns::[[f^oo]]++; }
971 )cpp",
972 [](HoverInfo &HI) {
973 HI.Name = "foo";
974 HI.Kind = index::SymbolKind::Variable;
975 HI.NamespaceScope = "ns::";
976 HI.Type = "int";
977 HI.Definition = "int foo";
978 }},
979 {
980 R"cpp(// Macro
981 #define MACRO 0
982 int main() { return ^[[MACRO]]; }
983 )cpp",
984 [](HoverInfo &HI) {
985 HI.Name = "MACRO";
986 HI.Kind = index::SymbolKind::Macro;
987 HI.Definition = "#define MACRO 0";
988 }},
989 {
990 R"cpp(// Macro
991 #define MACRO 0
992 #define MACRO2 ^[[MACRO]]
993 )cpp",
994 [](HoverInfo &HI) {
995 HI.Name = "MACRO";
996 HI.Kind = index::SymbolKind::Macro;
997 HI.Definition = "#define MACRO 0";
998 }},
999 {
1000 R"cpp(// Macro
1001 #define MACRO {\
1002 return 0;\
1003 }
1004 int main() ^[[MACRO]]
1005 )cpp",
1006 [](HoverInfo &HI) {
1007 HI.Name = "MACRO";
1008 HI.Kind = index::SymbolKind::Macro;
1009 HI.Definition =
1010 R"cpp(#define MACRO \
1011 { return 0; })cpp";
1012 }},
1013 {
1014 R"cpp(// Forward class declaration
1015 class Foo;
1016 class Foo {};
1017 [[F^oo]]* foo();
1018 )cpp",
1019 [](HoverInfo &HI) {
1020 HI.Name = "Foo";
1021 HI.Kind = index::SymbolKind::Class;
1022 HI.NamespaceScope = "";
1023 HI.Definition = "class Foo {}";
1024 HI.Documentation = "Forward class declaration";
1025 }},
1026 {
1027 R"cpp(// Function declaration
1028 void foo();
1029 void g() { [[f^oo]](); }
1030 void foo() {}
1031 )cpp",
1032 [](HoverInfo &HI) {
1033 HI.Name = "foo";
1034 HI.Kind = index::SymbolKind::Function;
1035 HI.NamespaceScope = "";
1036 HI.Type = "void ()";
1037 HI.Definition = "void foo()";
1038 HI.Documentation = "Function declaration";
1039 HI.ReturnType = "void";
1040 HI.Parameters = std::vector<HoverInfo::Param>{};
1041 }},
1042 {
1043 R"cpp(// Enum declaration
1044 enum Hello {
1045 ONE, TWO, THREE,
1046 };
1047 void foo() {
1048 [[Hel^lo]] hello = ONE;
1049 }
1050 )cpp",
1051 [](HoverInfo &HI) {
1052 HI.Name = "Hello";
1053 HI.Kind = index::SymbolKind::Enum;
1054 HI.NamespaceScope = "";
1055 HI.Definition = "enum Hello {}";
1056 HI.Documentation = "Enum declaration";
1057 }},
1058 {
1059 R"cpp(// Enumerator
1060 enum Hello {
1061 ONE, TWO, THREE,
1062 };
1063 void foo() {
1064 Hello hello = [[O^NE]];
1065 }
1066 )cpp",
1067 [](HoverInfo &HI) {
1068 HI.Name = "ONE";
1069 HI.Kind = index::SymbolKind::EnumConstant;
1070 HI.NamespaceScope = "";
1071 HI.LocalScope = "Hello::";
1072 HI.Type = "enum Hello";
1073 HI.Definition = "ONE";
1074 HI.Value = "0";
1075 }},
1076 {
1077 R"cpp(// Enumerator in anonymous enum
1078 enum {
1079 ONE, TWO, THREE,
1080 };
1081 void foo() {
1082 int hello = [[O^NE]];
1083 }
1084 )cpp",
1085 [](HoverInfo &HI) {
1086 HI.Name = "ONE";
1087 HI.Kind = index::SymbolKind::EnumConstant;
1088 HI.NamespaceScope = "";
1089 // FIXME: This should be `(anon enum)::`
1090 HI.LocalScope = "";
1091 HI.Type = "enum (anonymous)";
1092 HI.Definition = "ONE";
1093 HI.Value = "0";
1094 }},
1095 {
1096 R"cpp(// Global variable
1097 static int hey = 10;
1098 void foo() {
1099 [[he^y]]++;
1100 }
1101 )cpp",
1102 [](HoverInfo &HI) {
1103 HI.Name = "hey";
1104 HI.Kind = index::SymbolKind::Variable;
1105 HI.NamespaceScope = "";
1106 HI.Type = "int";
1107 HI.Definition = "static int hey = 10";
1108 HI.Documentation = "Global variable";
1109 // FIXME: Value shouldn't be set in this case
1110 HI.Value = "10";
1111 }},
1112 {
1113 R"cpp(// Global variable in namespace
1114 namespace ns1 {
1115 static int hey = 10;
1116 }
1117 void foo() {
1118 ns1::[[he^y]]++;
1119 }
1120 )cpp",
1121 [](HoverInfo &HI) {
1122 HI.Name = "hey";
1123 HI.Kind = index::SymbolKind::Variable;
1124 HI.NamespaceScope = "ns1::";
1125 HI.Type = "int";
1126 HI.Definition = "static int hey = 10";
1127 HI.Value = "10";
1128 }},
1129 {
1130 R"cpp(// Field in anonymous struct
1131 static struct {
1132 int hello;
1133 } s;
1134 void foo() {
1135 s.[[he^llo]]++;
1136 }
1137 )cpp",
1138 [](HoverInfo &HI) {
1139 HI.Name = "hello";
1140 HI.Kind = index::SymbolKind::Field;
1141 HI.NamespaceScope = "";
1142 HI.LocalScope = "(anonymous struct)::";
1143 HI.Type = "int";
1144 HI.Definition = "int hello";
1145 }},
1146 {
1147 R"cpp(// Templated function
1148 template <typename T>
1149 T foo() {
1150 return 17;
1151 }
1152 void g() { auto x = [[f^oo]]<int>(); }
1153 )cpp",
1154 [](HoverInfo &HI) {
1155 HI.Name = "foo";
1156 HI.Kind = index::SymbolKind::Function;
1157 HI.NamespaceScope = "";
1158 HI.Type = "int ()";
1159 HI.Definition = "template <> int foo<int>()";
1160 HI.Documentation = "Templated function";
1161 HI.ReturnType = "int";
1162 HI.Parameters = std::vector<HoverInfo::Param>{};
1163 // FIXME: We should populate template parameters with arguments in
1164 // case of instantiations.
1165 }},
1166 {
1167 R"cpp(// Anonymous union
1168 struct outer {
1169 union {
1170 int abc, def;
1171 } v;
1172 };
1173 void g() { struct outer o; o.v.[[d^ef]]++; }
1174 )cpp",
1175 [](HoverInfo &HI) {
1176 HI.Name = "def";
1177 HI.Kind = index::SymbolKind::Field;
1178 HI.NamespaceScope = "";
1179 HI.LocalScope = "outer::(anonymous union)::";
1180 HI.Type = "int";
1181 HI.Definition = "int def";
1182 }},
1183 {
1184 R"cpp(// documentation from index
1185 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
1186 void indexSymbol();
1187 void g() { [[ind^exSymbol]](); }
1188 )cpp",
1189 [](HoverInfo &HI) {
1190 HI.Name = "indexSymbol";
1191 HI.Kind = index::SymbolKind::Function;
1192 HI.NamespaceScope = "";
1193 HI.Type = "void ()";
1194 HI.Definition = "void indexSymbol()";
1195 HI.ReturnType = "void";
1196 HI.Parameters = std::vector<HoverInfo::Param>{};
1197 HI.Documentation = "comment from index";
1198 }},
1199 {
1200 R"cpp(// Simple initialization with auto
1201 void foo() {
1202 ^[[auto]] i = 1;
1203 }
1204 )cpp",
1205 [](HoverInfo &HI) {
1206 HI.Name = "int";
1207 // FIXME: Should be Builtin/Integral.
1208 HI.Kind = index::SymbolKind::Unknown;
1209 }},
1210 {
1211 R"cpp(// Simple initialization with const auto
1212 void foo() {
1213 const ^[[auto]] i = 1;
1214 }
1215 )cpp",
1216 [](HoverInfo &HI) { HI.Name = "int"; }},
1217 {
1218 R"cpp(// Simple initialization with const auto&
1219 void foo() {
1220 const ^[[auto]]& i = 1;
1221 }
1222 )cpp",
1223 [](HoverInfo &HI) { HI.Name = "int"; }},
1224 {
1225 R"cpp(// Simple initialization with auto&
1226 void foo() {
1227 int x;
1228 ^[[auto]]& i = x;
1229 }
1230 )cpp",
1231 [](HoverInfo &HI) { HI.Name = "int"; }},
1232 {
1233 R"cpp(// Simple initialization with auto*
1234 void foo() {
1235 int a = 1;
1236 ^[[auto]]* i = &a;
1237 }
1238 )cpp",
1239 [](HoverInfo &HI) { HI.Name = "int"; }},
1240 {
1241 R"cpp(// Auto with initializer list.
1242 namespace std
1243 {
1244 template<class _E>
1245 class initializer_list {};
1246 }
1247 void foo() {
1248 ^[[auto]] i = {1,2};
1249 }
1250 )cpp",
1251 [](HoverInfo &HI) {
1252 HI.Name = "initializer_list<int>";
1253 HI.Kind = index::SymbolKind::Class;
1254 }},
1255 {
1256 R"cpp(// User defined conversion to auto
1257 struct Bar {
1258 operator ^[[auto]]() const { return 10; }
1259 };
1260 )cpp",
1261 [](HoverInfo &HI) { HI.Name = "int"; }},
1262 {
1263 R"cpp(// Simple initialization with decltype(auto)
1264 void foo() {
1265 ^[[decltype]](auto) i = 1;
1266 }
1267 )cpp",
1268 [](HoverInfo &HI) { HI.Name = "int"; }},
1269 {
1270 R"cpp(// Simple initialization with const decltype(auto)
1271 void foo() {
1272 const int j = 0;
1273 ^[[decltype]](auto) i = j;
1274 }
1275 )cpp",
1276 [](HoverInfo &HI) { HI.Name = "const int"; }},
1277 {
1278 R"cpp(// Simple initialization with const& decltype(auto)
1279 void foo() {
1280 int k = 0;
1281 const int& j = k;
1282 ^[[decltype]](auto) i = j;
1283 }
1284 )cpp",
1285 [](HoverInfo &HI) { HI.Name = "const int &"; }},
1286 {
1287 R"cpp(// Simple initialization with & decltype(auto)
1288 void foo() {
1289 int k = 0;
1290 int& j = k;
1291 ^[[decltype]](auto) i = j;
1292 }
1293 )cpp",
1294 [](HoverInfo &HI) { HI.Name = "int &"; }},
1295 {
1296 R"cpp(// simple trailing return type
1297 ^[[auto]] main() -> int {
1298 return 0;
1299 }
1300 )cpp",
1301 [](HoverInfo &HI) { HI.Name = "int"; }},
1302 {
1303 R"cpp(// auto function return with trailing type
1304 struct Bar {};
1305 ^[[auto]] test() -> decltype(Bar()) {
1306 return Bar();
1307 }
1308 )cpp",
1309 [](HoverInfo &HI) {
1310 HI.Name = "Bar";
1311 HI.Kind = index::SymbolKind::Struct;
1312 HI.Documentation = "auto function return with trailing type";
1313 }},
1314 {
1315 R"cpp(// trailing return type
1316 struct Bar {};
1317 auto test() -> ^[[decltype]](Bar()) {
1318 return Bar();
1319 }
1320 )cpp",
1321 [](HoverInfo &HI) {
1322 HI.Name = "Bar";
1323 HI.Kind = index::SymbolKind::Struct;
1324 HI.Documentation = "trailing return type";
1325 }},
1326 {
1327 R"cpp(// auto in function return
1328 struct Bar {};
1329 ^[[auto]] test() {
1330 return Bar();
1331 }
1332 )cpp",
1333 [](HoverInfo &HI) {
1334 HI.Name = "Bar";
1335 HI.Kind = index::SymbolKind::Struct;
1336 HI.Documentation = "auto in function return";
1337 }},
1338 {
1339 R"cpp(// auto& in function return
1340 struct Bar {};
1341 ^[[auto]]& test() {
1342 static Bar x;
1343 return x;
1344 }
1345 )cpp",
1346 [](HoverInfo &HI) {
1347 HI.Name = "Bar";
1348 HI.Kind = index::SymbolKind::Struct;
1349 HI.Documentation = "auto& in function return";
1350 }},
1351 {
1352 R"cpp(// auto* in function return
1353 struct Bar {};
1354 ^[[auto]]* test() {
1355 Bar* bar;
1356 return bar;
1357 }
1358 )cpp",
1359 [](HoverInfo &HI) {
1360 HI.Name = "Bar";
1361 HI.Kind = index::SymbolKind::Struct;
1362 HI.Documentation = "auto* in function return";
1363 }},
1364 {
1365 R"cpp(// const auto& in function return
1366 struct Bar {};
1367 const ^[[auto]]& test() {
1368 static Bar x;
1369 return x;
1370 }
1371 )cpp",
1372 [](HoverInfo &HI) {
1373 HI.Name = "Bar";
1374 HI.Kind = index::SymbolKind::Struct;
1375 HI.Documentation = "const auto& in function return";
1376 }},
1377 {
1378 R"cpp(// decltype(auto) in function return
1379 struct Bar {};
1380 ^[[decltype]](auto) test() {
1381 return Bar();
1382 }
1383 )cpp",
1384 [](HoverInfo &HI) {
1385 HI.Name = "Bar";
1386 HI.Kind = index::SymbolKind::Struct;
1387 HI.Documentation = "decltype(auto) in function return";
1388 }},
1389 {
1390 R"cpp(// decltype(auto) reference in function return
1391 ^[[decltype]](auto) test() {
1392 static int a;
1393 return (a);
1394 }
1395 )cpp",
1396 [](HoverInfo &HI) { HI.Name = "int &"; }},
1397 {
1398 R"cpp(// decltype lvalue reference
1399 void foo() {
1400 int I = 0;
1401 ^[[decltype]](I) J = I;
1402 }
1403 )cpp",
1404 [](HoverInfo &HI) { HI.Name = "int"; }},
1405 {
1406 R"cpp(// decltype lvalue reference
1407 void foo() {
1408 int I= 0;
1409 int &K = I;
1410 ^[[decltype]](K) J = I;
1411 }
1412 )cpp",
1413 [](HoverInfo &HI) { HI.Name = "int &"; }},
1414 {
1415 R"cpp(// decltype lvalue reference parenthesis
1416 void foo() {
1417 int I = 0;
1418 ^[[decltype]]((I)) J = I;
1419 }
1420 )cpp",
1421 [](HoverInfo &HI) { HI.Name = "int &"; }},
1422 {
1423 R"cpp(// decltype rvalue reference
1424 void foo() {
1425 int I = 0;
1426 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
1427 }
1428 )cpp",
1429 [](HoverInfo &HI) { HI.Name = "int &&"; }},
1430 {
1431 R"cpp(// decltype rvalue reference function call
1432 int && bar();
1433 void foo() {
1434 int I = 0;
1435 ^[[decltype]](bar()) J = bar();
1436 }
1437 )cpp",
1438 [](HoverInfo &HI) { HI.Name = "int &&"; }},
1439 {
1440 R"cpp(// decltype of function with trailing return type.
1441 struct Bar {};
1442 auto test() -> decltype(Bar()) {
1443 return Bar();
1444 }
1445 void foo() {
1446 ^[[decltype]](test()) i = test();
1447 }
1448 )cpp",
1449 [](HoverInfo &HI) {
1450 HI.Name = "Bar";
1451 HI.Kind = index::SymbolKind::Struct;
1452 HI.Documentation =
1453 "decltype of function with trailing return type.";
1454 }},
1455 {
1456 R"cpp(// decltype of var with decltype.
1457 void foo() {
1458 int I = 0;
1459 decltype(I) J = I;
1460 ^[[decltype]](J) K = J;
1461 }
1462 )cpp",
1463 [](HoverInfo &HI) { HI.Name = "int"; }},
1464 {
1465 R"cpp(// More complicated structured types.
1466 int bar();
1467 ^[[auto]] (*foo)() = bar;
1468 )cpp",
1469 [](HoverInfo &HI) { HI.Name = "int"; }},
1470 {
1471 R"cpp(// Should not crash when evaluating the initializer.
1472 struct Test {};
1473 void test() { Test && [[te^st]] = {}; }
1474 )cpp",
1475 [](HoverInfo &HI) {
1476 HI.Name = "test";
1477 HI.Kind = index::SymbolKind::Variable;
1478 HI.NamespaceScope = "";
1479 HI.LocalScope = "test::";
1480 HI.Type = "struct Test &&";
1481 HI.Definition = "Test &&test = {}";
1482 HI.Value = "{}";
1483 }},
1484 {
1485 R"cpp(// auto on alias
1486 typedef int int_type;
1487 ^[[auto]] x = int_type();
1488 )cpp",
1489 [](HoverInfo &HI) { HI.Name = "int"; }},
1490 {
1491 R"cpp(// auto on alias
1492 struct cls {};
1493 typedef cls cls_type;
1494 ^[[auto]] y = cls_type();
1495 )cpp",
1496 [](HoverInfo &HI) {
1497 HI.Name = "cls";
1498 HI.Kind = index::SymbolKind::Struct;
1499 HI.Documentation = "auto on alias";
1500 }},
1501 {
1502 R"cpp(// auto on alias
1503 template <class>
1504 struct templ {};
1505 ^[[auto]] z = templ<int>();
1506 )cpp",
1507 [](HoverInfo &HI) {
1508 HI.Name = "templ<int>";
1509 HI.Kind = index::SymbolKind::Struct;
1510 HI.Documentation = "auto on alias";
1511 }},
1512 {
1513 R"cpp(// should not crash.
1514 template <class T> struct cls {
1515 int method();
1516 };
1517
1518 auto test = cls<int>().[[m^ethod]]();
1519 )cpp",
1520 [](HoverInfo &HI) {
1521 HI.Definition = "int method()";
1522 HI.Kind = index::SymbolKind::InstanceMethod;
1523 HI.NamespaceScope = "";
1524 HI.LocalScope = "cls<int>::";
1525 HI.Name = "method";
1526 HI.Parameters.emplace();
1527 HI.ReturnType = "int";
1528 HI.Type = "int ()";
1529 }},
1530 {
1531 R"cpp(// type of nested templates.
1532 template <class T> struct cls {};
1533 cls<cls<cls<int>>> [[fo^o]];
1534 )cpp",
1535 [](HoverInfo &HI) {
1536 HI.Definition = "cls<cls<cls<int>>> foo";
1537 HI.Kind = index::SymbolKind::Variable;
1538 HI.NamespaceScope = "";
1539 HI.Name = "foo";
1540 HI.Type = "cls<cls<cls<int> > >";
1541 HI.Value = "{}";
1542 }},
1543 {
1544 R"cpp(// type of nested templates.
1545 template <class T> struct cls {};
1546 [[cl^s]]<cls<cls<int>>> foo;
1547 )cpp",
1548 [](HoverInfo &HI) {
1549 HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
1550 HI.Kind = index::SymbolKind::Struct;
1551 HI.NamespaceScope = "";
1552 HI.Name = "cls<cls<cls<int> > >";
1553 HI.Documentation = "type of nested templates.";
1554 }},
1555 {
1556 R"cpp(// type with decltype
1557 int a;
1558 decltype(a) [[b^]] = a;)cpp",
1559 [](HoverInfo &HI) {
1560 HI.Definition = "decltype(a) b = a";
1561 HI.Kind = index::SymbolKind::Variable;
1562 HI.NamespaceScope = "";
1563 HI.Name = "b";
1564 HI.Type = "int";
1565 }},
1566 {
1567 R"cpp(// type with decltype
1568 int a;
1569 decltype(a) c;
1570 decltype(c) [[b^]] = a;)cpp",
1571 [](HoverInfo &HI) {
1572 HI.Definition = "decltype(c) b = a";
1573 HI.Kind = index::SymbolKind::Variable;
1574 HI.NamespaceScope = "";
1575 HI.Name = "b";
1576 HI.Type = "int";
1577 }},
1578 {
1579 R"cpp(// type with decltype
1580 int a;
1581 const decltype(a) [[b^]] = a;)cpp",
1582 [](HoverInfo &HI) {
1583 HI.Definition = "const decltype(a) b = a";
1584 HI.Kind = index::SymbolKind::Variable;
1585 HI.NamespaceScope = "";
1586 HI.Name = "b";
1587 HI.Type = "int";
1588 }},
1589 {
1590 R"cpp(// type with decltype
1591 int a;
1592 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
1593 [](HoverInfo &HI) {
1594 HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
1595 HI.Kind = index::SymbolKind::Function;
1596 HI.NamespaceScope = "";
1597 HI.Name = "foo";
1598 // FIXME: Handle composite types with decltype with a printing
1599 // policy.
1600 HI.Type = "auto (decltype(a)) -> decltype(a)";
1601 HI.ReturnType = "int";
1602 HI.Parameters = {
1603 {std::string("int"), std::string("x"), llvm::None}};
1604 }},
1605 {
1606 R"cpp(// sizeof expr
1607 void foo() {
1608 (void)[[size^of]](char);
1609 })cpp",
1610 [](HoverInfo &HI) {
1611 HI.Name = "expression";
1612 HI.Type = "unsigned long";
1613 HI.Value = "1";
1614 }},
1615 {
1616 R"cpp(// alignof expr
1617 void foo() {
1618 (void)[[align^of]](char);
1619 })cpp",
1620 [](HoverInfo &HI) {
1621 HI.Name = "expression";
1622 HI.Type = "unsigned long";
1623 HI.Value = "1";
1624 }},
1625 {
1626 R"cpp(
1627 template <typename T = int>
1628 void foo(const T& = T()) {
1629 [[f^oo]]<>(3);
1630 })cpp",
1631 [](HoverInfo &HI) {
1632 HI.Name = "foo";
1633 HI.Kind = index::SymbolKind::Function;
1634 HI.Type = "void (const int &)";
1635 HI.ReturnType = "void";
1636 HI.Parameters = {
1637 {std::string("const int &"), llvm::None, std::string("T()")}};
1638 HI.Definition = "template <> void foo<int>(const int &)";
1639 HI.NamespaceScope = "";
1640 }},
1641 };
1642
1643 // Create a tiny index, so tests above can verify documentation is fetched.
1644 Symbol IndexSym = func("indexSymbol");
1645 IndexSym.Documentation = "comment from index";
1646 SymbolSlab::Builder Symbols;
1647 Symbols.insert(IndexSym);
1648 auto Index =
1649 MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
1650
1651 for (const auto &Case : Cases) {
1652 SCOPED_TRACE(Case.Code);
1653
1654 Annotations T(Case.Code);
1655 TestTU TU = TestTU::withCode(T.code());
1656 TU.ExtraArgs.push_back("-std=c++17");
1657 TU.ExtraArgs.push_back("-Wno-gnu-designator");
1658 // Types might be different depending on the target triplet, we chose a
1659 // fixed one to make sure tests passes on different platform.
1660 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
1661 auto AST = TU.build();
1662 for (const auto &D : AST.getDiagnostics())
1663 ADD_FAILURE() << D;
1664 ASSERT_TRUE(AST.getDiagnostics().empty());
1665
1666 auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());
1667 ASSERT_TRUE(H);
1668 HoverInfo Expected;
1669 Expected.SymRange = T.range();
1670 Case.ExpectedBuilder(Expected);
1671
1672 SCOPED_TRACE(H->present().asPlainText());
1673 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
1674 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
1675 EXPECT_EQ(H->Name, Expected.Name);
1676 EXPECT_EQ(H->Kind, Expected.Kind);
1677 EXPECT_EQ(H->Documentation, Expected.Documentation);
1678 EXPECT_EQ(H->Definition, Expected.Definition);
1679 EXPECT_EQ(H->Type, Expected.Type);
1680 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
1681 EXPECT_EQ(H->Parameters, Expected.Parameters);
1682 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
1683 EXPECT_EQ(H->SymRange, Expected.SymRange);
1684 EXPECT_EQ(H->Value, Expected.Value);
1685 }
1686 }
1687
TEST(Hover,DocsFromIndex)1688 TEST(Hover, DocsFromIndex) {
1689 Annotations T(R"cpp(
1690 template <typename T> class X {};
1691 void foo() {
1692 au^to t = X<int>();
1693 X^<int> w;
1694 (void)w;
1695 })cpp");
1696
1697 TestTU TU = TestTU::withCode(T.code());
1698 auto AST = TU.build();
1699 for (const auto &D : AST.getDiagnostics())
1700 ADD_FAILURE() << D;
1701 ASSERT_TRUE(AST.getDiagnostics().empty());
1702
1703 Symbol IndexSym;
1704 IndexSym.ID = *getSymbolID(&findDecl(AST, "X"));
1705 IndexSym.Documentation = "comment from index";
1706 SymbolSlab::Builder Symbols;
1707 Symbols.insert(IndexSym);
1708 auto Index =
1709 MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
1710
1711 for (const auto &P : T.points()) {
1712 auto H = getHover(AST, P, format::getLLVMStyle(), Index.get());
1713 ASSERT_TRUE(H);
1714 EXPECT_EQ(H->Documentation, IndexSym.Documentation);
1715 }
1716 }
1717
TEST(Hover,DocsFromAST)1718 TEST(Hover, DocsFromAST) {
1719 Annotations T(R"cpp(
1720 // doc
1721 template <typename T> class X {};
1722 // doc
1723 template <typename T> void bar() {}
1724 // doc
1725 template <typename T> T baz;
1726 void foo() {
1727 au^to t = X<int>();
1728 X^<int>();
1729 b^ar<int>();
1730 au^to T = ba^z<X<int>>;
1731 ba^z<int> = 0;
1732 })cpp");
1733
1734 TestTU TU = TestTU::withCode(T.code());
1735 auto AST = TU.build();
1736 for (const auto &D : AST.getDiagnostics())
1737 ADD_FAILURE() << D;
1738 ASSERT_TRUE(AST.getDiagnostics().empty());
1739
1740 for (const auto &P : T.points()) {
1741 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
1742 ASSERT_TRUE(H);
1743 EXPECT_EQ(H->Documentation, "doc");
1744 }
1745 }
1746
TEST(Hover,DocsFromMostSpecial)1747 TEST(Hover, DocsFromMostSpecial) {
1748 Annotations T(R"cpp(
1749 // doc1
1750 template <typename T> class $doc1^X {};
1751 // doc2
1752 template <> class $doc2^X<int> {};
1753 // doc3
1754 template <typename T> class $doc3^X<T*> {};
1755 void foo() {
1756 X$doc1^<char>();
1757 X$doc2^<int>();
1758 X$doc3^<int*>();
1759 })cpp");
1760
1761 TestTU TU = TestTU::withCode(T.code());
1762 auto AST = TU.build();
1763 for (const auto &D : AST.getDiagnostics())
1764 ADD_FAILURE() << D;
1765 ASSERT_TRUE(AST.getDiagnostics().empty());
1766
1767 for (auto Comment : {"doc1", "doc2", "doc3"}) {
1768 for (const auto &P : T.points(Comment)) {
1769 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
1770 ASSERT_TRUE(H);
1771 EXPECT_EQ(H->Documentation, Comment);
1772 }
1773 }
1774 }
1775
TEST(Hover,Present)1776 TEST(Hover, Present) {
1777 struct {
1778 const std::function<void(HoverInfo &)> Builder;
1779 llvm::StringRef ExpectedRender;
1780 } Cases[] = {
1781 {
1782 [](HoverInfo &HI) {
1783 HI.Kind = index::SymbolKind::Unknown;
1784 HI.Name = "X";
1785 },
1786 R"(X)",
1787 },
1788 {
1789 [](HoverInfo &HI) {
1790 HI.Kind = index::SymbolKind::NamespaceAlias;
1791 HI.Name = "foo";
1792 },
1793 R"(namespace-alias foo)",
1794 },
1795 {
1796 [](HoverInfo &HI) {
1797 HI.Kind = index::SymbolKind::Class;
1798 HI.TemplateParameters = {
1799 {std::string("typename"), std::string("T"), llvm::None},
1800 {std::string("typename"), std::string("C"),
1801 std::string("bool")},
1802 };
1803 HI.Documentation = "documentation";
1804 HI.Definition =
1805 "template <typename T, typename C = bool> class Foo {}";
1806 HI.Name = "foo";
1807 HI.NamespaceScope.emplace();
1808 },
1809 R"(class foo
1810
1811 documentation
1812
1813 template <typename T, typename C = bool> class Foo {})",
1814 },
1815 {
1816 [](HoverInfo &HI) {
1817 HI.Kind = index::SymbolKind::Function;
1818 HI.Name = "foo";
1819 HI.Type = "type";
1820 HI.ReturnType = "ret_type";
1821 HI.Parameters.emplace();
1822 HoverInfo::Param P;
1823 HI.Parameters->push_back(P);
1824 P.Type = "type";
1825 HI.Parameters->push_back(P);
1826 P.Name = "foo";
1827 HI.Parameters->push_back(P);
1828 P.Default = "default";
1829 HI.Parameters->push_back(P);
1830 HI.NamespaceScope = "ns::";
1831 HI.Definition = "ret_type foo(params) {}";
1832 },
1833 R"(function foo
1834
1835 → ret_type
1836 Parameters:
1837 -
1838 - type
1839 - type foo
1840 - type foo = default
1841
1842 // In namespace ns
1843 ret_type foo(params) {})",
1844 },
1845 {
1846 [](HoverInfo &HI) {
1847 HI.Kind = index::SymbolKind::Variable;
1848 HI.LocalScope = "test::bar::";
1849 HI.Value = "value";
1850 HI.Name = "foo";
1851 HI.Type = "type";
1852 HI.Definition = "def";
1853 },
1854 R"(variable foo
1855
1856 Type: type
1857 Value = value
1858
1859 // In test::bar
1860 def)",
1861 },
1862 };
1863
1864 for (const auto &C : Cases) {
1865 HoverInfo HI;
1866 C.Builder(HI);
1867 EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
1868 }
1869 }
1870
1871 // This is a separate test as headings don't create any differences in plaintext
1872 // mode.
TEST(Hover,PresentHeadings)1873 TEST(Hover, PresentHeadings) {
1874 HoverInfo HI;
1875 HI.Kind = index::SymbolKind::Variable;
1876 HI.Name = "foo";
1877
1878 EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`");
1879 }
1880
1881 // This is a separate test as rulers behave differently in markdown vs
1882 // plaintext.
TEST(Hover,PresentRulers)1883 TEST(Hover, PresentRulers) {
1884 HoverInfo HI;
1885 HI.Kind = index::SymbolKind::Variable;
1886 HI.Name = "foo";
1887 HI.Value = "val";
1888 HI.Definition = "def";
1889
1890 llvm::StringRef ExpectedMarkdown = R"md(### variable `foo`
1891
1892 ---
1893 Value \= `val`
1894
1895 ---
1896 ```cpp
1897 def
1898 ```)md";
1899 EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
1900
1901 llvm::StringRef ExpectedPlaintext = R"pt(variable foo
1902
1903 Value = val
1904
1905 def)pt";
1906 EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
1907 }
1908 } // namespace
1909 } // namespace clangd
1910 } // namespace clang
1911