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/Basic/Specifiers.h"
16 #include "clang/Index/IndexSymbol.h"
17 #include "llvm/ADT/None.h"
18 #include "llvm/ADT/StringRef.h"
19
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include <string>
23 #include <vector>
24
25 namespace clang {
26 namespace clangd {
27 namespace {
28
29 using PassMode = HoverInfo::PassType::PassMode;
30
TEST(Hover,Structured)31 TEST(Hover, Structured) {
32 struct {
33 const char *const Code;
34 const std::function<void(HoverInfo &)> ExpectedBuilder;
35 } Cases[] = {
36 // Global scope.
37 {R"cpp(
38 // Best foo ever.
39 void [[fo^o]]() {}
40 )cpp",
41 [](HoverInfo &HI) {
42 HI.NamespaceScope = "";
43 HI.Name = "foo";
44 HI.Kind = index::SymbolKind::Function;
45 HI.Documentation = "Best foo ever.";
46 HI.Definition = "void foo()";
47 HI.ReturnType = "void";
48 HI.Type = "void ()";
49 HI.Parameters.emplace();
50 }},
51 // Inside namespace
52 {R"cpp(
53 namespace ns1 { namespace ns2 {
54 /// Best foo ever.
55 void [[fo^o]]() {}
56 }}
57 )cpp",
58 [](HoverInfo &HI) {
59 HI.NamespaceScope = "ns1::ns2::";
60 HI.Name = "foo";
61 HI.Kind = index::SymbolKind::Function;
62 HI.Documentation = "Best foo ever.";
63 HI.Definition = "void foo()";
64 HI.ReturnType = "void";
65 HI.Type = "void ()";
66 HI.Parameters.emplace();
67 }},
68 // Field
69 {R"cpp(
70 namespace ns1 { namespace ns2 {
71 struct Foo {
72 char [[b^ar]];
73 };
74 }}
75 )cpp",
76 [](HoverInfo &HI) {
77 HI.NamespaceScope = "ns1::ns2::";
78 HI.LocalScope = "Foo::";
79 HI.Name = "bar";
80 HI.Kind = index::SymbolKind::Field;
81 HI.Definition = "char bar";
82 HI.Type = "char";
83 HI.Offset = 0;
84 HI.Size = 1;
85 HI.AccessSpecifier = "public";
86 }},
87 // Local to class method.
88 {R"cpp(
89 namespace ns1 { namespace ns2 {
90 struct Foo {
91 void foo() {
92 int [[b^ar]];
93 }
94 };
95 }}
96 )cpp",
97 [](HoverInfo &HI) {
98 HI.NamespaceScope = "ns1::ns2::";
99 HI.LocalScope = "Foo::foo::";
100 HI.Name = "bar";
101 HI.Kind = index::SymbolKind::Variable;
102 HI.Definition = "int bar";
103 HI.Type = "int";
104 }},
105 // Anon namespace and local scope.
106 {R"cpp(
107 namespace ns1 { namespace {
108 struct {
109 char [[b^ar]];
110 } T;
111 }}
112 )cpp",
113 [](HoverInfo &HI) {
114 HI.NamespaceScope = "ns1::";
115 HI.LocalScope = "(anonymous struct)::";
116 HI.Name = "bar";
117 HI.Kind = index::SymbolKind::Field;
118 HI.Definition = "char bar";
119 HI.Type = "char";
120 HI.Offset = 0;
121 HI.Size = 1;
122 HI.AccessSpecifier = "public";
123 }},
124 // Struct definition shows size.
125 {R"cpp(
126 struct [[^X]]{};
127 )cpp",
128 [](HoverInfo &HI) {
129 HI.NamespaceScope = "";
130 HI.Name = "X";
131 HI.Kind = index::SymbolKind::Struct;
132 HI.Definition = "struct X {}";
133 HI.Size = 1;
134 }},
135 // Variable with template type
136 {R"cpp(
137 template <typename T, class... Ts> class Foo { public: Foo(int); };
138 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
139 )cpp",
140 [](HoverInfo &HI) {
141 HI.NamespaceScope = "";
142 HI.Name = "foo";
143 HI.Kind = index::SymbolKind::Variable;
144 HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
145 HI.Type = "Foo<int, char, bool>";
146 }},
147 // Implicit template instantiation
148 {R"cpp(
149 template <typename T> class vector{};
150 [[vec^tor]]<int> foo;
151 )cpp",
152 [](HoverInfo &HI) {
153 HI.NamespaceScope = "";
154 HI.Name = "vector<int>";
155 HI.Kind = index::SymbolKind::Class;
156 HI.Definition = "template <> class vector<int> {}";
157 }},
158 // Class template
159 {R"cpp(
160 template <template<typename, bool...> class C,
161 typename = char,
162 int = 0,
163 bool Q = false,
164 class... Ts> class Foo {};
165 template <template<typename, bool...> class T>
166 [[F^oo]]<T> foo;
167 )cpp",
168 [](HoverInfo &HI) {
169 HI.NamespaceScope = "";
170 HI.Name = "Foo";
171 HI.Kind = index::SymbolKind::Class;
172 HI.Definition =
173 R"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
174 bool Q = false, class... Ts>
175 class Foo {})cpp";
176 HI.TemplateParameters = {
177 {std::string("template <typename, bool...> class"),
178 std::string("C"), llvm::None},
179 {std::string("typename"), llvm::None, std::string("char")},
180 {std::string("int"), llvm::None, std::string("0")},
181 {std::string("bool"), std::string("Q"), std::string("false")},
182 {std::string("class..."), std::string("Ts"), llvm::None},
183 };
184 }},
185 // Function template
186 {R"cpp(
187 template <template<typename, bool...> class C,
188 typename = char,
189 int = 0,
190 bool Q = false,
191 class... Ts> void foo();
192 template<typename, bool...> class Foo;
193
194 void bar() {
195 [[fo^o]]<Foo>();
196 }
197 )cpp",
198 [](HoverInfo &HI) {
199 HI.NamespaceScope = "";
200 HI.Name = "foo";
201 HI.Kind = index::SymbolKind::Function;
202 HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";
203 HI.ReturnType = "void";
204 HI.Type = "void ()";
205 HI.Parameters.emplace();
206 }},
207 // Function decl
208 {R"cpp(
209 template<typename, bool...> class Foo {};
210 Foo<bool, true, false> foo(int, bool T = false);
211
212 void bar() {
213 [[fo^o]](3);
214 }
215 )cpp",
216 [](HoverInfo &HI) {
217 HI.NamespaceScope = "";
218 HI.Name = "foo";
219 HI.Kind = index::SymbolKind::Function;
220 HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
221 HI.ReturnType = "Foo<bool, true, false>";
222 HI.Type = "Foo<bool, true, false> (int, bool)";
223 HI.Parameters = {
224 {std::string("int"), llvm::None, llvm::None},
225 {std::string("bool"), std::string("T"), std::string("false")},
226 };
227 }},
228 // Pointers to lambdas
229 {R"cpp(
230 void foo() {
231 auto lamb = [](int T, bool B) -> bool { return T && B; };
232 auto *b = &lamb;
233 auto *[[^c]] = &b;
234 }
235 )cpp",
236 [](HoverInfo &HI) {
237 HI.NamespaceScope = "";
238 HI.LocalScope = "foo::";
239 HI.Name = "c";
240 HI.Kind = index::SymbolKind::Variable;
241 HI.Definition = "auto *c = &b";
242 HI.Type = "(lambda) **";
243 HI.ReturnType = "bool";
244 HI.Parameters = {
245 {std::string("int"), std::string("T"), llvm::None},
246 {std::string("bool"), std::string("B"), llvm::None},
247 };
248 return HI;
249 }},
250 // Lambda parameter with decltype reference
251 {R"cpp(
252 auto lamb = [](int T, bool B) -> bool { return T && B; };
253 void foo(decltype(lamb)& bar) {
254 [[ba^r]](0, false);
255 }
256 )cpp",
257 [](HoverInfo &HI) {
258 HI.NamespaceScope = "";
259 HI.LocalScope = "foo::";
260 HI.Name = "bar";
261 HI.Kind = index::SymbolKind::Parameter;
262 HI.Definition = "decltype(lamb) &bar";
263 HI.Type = "decltype(lamb) &";
264 HI.ReturnType = "bool";
265 HI.Parameters = {
266 {std::string("int"), std::string("T"), llvm::None},
267 {std::string("bool"), std::string("B"), llvm::None},
268 };
269 return HI;
270 }},
271 // Lambda parameter with decltype
272 {R"cpp(
273 auto lamb = [](int T, bool B) -> bool { return T && B; };
274 void foo(decltype(lamb) bar) {
275 [[ba^r]](0, false);
276 }
277 )cpp",
278 [](HoverInfo &HI) {
279 HI.NamespaceScope = "";
280 HI.LocalScope = "foo::";
281 HI.Name = "bar";
282 HI.Kind = index::SymbolKind::Parameter;
283 HI.Definition = "decltype(lamb) bar";
284 HI.Type = "class (lambda)";
285 HI.ReturnType = "bool";
286 HI.Parameters = {
287 {std::string("int"), std::string("T"), llvm::None},
288 {std::string("bool"), std::string("B"), llvm::None},
289 };
290 HI.Value = "false";
291 return HI;
292 }},
293 // Lambda variable
294 {R"cpp(
295 void foo() {
296 int bar = 5;
297 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
298 bool res = [[lam^b]](bar, false);
299 }
300 )cpp",
301 [](HoverInfo &HI) {
302 HI.NamespaceScope = "";
303 HI.LocalScope = "foo::";
304 HI.Name = "lamb";
305 HI.Kind = index::SymbolKind::Variable;
306 HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
307 HI.Type = "class (lambda)";
308 HI.ReturnType = "bool";
309 HI.Parameters = {
310 {std::string("int"), std::string("T"), llvm::None},
311 {std::string("bool"), std::string("B"), llvm::None},
312 };
313 return HI;
314 }},
315 // Local variable in lambda
316 {R"cpp(
317 void foo() {
318 auto lamb = []{int [[te^st]];};
319 }
320 )cpp",
321 [](HoverInfo &HI) {
322 HI.NamespaceScope = "";
323 HI.LocalScope = "foo::(anonymous class)::operator()::";
324 HI.Name = "test";
325 HI.Kind = index::SymbolKind::Variable;
326 HI.Definition = "int test";
327 HI.Type = "int";
328 }},
329 // Partially-specialized class template. (formerly type-parameter-0-0)
330 {R"cpp(
331 template <typename T> class X;
332 template <typename T> class [[^X]]<T*> {};
333 )cpp",
334 [](HoverInfo &HI) {
335 HI.Name = "X<T *>";
336 HI.NamespaceScope = "";
337 HI.Kind = index::SymbolKind::Class;
338 HI.Definition = "template <typename T> class X<T *> {}";
339 }},
340 // Constructor of partially-specialized class template
341 {R"cpp(
342 template<typename, typename=void> struct X;
343 template<typename T> struct X<T*>{ [[^X]](); };
344 )cpp",
345 [](HoverInfo &HI) {
346 HI.NamespaceScope = "";
347 HI.Name = "X";
348 HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>::
349 HI.Kind = index::SymbolKind::Constructor;
350 HI.Definition = "X()";
351 HI.Parameters.emplace();
352 HI.AccessSpecifier = "public";
353 }},
354 {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
355 [](HoverInfo &HI) {
356 HI.NamespaceScope = "";
357 HI.Name = "~X";
358 HI.LocalScope = "X::";
359 HI.Kind = index::SymbolKind::Destructor;
360 HI.Definition = "~X()";
361 HI.Parameters.emplace();
362 HI.AccessSpecifier = "private";
363 }},
364 {"class X { [[op^erator]] int(); };",
365 [](HoverInfo &HI) {
366 HI.NamespaceScope = "";
367 HI.Name = "operator int";
368 HI.LocalScope = "X::";
369 HI.Kind = index::SymbolKind::ConversionFunction;
370 HI.Definition = "operator int()";
371 HI.Parameters.emplace();
372 HI.AccessSpecifier = "private";
373 }},
374 {"class X { operator [[^X]](); };",
375 [](HoverInfo &HI) {
376 HI.NamespaceScope = "";
377 HI.Name = "X";
378 HI.Kind = index::SymbolKind::Class;
379 HI.Definition = "class X {}";
380 }},
381
382 // auto on structured bindings
383 {R"cpp(
384 void foo() {
385 struct S { int x; float y; };
386 [[au^to]] [x, y] = S();
387 }
388 )cpp",
389 [](HoverInfo &HI) {
390 HI.Name = "auto";
391 HI.Kind = index::SymbolKind::TypeAlias;
392 HI.Definition = "struct S";
393 }},
394 // undeduced auto
395 {R"cpp(
396 template<typename T>
397 void foo() {
398 [[au^to]] x = T{};
399 }
400 )cpp",
401 [](HoverInfo &HI) {
402 HI.Name = "auto";
403 HI.Kind = index::SymbolKind::TypeAlias;
404 HI.Definition = "/* not deduced */";
405 }},
406 // auto on lambda
407 {R"cpp(
408 void foo() {
409 [[au^to]] lamb = []{};
410 }
411 )cpp",
412 [](HoverInfo &HI) {
413 HI.Name = "auto";
414 HI.Kind = index::SymbolKind::TypeAlias;
415 HI.Definition = "class(lambda)";
416 }},
417 // auto on template instantiation
418 {R"cpp(
419 template<typename T> class Foo{};
420 void foo() {
421 [[au^to]] x = Foo<int>();
422 }
423 )cpp",
424 [](HoverInfo &HI) {
425 HI.Name = "auto";
426 HI.Kind = index::SymbolKind::TypeAlias;
427 HI.Definition = "class Foo<int>";
428 }},
429 // auto on specialized template
430 {R"cpp(
431 template<typename T> class Foo{};
432 template<> class Foo<int>{};
433 void foo() {
434 [[au^to]] x = Foo<int>();
435 }
436 )cpp",
437 [](HoverInfo &HI) {
438 HI.Name = "auto";
439 HI.Kind = index::SymbolKind::TypeAlias;
440 HI.Definition = "class Foo<int>";
441 }},
442
443 // macro
444 {R"cpp(
445 // Best MACRO ever.
446 #define MACRO(x,y,z) void foo(x, y, z);
447 [[MAC^RO]](int, double d, bool z = false);
448 )cpp",
449 [](HoverInfo &HI) {
450 HI.Name = "MACRO", HI.Kind = index::SymbolKind::Macro,
451 HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z);";
452 }},
453
454 // constexprs
455 {R"cpp(
456 constexpr int add(int a, int b) { return a + b; }
457 int [[b^ar]] = add(1, 2);
458 )cpp",
459 [](HoverInfo &HI) {
460 HI.Name = "bar";
461 HI.Definition = "int bar = add(1, 2)";
462 HI.Kind = index::SymbolKind::Variable;
463 HI.Type = "int";
464 HI.NamespaceScope = "";
465 HI.Value = "3";
466 }},
467 {R"cpp(
468 int [[b^ar]] = sizeof(char);
469 )cpp",
470 [](HoverInfo &HI) {
471 HI.Name = "bar";
472 HI.Definition = "int bar = sizeof(char)";
473 HI.Kind = index::SymbolKind::Variable;
474 HI.Type = "int";
475 HI.NamespaceScope = "";
476 HI.Value = "1";
477 }},
478 {R"cpp(
479 template<int a, int b> struct Add {
480 static constexpr int result = a + b;
481 };
482 int [[ba^r]] = Add<1, 2>::result;
483 )cpp",
484 [](HoverInfo &HI) {
485 HI.Name = "bar";
486 HI.Definition = "int bar = Add<1, 2>::result";
487 HI.Kind = index::SymbolKind::Variable;
488 HI.Type = "int";
489 HI.NamespaceScope = "";
490 HI.Value = "3";
491 }},
492 {R"cpp(
493 enum Color { RED, GREEN, };
494 Color x = [[GR^EEN]];
495 )cpp",
496 [](HoverInfo &HI) {
497 HI.Name = "GREEN";
498 HI.NamespaceScope = "";
499 HI.LocalScope = "Color::";
500 HI.Definition = "GREEN";
501 HI.Kind = index::SymbolKind::EnumConstant;
502 HI.Type = "enum Color";
503 HI.Value = "1"; // Numeric when hovering on the enumerator name.
504 }},
505 {R"cpp(
506 enum Color { RED, GREEN, };
507 Color x = GREEN;
508 Color y = [[^x]];
509 )cpp",
510 [](HoverInfo &HI) {
511 HI.Name = "x";
512 HI.NamespaceScope = "";
513 HI.Definition = "Color x = GREEN";
514 HI.Kind = index::SymbolKind::Variable;
515 HI.Type = "enum Color";
516 HI.Value = "GREEN (1)"; // Symbolic when hovering on an expression.
517 }},
518 {R"cpp(
519 template<int a, int b> struct Add {
520 static constexpr int result = a + b;
521 };
522 int bar = Add<1, 2>::[[resu^lt]];
523 )cpp",
524 [](HoverInfo &HI) {
525 HI.Name = "result";
526 HI.Definition = "static constexpr int result = 1 + 2";
527 HI.Kind = index::SymbolKind::StaticProperty;
528 HI.Type = "const int";
529 HI.NamespaceScope = "";
530 HI.LocalScope = "Add<1, 2>::";
531 HI.Value = "3";
532 HI.AccessSpecifier = "public";
533 }},
534 {R"cpp(
535 constexpr int answer() { return 40 + 2; }
536 int x = [[ans^wer]]();
537 )cpp",
538 [](HoverInfo &HI) {
539 HI.Name = "answer";
540 HI.Definition = "constexpr int answer()";
541 HI.Kind = index::SymbolKind::Function;
542 HI.Type = "int ()";
543 HI.ReturnType = "int";
544 HI.Parameters.emplace();
545 HI.NamespaceScope = "";
546 HI.Value = "42";
547 }},
548 {R"cpp(
549 const char *[[ba^r]] = "1234";
550 )cpp",
551 [](HoverInfo &HI) {
552 HI.Name = "bar";
553 HI.Definition = "const char *bar = \"1234\"";
554 HI.Kind = index::SymbolKind::Variable;
555 HI.Type = "const char *";
556 HI.NamespaceScope = "";
557 HI.Value = "&\"1234\"[0]";
558 }},
559 {R"cpp(// Should not crash
560 template <typename T>
561 struct Tmpl {
562 Tmpl(int name);
563 };
564
565 template <typename A>
566 void boom(int name) {
567 new Tmpl<A>([[na^me]]);
568 })cpp",
569 [](HoverInfo &HI) {
570 HI.Name = "name";
571 HI.Definition = "int name";
572 HI.Kind = index::SymbolKind::Parameter;
573 HI.Type = "int";
574 HI.NamespaceScope = "";
575 HI.LocalScope = "boom::";
576 }},
577 {
578 R"cpp(// Should not print inline or anon namespaces.
579 namespace ns {
580 inline namespace in_ns {
581 namespace a {
582 namespace {
583 namespace b {
584 inline namespace in_ns2 {
585 class Foo {};
586 } // in_ns2
587 } // b
588 } // anon
589 } // a
590 } // in_ns
591 } // ns
592 void foo() {
593 ns::a::b::[[F^oo]] x;
594 (void)x;
595 }
596 )cpp",
597 [](HoverInfo &HI) {
598 HI.Name = "Foo";
599 HI.Kind = index::SymbolKind::Class;
600 HI.NamespaceScope = "ns::a::b::";
601 HI.Definition = "class Foo {}";
602 }},
603 {
604 R"cpp(
605 template <typename T> class Foo {};
606 class X;
607 void foo() {
608 [[^auto]] x = Foo<X>();
609 }
610 )cpp",
611 [](HoverInfo &HI) {
612 HI.Name = "auto";
613 HI.Kind = index::SymbolKind::TypeAlias;
614 HI.Definition = "class Foo<X>";
615 }},
616 {// Falls back to primary template, when the type is not instantiated.
617 R"cpp(
618 // comment from primary
619 template <typename T> class Foo {};
620 // comment from specialization
621 template <typename T> class Foo<T*> {};
622 void foo() {
623 [[Fo^o]]<int*> *x = nullptr;
624 }
625 )cpp",
626 [](HoverInfo &HI) {
627 HI.Name = "Foo<int *>";
628 HI.Kind = index::SymbolKind::Class;
629 HI.NamespaceScope = "";
630 HI.Definition = "template <> class Foo<int *>";
631 // FIXME: Maybe force instantiation to make use of real template
632 // pattern.
633 HI.Documentation = "comment from primary";
634 }},
635 {// Template Type Parameter
636 R"cpp(
637 template <typename [[^T]] = int> void foo();
638 )cpp",
639 [](HoverInfo &HI) {
640 HI.Name = "T";
641 HI.Kind = index::SymbolKind::TemplateTypeParm;
642 HI.NamespaceScope = "";
643 HI.Definition = "typename T = int";
644 HI.LocalScope = "foo::";
645 HI.Type = "typename";
646 HI.AccessSpecifier = "public";
647 }},
648 {// TemplateTemplate Type Parameter
649 R"cpp(
650 template <template<typename> class [[^T]]> void foo();
651 )cpp",
652 [](HoverInfo &HI) {
653 HI.Name = "T";
654 HI.Kind = index::SymbolKind::TemplateTemplateParm;
655 HI.NamespaceScope = "";
656 HI.Definition = "template <typename> class T";
657 HI.LocalScope = "foo::";
658 HI.Type = "template <typename> class";
659 HI.AccessSpecifier = "public";
660 }},
661 {// NonType Template Parameter
662 R"cpp(
663 template <int [[^T]] = 5> void foo();
664 )cpp",
665 [](HoverInfo &HI) {
666 HI.Name = "T";
667 HI.Kind = index::SymbolKind::NonTypeTemplateParm;
668 HI.NamespaceScope = "";
669 HI.Definition = "int T = 5";
670 HI.LocalScope = "foo::";
671 HI.Type = "int";
672 HI.AccessSpecifier = "public";
673 }},
674
675 {// Getter
676 R"cpp(
677 struct X { int Y; float [[^y]]() { return Y; } };
678 )cpp",
679 [](HoverInfo &HI) {
680 HI.Name = "y";
681 HI.Kind = index::SymbolKind::InstanceMethod;
682 HI.NamespaceScope = "";
683 HI.Definition = "float y()";
684 HI.LocalScope = "X::";
685 HI.Documentation = "Trivial accessor for `Y`.";
686 HI.Type = "float ()";
687 HI.ReturnType = "float";
688 HI.Parameters.emplace();
689 HI.AccessSpecifier = "public";
690 }},
691 {// Setter
692 R"cpp(
693 struct X { int Y; void [[^setY]](float v) { Y = v; } };
694 )cpp",
695 [](HoverInfo &HI) {
696 HI.Name = "setY";
697 HI.Kind = index::SymbolKind::InstanceMethod;
698 HI.NamespaceScope = "";
699 HI.Definition = "void setY(float v)";
700 HI.LocalScope = "X::";
701 HI.Documentation = "Trivial setter for `Y`.";
702 HI.Type = "void (float)";
703 HI.ReturnType = "void";
704 HI.Parameters.emplace();
705 HI.Parameters->emplace_back();
706 HI.Parameters->back().Type = "float";
707 HI.Parameters->back().Name = "v";
708 HI.AccessSpecifier = "public";
709 }},
710 {// Setter (builder)
711 R"cpp(
712 struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };
713 )cpp",
714 [](HoverInfo &HI) {
715 HI.Name = "setY";
716 HI.Kind = index::SymbolKind::InstanceMethod;
717 HI.NamespaceScope = "";
718 HI.Definition = "X &setY(float v)";
719 HI.LocalScope = "X::";
720 HI.Documentation = "Trivial setter for `Y`.";
721 HI.Type = "X &(float)";
722 HI.ReturnType = "X &";
723 HI.Parameters.emplace();
724 HI.Parameters->emplace_back();
725 HI.Parameters->back().Type = "float";
726 HI.Parameters->back().Name = "v";
727 HI.AccessSpecifier = "public";
728 }},
729 {// Setter (move)
730 R"cpp(
731 namespace std { template<typename T> T&& move(T&& t); }
732 struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } };
733 )cpp",
734 [](HoverInfo &HI) {
735 HI.Name = "setY";
736 HI.Kind = index::SymbolKind::InstanceMethod;
737 HI.NamespaceScope = "";
738 HI.Definition = "void setY(float v)";
739 HI.LocalScope = "X::";
740 HI.Documentation = "Trivial setter for `Y`.";
741 HI.Type = "void (float)";
742 HI.ReturnType = "void";
743 HI.Parameters.emplace();
744 HI.Parameters->emplace_back();
745 HI.Parameters->back().Type = "float";
746 HI.Parameters->back().Name = "v";
747 HI.AccessSpecifier = "public";
748 }},
749 {// Field type initializer.
750 R"cpp(
751 struct X { int x = 2; };
752 X ^[[x]];
753 )cpp",
754 [](HoverInfo &HI) {
755 HI.Name = "x";
756 HI.Kind = index::SymbolKind::Variable;
757 HI.NamespaceScope = "";
758 HI.Definition = "X x";
759 HI.Type = "struct X";
760 }},
761 {// Don't crash on null types.
762 R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
763 [](HoverInfo &HI) {
764 HI.Name = "x";
765 HI.Kind = index::SymbolKind::Variable;
766 HI.NamespaceScope = "";
767 HI.Definition = "";
768 HI.Type = "NULL TYPE";
769 // Bindings are in theory public members of an anonymous struct.
770 HI.AccessSpecifier = "public";
771 }},
772 {// Extra info for function call.
773 R"cpp(
774 void fun(int arg_a, int &arg_b) {};
775 void code() {
776 int a = 1, b = 2;
777 fun(a, [[^b]]);
778 }
779 )cpp",
780 [](HoverInfo &HI) {
781 HI.Name = "b";
782 HI.Kind = index::SymbolKind::Variable;
783 HI.NamespaceScope = "";
784 HI.Definition = "int b = 2";
785 HI.LocalScope = "code::";
786 HI.Value = "2";
787 HI.Type = "int";
788 HI.CalleeArgInfo.emplace();
789 HI.CalleeArgInfo->Name = "arg_b";
790 HI.CalleeArgInfo->Type = "int &";
791 HI.CallPassType.emplace();
792 HI.CallPassType->PassBy = PassMode::Ref;
793 HI.CallPassType->Converted = false;
794 }},
795 {// Extra info for method call.
796 R"cpp(
797 class C {
798 public:
799 void fun(int arg_a = 3, int arg_b = 4) {}
800 };
801 void code() {
802 int a = 1, b = 2;
803 C c;
804 c.fun([[^a]], b);
805 }
806 )cpp",
807 [](HoverInfo &HI) {
808 HI.Name = "a";
809 HI.Kind = index::SymbolKind::Variable;
810 HI.NamespaceScope = "";
811 HI.Definition = "int a = 1";
812 HI.LocalScope = "code::";
813 HI.Value = "1";
814 HI.Type = "int";
815 HI.CalleeArgInfo.emplace();
816 HI.CalleeArgInfo->Name = "arg_a";
817 HI.CalleeArgInfo->Type = "int";
818 HI.CalleeArgInfo->Default = "3";
819 HI.CallPassType.emplace();
820 HI.CallPassType->PassBy = PassMode::Value;
821 HI.CallPassType->Converted = false;
822 }},
823 {// Dont crash on invalid decl
824 R"cpp(
825 // error-ok
826 struct Foo {
827 Bar [[x^x]];
828 };)cpp",
829 [](HoverInfo &HI) {
830 HI.Name = "xx";
831 HI.Kind = index::SymbolKind::Field;
832 HI.NamespaceScope = "";
833 HI.Definition = "int xx";
834 HI.LocalScope = "Foo::";
835 HI.Type = "int";
836 HI.AccessSpecifier = "public";
837 }},
838 {R"cpp(
839 // error-ok
840 struct Foo {
841 Bar xx;
842 int [[y^y]];
843 };)cpp",
844 [](HoverInfo &HI) {
845 HI.Name = "yy";
846 HI.Kind = index::SymbolKind::Field;
847 HI.NamespaceScope = "";
848 HI.Definition = "int yy";
849 HI.LocalScope = "Foo::";
850 HI.Type = "int";
851 HI.AccessSpecifier = "public";
852 }},
853 {// No crash on InitListExpr.
854 R"cpp(
855 struct Foo {
856 int a[10];
857 };
858 constexpr Foo k2 = {
859 ^[[{]]1} // FIXME: why the hover range is 1 character?
860 };
861 )cpp",
862 [](HoverInfo &HI) {
863 HI.Name = "expression";
864 HI.Kind = index::SymbolKind::Unknown;
865 HI.Type = "int [10]";
866 HI.Value = "{1}";
867 }}};
868 for (const auto &Case : Cases) {
869 SCOPED_TRACE(Case.Code);
870
871 Annotations T(Case.Code);
872 TestTU TU = TestTU::withCode(T.code());
873 TU.ExtraArgs.push_back("-std=c++17");
874 // Types might be different depending on the target triplet, we chose a
875 // fixed one to make sure tests passes on different platform.
876 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
877 auto AST = TU.build();
878
879 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
880 ASSERT_TRUE(H);
881 HoverInfo Expected;
882 Expected.SymRange = T.range();
883 Case.ExpectedBuilder(Expected);
884
885 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
886 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
887 EXPECT_EQ(H->Name, Expected.Name);
888 EXPECT_EQ(H->Kind, Expected.Kind);
889 EXPECT_EQ(H->Documentation, Expected.Documentation);
890 EXPECT_EQ(H->Definition, Expected.Definition);
891 EXPECT_EQ(H->Type, Expected.Type);
892 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
893 EXPECT_EQ(H->Parameters, Expected.Parameters);
894 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
895 EXPECT_EQ(H->SymRange, Expected.SymRange);
896 EXPECT_EQ(H->Value, Expected.Value);
897 EXPECT_EQ(H->Size, Expected.Size);
898 EXPECT_EQ(H->Offset, Expected.Offset);
899 EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier);
900 EXPECT_EQ(H->CalleeArgInfo, Expected.CalleeArgInfo);
901 EXPECT_EQ(H->CallPassType, Expected.CallPassType);
902 }
903 }
904
TEST(Hover,CallPassType)905 TEST(Hover, CallPassType) {
906 const llvm::StringRef CodePrefix = R"cpp(
907 class Base {};
908 class Derived : public Base {};
909 class CustomClass {
910 public:
911 CustomClass() {}
912 CustomClass(const Base &x) {}
913 CustomClass(int &x) {}
914 CustomClass(float x) {}
915 };
916
917 void int_by_ref(int &x) {}
918 void int_by_const_ref(const int &x) {}
919 void int_by_value(int x) {}
920 void base_by_ref(Base &x) {}
921 void base_by_const_ref(const Base &x) {}
922 void base_by_value(Base x) {}
923 void float_by_value(float x) {}
924 void custom_by_value(CustomClass x) {}
925
926 void fun() {
927 int int_x;
928 int &int_ref = int_x;
929 const int &int_const_ref = int_x;
930 Base base;
931 const Base &base_const_ref = base;
932 Derived derived;
933 float float_x;
934 )cpp";
935 const llvm::StringRef CodeSuffix = "}";
936
937 struct {
938 const char *const Code;
939 HoverInfo::PassType::PassMode PassBy;
940 bool Converted;
941 } Tests[] = {
942 // Integer tests
943 {"int_by_value([[^int_x]]);", PassMode::Value, false},
944 {"int_by_ref([[^int_x]]);", PassMode::Ref, false},
945 {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false},
946 {"int_by_value([[^int_ref]]);", PassMode::Value, false},
947 {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
948 {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
949 {"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef, false},
950 // Custom class tests
951 {"base_by_ref([[^base]]);", PassMode::Ref, false},
952 {"base_by_const_ref([[^base]]);", PassMode::ConstRef, false},
953 {"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef, false},
954 {"base_by_value([[^base]]);", PassMode::Value, false},
955 {"base_by_value([[^base_const_ref]]);", PassMode::Value, false},
956 {"base_by_ref([[^derived]]);", PassMode::Ref, false},
957 {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false},
958 {"base_by_value([[^derived]]);", PassMode::Value, false},
959 // Converted tests
960 {"float_by_value([[^int_x]]);", PassMode::Value, true},
961 {"float_by_value([[^int_ref]]);", PassMode::Value, true},
962 {"float_by_value([[^int_const_ref]]);", PassMode::Value, true},
963 {"custom_by_value([[^int_x]]);", PassMode::Ref, true},
964 {"custom_by_value([[^float_x]]);", PassMode::Value, true},
965 {"custom_by_value([[^base]]);", PassMode::ConstRef, true},
966 };
967 for (const auto &Test : Tests) {
968 SCOPED_TRACE(Test.Code);
969
970 const auto Code = (CodePrefix + Test.Code + CodeSuffix).str();
971 Annotations T(Code);
972 TestTU TU = TestTU::withCode(T.code());
973 TU.ExtraArgs.push_back("-std=c++17");
974 auto AST = TU.build();
975 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
976 ASSERT_TRUE(H);
977 EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy);
978 EXPECT_EQ(H->CallPassType->Converted, Test.Converted);
979 }
980 }
981
TEST(Hover,NoHover)982 TEST(Hover, NoHover) {
983 llvm::StringRef Tests[] = {
984 "^int main() {}",
985 "void foo() {^}",
986 // FIXME: "decltype(auto)" should be a single hover
987 "decltype(au^to) x = 0;",
988 // FIXME: not supported yet
989 R"cpp(// Lambda auto parameter
990 auto lamb = [](a^uto){};
991 )cpp",
992 R"cpp(// non-named decls don't get hover. Don't crash!
993 ^static_assert(1, "");
994 )cpp",
995 R"cpp(// non-evaluatable expr
996 template <typename T> void foo() {
997 (void)[[size^of]](T);
998 })cpp",
999 R"cpp(// should not crash on invalid semantic form of init-list-expr.
1000 /*error-ok*/
1001 struct Foo {
1002 int xyz = 0;
1003 };
1004 class Bar {};
1005 constexpr Foo s = ^{
1006 .xyz = Bar(),
1007 };
1008 )cpp",
1009 // literals
1010 "auto x = t^rue;",
1011 "auto x = '^A';",
1012 "auto x = ^(int){42};",
1013 "auto x = ^42.;",
1014 "auto x = ^42.0i;",
1015 "auto x = ^42;",
1016 "auto x = ^nullptr;",
1017 "auto x = ^\"asdf\";",
1018 };
1019
1020 for (const auto &Test : Tests) {
1021 SCOPED_TRACE(Test);
1022
1023 Annotations T(Test);
1024 TestTU TU = TestTU::withCode(T.code());
1025 TU.ExtraArgs.push_back("-std=c++17");
1026 auto AST = TU.build();
1027 auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
1028 ASSERT_FALSE(H);
1029 }
1030 }
1031
TEST(Hover,All)1032 TEST(Hover, All) {
1033 struct {
1034 const char *const Code;
1035 const std::function<void(HoverInfo &)> ExpectedBuilder;
1036 } Cases[] = {
1037 {
1038 R"cpp(// Local variable
1039 int main() {
1040 int bonjour;
1041 ^[[bonjour]] = 2;
1042 int test1 = bonjour;
1043 }
1044 )cpp",
1045 [](HoverInfo &HI) {
1046 HI.Name = "bonjour";
1047 HI.Kind = index::SymbolKind::Variable;
1048 HI.NamespaceScope = "";
1049 HI.LocalScope = "main::";
1050 HI.Type = "int";
1051 HI.Definition = "int bonjour";
1052 }},
1053 {
1054 R"cpp(// Local variable in method
1055 struct s {
1056 void method() {
1057 int bonjour;
1058 ^[[bonjour]] = 2;
1059 }
1060 };
1061 )cpp",
1062 [](HoverInfo &HI) {
1063 HI.Name = "bonjour";
1064 HI.Kind = index::SymbolKind::Variable;
1065 HI.NamespaceScope = "";
1066 HI.LocalScope = "s::method::";
1067 HI.Type = "int";
1068 HI.Definition = "int bonjour";
1069 }},
1070 {
1071 R"cpp(// Struct
1072 namespace ns1 {
1073 struct MyClass {};
1074 } // namespace ns1
1075 int main() {
1076 ns1::[[My^Class]]* Params;
1077 }
1078 )cpp",
1079 [](HoverInfo &HI) {
1080 HI.Name = "MyClass";
1081 HI.Kind = index::SymbolKind::Struct;
1082 HI.NamespaceScope = "ns1::";
1083 HI.Definition = "struct MyClass {}";
1084 }},
1085 {
1086 R"cpp(// Class
1087 namespace ns1 {
1088 class MyClass {};
1089 } // namespace ns1
1090 int main() {
1091 ns1::[[My^Class]]* Params;
1092 }
1093 )cpp",
1094 [](HoverInfo &HI) {
1095 HI.Name = "MyClass";
1096 HI.Kind = index::SymbolKind::Class;
1097 HI.NamespaceScope = "ns1::";
1098 HI.Definition = "class MyClass {}";
1099 }},
1100 {
1101 R"cpp(// Union
1102 namespace ns1 {
1103 union MyUnion { int x; int y; };
1104 } // namespace ns1
1105 int main() {
1106 ns1::[[My^Union]] Params;
1107 }
1108 )cpp",
1109 [](HoverInfo &HI) {
1110 HI.Name = "MyUnion";
1111 HI.Kind = index::SymbolKind::Union;
1112 HI.NamespaceScope = "ns1::";
1113 HI.Definition = "union MyUnion {}";
1114 }},
1115 {
1116 R"cpp(// Function definition via pointer
1117 void foo(int) {}
1118 int main() {
1119 auto *X = &^[[foo]];
1120 }
1121 )cpp",
1122 [](HoverInfo &HI) {
1123 HI.Name = "foo";
1124 HI.Kind = index::SymbolKind::Function;
1125 HI.NamespaceScope = "";
1126 HI.Type = "void (int)";
1127 HI.Definition = "void foo(int)";
1128 HI.Documentation = "Function definition via pointer";
1129 HI.ReturnType = "void";
1130 HI.Parameters = {
1131 {std::string("int"), llvm::None, llvm::None},
1132 };
1133 }},
1134 {
1135 R"cpp(// Function declaration via call
1136 int foo(int);
1137 int main() {
1138 return ^[[foo]](42);
1139 }
1140 )cpp",
1141 [](HoverInfo &HI) {
1142 HI.Name = "foo";
1143 HI.Kind = index::SymbolKind::Function;
1144 HI.NamespaceScope = "";
1145 HI.Type = "int (int)";
1146 HI.Definition = "int foo(int)";
1147 HI.Documentation = "Function declaration via call";
1148 HI.ReturnType = "int";
1149 HI.Parameters = {
1150 {std::string("int"), llvm::None, llvm::None},
1151 };
1152 }},
1153 {
1154 R"cpp(// Field
1155 struct Foo { int x; };
1156 int main() {
1157 Foo bar;
1158 (void)bar.^[[x]];
1159 }
1160 )cpp",
1161 [](HoverInfo &HI) {
1162 HI.Name = "x";
1163 HI.Kind = index::SymbolKind::Field;
1164 HI.NamespaceScope = "";
1165 HI.LocalScope = "Foo::";
1166 HI.Type = "int";
1167 HI.Definition = "int x";
1168 }},
1169 {
1170 R"cpp(// Field with initialization
1171 struct Foo { int x = 5; };
1172 int main() {
1173 Foo bar;
1174 (void)bar.^[[x]];
1175 }
1176 )cpp",
1177 [](HoverInfo &HI) {
1178 HI.Name = "x";
1179 HI.Kind = index::SymbolKind::Field;
1180 HI.NamespaceScope = "";
1181 HI.LocalScope = "Foo::";
1182 HI.Type = "int";
1183 HI.Definition = "int x = 5";
1184 }},
1185 {
1186 R"cpp(// Static field
1187 struct Foo { static int x; };
1188 int main() {
1189 (void)Foo::^[[x]];
1190 }
1191 )cpp",
1192 [](HoverInfo &HI) {
1193 HI.Name = "x";
1194 HI.Kind = index::SymbolKind::StaticProperty;
1195 HI.NamespaceScope = "";
1196 HI.LocalScope = "Foo::";
1197 HI.Type = "int";
1198 HI.Definition = "static int x";
1199 }},
1200 {
1201 R"cpp(// Field, member initializer
1202 struct Foo {
1203 int x;
1204 Foo() : ^[[x]](0) {}
1205 };
1206 )cpp",
1207 [](HoverInfo &HI) {
1208 HI.Name = "x";
1209 HI.Kind = index::SymbolKind::Field;
1210 HI.NamespaceScope = "";
1211 HI.LocalScope = "Foo::";
1212 HI.Type = "int";
1213 HI.Definition = "int x";
1214 }},
1215 {
1216 R"cpp(// Field, GNU old-style field designator
1217 struct Foo { int x; };
1218 int main() {
1219 Foo bar = { ^[[x]] : 1 };
1220 }
1221 )cpp",
1222 [](HoverInfo &HI) {
1223 HI.Name = "x";
1224 HI.Kind = index::SymbolKind::Field;
1225 HI.NamespaceScope = "";
1226 HI.LocalScope = "Foo::";
1227 HI.Type = "int";
1228 HI.Definition = "int x";
1229 // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is
1230 // of struct type and omitted.
1231 }},
1232 {
1233 R"cpp(// Field, field designator
1234 struct Foo { int x; int y; };
1235 int main() {
1236 Foo bar = { .^[[x]] = 2, .y = 2 };
1237 }
1238 )cpp",
1239 [](HoverInfo &HI) {
1240 HI.Name = "x";
1241 HI.Kind = index::SymbolKind::Field;
1242 HI.NamespaceScope = "";
1243 HI.LocalScope = "Foo::";
1244 HI.Type = "int";
1245 HI.Definition = "int x";
1246 }},
1247 {
1248 R"cpp(// Method call
1249 struct Foo { int x(); };
1250 int main() {
1251 Foo bar;
1252 bar.^[[x]]();
1253 }
1254 )cpp",
1255 [](HoverInfo &HI) {
1256 HI.Name = "x";
1257 HI.Kind = index::SymbolKind::InstanceMethod;
1258 HI.NamespaceScope = "";
1259 HI.LocalScope = "Foo::";
1260 HI.Type = "int ()";
1261 HI.Definition = "int x()";
1262 HI.ReturnType = "int";
1263 HI.Parameters = std::vector<HoverInfo::Param>{};
1264 }},
1265 {
1266 R"cpp(// Static method call
1267 struct Foo { static int x(); };
1268 int main() {
1269 Foo::^[[x]]();
1270 }
1271 )cpp",
1272 [](HoverInfo &HI) {
1273 HI.Name = "x";
1274 HI.Kind = index::SymbolKind::StaticMethod;
1275 HI.NamespaceScope = "";
1276 HI.LocalScope = "Foo::";
1277 HI.Type = "int ()";
1278 HI.Definition = "static int x()";
1279 HI.ReturnType = "int";
1280 HI.Parameters = std::vector<HoverInfo::Param>{};
1281 }},
1282 {
1283 R"cpp(// Typedef
1284 typedef int Foo;
1285 int main() {
1286 ^[[Foo]] bar;
1287 }
1288 )cpp",
1289 [](HoverInfo &HI) {
1290 HI.Name = "Foo";
1291 HI.Kind = index::SymbolKind::TypeAlias;
1292 HI.NamespaceScope = "";
1293 HI.Definition = "typedef int Foo";
1294 HI.Documentation = "Typedef";
1295 // FIXME: Maybe put underlying type into HI.Type for aliases?
1296 }},
1297 {
1298 R"cpp(// Typedef with embedded definition
1299 typedef struct Bar {} Foo;
1300 int main() {
1301 ^[[Foo]] bar;
1302 }
1303 )cpp",
1304 [](HoverInfo &HI) {
1305 HI.Name = "Foo";
1306 HI.Kind = index::SymbolKind::TypeAlias;
1307 HI.NamespaceScope = "";
1308 HI.Definition = "typedef struct Bar Foo";
1309 HI.Documentation = "Typedef with embedded definition";
1310 }},
1311 {
1312 R"cpp(// Namespace
1313 namespace ns {
1314 struct Foo { static void bar(); };
1315 } // namespace ns
1316 int main() { ^[[ns]]::Foo::bar(); }
1317 )cpp",
1318 [](HoverInfo &HI) {
1319 HI.Name = "ns";
1320 HI.Kind = index::SymbolKind::Namespace;
1321 HI.NamespaceScope = "";
1322 HI.Definition = "namespace ns {}";
1323 }},
1324 {
1325 R"cpp(// Anonymous namespace
1326 namespace ns {
1327 namespace {
1328 int foo;
1329 } // anonymous namespace
1330 } // namespace ns
1331 int main() { ns::[[f^oo]]++; }
1332 )cpp",
1333 [](HoverInfo &HI) {
1334 HI.Name = "foo";
1335 HI.Kind = index::SymbolKind::Variable;
1336 HI.NamespaceScope = "ns::";
1337 HI.Type = "int";
1338 HI.Definition = "int foo";
1339 }},
1340 {
1341 R"cpp(// Macro
1342 #define MACRO 0
1343 int main() { return ^[[MACRO]]; }
1344 )cpp",
1345 [](HoverInfo &HI) {
1346 HI.Name = "MACRO";
1347 HI.Kind = index::SymbolKind::Macro;
1348 HI.Definition = "#define MACRO 0";
1349 }},
1350 {
1351 R"cpp(// Macro
1352 #define MACRO 0
1353 #define MACRO2 ^[[MACRO]]
1354 )cpp",
1355 [](HoverInfo &HI) {
1356 HI.Name = "MACRO";
1357 HI.Kind = index::SymbolKind::Macro;
1358 HI.Definition = "#define MACRO 0";
1359 }},
1360 {
1361 R"cpp(// Macro
1362 #define MACRO {\
1363 return 0;\
1364 }
1365 int main() ^[[MACRO]]
1366 )cpp",
1367 [](HoverInfo &HI) {
1368 HI.Name = "MACRO";
1369 HI.Kind = index::SymbolKind::Macro;
1370 HI.Definition =
1371 R"cpp(#define MACRO \
1372 { return 0; })cpp";
1373 }},
1374 {
1375 R"cpp(// Forward class declaration
1376 class Foo;
1377 class Foo {};
1378 [[F^oo]]* foo();
1379 )cpp",
1380 [](HoverInfo &HI) {
1381 HI.Name = "Foo";
1382 HI.Kind = index::SymbolKind::Class;
1383 HI.NamespaceScope = "";
1384 HI.Definition = "class Foo {}";
1385 HI.Documentation = "Forward class declaration";
1386 }},
1387 {
1388 R"cpp(// Function declaration
1389 void foo();
1390 void g() { [[f^oo]](); }
1391 void foo() {}
1392 )cpp",
1393 [](HoverInfo &HI) {
1394 HI.Name = "foo";
1395 HI.Kind = index::SymbolKind::Function;
1396 HI.NamespaceScope = "";
1397 HI.Type = "void ()";
1398 HI.Definition = "void foo()";
1399 HI.Documentation = "Function declaration";
1400 HI.ReturnType = "void";
1401 HI.Parameters = std::vector<HoverInfo::Param>{};
1402 }},
1403 {
1404 R"cpp(// Enum declaration
1405 enum Hello {
1406 ONE, TWO, THREE,
1407 };
1408 void foo() {
1409 [[Hel^lo]] hello = ONE;
1410 }
1411 )cpp",
1412 [](HoverInfo &HI) {
1413 HI.Name = "Hello";
1414 HI.Kind = index::SymbolKind::Enum;
1415 HI.NamespaceScope = "";
1416 HI.Definition = "enum Hello {}";
1417 HI.Documentation = "Enum declaration";
1418 }},
1419 {
1420 R"cpp(// Enumerator
1421 enum Hello {
1422 ONE, TWO, THREE,
1423 };
1424 void foo() {
1425 Hello hello = [[O^NE]];
1426 }
1427 )cpp",
1428 [](HoverInfo &HI) {
1429 HI.Name = "ONE";
1430 HI.Kind = index::SymbolKind::EnumConstant;
1431 HI.NamespaceScope = "";
1432 HI.LocalScope = "Hello::";
1433 HI.Type = "enum Hello";
1434 HI.Definition = "ONE";
1435 HI.Value = "0";
1436 }},
1437 {
1438 R"cpp(// Enumerator in anonymous enum
1439 enum {
1440 ONE, TWO, THREE,
1441 };
1442 void foo() {
1443 int hello = [[O^NE]];
1444 }
1445 )cpp",
1446 [](HoverInfo &HI) {
1447 HI.Name = "ONE";
1448 HI.Kind = index::SymbolKind::EnumConstant;
1449 HI.NamespaceScope = "";
1450 // FIXME: This should be `(anon enum)::`
1451 HI.LocalScope = "";
1452 HI.Type = "enum (anonymous)";
1453 HI.Definition = "ONE";
1454 HI.Value = "0";
1455 }},
1456 {
1457 R"cpp(// Global variable
1458 static int hey = 10;
1459 void foo() {
1460 [[he^y]]++;
1461 }
1462 )cpp",
1463 [](HoverInfo &HI) {
1464 HI.Name = "hey";
1465 HI.Kind = index::SymbolKind::Variable;
1466 HI.NamespaceScope = "";
1467 HI.Type = "int";
1468 HI.Definition = "static int hey = 10";
1469 HI.Documentation = "Global variable";
1470 // FIXME: Value shouldn't be set in this case
1471 HI.Value = "10";
1472 }},
1473 {
1474 R"cpp(// Global variable in namespace
1475 namespace ns1 {
1476 static int hey = 10;
1477 }
1478 void foo() {
1479 ns1::[[he^y]]++;
1480 }
1481 )cpp",
1482 [](HoverInfo &HI) {
1483 HI.Name = "hey";
1484 HI.Kind = index::SymbolKind::Variable;
1485 HI.NamespaceScope = "ns1::";
1486 HI.Type = "int";
1487 HI.Definition = "static int hey = 10";
1488 HI.Value = "10";
1489 }},
1490 {
1491 R"cpp(// Field in anonymous struct
1492 static struct {
1493 int hello;
1494 } s;
1495 void foo() {
1496 s.[[he^llo]]++;
1497 }
1498 )cpp",
1499 [](HoverInfo &HI) {
1500 HI.Name = "hello";
1501 HI.Kind = index::SymbolKind::Field;
1502 HI.NamespaceScope = "";
1503 HI.LocalScope = "(anonymous struct)::";
1504 HI.Type = "int";
1505 HI.Definition = "int hello";
1506 }},
1507 {
1508 R"cpp(// Templated function
1509 template <typename T>
1510 T foo() {
1511 return 17;
1512 }
1513 void g() { auto x = [[f^oo]]<int>(); }
1514 )cpp",
1515 [](HoverInfo &HI) {
1516 HI.Name = "foo";
1517 HI.Kind = index::SymbolKind::Function;
1518 HI.NamespaceScope = "";
1519 HI.Type = "int ()";
1520 HI.Definition = "template <> int foo<int>()";
1521 HI.Documentation = "Templated function";
1522 HI.ReturnType = "int";
1523 HI.Parameters = std::vector<HoverInfo::Param>{};
1524 // FIXME: We should populate template parameters with arguments in
1525 // case of instantiations.
1526 }},
1527 {
1528 R"cpp(// Anonymous union
1529 struct outer {
1530 union {
1531 int abc, def;
1532 } v;
1533 };
1534 void g() { struct outer o; o.v.[[d^ef]]++; }
1535 )cpp",
1536 [](HoverInfo &HI) {
1537 HI.Name = "def";
1538 HI.Kind = index::SymbolKind::Field;
1539 HI.NamespaceScope = "";
1540 HI.LocalScope = "outer::(anonymous union)::";
1541 HI.Type = "int";
1542 HI.Definition = "int def";
1543 }},
1544 {
1545 R"cpp(// documentation from index
1546 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
1547 void indexSymbol();
1548 void g() { [[ind^exSymbol]](); }
1549 )cpp",
1550 [](HoverInfo &HI) {
1551 HI.Name = "indexSymbol";
1552 HI.Kind = index::SymbolKind::Function;
1553 HI.NamespaceScope = "";
1554 HI.Type = "void ()";
1555 HI.Definition = "void indexSymbol()";
1556 HI.ReturnType = "void";
1557 HI.Parameters = std::vector<HoverInfo::Param>{};
1558 HI.Documentation = "comment from index";
1559 }},
1560 {
1561 R"cpp(// Simple initialization with auto
1562 void foo() {
1563 ^[[auto]] i = 1;
1564 }
1565 )cpp",
1566 [](HoverInfo &HI) {
1567 HI.Name = "auto";
1568 HI.Kind = index::SymbolKind::TypeAlias;
1569 HI.Definition = "int";
1570 }},
1571 {
1572 R"cpp(// Simple initialization with const auto
1573 void foo() {
1574 const ^[[auto]] i = 1;
1575 }
1576 )cpp",
1577 [](HoverInfo &HI) {
1578 HI.Name = "auto";
1579 HI.Kind = index::SymbolKind::TypeAlias;
1580 HI.Definition = "int";
1581 }},
1582 {
1583 R"cpp(// Simple initialization with const auto&
1584 void foo() {
1585 const ^[[auto]]& i = 1;
1586 }
1587 )cpp",
1588 [](HoverInfo &HI) {
1589 HI.Name = "auto";
1590 HI.Kind = index::SymbolKind::TypeAlias;
1591 HI.Definition = "int";
1592 }},
1593 {
1594 R"cpp(// Simple initialization with auto&
1595 void foo() {
1596 int x;
1597 ^[[auto]]& i = x;
1598 }
1599 )cpp",
1600 [](HoverInfo &HI) {
1601 HI.Name = "auto";
1602 HI.Kind = index::SymbolKind::TypeAlias;
1603 HI.Definition = "int";
1604 }},
1605 {
1606 R"cpp(// Simple initialization with auto*
1607 void foo() {
1608 int a = 1;
1609 ^[[auto]]* i = &a;
1610 }
1611 )cpp",
1612 [](HoverInfo &HI) {
1613 HI.Name = "auto";
1614 HI.Kind = index::SymbolKind::TypeAlias;
1615 HI.Definition = "int";
1616 }},
1617 {
1618 R"cpp(// Simple initialization with auto from pointer
1619 void foo() {
1620 int a = 1;
1621 ^[[auto]] i = &a;
1622 }
1623 )cpp",
1624 [](HoverInfo &HI) {
1625 HI.Name = "auto";
1626 HI.Kind = index::SymbolKind::TypeAlias;
1627 HI.Definition = "int *";
1628 }},
1629 {
1630 R"cpp(// Auto with initializer list.
1631 namespace std
1632 {
1633 template<class _E>
1634 class initializer_list {};
1635 }
1636 void foo() {
1637 ^[[auto]] i = {1,2};
1638 }
1639 )cpp",
1640 [](HoverInfo &HI) {
1641 HI.Name = "auto";
1642 HI.Kind = index::SymbolKind::TypeAlias;
1643 HI.Definition = "class std::initializer_list<int>";
1644 }},
1645 {
1646 R"cpp(// User defined conversion to auto
1647 struct Bar {
1648 operator ^[[auto]]() const { return 10; }
1649 };
1650 )cpp",
1651 [](HoverInfo &HI) {
1652 HI.Name = "auto";
1653 HI.Kind = index::SymbolKind::TypeAlias;
1654 HI.Definition = "int";
1655 }},
1656 {
1657 R"cpp(// Simple initialization with decltype(auto)
1658 void foo() {
1659 ^[[decltype]](auto) i = 1;
1660 }
1661 )cpp",
1662 [](HoverInfo &HI) {
1663 HI.Name = "decltype";
1664 HI.Kind = index::SymbolKind::TypeAlias;
1665 HI.Definition = "int";
1666 }},
1667 {
1668 R"cpp(// Simple initialization with const decltype(auto)
1669 void foo() {
1670 const int j = 0;
1671 ^[[decltype]](auto) i = j;
1672 }
1673 )cpp",
1674 [](HoverInfo &HI) {
1675 HI.Name = "decltype";
1676 HI.Kind = index::SymbolKind::TypeAlias;
1677 HI.Definition = "const int";
1678 }},
1679 {
1680 R"cpp(// Simple initialization with const& decltype(auto)
1681 void foo() {
1682 int k = 0;
1683 const int& j = k;
1684 ^[[decltype]](auto) i = j;
1685 }
1686 )cpp",
1687 [](HoverInfo &HI) {
1688 HI.Name = "decltype";
1689 HI.Kind = index::SymbolKind::TypeAlias;
1690 HI.Definition = "const int &";
1691 }},
1692 {
1693 R"cpp(// Simple initialization with & decltype(auto)
1694 void foo() {
1695 int k = 0;
1696 int& j = k;
1697 ^[[decltype]](auto) i = j;
1698 }
1699 )cpp",
1700 [](HoverInfo &HI) {
1701 HI.Name = "decltype";
1702 HI.Kind = index::SymbolKind::TypeAlias;
1703 HI.Definition = "int &";
1704 }},
1705 {
1706 R"cpp(// simple trailing return type
1707 ^[[auto]] main() -> int {
1708 return 0;
1709 }
1710 )cpp",
1711 [](HoverInfo &HI) {
1712 HI.Name = "auto";
1713 HI.Kind = index::SymbolKind::TypeAlias;
1714 HI.Definition = "int";
1715 }},
1716 {
1717 R"cpp(// auto function return with trailing type
1718 struct Bar {};
1719 ^[[auto]] test() -> decltype(Bar()) {
1720 return Bar();
1721 }
1722 )cpp",
1723 [](HoverInfo &HI) {
1724 HI.Name = "auto";
1725 HI.Kind = index::SymbolKind::TypeAlias;
1726 HI.Definition = "struct Bar";
1727 HI.Documentation = "auto function return with trailing type";
1728 }},
1729 {
1730 R"cpp(// trailing return type
1731 struct Bar {};
1732 auto test() -> ^[[decltype]](Bar()) {
1733 return Bar();
1734 }
1735 )cpp",
1736 [](HoverInfo &HI) {
1737 HI.Name = "decltype";
1738 HI.Kind = index::SymbolKind::TypeAlias;
1739 HI.Definition = "struct Bar";
1740 HI.Documentation = "trailing return type";
1741 }},
1742 {
1743 R"cpp(// auto in function return
1744 struct Bar {};
1745 ^[[auto]] test() {
1746 return Bar();
1747 }
1748 )cpp",
1749 [](HoverInfo &HI) {
1750 HI.Name = "auto";
1751 HI.Kind = index::SymbolKind::TypeAlias;
1752 HI.Definition = "struct Bar";
1753 HI.Documentation = "auto in function return";
1754 }},
1755 {
1756 R"cpp(// auto& in function return
1757 struct Bar {};
1758 ^[[auto]]& test() {
1759 static Bar x;
1760 return x;
1761 }
1762 )cpp",
1763 [](HoverInfo &HI) {
1764 HI.Name = "auto";
1765 HI.Kind = index::SymbolKind::TypeAlias;
1766 HI.Definition = "struct Bar";
1767 HI.Documentation = "auto& in function return";
1768 }},
1769 {
1770 R"cpp(// auto* in function return
1771 struct Bar {};
1772 ^[[auto]]* test() {
1773 Bar* bar;
1774 return bar;
1775 }
1776 )cpp",
1777 [](HoverInfo &HI) {
1778 HI.Name = "auto";
1779 HI.Kind = index::SymbolKind::TypeAlias;
1780 HI.Definition = "struct Bar";
1781 HI.Documentation = "auto* in function return";
1782 }},
1783 {
1784 R"cpp(// const auto& in function return
1785 struct Bar {};
1786 const ^[[auto]]& test() {
1787 static Bar x;
1788 return x;
1789 }
1790 )cpp",
1791 [](HoverInfo &HI) {
1792 HI.Name = "auto";
1793 HI.Kind = index::SymbolKind::TypeAlias;
1794 HI.Definition = "struct Bar";
1795 HI.Documentation = "const auto& in function return";
1796 }},
1797 {
1798 R"cpp(// decltype(auto) in function return
1799 struct Bar {};
1800 ^[[decltype]](auto) test() {
1801 return Bar();
1802 }
1803 )cpp",
1804 [](HoverInfo &HI) {
1805 HI.Name = "decltype";
1806 HI.Kind = index::SymbolKind::TypeAlias;
1807 HI.Definition = "struct Bar";
1808 HI.Documentation = "decltype(auto) in function return";
1809 }},
1810 {
1811 R"cpp(// decltype(auto) reference in function return
1812 ^[[decltype]](auto) test() {
1813 static int a;
1814 return (a);
1815 }
1816 )cpp",
1817 [](HoverInfo &HI) {
1818 HI.Name = "decltype";
1819 HI.Kind = index::SymbolKind::TypeAlias;
1820 HI.Definition = "int &";
1821 }},
1822 {
1823 R"cpp(// decltype lvalue reference
1824 void foo() {
1825 int I = 0;
1826 ^[[decltype]](I) J = I;
1827 }
1828 )cpp",
1829 [](HoverInfo &HI) {
1830 HI.Name = "decltype";
1831 HI.Kind = index::SymbolKind::TypeAlias;
1832 HI.Definition = "int";
1833 }},
1834 {
1835 R"cpp(// decltype lvalue reference
1836 void foo() {
1837 int I= 0;
1838 int &K = I;
1839 ^[[decltype]](K) J = I;
1840 }
1841 )cpp",
1842 [](HoverInfo &HI) {
1843 HI.Name = "decltype";
1844 HI.Kind = index::SymbolKind::TypeAlias;
1845 HI.Definition = "int &";
1846 }},
1847 {
1848 R"cpp(// decltype lvalue reference parenthesis
1849 void foo() {
1850 int I = 0;
1851 ^[[decltype]]((I)) J = I;
1852 }
1853 )cpp",
1854 [](HoverInfo &HI) {
1855 HI.Name = "decltype";
1856 HI.Kind = index::SymbolKind::TypeAlias;
1857 HI.Definition = "int &";
1858 }},
1859 {
1860 R"cpp(// decltype rvalue reference
1861 void foo() {
1862 int I = 0;
1863 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
1864 }
1865 )cpp",
1866 [](HoverInfo &HI) {
1867 HI.Name = "decltype";
1868 HI.Kind = index::SymbolKind::TypeAlias;
1869 HI.Definition = "int &&";
1870 }},
1871 {
1872 R"cpp(// decltype rvalue reference function call
1873 int && bar();
1874 void foo() {
1875 int I = 0;
1876 ^[[decltype]](bar()) J = bar();
1877 }
1878 )cpp",
1879 [](HoverInfo &HI) {
1880 HI.Name = "decltype";
1881 HI.Kind = index::SymbolKind::TypeAlias;
1882 HI.Definition = "int &&";
1883 }},
1884 {
1885 R"cpp(// decltype of function with trailing return type.
1886 struct Bar {};
1887 auto test() -> decltype(Bar()) {
1888 return Bar();
1889 }
1890 void foo() {
1891 ^[[decltype]](test()) i = test();
1892 }
1893 )cpp",
1894 [](HoverInfo &HI) {
1895 HI.Name = "decltype";
1896 HI.Kind = index::SymbolKind::TypeAlias;
1897 HI.Definition = "struct Bar";
1898 HI.Documentation =
1899 "decltype of function with trailing return type.";
1900 }},
1901 {
1902 R"cpp(// decltype of var with decltype.
1903 void foo() {
1904 int I = 0;
1905 decltype(I) J = I;
1906 ^[[decltype]](J) K = J;
1907 }
1908 )cpp",
1909 [](HoverInfo &HI) {
1910 HI.Name = "decltype";
1911 HI.Kind = index::SymbolKind::TypeAlias;
1912 HI.Definition = "int";
1913 }},
1914 {
1915 R"cpp(// decltype of dependent type
1916 template <typename T>
1917 struct X {
1918 using Y = ^[[decltype]](T::Z);
1919 };
1920 )cpp",
1921 [](HoverInfo &HI) {
1922 HI.Name = "decltype";
1923 HI.Kind = index::SymbolKind::TypeAlias;
1924 HI.Definition = "<dependent type>";
1925 }},
1926 {
1927 R"cpp(// More complicated structured types.
1928 int bar();
1929 ^[[auto]] (*foo)() = bar;
1930 )cpp",
1931 [](HoverInfo &HI) {
1932 HI.Name = "auto";
1933 HI.Kind = index::SymbolKind::TypeAlias;
1934 HI.Definition = "int";
1935 }},
1936 {
1937 R"cpp(// Should not crash when evaluating the initializer.
1938 struct Test {};
1939 void test() { Test && [[te^st]] = {}; }
1940 )cpp",
1941 [](HoverInfo &HI) {
1942 HI.Name = "test";
1943 HI.Kind = index::SymbolKind::Variable;
1944 HI.NamespaceScope = "";
1945 HI.LocalScope = "test::";
1946 HI.Type = "Test &&";
1947 HI.Definition = "Test &&test = {}";
1948 }},
1949 {
1950 R"cpp(// auto on alias
1951 typedef int int_type;
1952 ^[[auto]] x = int_type();
1953 )cpp",
1954 [](HoverInfo &HI) {
1955 HI.Name = "auto";
1956 HI.Kind = index::SymbolKind::TypeAlias;
1957 HI.Definition = "int";
1958 }},
1959 {
1960 R"cpp(// auto on alias
1961 struct cls {};
1962 typedef cls cls_type;
1963 ^[[auto]] y = cls_type();
1964 )cpp",
1965 [](HoverInfo &HI) {
1966 HI.Name = "auto";
1967 HI.Kind = index::SymbolKind::TypeAlias;
1968 HI.Definition = "struct cls";
1969 HI.Documentation = "auto on alias";
1970 }},
1971 {
1972 R"cpp(// auto on alias
1973 template <class>
1974 struct templ {};
1975 ^[[auto]] z = templ<int>();
1976 )cpp",
1977 [](HoverInfo &HI) {
1978 HI.Name = "auto";
1979 HI.Kind = index::SymbolKind::TypeAlias;
1980 HI.Definition = "struct templ<int>";
1981 HI.Documentation = "auto on alias";
1982 }},
1983 {
1984 R"cpp(// Undeduced auto declaration
1985 template<typename T>
1986 void foo() {
1987 ^[[auto]] x = T();
1988 }
1989 )cpp",
1990 [](HoverInfo &HI) {
1991 HI.Name = "auto";
1992 HI.Kind = index::SymbolKind::TypeAlias;
1993 HI.Definition = "/* not deduced */";
1994 }},
1995 {
1996 R"cpp(// Undeduced auto return type
1997 template<typename T>
1998 ^[[auto]] foo() {
1999 return T();
2000 }
2001 )cpp",
2002 [](HoverInfo &HI) {
2003 HI.Name = "auto";
2004 HI.Kind = index::SymbolKind::TypeAlias;
2005 HI.Definition = "/* not deduced */";
2006 }},
2007 {
2008 R"cpp(// Template auto parameter
2009 template<[[a^uto]] T>
2010 void func() {
2011 }
2012 )cpp",
2013 [](HoverInfo &HI) {
2014 // FIXME: not sure this is what we want, but this
2015 // is what we currently get with getDeducedType
2016 HI.Name = "auto";
2017 HI.Kind = index::SymbolKind::TypeAlias;
2018 HI.Definition = "/* not deduced */";
2019 }},
2020 {
2021 R"cpp(// Undeduced decltype(auto) return type
2022 template<typename T>
2023 ^[[decltype]](auto) foo() {
2024 return T();
2025 }
2026 )cpp",
2027 [](HoverInfo &HI) {
2028 HI.Name = "decltype";
2029 HI.Kind = index::SymbolKind::TypeAlias;
2030 HI.Definition = "/* not deduced */";
2031 }},
2032 {
2033 R"cpp(// should not crash.
2034 template <class T> struct cls {
2035 int method();
2036 };
2037
2038 auto test = cls<int>().[[m^ethod]]();
2039 )cpp",
2040 [](HoverInfo &HI) {
2041 HI.Definition = "int method()";
2042 HI.Kind = index::SymbolKind::InstanceMethod;
2043 HI.NamespaceScope = "";
2044 HI.LocalScope = "cls<int>::";
2045 HI.Name = "method";
2046 HI.Parameters.emplace();
2047 HI.ReturnType = "int";
2048 HI.Type = "int ()";
2049 }},
2050 {
2051 R"cpp(// type of nested templates.
2052 template <class T> struct cls {};
2053 cls<cls<cls<int>>> [[fo^o]];
2054 )cpp",
2055 [](HoverInfo &HI) {
2056 HI.Definition = "cls<cls<cls<int>>> foo";
2057 HI.Kind = index::SymbolKind::Variable;
2058 HI.NamespaceScope = "";
2059 HI.Name = "foo";
2060 HI.Type = "cls<cls<cls<int>>>";
2061 }},
2062 {
2063 R"cpp(// type of nested templates.
2064 template <class T> struct cls {};
2065 [[cl^s]]<cls<cls<int>>> foo;
2066 )cpp",
2067 [](HoverInfo &HI) {
2068 HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
2069 HI.Kind = index::SymbolKind::Struct;
2070 HI.NamespaceScope = "";
2071 HI.Name = "cls<cls<cls<int>>>";
2072 HI.Documentation = "type of nested templates.";
2073 }},
2074 {
2075 R"cpp(// type with decltype
2076 int a;
2077 decltype(a) [[b^]] = a;)cpp",
2078 [](HoverInfo &HI) {
2079 HI.Definition = "decltype(a) b = a";
2080 HI.Kind = index::SymbolKind::Variable;
2081 HI.NamespaceScope = "";
2082 HI.Name = "b";
2083 HI.Type = "int";
2084 }},
2085 {
2086 R"cpp(// type with decltype
2087 int a;
2088 decltype(a) c;
2089 decltype(c) [[b^]] = a;)cpp",
2090 [](HoverInfo &HI) {
2091 HI.Definition = "decltype(c) b = a";
2092 HI.Kind = index::SymbolKind::Variable;
2093 HI.NamespaceScope = "";
2094 HI.Name = "b";
2095 HI.Type = "int";
2096 }},
2097 {
2098 R"cpp(// type with decltype
2099 int a;
2100 const decltype(a) [[b^]] = a;)cpp",
2101 [](HoverInfo &HI) {
2102 HI.Definition = "const decltype(a) b = a";
2103 HI.Kind = index::SymbolKind::Variable;
2104 HI.NamespaceScope = "";
2105 HI.Name = "b";
2106 HI.Type = "int";
2107 }},
2108 {
2109 R"cpp(// type with decltype
2110 int a;
2111 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
2112 [](HoverInfo &HI) {
2113 HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
2114 HI.Kind = index::SymbolKind::Function;
2115 HI.NamespaceScope = "";
2116 HI.Name = "foo";
2117 // FIXME: Handle composite types with decltype with a printing
2118 // policy.
2119 HI.Type = "auto (decltype(a)) -> decltype(a)";
2120 HI.ReturnType = "int";
2121 HI.Parameters = {
2122 {std::string("int"), std::string("x"), llvm::None}};
2123 }},
2124 {
2125 R"cpp(// sizeof expr
2126 void foo() {
2127 (void)[[size^of]](char);
2128 })cpp",
2129 [](HoverInfo &HI) {
2130 HI.Name = "expression";
2131 HI.Type = "unsigned long";
2132 HI.Value = "1";
2133 }},
2134 {
2135 R"cpp(// alignof expr
2136 void foo() {
2137 (void)[[align^of]](char);
2138 })cpp",
2139 [](HoverInfo &HI) {
2140 HI.Name = "expression";
2141 HI.Type = "unsigned long";
2142 HI.Value = "1";
2143 }},
2144 {
2145 R"cpp(
2146 template <typename T = int>
2147 void foo(const T& = T()) {
2148 [[f^oo]]<>(3);
2149 })cpp",
2150 [](HoverInfo &HI) {
2151 HI.Name = "foo";
2152 HI.Kind = index::SymbolKind::Function;
2153 HI.Type = "void (const int &)";
2154 HI.ReturnType = "void";
2155 HI.Parameters = {
2156 {std::string("const int &"), llvm::None, std::string("T()")}};
2157 HI.Definition = "template <> void foo<int>(const int &)";
2158 HI.NamespaceScope = "";
2159 }},
2160 {
2161 R"cpp(// should not crash
2162 @interface ObjC {
2163 char [[da^ta]];
2164 }@end
2165 )cpp",
2166 [](HoverInfo &HI) {
2167 HI.Name = "data";
2168 HI.Type = "char";
2169 HI.Kind = index::SymbolKind::Field;
2170 HI.NamespaceScope = "ObjC::"; // FIXME: fix it
2171 HI.Definition = "char data";
2172 }},
2173 {
2174 R"cpp(
2175 @interface MYObject
2176 @end
2177 @interface Interface
2178 @property(retain) [[MYOb^ject]] *x;
2179 @end
2180 )cpp",
2181 [](HoverInfo &HI) {
2182 HI.Name = "MYObject";
2183 HI.Kind = index::SymbolKind::Class;
2184 HI.NamespaceScope = "";
2185 HI.Definition = "@interface MYObject\n@end";
2186 }},
2187 {
2188 R"cpp(
2189 @interface MYObject
2190 @end
2191 @interface Interface
2192 - (void)doWith:([[MYOb^ject]] *)object;
2193 @end
2194 )cpp",
2195 [](HoverInfo &HI) {
2196 HI.Name = "MYObject";
2197 HI.Kind = index::SymbolKind::Class;
2198 HI.NamespaceScope = "";
2199 HI.Definition = "@interface MYObject\n@end";
2200 }},
2201 {
2202 R"cpp(// this expr
2203 // comment
2204 namespace ns {
2205 class Foo {
2206 Foo* bar() {
2207 return [[t^his]];
2208 }
2209 };
2210 }
2211 )cpp",
2212 [](HoverInfo &HI) {
2213 HI.Name = "this";
2214 HI.Definition = "ns::Foo *";
2215 }},
2216 {
2217 R"cpp(// this expr for template class
2218 namespace ns {
2219 template <typename T>
2220 class Foo {
2221 Foo* bar() const {
2222 return [[t^his]];
2223 }
2224 };
2225 }
2226 )cpp",
2227 [](HoverInfo &HI) {
2228 HI.Name = "this";
2229 HI.Definition = "const Foo<T> *";
2230 }},
2231 {
2232 R"cpp(// this expr for specialization class
2233 namespace ns {
2234 template <typename T> class Foo {};
2235 template <>
2236 struct Foo<int> {
2237 Foo* bar() {
2238 return [[thi^s]];
2239 }
2240 };
2241 }
2242 )cpp",
2243 [](HoverInfo &HI) {
2244 HI.Name = "this";
2245 HI.Definition = "Foo<int> *";
2246 }},
2247 {
2248 R"cpp(// this expr for partial specialization struct
2249 namespace ns {
2250 template <typename T, typename F> struct Foo {};
2251 template <typename F>
2252 struct Foo<int, F> {
2253 Foo* bar() const {
2254 return [[thi^s]];
2255 }
2256 };
2257 }
2258 )cpp",
2259 [](HoverInfo &HI) {
2260 HI.Name = "this";
2261 HI.Definition = "const Foo<int, F> *";
2262 }},
2263 };
2264
2265 // Create a tiny index, so tests above can verify documentation is fetched.
2266 Symbol IndexSym = func("indexSymbol");
2267 IndexSym.Documentation = "comment from index";
2268 SymbolSlab::Builder Symbols;
2269 Symbols.insert(IndexSym);
2270 auto Index =
2271 MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
2272
2273 for (const auto &Case : Cases) {
2274 SCOPED_TRACE(Case.Code);
2275
2276 Annotations T(Case.Code);
2277 TestTU TU = TestTU::withCode(T.code());
2278 TU.ExtraArgs.push_back("-std=c++17");
2279 TU.ExtraArgs.push_back("-xobjective-c++");
2280
2281 TU.ExtraArgs.push_back("-Wno-gnu-designator");
2282 // Types might be different depending on the target triplet, we chose a
2283 // fixed one to make sure tests passes on different platform.
2284 TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
2285 auto AST = TU.build();
2286
2287 auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());
2288 ASSERT_TRUE(H);
2289 HoverInfo Expected;
2290 Expected.SymRange = T.range();
2291 Case.ExpectedBuilder(Expected);
2292
2293 SCOPED_TRACE(H->present().asPlainText());
2294 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
2295 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
2296 EXPECT_EQ(H->Name, Expected.Name);
2297 EXPECT_EQ(H->Kind, Expected.Kind);
2298 EXPECT_EQ(H->Documentation, Expected.Documentation);
2299 EXPECT_EQ(H->Definition, Expected.Definition);
2300 EXPECT_EQ(H->Type, Expected.Type);
2301 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
2302 EXPECT_EQ(H->Parameters, Expected.Parameters);
2303 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
2304 EXPECT_EQ(H->SymRange, Expected.SymRange);
2305 EXPECT_EQ(H->Value, Expected.Value);
2306 }
2307 }
2308
TEST(Hover,DocsFromIndex)2309 TEST(Hover, DocsFromIndex) {
2310 Annotations T(R"cpp(
2311 template <typename T> class X {};
2312 void foo() {
2313 auto t = X<int>();
2314 X^<int> w;
2315 (void)w;
2316 })cpp");
2317
2318 TestTU TU = TestTU::withCode(T.code());
2319 auto AST = TU.build();
2320 Symbol IndexSym;
2321 IndexSym.ID = getSymbolID(&findDecl(AST, "X"));
2322 IndexSym.Documentation = "comment from index";
2323 SymbolSlab::Builder Symbols;
2324 Symbols.insert(IndexSym);
2325 auto Index =
2326 MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
2327
2328 for (const auto &P : T.points()) {
2329 auto H = getHover(AST, P, format::getLLVMStyle(), Index.get());
2330 ASSERT_TRUE(H);
2331 EXPECT_EQ(H->Documentation, IndexSym.Documentation);
2332 }
2333 }
2334
TEST(Hover,DocsFromAST)2335 TEST(Hover, DocsFromAST) {
2336 Annotations T(R"cpp(
2337 // doc
2338 template <typename T> class X {};
2339 // doc
2340 template <typename T> void bar() {}
2341 // doc
2342 template <typename T> T baz;
2343 void foo() {
2344 au^to t = X<int>();
2345 X^<int>();
2346 b^ar<int>();
2347 au^to T = ba^z<X<int>>;
2348 ba^z<int> = 0;
2349 })cpp");
2350
2351 TestTU TU = TestTU::withCode(T.code());
2352 auto AST = TU.build();
2353 for (const auto &P : T.points()) {
2354 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
2355 ASSERT_TRUE(H);
2356 EXPECT_EQ(H->Documentation, "doc");
2357 }
2358 }
2359
TEST(Hover,DocsFromMostSpecial)2360 TEST(Hover, DocsFromMostSpecial) {
2361 Annotations T(R"cpp(
2362 // doc1
2363 template <typename T> class $doc1^X {};
2364 // doc2
2365 template <> class $doc2^X<int> {};
2366 // doc3
2367 template <typename T> class $doc3^X<T*> {};
2368 void foo() {
2369 X$doc1^<char>();
2370 X$doc2^<int>();
2371 X$doc3^<int*>();
2372 })cpp");
2373
2374 TestTU TU = TestTU::withCode(T.code());
2375 auto AST = TU.build();
2376 for (auto Comment : {"doc1", "doc2", "doc3"}) {
2377 for (const auto &P : T.points(Comment)) {
2378 auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
2379 ASSERT_TRUE(H);
2380 EXPECT_EQ(H->Documentation, Comment);
2381 }
2382 }
2383 }
2384
TEST(Hover,Present)2385 TEST(Hover, Present) {
2386 struct {
2387 const std::function<void(HoverInfo &)> Builder;
2388 llvm::StringRef ExpectedRender;
2389 } Cases[] = {
2390 {
2391 [](HoverInfo &HI) {
2392 HI.Kind = index::SymbolKind::Unknown;
2393 HI.Name = "X";
2394 },
2395 R"(X)",
2396 },
2397 {
2398 [](HoverInfo &HI) {
2399 HI.Kind = index::SymbolKind::NamespaceAlias;
2400 HI.Name = "foo";
2401 },
2402 R"(namespace-alias foo)",
2403 },
2404 {
2405 [](HoverInfo &HI) {
2406 HI.Kind = index::SymbolKind::Class;
2407 HI.Size = 10;
2408 HI.TemplateParameters = {
2409 {std::string("typename"), std::string("T"), llvm::None},
2410 {std::string("typename"), std::string("C"),
2411 std::string("bool")},
2412 };
2413 HI.Documentation = "documentation";
2414 HI.Definition =
2415 "template <typename T, typename C = bool> class Foo {}";
2416 HI.Name = "foo";
2417 HI.NamespaceScope.emplace();
2418 },
2419 R"(class foo
2420
2421 Size: 10 bytes
2422 documentation
2423
2424 template <typename T, typename C = bool> class Foo {})",
2425 },
2426 {
2427 [](HoverInfo &HI) {
2428 HI.Kind = index::SymbolKind::Function;
2429 HI.Name = "foo";
2430 HI.Type = "type";
2431 HI.ReturnType = "ret_type";
2432 HI.Parameters.emplace();
2433 HoverInfo::Param P;
2434 HI.Parameters->push_back(P);
2435 P.Type = "type";
2436 HI.Parameters->push_back(P);
2437 P.Name = "foo";
2438 HI.Parameters->push_back(P);
2439 P.Default = "default";
2440 HI.Parameters->push_back(P);
2441 HI.NamespaceScope = "ns::";
2442 HI.Definition = "ret_type foo(params) {}";
2443 },
2444 "function foo\n"
2445 "\n"
2446 "→ ret_type\n"
2447 "Parameters:\n"
2448 "- \n"
2449 "- type\n"
2450 "- type foo\n"
2451 "- type foo = default\n"
2452 "\n"
2453 "// In namespace ns\n"
2454 "ret_type foo(params) {}",
2455 },
2456 {
2457 [](HoverInfo &HI) {
2458 HI.Kind = index::SymbolKind::Field;
2459 HI.LocalScope = "test::Bar::";
2460 HI.Value = "value";
2461 HI.Name = "foo";
2462 HI.Type = "type";
2463 HI.Definition = "def";
2464 HI.Size = 4;
2465 HI.Offset = 12;
2466 },
2467 R"(field foo
2468
2469 Type: type
2470 Value = value
2471 Offset: 12 bytes
2472 Size: 4 bytes
2473
2474 // In test::Bar
2475 def)",
2476 },
2477 {
2478 [](HoverInfo &HI) {
2479 HI.Kind = index::SymbolKind::Field;
2480 HI.AccessSpecifier = "public";
2481 HI.Name = "foo";
2482 HI.LocalScope = "test::Bar::";
2483 HI.Definition = "def";
2484 },
2485 R"(field foo
2486
2487 // In test::Bar
2488 public: def)",
2489 },
2490 {
2491 [](HoverInfo &HI) {
2492 HI.Definition = "int method()";
2493 HI.AccessSpecifier = "protected";
2494 HI.Kind = index::SymbolKind::InstanceMethod;
2495 HI.NamespaceScope = "";
2496 HI.LocalScope = "cls<int>::";
2497 HI.Name = "method";
2498 HI.Parameters.emplace();
2499 HI.ReturnType = "int";
2500 HI.Type = "int ()";
2501 },
2502 R"(instance-method method
2503
2504 → int
2505
2506 // In cls<int>
2507 protected: int method())",
2508 },
2509 {
2510 [](HoverInfo &HI) {
2511 HI.Kind = index::SymbolKind::Union;
2512 HI.AccessSpecifier = "private";
2513 HI.Name = "foo";
2514 HI.NamespaceScope = "ns1::";
2515 HI.Definition = "union foo {}";
2516 },
2517 R"(union foo
2518
2519 // In namespace ns1
2520 private: union foo {})",
2521 },
2522 {
2523 [](HoverInfo &HI) {
2524 HI.Kind = index::SymbolKind::Variable;
2525 HI.Name = "foo";
2526 HI.Definition = "int foo = 3";
2527 HI.LocalScope = "test::Bar::";
2528 HI.Value = "3";
2529 HI.Type = "int";
2530 HI.CalleeArgInfo.emplace();
2531 HI.CalleeArgInfo->Name = "arg_a";
2532 HI.CalleeArgInfo->Type = "int";
2533 HI.CalleeArgInfo->Default = "7";
2534 HI.CallPassType.emplace();
2535 HI.CallPassType->PassBy = PassMode::Value;
2536 HI.CallPassType->Converted = false;
2537 },
2538 R"(variable foo
2539
2540 Type: int
2541 Value = 3
2542 Passed as arg_a
2543
2544 // In test::Bar
2545 int foo = 3)",
2546 },
2547 {
2548 [](HoverInfo &HI) {
2549 HI.Kind = index::SymbolKind::Variable;
2550 HI.Name = "foo";
2551 HI.Definition = "int foo = 3";
2552 HI.LocalScope = "test::Bar::";
2553 HI.Value = "3";
2554 HI.Type = "int";
2555 HI.CalleeArgInfo.emplace();
2556 HI.CalleeArgInfo->Name = "arg_a";
2557 HI.CalleeArgInfo->Type = "int";
2558 HI.CalleeArgInfo->Default = "7";
2559 HI.CallPassType.emplace();
2560 HI.CallPassType->PassBy = PassMode::Ref;
2561 HI.CallPassType->Converted = false;
2562 },
2563 R"(variable foo
2564
2565 Type: int
2566 Value = 3
2567 Passed by reference as arg_a
2568
2569 // In test::Bar
2570 int foo = 3)",
2571 },
2572 {
2573 [](HoverInfo &HI) {
2574 HI.Kind = index::SymbolKind::Variable;
2575 HI.Name = "foo";
2576 HI.Definition = "int foo = 3";
2577 HI.LocalScope = "test::Bar::";
2578 HI.Value = "3";
2579 HI.Type = "int";
2580 HI.CalleeArgInfo.emplace();
2581 HI.CalleeArgInfo->Name = "arg_a";
2582 HI.CalleeArgInfo->Type = "int";
2583 HI.CalleeArgInfo->Default = "7";
2584 HI.CallPassType.emplace();
2585 HI.CallPassType->PassBy = PassMode::Value;
2586 HI.CallPassType->Converted = true;
2587 },
2588 R"(variable foo
2589
2590 Type: int
2591 Value = 3
2592 Passed as arg_a (converted to int)
2593
2594 // In test::Bar
2595 int foo = 3)",
2596 },
2597 {
2598 [](HoverInfo &HI) {
2599 HI.Kind = index::SymbolKind::Variable;
2600 HI.Name = "foo";
2601 HI.Definition = "int foo = 3";
2602 HI.LocalScope = "test::Bar::";
2603 HI.Value = "3";
2604 HI.Type = "int";
2605 HI.CalleeArgInfo.emplace();
2606 HI.CalleeArgInfo->Name = "arg_a";
2607 HI.CalleeArgInfo->Type = "int";
2608 HI.CalleeArgInfo->Default = "7";
2609 HI.CallPassType.emplace();
2610 HI.CallPassType->PassBy = PassMode::ConstRef;
2611 HI.CallPassType->Converted = true;
2612 },
2613 R"(variable foo
2614
2615 Type: int
2616 Value = 3
2617 Passed by const reference as arg_a (converted to int)
2618
2619 // In test::Bar
2620 int foo = 3)",
2621 }};
2622
2623 for (const auto &C : Cases) {
2624 HoverInfo HI;
2625 C.Builder(HI);
2626 EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
2627 }
2628 }
2629
TEST(Hover,ParseDocumentation)2630 TEST(Hover, ParseDocumentation) {
2631 struct Case {
2632 llvm::StringRef Documentation;
2633 llvm::StringRef ExpectedRenderMarkdown;
2634 llvm::StringRef ExpectedRenderPlainText;
2635 } Cases[] = {{
2636 " \n foo\nbar",
2637 "foo bar",
2638 "foo bar",
2639 },
2640 {
2641 "foo\nbar \n ",
2642 "foo bar",
2643 "foo bar",
2644 },
2645 {
2646 "foo \nbar",
2647 "foo bar",
2648 "foo bar",
2649 },
2650 {
2651 "foo \nbar",
2652 "foo bar",
2653 "foo bar",
2654 },
2655 {
2656 "foo\n\n\nbar",
2657 "foo \nbar",
2658 "foo\nbar",
2659 },
2660 {
2661 "foo\n\n\n\tbar",
2662 "foo \nbar",
2663 "foo\nbar",
2664 },
2665 {
2666 "foo\n\n\n bar",
2667 "foo \nbar",
2668 "foo\nbar",
2669 },
2670 {
2671 "foo.\nbar",
2672 "foo. \nbar",
2673 "foo.\nbar",
2674 },
2675 {
2676 "foo. \nbar",
2677 "foo. \nbar",
2678 "foo.\nbar",
2679 },
2680 {
2681 "foo\n*bar",
2682 "foo \n\\*bar",
2683 "foo\n*bar",
2684 },
2685 {
2686 "foo\nbar",
2687 "foo bar",
2688 "foo bar",
2689 },
2690 {
2691 "Tests primality of `p`.",
2692 "Tests primality of `p`.",
2693 "Tests primality of `p`.",
2694 },
2695 {
2696 "'`' should not occur in `Code`",
2697 "'\\`' should not occur in `Code`",
2698 "'`' should not occur in `Code`",
2699 },
2700 {
2701 "`not\nparsed`",
2702 "\\`not parsed\\`",
2703 "`not parsed`",
2704 }};
2705
2706 for (const auto &C : Cases) {
2707 markup::Document Output;
2708 parseDocumentation(C.Documentation, Output);
2709
2710 EXPECT_EQ(Output.asMarkdown(), C.ExpectedRenderMarkdown);
2711 EXPECT_EQ(Output.asPlainText(), C.ExpectedRenderPlainText);
2712 }
2713 }
2714
2715 // This is a separate test as headings don't create any differences in plaintext
2716 // mode.
TEST(Hover,PresentHeadings)2717 TEST(Hover, PresentHeadings) {
2718 HoverInfo HI;
2719 HI.Kind = index::SymbolKind::Variable;
2720 HI.Name = "foo";
2721
2722 EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`");
2723 }
2724
2725 // This is a separate test as rulers behave differently in markdown vs
2726 // plaintext.
TEST(Hover,PresentRulers)2727 TEST(Hover, PresentRulers) {
2728 HoverInfo HI;
2729 HI.Kind = index::SymbolKind::Variable;
2730 HI.Name = "foo";
2731 HI.Value = "val";
2732 HI.Definition = "def";
2733
2734 llvm::StringRef ExpectedMarkdown = //
2735 "### variable `foo` \n"
2736 "\n"
2737 "---\n"
2738 "Value = `val` \n"
2739 "\n"
2740 "---\n"
2741 "```cpp\n"
2742 "def\n"
2743 "```";
2744 EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
2745
2746 llvm::StringRef ExpectedPlaintext = R"pt(variable foo
2747
2748 Value = val
2749
2750 def)pt";
2751 EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
2752 }
2753 } // namespace
2754 } // namespace clangd
2755 } // namespace clang
2756