clang-tools 10.0.0

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