1 //===-- HoverTests.cpp ----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "Annotations.h"
14 #include "TestIndex.h"
16 #include "index/MemIndex.h"
17 #include "clang/AST/Attr.h"
18 #include "clang/Format/Format.h"
19 #include "clang/Index/IndexSymbol.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Twine.h"
23 #include "gtest/gtest.h"
33 using PassMode
= HoverInfo::PassType::PassMode
;
35 std::string
guard(llvm::StringRef Code
) {
36 return "#pragma once\n" + Code
.str();
39 TEST(Hover
, Structured
) {
41 const char *const Code
;
42 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
50 HI
.NamespaceScope
= "";
52 HI
.Kind
= index::SymbolKind::Function
;
53 HI
.Documentation
= "Best foo ever.";
54 HI
.Definition
= "void foo()";
55 HI
.ReturnType
= "void";
57 HI
.Parameters
.emplace();
61 namespace ns1 { namespace ns2 {
67 HI
.NamespaceScope
= "ns1::ns2::";
69 HI
.Kind
= index::SymbolKind::Function
;
70 HI
.Documentation
= "Best foo ever.";
71 HI
.Definition
= "void foo()";
72 HI
.ReturnType
= "void";
74 HI
.Parameters
.emplace();
78 namespace ns1 { namespace ns2 {
86 HI
.NamespaceScope
= "ns1::ns2::";
87 HI
.LocalScope
= "Foo::";
89 HI
.Kind
= index::SymbolKind::Field
;
90 HI
.Definition
= "char bar";
95 HI
.AccessSpecifier
= "private";
105 HI
.NamespaceScope
= "";
106 HI
.LocalScope
= "Foo::";
108 HI
.Kind
= index::SymbolKind::Field
;
109 HI
.Definition
= "char bar";
113 HI
.AccessSpecifier
= "public";
123 HI
.NamespaceScope
= "";
124 HI
.LocalScope
= "Foo::";
126 HI
.Kind
= index::SymbolKind::Field
;
127 HI
.Definition
= "int x : 1";
131 HI
.AccessSpecifier
= "public";
133 // Local to class method.
135 namespace ns1 { namespace ns2 {
144 HI
.NamespaceScope
= "ns1::ns2::";
145 HI
.LocalScope
= "Foo::foo::";
147 HI
.Kind
= index::SymbolKind::Variable
;
148 HI
.Definition
= "int bar";
151 // Predefined variable
158 HI
.Name
= "__func__";
159 HI
.Kind
= index::SymbolKind::Variable
;
161 "Name of the current function (predefined variable)";
162 HI
.Value
= "\"foo\"";
163 HI
.Type
= "const char[4]";
165 // Predefined variable (dependent)
167 template<int> void foo() {
172 HI
.Name
= "__func__";
173 HI
.Kind
= index::SymbolKind::Variable
;
175 "Name of the current function (predefined variable)";
176 HI
.Type
= "const char[]";
178 // Anon namespace and local scope.
180 namespace ns1 { namespace {
187 HI
.NamespaceScope
= "ns1::";
188 HI
.LocalScope
= "(anonymous struct)::";
190 HI
.Kind
= index::SymbolKind::Field
;
191 HI
.Definition
= "char bar";
195 HI
.AccessSpecifier
= "public";
197 // Struct definition shows size.
202 HI
.NamespaceScope
= "";
204 HI
.Kind
= index::SymbolKind::Struct
;
205 HI
.Definition
= "struct X {}";
208 // Variable with template type
210 template <typename T, class... Ts> class Foo { public: Foo(int); };
211 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
214 HI
.NamespaceScope
= "";
216 HI
.Kind
= index::SymbolKind::Variable
;
217 HI
.Definition
= "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
218 HI
.Type
= "Foo<int, char, bool>";
220 // Implicit template instantiation
222 template <typename T> class vector{};
223 [[vec^tor]]<int> foo;
226 HI
.NamespaceScope
= "";
227 HI
.Name
= "vector<int>";
228 HI
.Kind
= index::SymbolKind::Class
;
229 HI
.Definition
= "template <> class vector<int> {}";
233 template <template<typename, bool...> class C,
237 class... Ts> class Foo final {};
238 template <template<typename, bool...> class T>
242 HI
.NamespaceScope
= "";
244 HI
.Kind
= index::SymbolKind::Class
;
246 R
"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
247 bool Q = false, class... Ts>
248 class Foo final {})cpp";
249 HI
.TemplateParameters
= {
250 {{"template <typename, bool...> class"},
253 {{"typename"}, std::nullopt
, std::string("char")},
254 {{"int"}, std::nullopt
, std::string("0")},
255 {{"bool"}, std::string("Q"), std::string("false")},
256 {{"class..."}, std::string("Ts"), std::nullopt
},
261 template <template<typename, bool...> class C,
265 class... Ts> void foo();
266 template<typename, bool...> class Foo;
273 HI
.NamespaceScope
= "";
275 HI
.Kind
= index::SymbolKind::Function
;
276 HI
.Definition
= "template <> void foo<Foo, char, 0, false, <>>()";
277 HI
.ReturnType
= "void";
279 HI
.Parameters
.emplace();
283 template<typename, bool...> class Foo {};
284 Foo<bool, true, false> foo(int, bool T = false);
291 HI
.NamespaceScope
= "";
293 HI
.Kind
= index::SymbolKind::Function
;
294 HI
.Definition
= "Foo<bool, true, false> foo(int, bool T = false)";
295 HI
.ReturnType
= "Foo<bool, true, false>";
296 HI
.Type
= "Foo<bool, true, false> (int, bool)";
298 {{"int"}, std::nullopt
, std::nullopt
},
299 {{"bool"}, std::string("T"), std::string("false")},
302 // Pointers to lambdas
305 auto lamb = [](int T, bool B) -> bool { return T && B; };
311 HI
.NamespaceScope
= "";
312 HI
.LocalScope
= "foo::";
314 HI
.Kind
= index::SymbolKind::Variable
;
315 HI
.Definition
= "auto *c = &b";
316 HI
.Type
= "(lambda) **";
317 HI
.ReturnType
= "bool";
319 {{"int"}, std::string("T"), std::nullopt
},
320 {{"bool"}, std::string("B"), std::nullopt
},
324 // Lambda parameter with decltype reference
326 auto lamb = [](int T, bool B) -> bool { return T && B; };
327 void foo(decltype(lamb)& bar) {
332 HI
.NamespaceScope
= "";
333 HI
.LocalScope
= "foo::";
335 HI
.Kind
= index::SymbolKind::Parameter
;
336 HI
.Definition
= "decltype(lamb) &bar";
337 HI
.Type
= {"decltype(lamb) &", "(lambda) &"};
338 HI
.ReturnType
= "bool";
340 {{"int"}, std::string("T"), std::nullopt
},
341 {{"bool"}, std::string("B"), std::nullopt
},
345 // Lambda parameter with decltype
347 auto lamb = [](int T, bool B) -> bool { return T && B; };
348 void foo(decltype(lamb) bar) {
353 HI
.NamespaceScope
= "";
354 HI
.LocalScope
= "foo::";
356 HI
.Kind
= index::SymbolKind::Parameter
;
357 HI
.Definition
= "decltype(lamb) bar";
358 HI
.Type
= "class (lambda)";
359 HI
.ReturnType
= "bool";
361 {{"int"}, std::string("T"), std::nullopt
},
362 {{"bool"}, std::string("B"), std::nullopt
},
371 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
372 bool res = [[lam^b]](bar, false);
376 HI
.NamespaceScope
= "";
377 HI
.LocalScope
= "foo::";
379 HI
.Kind
= index::SymbolKind::Variable
;
380 HI
.Definition
= "auto lamb = [&bar](int T, bool B) -> bool {}";
381 HI
.Type
= "class (lambda)";
382 HI
.ReturnType
= "bool";
384 {{"int"}, std::string("T"), std::nullopt
},
385 {{"bool"}, std::string("B"), std::nullopt
},
389 // Local variable in lambda
392 auto lamb = []{int [[te^st]];};
396 HI
.NamespaceScope
= "";
397 HI
.LocalScope
= "foo::(anonymous class)::operator()::";
399 HI
.Kind
= index::SymbolKind::Variable
;
400 HI
.Definition
= "int test";
403 // Partially-specialized class template. (formerly type-parameter-0-0)
405 template <typename T> class X;
406 template <typename T> class [[^X]]<T*> {};
410 HI
.NamespaceScope
= "";
411 HI
.Kind
= index::SymbolKind::Class
;
412 HI
.Definition
= "template <typename T> class X<T *> {}";
414 // Constructor of partially-specialized class template
416 template<typename, typename=void> struct X;
417 template<typename T> struct X<T*>{ [[^X]](); };
420 HI
.NamespaceScope
= "";
422 HI
.LocalScope
= "X<T *>::"; // FIXME: X<T *, void>::
423 HI
.Kind
= index::SymbolKind::Constructor
;
424 HI
.Definition
= "X()";
425 HI
.Parameters
.emplace();
426 HI
.AccessSpecifier
= "public";
428 {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
430 HI
.NamespaceScope
= "";
432 HI
.LocalScope
= "X::";
433 HI
.Kind
= index::SymbolKind::Destructor
;
434 HI
.Definition
= "~X()";
435 HI
.Parameters
.emplace();
436 HI
.AccessSpecifier
= "private";
438 {"class X { [[op^erator]] int(); };",
440 HI
.NamespaceScope
= "";
441 HI
.Name
= "operator int";
442 HI
.LocalScope
= "X::";
443 HI
.Kind
= index::SymbolKind::ConversionFunction
;
444 HI
.Definition
= "operator int()";
445 HI
.Parameters
.emplace();
446 HI
.AccessSpecifier
= "private";
448 {"class X { operator [[^X]](); };",
450 HI
.NamespaceScope
= "";
452 HI
.Kind
= index::SymbolKind::Class
;
453 HI
.Definition
= "class X {}";
456 // auto on structured bindings
459 struct S { int x; float y; };
460 [[au^to]] [x, y] = S();
465 HI
.Kind
= index::SymbolKind::TypeAlias
;
477 HI
.Kind
= index::SymbolKind::TypeAlias
;
478 HI
.Definition
= "/* not deduced */";
482 template <class T> concept F = true;
487 HI
.Kind
= index::SymbolKind::TypeAlias
;
488 HI
.Definition
= "int";
493 [[au^to]] lamb = []{};
498 HI
.Kind
= index::SymbolKind::TypeAlias
;
499 HI
.Definition
= "class(lambda)";
501 // auto on template instantiation
503 template<typename T> class Foo{};
505 [[au^to]] x = Foo<int>();
510 HI
.Kind
= index::SymbolKind::TypeAlias
;
511 HI
.Definition
= "Foo<int>";
513 // auto on specialized template
515 template<typename T> class Foo{};
516 template<> class Foo<int>{};
518 [[au^to]] x = Foo<int>();
523 HI
.Kind
= index::SymbolKind::TypeAlias
;
524 HI
.Definition
= "Foo<int>";
534 HI
.Kind
= index::SymbolKind::Macro
;
535 HI
.Definition
= "#define MACRO";
545 HI
.Kind
= index::SymbolKind::Macro
;
546 HI
.Value
= "41 (0x29)";
548 HI
.Definition
= "#define MACRO 41\n\n"
553 // function-like macro
556 #define MACRO(x,y,z) void foo(x, y, z)
557 [[MAC^RO]](int, double d, bool z = false);
561 HI
.Kind
= index::SymbolKind::Macro
;
562 HI
.Definition
= "#define MACRO(x, y, z) void foo(x, y, z)\n\n"
564 "void foo(int, double d, bool z = false)";
569 #define STRINGIFY_AUX(s) #s
570 #define STRINGIFY(s) STRINGIFY_AUX(s)
571 #define DECL_STR(NAME, VALUE) const char *v_##NAME = STRINGIFY(VALUE)
574 [[DECL^_STR]](foo, FOO);
577 HI
.Name
= "DECL_STR";
578 HI
.Kind
= index::SymbolKind::Macro
;
579 HI
.Type
= HoverInfo::PrintedType("const char *");
580 HI
.Definition
= "#define DECL_STR(NAME, VALUE) const char *v_##NAME = "
581 "STRINGIFY(VALUE)\n\n"
583 "const char *v_foo = \"41\"";
588 constexpr int add(int a, int b) { return a + b; }
589 int [[b^ar]] = add(1, 2);
593 HI
.Definition
= "int bar = add(1, 2)";
594 HI
.Kind
= index::SymbolKind::Variable
;
596 HI
.NamespaceScope
= "";
600 int [[b^ar]] = sizeof(char);
604 HI
.Definition
= "int bar = sizeof(char)";
605 HI
.Kind
= index::SymbolKind::Variable
;
607 HI
.NamespaceScope
= "";
611 template<int a, int b> struct Add {
612 static constexpr int result = a + b;
614 int [[ba^r]] = Add<1, 2>::result;
618 HI
.Definition
= "int bar = Add<1, 2>::result";
619 HI
.Kind
= index::SymbolKind::Variable
;
621 HI
.NamespaceScope
= "";
625 enum Color { RED = -123, GREEN = 5, };
626 Color x = [[GR^EEN]];
630 HI
.NamespaceScope
= "";
631 HI
.LocalScope
= "Color::";
632 HI
.Definition
= "GREEN = 5";
633 HI
.Kind
= index::SymbolKind::EnumConstant
;
634 HI
.Type
= "enum Color";
635 HI
.Value
= "5"; // Numeric on the enumerator name, no hex as small.
638 enum Color { RED = -123, GREEN = 5, };
644 HI
.NamespaceScope
= "";
645 HI
.Definition
= "Color x = RED";
646 HI
.Kind
= index::SymbolKind::Variable
;
648 HI
.Value
= "RED (0xffffff85)"; // Symbolic on an expression.
651 template<int a, int b> struct Add {
652 static constexpr int result = a + b;
654 int bar = Add<1, 2>::[[resu^lt]];
658 HI
.Definition
= "static constexpr int result = a + b";
659 HI
.Kind
= index::SymbolKind::StaticProperty
;
660 HI
.Type
= "const int";
661 HI
.NamespaceScope
= "";
662 HI
.LocalScope
= "Add<1, 2>::";
664 HI
.AccessSpecifier
= "public";
668 constexpr my_int answer() { return 40 + 2; }
669 int x = [[ans^wer]]();
673 HI
.Definition
= "constexpr my_int answer()";
674 HI
.Kind
= index::SymbolKind::Function
;
675 HI
.Type
= {"my_int ()", "int ()"};
676 HI
.ReturnType
= {"my_int", "int"};
677 HI
.Parameters
.emplace();
678 HI
.NamespaceScope
= "";
679 HI
.Value
= "42 (0x2a)";
682 const char *[[ba^r]] = "1234";
686 HI
.Definition
= "const char *bar = \"1234\"";
687 HI
.Kind
= index::SymbolKind::Variable
;
688 HI
.Type
= "const char *";
689 HI
.NamespaceScope
= "";
690 HI
.Value
= "&\"1234\"[0]";
692 {R
"cpp(// Should not crash
693 template <typename T>
698 template <typename A>
699 void boom(int name) {
700 new Tmpl<A>([[na^me]]);
704 HI
.Definition
= "int name";
705 HI
.Kind
= index::SymbolKind::Parameter
;
707 HI
.NamespaceScope
= "";
708 HI
.LocalScope
= "boom::";
711 R
"cpp(// Should not print inline or anon namespaces.
713 inline namespace in_ns {
717 inline namespace in_ns2 {
726 ns::a::b::[[F^oo]] x;
732 HI
.Kind
= index::SymbolKind::Class
;
733 HI
.NamespaceScope
= "ns::a::b::";
734 HI
.Definition
= "class Foo {}";
738 template <typename T> class Foo {};
741 [[^auto]] x = Foo<X>();
746 HI
.Kind
= index::SymbolKind::TypeAlias
;
747 HI
.Definition
= "Foo<X>";
749 {// Falls back to primary template, when the type is not instantiated.
751 // comment from primary
752 template <typename T> class Foo {};
753 // comment from specialization
754 template <typename T> class Foo<T*> {};
756 [[Fo^o]]<int*> *x = nullptr;
760 HI
.Name
= "Foo<int *>";
761 HI
.Kind
= index::SymbolKind::Class
;
762 HI
.NamespaceScope
= "";
763 HI
.Definition
= "template <> class Foo<int *>";
764 // FIXME: Maybe force instantiation to make use of real template
766 HI
.Documentation
= "comment from primary";
768 {// Template Type Parameter
770 template <typename [[^T]] = int> void foo();
774 HI
.Kind
= index::SymbolKind::TemplateTypeParm
;
775 HI
.NamespaceScope
= "";
776 HI
.Definition
= "typename T = int";
777 HI
.LocalScope
= "foo::";
778 HI
.Type
= "typename";
779 HI
.AccessSpecifier
= "public";
781 {// TemplateTemplate Type Parameter
783 template <template<typename> class [[^T]]> void foo();
787 HI
.Kind
= index::SymbolKind::TemplateTemplateParm
;
788 HI
.NamespaceScope
= "";
789 HI
.Definition
= "template <typename> class T";
790 HI
.LocalScope
= "foo::";
791 HI
.Type
= "template <typename> class";
792 HI
.AccessSpecifier
= "public";
794 {// NonType Template Parameter
796 template <int [[^T]] = 5> void foo();
800 HI
.Kind
= index::SymbolKind::NonTypeTemplateParm
;
801 HI
.NamespaceScope
= "";
802 HI
.Definition
= "int T = 5";
803 HI
.LocalScope
= "foo::";
805 HI
.AccessSpecifier
= "public";
810 struct X { int Y; float [[^y]]() { return Y; } };
814 HI
.Kind
= index::SymbolKind::InstanceMethod
;
815 HI
.NamespaceScope
= "";
816 HI
.Definition
= "float y()";
817 HI
.LocalScope
= "X::";
818 HI
.Documentation
= "Trivial accessor for `Y`.";
819 HI
.Type
= "float ()";
820 HI
.ReturnType
= "float";
821 HI
.Parameters
.emplace();
822 HI
.AccessSpecifier
= "public";
826 struct X { int Y; void [[^setY]](float v) { Y = v; } };
830 HI
.Kind
= index::SymbolKind::InstanceMethod
;
831 HI
.NamespaceScope
= "";
832 HI
.Definition
= "void setY(float v)";
833 HI
.LocalScope
= "X::";
834 HI
.Documentation
= "Trivial setter for `Y`.";
835 HI
.Type
= "void (float)";
836 HI
.ReturnType
= "void";
837 HI
.Parameters
.emplace();
838 HI
.Parameters
->emplace_back();
839 HI
.Parameters
->back().Type
= "float";
840 HI
.Parameters
->back().Name
= "v";
841 HI
.AccessSpecifier
= "public";
845 struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };
849 HI
.Kind
= index::SymbolKind::InstanceMethod
;
850 HI
.NamespaceScope
= "";
851 HI
.Definition
= "X &setY(float v)";
852 HI
.LocalScope
= "X::";
853 HI
.Documentation
= "Trivial setter for `Y`.";
854 HI
.Type
= "X &(float)";
855 HI
.ReturnType
= "X &";
856 HI
.Parameters
.emplace();
857 HI
.Parameters
->emplace_back();
858 HI
.Parameters
->back().Type
= "float";
859 HI
.Parameters
->back().Name
= "v";
860 HI
.AccessSpecifier
= "public";
864 namespace std { template<typename T> T&& move(T&& t); }
865 struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } };
869 HI
.Kind
= index::SymbolKind::InstanceMethod
;
870 HI
.NamespaceScope
= "";
871 HI
.Definition
= "void setY(float v)";
872 HI
.LocalScope
= "X::";
873 HI
.Documentation
= "Trivial setter for `Y`.";
874 HI
.Type
= "void (float)";
875 HI
.ReturnType
= "void";
876 HI
.Parameters
.emplace();
877 HI
.Parameters
->emplace_back();
878 HI
.Parameters
->back().Type
= "float";
879 HI
.Parameters
->back().Name
= "v";
880 HI
.AccessSpecifier
= "public";
882 {// Field type initializer.
884 struct X { int x = 2; };
889 HI
.Kind
= index::SymbolKind::Variable
;
890 HI
.NamespaceScope
= "";
891 HI
.Definition
= "X x";
894 {// Don't crash on null types.
895 R
"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
898 HI
.Kind
= index::SymbolKind::Variable
;
899 HI
.NamespaceScope
= "";
901 HI
.Type
= "NULL TYPE";
902 // Bindings are in theory public members of an anonymous struct.
903 HI
.AccessSpecifier
= "public";
905 {// Extra info for function call.
907 void fun(int arg_a, int &arg_b) {};
915 HI
.Kind
= index::SymbolKind::Variable
;
916 HI
.NamespaceScope
= "";
917 HI
.Definition
= "int b = 2";
918 HI
.LocalScope
= "code::";
921 HI
.CalleeArgInfo
.emplace();
922 HI
.CalleeArgInfo
->Name
= "arg_b";
923 HI
.CalleeArgInfo
->Type
= "int &";
924 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Ref
, false};
926 {// make_unique-like function call
929 explicit Foo(int arg_a) {}
931 template<class T, class... Args>
932 T make(Args&&... args)
939 auto foo = make<Foo>([[^a]]);
944 HI
.Kind
= index::SymbolKind::Variable
;
945 HI
.NamespaceScope
= "";
946 HI
.Definition
= "int a = 1";
947 HI
.LocalScope
= "code::";
950 HI
.CalleeArgInfo
.emplace();
951 HI
.CalleeArgInfo
->Name
= "arg_a";
952 HI
.CalleeArgInfo
->Type
= "int";
953 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
957 void foobar(const float &arg);
965 HI
.Kind
= index::SymbolKind::Variable
;
966 HI
.NamespaceScope
= "";
967 HI
.Definition
= "int a = 0";
968 HI
.LocalScope
= "main::";
971 HI
.CalleeArgInfo
.emplace();
972 HI
.CalleeArgInfo
->Name
= "arg";
973 HI
.CalleeArgInfo
->Type
= "const float &";
974 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, true};
979 explicit Foo(const float& arg) {}
988 HI
.Kind
= index::SymbolKind::Variable
;
989 HI
.NamespaceScope
= "";
990 HI
.Definition
= "int a = 0";
991 HI
.LocalScope
= "main::";
994 HI
.CalleeArgInfo
.emplace();
995 HI
.CalleeArgInfo
->Name
= "arg";
996 HI
.CalleeArgInfo
->Type
= "const float &";
997 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, true};
999 {// Literal passed to function call
1001 void fun(int arg_a, const int &arg_b) {};
1008 HI
.Name
= "literal";
1009 HI
.Kind
= index::SymbolKind::Unknown
;
1010 HI
.CalleeArgInfo
.emplace();
1011 HI
.CalleeArgInfo
->Name
= "arg_b";
1012 HI
.CalleeArgInfo
->Type
= "const int &";
1013 HI
.CallPassType
= HoverInfo::PassType
{PassMode::ConstRef
, false};
1015 {// Expression passed to function call
1017 void fun(int arg_a, const int &arg_b) {};
1024 HI
.Name
= "expression";
1025 HI
.Kind
= index::SymbolKind::Unknown
;
1028 HI
.CalleeArgInfo
.emplace();
1029 HI
.CalleeArgInfo
->Name
= "arg_b";
1030 HI
.CalleeArgInfo
->Type
= "const int &";
1031 HI
.CallPassType
= HoverInfo::PassType
{PassMode::ConstRef
, false};
1035 int add(int lhs, int rhs);
1041 HI
.Name
= "expression";
1042 HI
.Kind
= index::SymbolKind::Unknown
;
1045 HI
.CalleeArgInfo
.emplace();
1046 HI
.CalleeArgInfo
->Name
= "lhs";
1047 HI
.CalleeArgInfo
->Type
= "int";
1048 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
1052 void foobar(const float &arg);
1058 HI
.Name
= "literal";
1059 HI
.Kind
= index::SymbolKind::Unknown
;
1060 HI
.CalleeArgInfo
.emplace();
1061 HI
.CalleeArgInfo
->Name
= "arg";
1062 HI
.CalleeArgInfo
->Type
= "const float &";
1063 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, true};
1065 {// Extra info for method call.
1069 void fun(int arg_a = 3, int arg_b = 4) {}
1079 HI
.Kind
= index::SymbolKind::Variable
;
1080 HI
.NamespaceScope
= "";
1081 HI
.Definition
= "int a = 1";
1082 HI
.LocalScope
= "code::";
1085 HI
.CalleeArgInfo
.emplace();
1086 HI
.CalleeArgInfo
->Name
= "arg_a";
1087 HI
.CalleeArgInfo
->Type
= "int";
1088 HI
.CalleeArgInfo
->Default
= "3";
1089 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
1104 HI
.Kind
= index::SymbolKind::Variable
;
1105 HI
.NamespaceScope
= "";
1106 HI
.Definition
= "const int x = 0";
1107 HI
.LocalScope
= "bar::";
1109 HI
.Type
= "const int";
1110 HI
.CalleeArgInfo
.emplace();
1111 HI
.CalleeArgInfo
->Type
= "Foo";
1112 HI
.CallPassType
= HoverInfo::PassType
{PassMode::ConstRef
, true};
1114 {// Dont crash on invalid decl
1122 HI
.Kind
= index::SymbolKind::Field
;
1123 HI
.NamespaceScope
= "";
1124 HI
.Definition
= "int xx";
1125 HI
.LocalScope
= "Foo::";
1127 HI
.AccessSpecifier
= "public";
1137 HI
.Kind
= index::SymbolKind::Field
;
1138 HI
.NamespaceScope
= "";
1139 HI
.Definition
= "int yy";
1140 HI
.LocalScope
= "Foo::";
1142 HI
.AccessSpecifier
= "public";
1144 {// No crash on InitListExpr.
1149 constexpr Foo k2 = {
1150 ^[[{]]1} // FIXME: why the hover range is 1 character?
1154 HI
.Name
= "expression";
1155 HI
.Kind
= index::SymbolKind::Unknown
;
1156 HI
.Type
= "int[10]";
1159 {// Var template decl
1163 template <int Size> m_int ^[[arr]][Size];
1167 HI
.Kind
= index::SymbolKind::Variable
;
1168 HI
.Type
= {"m_int[Size]", "int[Size]"};
1169 HI
.NamespaceScope
= "";
1170 HI
.Definition
= "template <int Size> m_int arr[Size]";
1171 HI
.TemplateParameters
= {{{"int"}, {"Size"}, std::nullopt
}};
1173 {// Var template decl specialization
1177 template <int Size> m_int arr[Size];
1179 template <> m_int ^[[arr]]<4>[4];
1183 HI
.Kind
= index::SymbolKind::Variable
;
1184 HI
.Type
= {"m_int[4]", "int[4]"};
1185 HI
.NamespaceScope
= "";
1186 HI
.Definition
= "m_int arr[4]";
1190 template<typename T>
1196 TestHover<int>::Type ^[[a]];
1201 HI
.NamespaceScope
= "";
1202 HI
.LocalScope
= "code::";
1203 HI
.Definition
= "TestHover<int>::Type a";
1204 HI
.Kind
= index::SymbolKind::Variable
;
1205 HI
.Type
= {"TestHover<int>::Type", "int"};
1207 {// Canonical template type
1209 template<typename T>
1210 void ^[[foo]](T arg) {}
1214 HI
.Kind
= index::SymbolKind::Function
;
1215 HI
.NamespaceScope
= "";
1216 HI
.Definition
= "template <typename T> void foo(T arg)";
1217 HI
.Type
= "void (T)";
1218 HI
.ReturnType
= "void";
1219 HI
.Parameters
= {{{"T"}, std::string("arg"), std::nullopt
}};
1220 HI
.TemplateParameters
= {
1221 {{"typename"}, std::string("T"), std::nullopt
}};
1223 {// TypeAlias Template
1225 template<typename T>
1226 using ^[[alias]] = T;
1230 HI
.NamespaceScope
= "";
1232 HI
.Kind
= index::SymbolKind::TypeAlias
;
1233 HI
.Definition
= "template <typename T> using alias = T";
1235 HI
.TemplateParameters
= {
1236 {{"typename"}, std::string("T"), std::nullopt
}};
1238 {// TypeAlias Template
1240 template<typename T>
1243 template<typename T>
1244 using ^[[AA]] = A<T>;
1248 HI
.NamespaceScope
= "";
1250 HI
.Kind
= index::SymbolKind::TypeAlias
;
1251 HI
.Definition
= "template <typename T> using AA = A<T>";
1252 HI
.Type
= {"A<T>", "type-parameter-0-0"}; // FIXME: should be 'T'
1253 HI
.TemplateParameters
= {
1254 {{"typename"}, std::string("T"), std::nullopt
}};
1264 HI
.NamespaceScope
= "";
1266 HI
.Kind
= index::SymbolKind::Variable
;
1267 HI
.Definition
= "m_int arr[10]";
1268 HI
.Type
= {"m_int[10]", "int[10]"};
1270 {// Incomplete array
1274 extern m_int ^[[arr]][];
1278 HI
.NamespaceScope
= "";
1280 HI
.Kind
= index::SymbolKind::Variable
;
1281 HI
.Definition
= "extern m_int arr[]";
1282 HI
.Type
= {"m_int[]", "int[]"};
1284 {// Dependent size array
1290 m_int ^[[arr]][Size];
1295 HI
.NamespaceScope
= "";
1296 HI
.LocalScope
= "Test<Size>::";
1297 HI
.AccessSpecifier
= "public";
1298 HI
.Kind
= index::SymbolKind::Field
;
1299 HI
.Definition
= "m_int arr[Size]";
1300 HI
.Type
= {"m_int[Size]", "int[Size]"};
1302 {// Bitfield offset, size and padding
1311 HI
.NamespaceScope
= "";
1312 HI
.LocalScope
= "Foo::";
1314 HI
.Kind
= index::SymbolKind::Field
;
1315 HI
.Definition
= "char y : 1";
1320 HI
.AccessSpecifier
= "public";
1322 for (const auto &Case
: Cases
) {
1323 SCOPED_TRACE(Case
.Code
);
1325 Annotations
T(Case
.Code
);
1326 TestTU TU
= TestTU::withCode(T
.code());
1327 TU
.ExtraArgs
.push_back("-std=c++20");
1328 // Types might be different depending on the target triplet, we chose a
1329 // fixed one to make sure tests passes on different platform.
1330 TU
.ExtraArgs
.push_back("--target=x86_64-pc-linux-gnu");
1331 auto AST
= TU
.build();
1333 Cfg
.Hover
.ShowAKA
= true;
1334 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
1336 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
1339 Expected
.SymRange
= T
.range();
1340 Case
.ExpectedBuilder(Expected
);
1342 EXPECT_EQ(H
->NamespaceScope
, Expected
.NamespaceScope
);
1343 EXPECT_EQ(H
->LocalScope
, Expected
.LocalScope
);
1344 EXPECT_EQ(H
->Name
, Expected
.Name
);
1345 EXPECT_EQ(H
->Kind
, Expected
.Kind
);
1346 EXPECT_EQ(H
->Documentation
, Expected
.Documentation
);
1347 EXPECT_EQ(H
->Definition
, Expected
.Definition
);
1348 EXPECT_EQ(H
->Type
, Expected
.Type
);
1349 EXPECT_EQ(H
->ReturnType
, Expected
.ReturnType
);
1350 EXPECT_EQ(H
->Parameters
, Expected
.Parameters
);
1351 EXPECT_EQ(H
->TemplateParameters
, Expected
.TemplateParameters
);
1352 EXPECT_EQ(H
->SymRange
, Expected
.SymRange
);
1353 EXPECT_EQ(H
->Value
, Expected
.Value
);
1354 EXPECT_EQ(H
->Size
, Expected
.Size
);
1355 EXPECT_EQ(H
->Offset
, Expected
.Offset
);
1356 EXPECT_EQ(H
->AccessSpecifier
, Expected
.AccessSpecifier
);
1357 EXPECT_EQ(H
->CalleeArgInfo
, Expected
.CalleeArgInfo
);
1358 EXPECT_EQ(H
->CallPassType
, Expected
.CallPassType
);
1362 TEST(Hover
, DefinitionLanuage
) {
1364 const char *const Code
;
1365 const std::string ClangLanguageFlag
;
1366 const char *const ExpectedDefinitionLanguage
;
1367 } Cases
[] = {{R
"cpp(
1368 void [[some^Global]]() {}
1372 void [[some^Global]]() {}
1374 "-xobjective-c++", "objective-cpp"},
1376 void [[some^Global]]() {}
1378 "-xobjective-c", "objective-c"}};
1379 for (const auto &Case
: Cases
) {
1380 SCOPED_TRACE(Case
.Code
);
1382 Annotations
T(Case
.Code
);
1383 TestTU TU
= TestTU::withCode(T
.code());
1384 if (!Case
.ClangLanguageFlag
.empty())
1385 TU
.ExtraArgs
.push_back(Case
.ClangLanguageFlag
);
1386 auto AST
= TU
.build();
1388 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
1391 EXPECT_STREQ(H
->DefinitionLanguage
, Case
.ExpectedDefinitionLanguage
);
1395 TEST(Hover
, CallPassType
) {
1396 const llvm::StringRef CodePrefix
= R
"cpp(
1398 class Derived : public Base {};
1402 CustomClass(const Base &x) {}
1403 CustomClass(int &x) {}
1404 CustomClass(float x) {}
1405 CustomClass(int x, int y) {}
1408 void int_by_ref(int &x) {}
1409 void int_by_const_ref(const int &x) {}
1410 void int_by_value(int x) {}
1411 void base_by_ref(Base &x) {}
1412 void base_by_const_ref(const Base &x) {}
1413 void base_by_value(Base x) {}
1414 void float_by_value(float x) {}
1415 void custom_by_value(CustomClass x) {}
1419 int &int_ref = int_x;
1420 const int &int_const_ref = int_x;
1422 const Base &base_const_ref = base;
1426 const llvm::StringRef CodeSuffix
= "}";
1429 const char *const Code
;
1430 HoverInfo::PassType::PassMode PassBy
;
1434 {"int_by_value([[^int_x]]);", PassMode::Value
, false},
1435 {"int_by_value([[^123]]);", PassMode::Value
, false},
1436 {"int_by_ref([[^int_x]]);", PassMode::Ref
, false},
1437 {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef
, false},
1438 {"int_by_const_ref([[^123]]);", PassMode::ConstRef
, false},
1439 {"int_by_value([[^int_ref]]);", PassMode::Value
, false},
1440 {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef
, false},
1441 {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef
, false},
1442 {"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef
, false},
1443 // Custom class tests
1444 {"base_by_ref([[^base]]);", PassMode::Ref
, false},
1445 {"base_by_const_ref([[^base]]);", PassMode::ConstRef
, false},
1446 {"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef
, false},
1447 {"base_by_value([[^base]]);", PassMode::Value
, false},
1448 {"base_by_value([[^base_const_ref]]);", PassMode::Value
, false},
1449 {"base_by_ref([[^derived]]);", PassMode::Ref
, false},
1450 {"base_by_const_ref([[^derived]]);", PassMode::ConstRef
, false},
1451 {"base_by_value([[^derived]]);", PassMode::Value
, false},
1452 // Custom class constructor tests
1453 {"CustomClass c1([[^base]]);", PassMode::ConstRef
, false},
1454 {"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef
, false},
1455 {"CustomClass c3([[^int_x]]);", PassMode::Ref
, false},
1456 {"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value
, false},
1458 {"float_by_value([[^int_x]]);", PassMode::Value
, true},
1459 {"float_by_value([[^int_ref]]);", PassMode::Value
, true},
1460 {"float_by_value([[^int_const_ref]]);", PassMode::Value
, true},
1461 {"float_by_value([[^123.0f]]);", PassMode::Value
, false},
1462 {"float_by_value([[^123]]);", PassMode::Value
, true},
1463 {"custom_by_value([[^int_x]]);", PassMode::Ref
, true},
1464 {"custom_by_value([[^float_x]]);", PassMode::Value
, true},
1465 {"custom_by_value([[^base]]);", PassMode::ConstRef
, true},
1467 for (const auto &Test
: Tests
) {
1468 SCOPED_TRACE(Test
.Code
);
1470 const auto Code
= (CodePrefix
+ Test
.Code
+ CodeSuffix
).str();
1471 Annotations
T(Code
);
1472 TestTU TU
= TestTU::withCode(T
.code());
1473 TU
.ExtraArgs
.push_back("-std=c++17");
1474 auto AST
= TU
.build();
1475 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
1477 EXPECT_EQ(H
->CallPassType
->PassBy
, Test
.PassBy
);
1478 EXPECT_EQ(H
->CallPassType
->Converted
, Test
.Converted
);
1482 TEST(Hover
, NoHover
) {
1483 llvm::StringRef Tests
[] = {
1486 // FIXME: "decltype(auto)" should be a single hover
1487 "decltype(au^to) x = 0;",
1488 // FIXME: not supported yet
1489 R
"cpp(// Lambda auto parameter
1490 auto lamb = [](a^uto){};
1492 R
"cpp(// non-named decls don't get hover. Don't crash!
1493 ^static_assert(1, "");
1495 R
"cpp(// non-evaluatable expr
1496 template <typename T> void foo() {
1497 (void)[[size^of]](T);
1499 R
"cpp(// should not crash on invalid semantic form of init-list-expr.
1505 constexpr Foo s = ^{
1511 "auto x = ^(int){42};",
1515 "auto x = ^nullptr;",
1518 for (const auto &Test
: Tests
) {
1521 Annotations
T(Test
);
1522 TestTU TU
= TestTU::withCode(T
.code());
1523 TU
.ExtraArgs
.push_back("-std=c++17");
1524 auto AST
= TU
.build();
1525 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
1532 const char *const Code
;
1533 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
1535 {"auto x = [['^A']]; // character literal",
1537 HI
.Name
= "expression";
1539 HI
.Value
= "65 (0x41)";
1541 {"auto s = ^[[\"Hello, world!\"]]; // string literal",
1543 HI
.Name
= "string-literal";
1545 HI
.Type
= "const char[14]";
1548 R
"cpp(// Local variable
1552 int test1 = bonjour;
1556 HI
.Name
= "bonjour";
1557 HI
.Kind
= index::SymbolKind::Variable
;
1558 HI
.NamespaceScope
= "";
1559 HI
.LocalScope
= "main::";
1561 HI
.Definition
= "int bonjour";
1564 R
"cpp(// Local variable in method
1573 HI
.Name
= "bonjour";
1574 HI
.Kind
= index::SymbolKind::Variable
;
1575 HI
.NamespaceScope
= "";
1576 HI
.LocalScope
= "s::method::";
1578 HI
.Definition
= "int bonjour";
1586 ns1::[[My^Class]]* Params;
1590 HI
.Name
= "MyClass";
1591 HI
.Kind
= index::SymbolKind::Struct
;
1592 HI
.NamespaceScope
= "ns1::";
1593 HI
.Definition
= "struct MyClass {}";
1601 ns1::[[My^Class]]* Params;
1605 HI
.Name
= "MyClass";
1606 HI
.Kind
= index::SymbolKind::Class
;
1607 HI
.NamespaceScope
= "ns1::";
1608 HI
.Definition
= "class MyClass {}";
1613 union MyUnion { int x; int y; };
1616 ns1::[[My^Union]] Params;
1620 HI
.Name
= "MyUnion";
1621 HI
.Kind
= index::SymbolKind::Union
;
1622 HI
.NamespaceScope
= "ns1::";
1623 HI
.Definition
= "union MyUnion {}";
1626 R
"cpp(// Function definition via pointer
1629 auto *X = &^[[foo]];
1634 HI
.Kind
= index::SymbolKind::Function
;
1635 HI
.NamespaceScope
= "";
1636 HI
.Type
= "void (int)";
1637 HI
.Definition
= "void foo(int)";
1638 HI
.Documentation
= "Function definition via pointer";
1639 HI
.ReturnType
= "void";
1641 {{"int"}, std::nullopt
, std::nullopt
},
1645 R
"cpp(// Function declaration via call
1648 return ^[[foo]](42);
1653 HI
.Kind
= index::SymbolKind::Function
;
1654 HI
.NamespaceScope
= "";
1655 HI
.Type
= "int (int)";
1656 HI
.Definition
= "int foo(int)";
1657 HI
.Documentation
= "Function declaration via call";
1658 HI
.ReturnType
= "int";
1660 {{"int"}, std::nullopt
, std::nullopt
},
1665 struct Foo { int x; };
1673 HI
.Kind
= index::SymbolKind::Field
;
1674 HI
.NamespaceScope
= "";
1675 HI
.LocalScope
= "Foo::";
1677 HI
.Definition
= "int x";
1680 R
"cpp(// Field with initialization
1681 struct Foo { int x = 5; };
1689 HI
.Kind
= index::SymbolKind::Field
;
1690 HI
.NamespaceScope
= "";
1691 HI
.LocalScope
= "Foo::";
1693 HI
.Definition
= "int x = 5";
1696 R
"cpp(// Static field
1697 struct Foo { static int x; };
1704 HI
.Kind
= index::SymbolKind::StaticProperty
;
1705 HI
.NamespaceScope
= "";
1706 HI
.LocalScope
= "Foo::";
1708 HI
.Definition
= "static int x";
1711 R
"cpp(// Field, member initializer
1714 Foo() : ^[[x]](0) {}
1719 HI
.Kind
= index::SymbolKind::Field
;
1720 HI
.NamespaceScope
= "";
1721 HI
.LocalScope
= "Foo::";
1723 HI
.Definition
= "int x";
1726 R
"cpp(// Field, GNU old-style field designator
1727 struct Foo { int x; };
1729 Foo bar = { ^[[x]] : 1 };
1734 HI
.Kind
= index::SymbolKind::Field
;
1735 HI
.NamespaceScope
= "";
1736 HI
.LocalScope
= "Foo::";
1738 HI
.Definition
= "int x";
1739 // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is
1740 // of struct type and omitted.
1743 R
"cpp(// Field, field designator
1744 struct Foo { int x; int y; };
1746 Foo bar = { .^[[x]] = 2, .y = 2 };
1751 HI
.Kind
= index::SymbolKind::Field
;
1752 HI
.NamespaceScope
= "";
1753 HI
.LocalScope
= "Foo::";
1755 HI
.Definition
= "int x";
1758 R
"cpp(// Method call
1759 struct Foo { int x(); };
1767 HI
.Kind
= index::SymbolKind::InstanceMethod
;
1768 HI
.NamespaceScope
= "";
1769 HI
.LocalScope
= "Foo::";
1771 HI
.Definition
= "int x()";
1772 HI
.ReturnType
= "int";
1773 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
1776 R
"cpp(// Static method call
1777 struct Foo { static int x(); };
1784 HI
.Kind
= index::SymbolKind::StaticMethod
;
1785 HI
.NamespaceScope
= "";
1786 HI
.LocalScope
= "Foo::";
1788 HI
.Definition
= "static int x()";
1789 HI
.ReturnType
= "int";
1790 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
1801 HI
.Kind
= index::SymbolKind::TypeAlias
;
1802 HI
.NamespaceScope
= "";
1803 HI
.Definition
= "typedef int Foo";
1805 HI
.Documentation
= "Typedef";
1808 R
"cpp(// Typedef with embedded definition
1809 typedef struct Bar {} Foo;
1816 HI
.Kind
= index::SymbolKind::TypeAlias
;
1817 HI
.NamespaceScope
= "";
1818 HI
.Definition
= "typedef struct Bar Foo";
1819 HI
.Type
= "struct Bar";
1820 HI
.Documentation
= "Typedef with embedded definition";
1825 struct Foo { static void bar(); };
1827 int main() { ^[[ns]]::Foo::bar(); }
1831 HI
.Kind
= index::SymbolKind::Namespace
;
1832 HI
.NamespaceScope
= "";
1833 HI
.Definition
= "namespace ns {}";
1836 R
"cpp(// Anonymous namespace
1840 } // anonymous namespace
1842 int main() { ns::[[f^oo]]++; }
1846 HI
.Kind
= index::SymbolKind::Variable
;
1847 HI
.NamespaceScope
= "ns::";
1849 HI
.Definition
= "int foo";
1852 R
"cpp(// Function definition via using declaration
1863 HI
.Kind
= index::SymbolKind::Function
;
1864 HI
.NamespaceScope
= "ns::";
1865 HI
.Type
= "void ()";
1866 HI
.Definition
= "void foo()";
1867 HI
.Documentation
= "";
1868 HI
.ReturnType
= "void";
1869 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
1872 R
"cpp( // using declaration and two possible function declarations
1873 namespace ns { void foo(int); void foo(char); }
1875 template <typename T> void bar() { [[f^oo]](T{}); }
1879 HI
.Kind
= index::SymbolKind::Using
;
1880 HI
.NamespaceScope
= "";
1881 HI
.Definition
= "using ns::foo";
1886 int main() { return ^[[MACRO]]; }
1892 HI
.Kind
= index::SymbolKind::Macro
;
1893 HI
.Definition
= "#define MACRO 0\n\n"
1900 #define MACRO2 ^[[MACRO]]
1904 HI
.Kind
= index::SymbolKind::Macro
;
1905 HI
.Definition
= "#define MACRO 0";
1906 // NOTE MACRO doesn't have expansion since it technically isn't
1914 int main() ^[[MACRO]]
1918 HI
.Kind
= index::SymbolKind::Macro
;
1920 R
"cpp(#define MACRO \
1927 R
"cpp(// Forward class declaration
1934 HI
.Kind
= index::SymbolKind::Class
;
1935 HI
.NamespaceScope
= "";
1936 HI
.Definition
= "class Foo {}";
1937 HI
.Documentation
= "Forward class declaration";
1940 R
"cpp(// Function declaration
1942 void g() { [[f^oo]](); }
1947 HI
.Kind
= index::SymbolKind::Function
;
1948 HI
.NamespaceScope
= "";
1949 HI
.Type
= "void ()";
1950 HI
.Definition
= "void foo()";
1951 HI
.Documentation
= "Function declaration";
1952 HI
.ReturnType
= "void";
1953 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
1956 R
"cpp(// Enum declaration
1961 [[Hel^lo]] hello = ONE;
1966 HI
.Kind
= index::SymbolKind::Enum
;
1967 HI
.NamespaceScope
= "";
1968 HI
.Definition
= "enum Hello {}";
1969 HI
.Documentation
= "Enum declaration";
1977 Hello hello = [[O^NE]];
1982 HI
.Kind
= index::SymbolKind::EnumConstant
;
1983 HI
.NamespaceScope
= "";
1984 HI
.LocalScope
= "Hello::";
1985 HI
.Type
= "enum Hello";
1986 HI
.Definition
= "ONE";
1990 R
"cpp(// C++20's using enum
1996 Hello hello = [[O^NE]];
2001 HI
.Kind
= index::SymbolKind::EnumConstant
;
2002 HI
.NamespaceScope
= "";
2003 HI
.LocalScope
= "Hello::";
2004 HI
.Type
= "enum Hello";
2005 HI
.Definition
= "ONE";
2009 R
"cpp(// Enumerator in anonymous enum
2014 int hello = [[O^NE]];
2019 HI
.Kind
= index::SymbolKind::EnumConstant
;
2020 HI
.NamespaceScope
= "";
2021 // FIXME: This should be `(anon enum)::`
2023 HI
.Type
= "enum (unnamed)";
2024 HI
.Definition
= "ONE";
2028 R
"cpp(// Global variable
2029 static int hey = 10;
2036 HI
.Kind
= index::SymbolKind::Variable
;
2037 HI
.NamespaceScope
= "";
2039 HI
.Definition
= "static int hey = 10";
2040 HI
.Documentation
= "Global variable";
2041 // FIXME: Value shouldn't be set in this case
2042 HI
.Value
= "10 (0xa)";
2045 R
"cpp(// Global variable in namespace
2047 static long long hey = -36637162602497;
2055 HI
.Kind
= index::SymbolKind::Variable
;
2056 HI
.NamespaceScope
= "ns1::";
2057 HI
.Type
= "long long";
2058 HI
.Definition
= "static long long hey = -36637162602497";
2059 HI
.Value
= "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits
2062 R
"cpp(// Field in anonymous struct
2072 HI
.Kind
= index::SymbolKind::Field
;
2073 HI
.NamespaceScope
= "";
2074 HI
.LocalScope
= "(anonymous struct)::";
2076 HI
.Definition
= "int hello";
2079 R
"cpp(// Templated function
2080 template <typename T>
2084 void g() { auto x = [[f^oo]]<int>(); }
2088 HI
.Kind
= index::SymbolKind::Function
;
2089 HI
.NamespaceScope
= "";
2091 HI
.Definition
= "template <> int foo<int>()";
2092 HI
.Documentation
= "Templated function";
2093 HI
.ReturnType
= "int";
2094 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
2095 // FIXME: We should populate template parameters with arguments in
2096 // case of instantiations.
2099 R
"cpp(// Anonymous union
2105 void g() { struct outer o; o.v.[[d^ef]]++; }
2109 HI
.Kind
= index::SymbolKind::Field
;
2110 HI
.NamespaceScope
= "";
2111 HI
.LocalScope
= "outer::(anonymous union)::";
2113 HI
.Definition
= "int def";
2116 R
"cpp(// documentation from index
2117 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
2119 void g() { [[ind^exSymbol]](); }
2122 HI
.Name
= "indexSymbol";
2123 HI
.Kind
= index::SymbolKind::Function
;
2124 HI
.NamespaceScope
= "";
2125 HI
.Type
= "void ()";
2126 HI
.Definition
= "void indexSymbol()";
2127 HI
.ReturnType
= "void";
2128 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
2129 HI
.Documentation
= "comment from index";
2132 R
"cpp(// Simple initialization with auto
2139 HI
.Kind
= index::SymbolKind::TypeAlias
;
2140 HI
.Definition
= "int";
2143 R
"cpp(// Simple initialization with const auto
2145 const ^[[auto]] i = 1;
2150 HI
.Kind
= index::SymbolKind::TypeAlias
;
2151 HI
.Definition
= "int";
2154 R
"cpp(// Simple initialization with const auto&
2156 const ^[[auto]]& i = 1;
2161 HI
.Kind
= index::SymbolKind::TypeAlias
;
2162 HI
.Definition
= "int";
2165 R
"cpp(// Simple initialization with auto&
2173 HI
.Kind
= index::SymbolKind::TypeAlias
;
2174 HI
.Definition
= "int";
2177 R
"cpp(// Simple initialization with auto*
2185 HI
.Kind
= index::SymbolKind::TypeAlias
;
2186 HI
.Definition
= "int";
2189 R
"cpp(// Simple initialization with auto from pointer
2197 HI
.Kind
= index::SymbolKind::TypeAlias
;
2198 HI
.Definition
= "int *";
2201 R
"cpp(// Auto with initializer list.
2205 class initializer_list {};
2208 ^[[auto]] i = {1,2};
2213 HI
.Kind
= index::SymbolKind::TypeAlias
;
2214 HI
.Definition
= "std::initializer_list<int>";
2217 R
"cpp(// User defined conversion to auto
2219 operator ^[[auto]]() const { return 10; }
2224 HI
.Kind
= index::SymbolKind::TypeAlias
;
2225 HI
.Definition
= "int";
2228 R
"cpp(// Simple initialization with decltype(auto)
2230 ^[[decltype]](auto) i = 1;
2234 HI
.Name
= "decltype";
2235 HI
.Kind
= index::SymbolKind::TypeAlias
;
2236 HI
.Definition
= "int";
2239 R
"cpp(// Simple initialization with const decltype(auto)
2242 ^[[decltype]](auto) i = j;
2246 HI
.Name
= "decltype";
2247 HI
.Kind
= index::SymbolKind::TypeAlias
;
2248 HI
.Definition
= "const int";
2251 R
"cpp(// Simple initialization with const& decltype(auto)
2255 ^[[decltype]](auto) i = j;
2259 HI
.Name
= "decltype";
2260 HI
.Kind
= index::SymbolKind::TypeAlias
;
2261 HI
.Definition
= "const int &";
2264 R
"cpp(// Simple initialization with & decltype(auto)
2268 ^[[decltype]](auto) i = j;
2272 HI
.Name
= "decltype";
2273 HI
.Kind
= index::SymbolKind::TypeAlias
;
2274 HI
.Definition
= "int &";
2277 R
"cpp(// simple trailing return type
2278 ^[[auto]] main() -> int {
2284 HI
.Kind
= index::SymbolKind::TypeAlias
;
2285 HI
.Definition
= "int";
2288 R
"cpp(// auto function return with trailing type
2290 ^[[auto]] test() -> decltype(Bar()) {
2296 HI
.Kind
= index::SymbolKind::TypeAlias
;
2297 HI
.Definition
= "Bar";
2298 HI
.Documentation
= "auto function return with trailing type";
2301 R
"cpp(// trailing return type
2303 auto test() -> ^[[decltype]](Bar()) {
2308 HI
.Name
= "decltype";
2309 HI
.Kind
= index::SymbolKind::TypeAlias
;
2310 HI
.Definition
= "Bar";
2311 HI
.Documentation
= "trailing return type";
2314 R
"cpp(// auto in function return
2322 HI
.Kind
= index::SymbolKind::TypeAlias
;
2323 HI
.Definition
= "Bar";
2324 HI
.Documentation
= "auto in function return";
2327 R
"cpp(// auto& in function return
2336 HI
.Kind
= index::SymbolKind::TypeAlias
;
2337 HI
.Definition
= "Bar";
2338 HI
.Documentation
= "auto& in function return";
2341 R
"cpp(// auto* in function return
2350 HI
.Kind
= index::SymbolKind::TypeAlias
;
2351 HI
.Definition
= "Bar";
2352 HI
.Documentation
= "auto* in function return";
2355 R
"cpp(// const auto& in function return
2357 const ^[[auto]]& test() {
2364 HI
.Kind
= index::SymbolKind::TypeAlias
;
2365 HI
.Definition
= "Bar";
2366 HI
.Documentation
= "const auto& in function return";
2369 R
"cpp(// decltype(auto) in function return
2371 ^[[decltype]](auto) test() {
2376 HI
.Name
= "decltype";
2377 HI
.Kind
= index::SymbolKind::TypeAlias
;
2378 HI
.Definition
= "Bar";
2379 HI
.Documentation
= "decltype(auto) in function return";
2382 R
"cpp(// decltype(auto) reference in function return
2383 ^[[decltype]](auto) test() {
2389 HI
.Name
= "decltype";
2390 HI
.Kind
= index::SymbolKind::TypeAlias
;
2391 HI
.Definition
= "int &";
2394 R
"cpp(// decltype lvalue reference
2397 ^[[decltype]](I) J = I;
2401 HI
.Name
= "decltype";
2402 HI
.Kind
= index::SymbolKind::TypeAlias
;
2403 HI
.Definition
= "int";
2406 R
"cpp(// decltype lvalue reference
2410 ^[[decltype]](K) J = I;
2414 HI
.Name
= "decltype";
2415 HI
.Kind
= index::SymbolKind::TypeAlias
;
2416 HI
.Definition
= "int &";
2419 R
"cpp(// decltype lvalue reference parenthesis
2422 ^[[decltype]]((I)) J = I;
2426 HI
.Name
= "decltype";
2427 HI
.Kind
= index::SymbolKind::TypeAlias
;
2428 HI
.Definition
= "int &";
2431 R
"cpp(// decltype rvalue reference
2434 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
2438 HI
.Name
= "decltype";
2439 HI
.Kind
= index::SymbolKind::TypeAlias
;
2440 HI
.Definition
= "int &&";
2443 R
"cpp(// decltype rvalue reference function call
2447 ^[[decltype]](bar()) J = bar();
2451 HI
.Name
= "decltype";
2452 HI
.Kind
= index::SymbolKind::TypeAlias
;
2453 HI
.Definition
= "int &&";
2456 R
"cpp(// decltype of function with trailing return type.
2458 auto test() -> decltype(Bar()) {
2462 ^[[decltype]](test()) i = test();
2466 HI
.Name
= "decltype";
2467 HI
.Kind
= index::SymbolKind::TypeAlias
;
2468 HI
.Definition
= "Bar";
2470 "decltype of function with trailing return type.";
2473 R
"cpp(// decltype of var with decltype.
2477 ^[[decltype]](J) K = J;
2481 HI
.Name
= "decltype";
2482 HI
.Kind
= index::SymbolKind::TypeAlias
;
2483 HI
.Definition
= "int";
2486 R
"cpp(// decltype of dependent type
2487 template <typename T>
2489 using Y = ^[[decltype]](T::Z);
2493 HI
.Name
= "decltype";
2494 HI
.Kind
= index::SymbolKind::TypeAlias
;
2495 HI
.Definition
= "<dependent type>";
2498 R
"cpp(// More complicated structured types.
2500 ^[[auto]] (*foo)() = bar;
2504 HI
.Kind
= index::SymbolKind::TypeAlias
;
2505 HI
.Definition
= "int";
2508 R
"cpp(// Should not crash when evaluating the initializer.
2510 void test() { Test && [[te^st]] = {}; }
2514 HI
.Kind
= index::SymbolKind::Variable
;
2515 HI
.NamespaceScope
= "";
2516 HI
.LocalScope
= "test::";
2517 HI
.Type
= "Test &&";
2518 HI
.Definition
= "Test &&test = {}";
2521 R
"cpp(// auto on alias
2522 typedef int int_type;
2523 ^[[auto]] x = int_type();
2527 HI
.Kind
= index::SymbolKind::TypeAlias
;
2528 HI
.Definition
= "int_type // aka: int";
2531 R
"cpp(// auto on alias
2533 typedef cls cls_type;
2534 ^[[auto]] y = cls_type();
2538 HI
.Kind
= index::SymbolKind::TypeAlias
;
2539 HI
.Definition
= "cls_type // aka: cls";
2540 HI
.Documentation
= "auto on alias";
2543 R
"cpp(// auto on alias
2546 ^[[auto]] z = templ<int>();
2550 HI
.Kind
= index::SymbolKind::TypeAlias
;
2551 HI
.Definition
= "templ<int>";
2552 HI
.Documentation
= "auto on alias";
2555 R
"cpp(// Undeduced auto declaration
2556 template<typename T>
2563 HI
.Kind
= index::SymbolKind::TypeAlias
;
2564 HI
.Definition
= "/* not deduced */";
2567 R
"cpp(// Undeduced auto return type
2568 template<typename T>
2575 HI
.Kind
= index::SymbolKind::TypeAlias
;
2576 HI
.Definition
= "/* not deduced */";
2579 R
"cpp(// Template auto parameter
2580 template<[[a^uto]] T>
2585 // FIXME: not sure this is what we want, but this
2586 // is what we currently get with getDeducedType
2588 HI
.Kind
= index::SymbolKind::TypeAlias
;
2589 HI
.Definition
= "/* not deduced */";
2592 R
"cpp(// Undeduced decltype(auto) return type
2593 template<typename T>
2594 ^[[decltype]](auto) foo() {
2599 HI
.Name
= "decltype";
2600 HI
.Kind
= index::SymbolKind::TypeAlias
;
2601 HI
.Definition
= "/* not deduced */";
2604 R
"cpp(// should not crash.
2605 template <class T> struct cls {
2609 auto test = cls<int>().[[m^ethod]]();
2612 HI
.Definition
= "int method()";
2613 HI
.Kind
= index::SymbolKind::InstanceMethod
;
2614 HI
.NamespaceScope
= "";
2615 HI
.LocalScope
= "cls<int>::";
2617 HI
.Parameters
.emplace();
2618 HI
.ReturnType
= "int";
2622 R
"cpp(// type of nested templates.
2623 template <class T> struct cls {};
2624 cls<cls<cls<int>>> [[fo^o]];
2627 HI
.Definition
= "cls<cls<cls<int>>> foo";
2628 HI
.Kind
= index::SymbolKind::Variable
;
2629 HI
.NamespaceScope
= "";
2631 HI
.Type
= "cls<cls<cls<int>>>";
2634 R
"cpp(// type of nested templates.
2635 template <class T> struct cls {};
2636 [[cl^s]]<cls<cls<int>>> foo;
2639 HI
.Definition
= "template <> struct cls<cls<cls<int>>> {}";
2640 HI
.Kind
= index::SymbolKind::Struct
;
2641 HI
.NamespaceScope
= "";
2642 HI
.Name
= "cls<cls<cls<int>>>";
2643 HI
.Documentation
= "type of nested templates.";
2646 R
"cpp(// type with decltype
2648 decltype(a) [[b^]] = a;)cpp",
2650 HI
.Definition
= "decltype(a) b = a";
2651 HI
.Kind
= index::SymbolKind::Variable
;
2652 HI
.NamespaceScope
= "";
2657 R
"cpp(// type with decltype
2660 decltype(c) [[b^]] = a;)cpp",
2662 HI
.Definition
= "decltype(c) b = a";
2663 HI
.Kind
= index::SymbolKind::Variable
;
2664 HI
.NamespaceScope
= "";
2669 R
"cpp(// type with decltype
2671 const decltype(a) [[b^]] = a;)cpp",
2673 HI
.Definition
= "const decltype(a) b = a";
2674 HI
.Kind
= index::SymbolKind::Variable
;
2675 HI
.NamespaceScope
= "";
2680 R
"cpp(// type with decltype
2682 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
2684 HI
.Definition
= "auto foo(decltype(a) x) -> decltype(a)";
2685 HI
.Kind
= index::SymbolKind::Function
;
2686 HI
.NamespaceScope
= "";
2688 // FIXME: Handle composite types with decltype with a printing
2690 HI
.Type
= {"auto (decltype(a)) -> decltype(a)",
2691 "auto (int) -> int"};
2692 HI
.ReturnType
= "int";
2693 HI
.Parameters
= {{{"int"}, std::string("x"), std::nullopt
}};
2696 R
"cpp(// sizeof expr
2698 (void)[[size^of]](char);
2701 HI
.Name
= "expression";
2702 HI
.Type
= "unsigned long";
2706 R
"cpp(// alignof expr
2708 (void)[[align^of]](char);
2711 HI
.Name
= "expression";
2712 HI
.Type
= "unsigned long";
2717 template <typename T = int>
2718 void foo(const T& = T()) {
2723 HI
.Kind
= index::SymbolKind::Function
;
2724 HI
.Type
= "void (const int &)";
2725 HI
.ReturnType
= "void";
2727 {{"const int &"}, std::nullopt
, std::string("T()")}};
2728 HI
.Definition
= "template <> void foo<int>(const int &)";
2729 HI
.NamespaceScope
= "";
2732 R
"cpp(// should not crash
2740 HI
.Kind
= index::SymbolKind::Field
;
2741 HI
.LocalScope
= "ObjC::";
2742 HI
.NamespaceScope
= "";
2743 HI
.Definition
= "char data";
2749 @interface Interface
2750 @property(retain) [[MYOb^ject]] *x;
2754 HI
.Name
= "MYObject";
2755 HI
.Kind
= index::SymbolKind::Class
;
2756 HI
.NamespaceScope
= "";
2757 HI
.Definition
= "@interface MYObject\n@end";
2763 @interface Interface
2764 - (void)doWith:([[MYOb^ject]] *)object;
2768 HI
.Name
= "MYObject";
2769 HI
.Kind
= index::SymbolKind::Class
;
2770 HI
.NamespaceScope
= "";
2771 HI
.Definition
= "@interface MYObject\n@end";
2786 HI
.Definition
= "ns::Foo *";
2789 R
"cpp(// this expr for template class
2791 template <typename T>
2801 HI
.Definition
= "const Foo<T> *";
2804 R
"cpp(// this expr for specialization class
2806 template <typename T> class Foo {};
2817 HI
.Definition
= "Foo<int> *";
2820 R
"cpp(// this expr for partial specialization struct
2822 template <typename T, typename F> struct Foo {};
2823 template <typename F>
2824 struct Foo<int, F> {
2833 HI
.Definition
= "const Foo<int, F> *";
2839 @interface MYObject (Private)
2840 @property(nonatomic, assign) int privateField;
2843 int someFunction() {
2844 MYObject *obj = [MYObject sharedInstance];
2845 return obj.[[private^Field]];
2849 HI
.Name
= "privateField";
2850 HI
.Kind
= index::SymbolKind::InstanceProperty
;
2851 HI
.LocalScope
= "MYObject(Private)::";
2852 HI
.NamespaceScope
= "";
2853 HI
.Definition
= "@property(nonatomic, assign, unsafe_unretained, "
2854 "readwrite) int privateField;";
2858 @protocol MYProtocol
2859 @property(nonatomic, assign) int prop1;
2862 int someFunction() {
2863 id<MYProtocol> obj = 0;
2864 return obj.[[pro^p1]];
2869 HI
.Kind
= index::SymbolKind::InstanceProperty
;
2870 HI
.LocalScope
= "MYProtocol::";
2871 HI
.NamespaceScope
= "";
2872 HI
.Definition
= "@property(nonatomic, assign, unsafe_unretained, "
2873 "readwrite) int prop1;";
2877 @protocol MYProtocol
2882 @interface MYObject (Ext) <[[MYProt^ocol]]>
2886 HI
.Name
= "MYProtocol";
2887 HI
.Kind
= index::SymbolKind::Protocol
;
2888 HI
.NamespaceScope
= "";
2889 HI
.Definition
= "@protocol MYProtocol\n@end";
2895 @implementation Foo(Private)
2896 + (int)somePrivateMethod {
2897 int [[res^ult]] = 2;
2904 HI
.Definition
= "int result = 2";
2905 HI
.Kind
= index::SymbolKind::Variable
;
2907 HI
.LocalScope
= "+[Foo(Private) somePrivateMethod]::";
2908 HI
.NamespaceScope
= "";
2916 - (int)variadicArgMethod:(id)first, ... {
2917 int [[res^ult]] = 0;
2924 HI
.Definition
= "int result = 0";
2925 HI
.Kind
= index::SymbolKind::Variable
;
2927 HI
.LocalScope
= "-[Foo variadicArgMethod:, ...]::";
2928 HI
.NamespaceScope
= "";
2932 void foo(int * __attribute__(([[non^null]], noescape)) );
2935 HI
.Name
= "nonnull";
2936 HI
.Kind
= index::SymbolKind::Unknown
; // FIXME: no suitable value
2937 HI
.Definition
= "__attribute__((nonnull))";
2938 HI
.Documentation
= Attr::getDocumentation(attr::NonNull
).str();
2943 struct strong_ordering {
2945 constexpr operator int() const { return n; }
2946 static const strong_ordering equal, greater, less;
2948 constexpr strong_ordering strong_ordering::equal = {0};
2949 constexpr strong_ordering strong_ordering::greater = {1};
2950 constexpr strong_ordering strong_ordering::less = {-1};
2957 auto operator<=>(const Foo&) const = default;
2960 bool x = Foo(1) [[!^=]] Foo(2);
2963 HI
.Type
= "bool (const Foo &) const noexcept";
2965 HI
.Name
= "operator==";
2966 HI
.Parameters
= {{{"const Foo &"}, std::nullopt
, std::nullopt
}};
2967 HI
.ReturnType
= "bool";
2968 HI
.Kind
= index::SymbolKind::InstanceMethod
;
2969 HI
.LocalScope
= "Foo::";
2970 HI
.NamespaceScope
= "";
2972 "bool operator==(const Foo &) const noexcept = default";
2973 HI
.Documentation
= "Foo spaceship";
2977 // Create a tiny index, so tests above can verify documentation is fetched.
2978 Symbol IndexSym
= func("indexSymbol");
2979 IndexSym
.Documentation
= "comment from index";
2980 SymbolSlab::Builder Symbols
;
2981 Symbols
.insert(IndexSym
);
2983 MemIndex::build(std::move(Symbols
).build(), RefSlab(), RelationSlab());
2985 for (const auto &Case
: Cases
) {
2986 SCOPED_TRACE(Case
.Code
);
2988 Annotations
T(Case
.Code
);
2989 TestTU TU
= TestTU::withCode(T
.code());
2990 TU
.ExtraArgs
.push_back("-std=c++20");
2991 TU
.ExtraArgs
.push_back("-xobjective-c++");
2993 TU
.ExtraArgs
.push_back("-Wno-gnu-designator");
2994 // Types might be different depending on the target triplet, we chose a
2995 // fixed one to make sure tests passes on different platform.
2996 TU
.ExtraArgs
.push_back("--target=x86_64-pc-linux-gnu");
2997 auto AST
= TU
.build();
2999 Cfg
.Hover
.ShowAKA
= true;
3000 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
3001 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), Index
.get());
3004 Expected
.SymRange
= T
.range();
3005 Case
.ExpectedBuilder(Expected
);
3007 SCOPED_TRACE(H
->present().asPlainText());
3008 EXPECT_EQ(H
->NamespaceScope
, Expected
.NamespaceScope
);
3009 EXPECT_EQ(H
->LocalScope
, Expected
.LocalScope
);
3010 EXPECT_EQ(H
->Name
, Expected
.Name
);
3011 EXPECT_EQ(H
->Kind
, Expected
.Kind
);
3012 EXPECT_EQ(H
->Documentation
, Expected
.Documentation
);
3013 EXPECT_EQ(H
->Definition
, Expected
.Definition
);
3014 EXPECT_EQ(H
->Type
, Expected
.Type
);
3015 EXPECT_EQ(H
->ReturnType
, Expected
.ReturnType
);
3016 EXPECT_EQ(H
->Parameters
, Expected
.Parameters
);
3017 EXPECT_EQ(H
->TemplateParameters
, Expected
.TemplateParameters
);
3018 EXPECT_EQ(H
->SymRange
, Expected
.SymRange
);
3019 EXPECT_EQ(H
->Value
, Expected
.Value
);
3023 TEST(Hover
, Providers
) {
3026 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
3027 } Cases
[] = {{R
"cpp(
3031 [](HoverInfo
&HI
) { HI
.Provider
= ""; }},
3036 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3041 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3046 [](HoverInfo
&HI
) { HI
.Provider
= ""; }},
3051 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3056 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3063 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3064 // Hover selects the underlying decl of the using decl
3072 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3075 using namespace fo^o;
3077 [](HoverInfo
&HI
) { HI
.Provider
= ""; }},
3080 for (const auto &Case
: Cases
) {
3081 Annotations Code
{Case
.Code
};
3082 SCOPED_TRACE(Code
.code());
3085 TU
.Filename
= "foo.cpp";
3086 TU
.Code
= Code
.code();
3087 TU
.AdditionalFiles
["foo.h"] = guard(R
"cpp(
3090 Foo& operator+(const Foo, const Foo);
3092 TU
.AdditionalFiles
["all.h"] = guard("#include \"foo.h\"");
3094 auto AST
= TU
.build();
3095 auto H
= getHover(AST
, Code
.point(), format::getLLVMStyle(), nullptr);
3098 Case
.ExpectedBuilder(Expected
);
3099 SCOPED_TRACE(H
->present().asMarkdown());
3100 EXPECT_EQ(H
->Provider
, Expected
.Provider
);
3104 TEST(Hover
, ParseProviderInfo
) {
3107 HIFoo
.Provider
= "\"foo.h\"";
3110 HIFooBar
.Name
= "foo";
3111 HIFooBar
.Provider
= "<bar.h>";
3114 llvm::StringRef ExpectedMarkdown
;
3115 } Cases
[] = {{HIFoo
, "### `foo` \nprovided by `\"foo.h\"`"},
3116 {HIFooBar
, "### `foo` \nprovided by `<bar.h>`"}};
3118 for (const auto &Case
: Cases
)
3119 EXPECT_EQ(Case
.HI
.present().asMarkdown(), Case
.ExpectedMarkdown
);
3122 TEST(Hover
, UsedSymbols
) {
3125 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
3126 } Cases
[] = {{R
"cpp(
3128 int fstBar = bar1();
3129 int another= bar1(0);
3130 int sndBar = bar2();
3135 HI
.UsedSymbolNames
= {"BAR", "Bar", "bar1", "bar2"};
3139 std::vector<int> vec;
3141 [](HoverInfo
&HI
) { HI
.UsedSymbolNames
= {"vector"}; }}};
3142 for (const auto &Case
: Cases
) {
3143 Annotations Code
{Case
.Code
};
3144 SCOPED_TRACE(Code
.code());
3147 TU
.Filename
= "foo.cpp";
3148 TU
.Code
= Code
.code();
3149 TU
.AdditionalFiles
["bar.h"] = guard(R
"cpp(
3156 TU
.AdditionalFiles
["system/vector"] = guard(R
"cpp(
3162 TU
.ExtraArgs
.push_back("-isystem" + testPath("system"));
3164 auto AST
= TU
.build();
3165 auto H
= getHover(AST
, Code
.point(), format::getLLVMStyle(), nullptr);
3168 Case
.ExpectedBuilder(Expected
);
3169 SCOPED_TRACE(H
->present().asMarkdown());
3170 EXPECT_EQ(H
->UsedSymbolNames
, Expected
.UsedSymbolNames
);
3174 TEST(Hover
, DocsFromIndex
) {
3175 Annotations
T(R
"cpp(
3176 template <typename T> class X {};
3183 TestTU TU
= TestTU::withCode(T
.code());
3184 auto AST
= TU
.build();
3186 IndexSym
.ID
= getSymbolID(&findDecl(AST
, "X"));
3187 IndexSym
.Documentation
= "comment from index";
3188 SymbolSlab::Builder Symbols
;
3189 Symbols
.insert(IndexSym
);
3191 MemIndex::build(std::move(Symbols
).build(), RefSlab(), RelationSlab());
3193 for (const auto &P
: T
.points()) {
3194 auto H
= getHover(AST
, P
, format::getLLVMStyle(), Index
.get());
3196 EXPECT_EQ(H
->Documentation
, IndexSym
.Documentation
);
3200 TEST(Hover
, DocsFromAST
) {
3201 Annotations
T(R
"cpp(
3203 template <typename T> class X {};
3205 template <typename T> void bar() {}
3207 template <typename T> T baz;
3212 au^to T = ba^z<X<int>>;
3216 TestTU TU
= TestTU::withCode(T
.code());
3217 auto AST
= TU
.build();
3218 for (const auto &P
: T
.points()) {
3219 auto H
= getHover(AST
, P
, format::getLLVMStyle(), nullptr);
3221 EXPECT_EQ(H
->Documentation
, "doc");
3225 TEST(Hover
, NoCrash
) {
3226 Annotations
T(R
"cpp(
3228 template<typename T> T foo(T);
3230 // Setter variable heuristic might fail if the callexpr is broken.
3231 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");
3233 TestTU TU
= TestTU::withCode(T
.code());
3234 auto AST
= TU
.build();
3235 for (const auto &P
: T
.points())
3236 getHover(AST
, P
, format::getLLVMStyle(), nullptr);
3239 TEST(Hover
, NoCrashAPInt64
) {
3240 Annotations
T(R
"cpp(
3241 constexpr unsigned long value = -1; // wrap around
3242 void foo() { va^lue; }
3244 auto AST
= TestTU::withCode(T
.code()).build();
3245 getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3248 TEST(Hover
, DocsFromMostSpecial
) {
3249 Annotations
T(R
"cpp(
3251 template <typename T> class $doc1^X {};
3253 template <> class $doc2^X<int> {};
3255 template <typename T> class $doc3^X<T*> {};
3262 TestTU TU
= TestTU::withCode(T
.code());
3263 auto AST
= TU
.build();
3264 for (const auto *Comment
: {"doc1", "doc2", "doc3"}) {
3265 for (const auto &P
: T
.points(Comment
)) {
3266 auto H
= getHover(AST
, P
, format::getLLVMStyle(), nullptr);
3268 EXPECT_EQ(H
->Documentation
, Comment
);
3273 TEST(Hover
, Present
) {
3275 const std::function
<void(HoverInfo
&)> Builder
;
3276 llvm::StringRef ExpectedRender
;
3280 HI
.Kind
= index::SymbolKind::Unknown
;
3287 HI
.Kind
= index::SymbolKind::NamespaceAlias
;
3290 R
"(namespace-alias foo)",
3294 HI
.Kind
= index::SymbolKind::Class
;
3296 HI
.TemplateParameters
= {
3297 {{"typename"}, std::string("T"), std::nullopt
},
3298 {{"typename"}, std::string("C"), std::string("bool")},
3300 HI
.Documentation
= "documentation";
3302 "template <typename T, typename C = bool> class Foo {}";
3304 HI
.NamespaceScope
.emplace();
3311 template <typename T, typename C = bool> class Foo {})",
3315 HI
.Kind
= index::SymbolKind::Function
;
3317 HI
.Type
= {"type", "c_type"};
3318 HI
.ReturnType
= {"ret_type", "can_ret_type"};
3319 HI
.Parameters
.emplace();
3321 HI
.Parameters
->push_back(P
);
3322 P
.Type
= {"type", "can_type"};
3323 HI
.Parameters
->push_back(P
);
3325 HI
.Parameters
->push_back(P
);
3326 P
.Default
= "default";
3327 HI
.Parameters
->push_back(P
);
3328 HI
.NamespaceScope
= "ns::";
3329 HI
.Definition
= "ret_type foo(params) {}";
3333 "→ ret_type (aka can_ret_type)\n"
3336 "- type (aka can_type)\n"
3337 "- type foo (aka can_type)\n"
3338 "- type foo = default (aka can_type)\n"
3340 "// In namespace ns\n"
3341 "ret_type foo(params) {}",
3345 HI
.Kind
= index::SymbolKind::Field
;
3346 HI
.LocalScope
= "test::Bar::";
3349 HI
.Type
= {"type", "can_type"};
3350 HI
.Definition
= "def";
3357 Type: type (aka can_type)
3360 Size: 4 bytes (+4 bytes padding)
3367 HI
.Kind
= index::SymbolKind::Field
;
3368 HI
.LocalScope
= "test::Bar::";
3371 HI
.Type
= {"type", "can_type"};
3372 HI
.Definition
= "def";
3379 Type: type (aka can_type)
3381 Offset: 4 bytes and 3 bits
3382 Size: 25 bits (+4 bits padding)
3389 HI
.Kind
= index::SymbolKind::Field
;
3390 HI
.AccessSpecifier
= "public";
3392 HI
.LocalScope
= "test::Bar::";
3393 HI
.Definition
= "def";
3402 HI
.Definition
= "size_t method()";
3403 HI
.AccessSpecifier
= "protected";
3404 HI
.Kind
= index::SymbolKind::InstanceMethod
;
3405 HI
.NamespaceScope
= "";
3406 HI
.LocalScope
= "cls<int>::";
3408 HI
.Parameters
.emplace();
3409 HI
.ReturnType
= {"size_t", "unsigned long"};
3410 HI
.Type
= {"size_t ()", "unsigned long ()"};
3412 R
"(instance-method method
3414 → size_t (aka unsigned long)
3417 protected: size_t method())",
3421 HI
.Definition
= "cls(int a, int b = 5)";
3422 HI
.AccessSpecifier
= "public";
3423 HI
.Kind
= index::SymbolKind::Constructor
;
3424 HI
.NamespaceScope
= "";
3425 HI
.LocalScope
= "cls";
3427 HI
.Parameters
.emplace();
3428 HI
.Parameters
->emplace_back();
3429 HI
.Parameters
->back().Type
= "int";
3430 HI
.Parameters
->back().Name
= "a";
3431 HI
.Parameters
->emplace_back();
3432 HI
.Parameters
->back().Type
= "int";
3433 HI
.Parameters
->back().Name
= "b";
3434 HI
.Parameters
->back().Default
= "5";
3443 public: cls(int a, int b = 5))",
3447 HI
.Kind
= index::SymbolKind::Union
;
3448 HI
.AccessSpecifier
= "private";
3450 HI
.NamespaceScope
= "ns1::";
3451 HI
.Definition
= "union foo {}";
3456 private: union foo {})",
3460 HI
.Kind
= index::SymbolKind::Variable
;
3462 HI
.Definition
= "int foo = 3";
3463 HI
.LocalScope
= "test::Bar::";
3466 HI
.CalleeArgInfo
.emplace();
3467 HI
.CalleeArgInfo
->Name
= "arg_a";
3468 HI
.CalleeArgInfo
->Type
= "int";
3469 HI
.CalleeArgInfo
->Default
= "7";
3470 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
3483 HI
.Kind
= index::SymbolKind::Variable
;
3485 HI
.CalleeArgInfo
.emplace();
3486 HI
.CalleeArgInfo
->Type
= "int";
3487 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
3495 HI
.Kind
= index::SymbolKind::Variable
;
3497 HI
.Definition
= "int foo = 3";
3498 HI
.LocalScope
= "test::Bar::";
3501 HI
.CalleeArgInfo
.emplace();
3502 HI
.CalleeArgInfo
->Name
= "arg_a";
3503 HI
.CalleeArgInfo
->Type
= "int";
3504 HI
.CalleeArgInfo
->Default
= "7";
3505 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Ref
, false};
3511 Passed by reference as arg_a
3518 HI
.Kind
= index::SymbolKind::Variable
;
3520 HI
.Definition
= "int foo = 3";
3521 HI
.LocalScope
= "test::Bar::";
3524 HI
.CalleeArgInfo
.emplace();
3525 HI
.CalleeArgInfo
->Name
= "arg_a";
3526 HI
.CalleeArgInfo
->Type
= {"alias_int", "int"};
3527 HI
.CalleeArgInfo
->Default
= "7";
3528 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, true};
3534 Passed as arg_a (converted to alias_int)
3541 HI
.Kind
= index::SymbolKind::Macro
;
3542 HI
.Name
= "PLUS_ONE";
3543 HI
.Definition
= "#define PLUS_ONE(X) (X+1)\n\n"
3549 #define PLUS_ONE(X) (X+1)
3556 HI
.Kind
= index::SymbolKind::Variable
;
3558 HI
.Definition
= "int foo = 3";
3559 HI
.LocalScope
= "test::Bar::";
3562 HI
.CalleeArgInfo
.emplace();
3563 HI
.CalleeArgInfo
->Name
= "arg_a";
3564 HI
.CalleeArgInfo
->Type
= "int";
3565 HI
.CalleeArgInfo
->Default
= "7";
3566 HI
.CallPassType
= HoverInfo::PassType
{PassMode::ConstRef
, true};
3572 Passed by const reference as arg_a (converted to int)
3579 HI
.Name
= "stdio.h";
3580 HI
.Definition
= "/usr/include/stdio.h";
3584 /usr/include/stdio.h)",
3586 {[](HoverInfo
&HI
) {
3588 HI
.UsedSymbolNames
= {"Foo", "Bar", "Bar"};
3592 provides Foo, Bar, Bar)"},
3593 {[](HoverInfo
&HI
) {
3595 HI
.UsedSymbolNames
= {"Foo", "Bar", "Baz", "Foobar", "Qux", "Quux"};
3599 provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}};
3601 for (const auto &C
: Cases
) {
3605 Cfg
.Hover
.ShowAKA
= true;
3606 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
3607 EXPECT_EQ(HI
.present().asPlainText(), C
.ExpectedRender
);
3611 TEST(Hover
, ParseDocumentation
) {
3613 llvm::StringRef Documentation
;
3614 llvm::StringRef ExpectedRenderMarkdown
;
3615 llvm::StringRef ExpectedRenderPlainText
;
3672 "Tests primality of `p`.",
3673 "Tests primality of `p`.",
3674 "Tests primality of `p`.",
3677 "'`' should not occur in `Code`",
3678 "'\\`' should not occur in `Code`",
3679 "'`' should not occur in `Code`",
3687 for (const auto &C
: Cases
) {
3688 markup::Document Output
;
3689 parseDocumentation(C
.Documentation
, Output
);
3691 EXPECT_EQ(Output
.asMarkdown(), C
.ExpectedRenderMarkdown
);
3692 EXPECT_EQ(Output
.asPlainText(), C
.ExpectedRenderPlainText
);
3696 // This is a separate test as headings don't create any differences in
3698 TEST(Hover
, PresentHeadings
) {
3700 HI
.Kind
= index::SymbolKind::Variable
;
3703 EXPECT_EQ(HI
.present().asMarkdown(), "### variable `foo`");
3706 // This is a separate test as rulers behave differently in markdown vs
3708 TEST(Hover
, PresentRulers
) {
3710 HI
.Kind
= index::SymbolKind::Variable
;
3713 HI
.Definition
= "def";
3715 llvm::StringRef ExpectedMarkdown
= //
3716 "### variable `foo` \n"
3725 EXPECT_EQ(HI
.present().asMarkdown(), ExpectedMarkdown
);
3727 llvm::StringRef ExpectedPlaintext
= R
"pt(variable foo
3732 EXPECT_EQ(HI
.present().asPlainText(), ExpectedPlaintext
);
3735 TEST(Hover
, SpaceshipTemplateNoCrash
) {
3736 Annotations
T(R
"cpp(
3738 struct strong_ordering {
3740 constexpr operator int() const { return n; }
3741 static const strong_ordering equal, greater, less;
3743 constexpr strong_ordering strong_ordering::equal = {0};
3744 constexpr strong_ordering strong_ordering::greater = {1};
3745 constexpr strong_ordering strong_ordering::less = {-1};
3748 template <typename T>
3751 friend auto operator<=>(S, S) = default;
3753 static_assert(S<void>() =^= S<void>());
3756 TestTU TU
= TestTU::withCode(T
.code());
3757 TU
.ExtraArgs
.push_back("-std=c++20");
3758 auto AST
= TU
.build();
3759 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3760 EXPECT_EQ(HI
->Documentation
, "Foo bar baz");
3763 TEST(Hover
, ForwardStructNoCrash
) {
3764 Annotations
T(R
"cpp(
3767 auto baz = (Fo^o*)&bar;
3770 TestTU TU
= TestTU::withCode(T
.code());
3771 auto AST
= TU
.build();
3772 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3774 EXPECT_EQ(*HI
->Value
, "&bar");
3777 TEST(Hover
, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls
) {
3779 const char *const Code
;
3780 const std::optional
<std::string
> HoverValue
;
3783 // error-ok testing behavior on invalid decl
3785 void foo(Foo p^aram = nullptr);
3790 void foo(Foo *p^aram = nullptr);
3795 for (const auto &C
: Cases
) {
3796 Annotations
T(C
.Code
);
3797 TestTU TU
= TestTU::withCode(T
.code());
3798 auto AST
= TU
.build();
3799 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3801 ASSERT_EQ(HI
->Value
, C
.HoverValue
);
3805 TEST(Hover
, DisableShowAKA
) {
3806 Annotations
T(R
"cpp(
3812 Cfg
.Hover
.ShowAKA
= false;
3813 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
3815 TestTU TU
= TestTU::withCode(T
.code());
3816 TU
.ExtraArgs
.push_back("-std=c++17");
3817 auto AST
= TU
.build();
3818 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3821 EXPECT_EQ(H
->Type
, HoverInfo::PrintedType("m_int"));
3824 TEST(Hover
, HideBigInitializers
) {
3825 Annotations
T(R
"cpp(
3826 #define A(x) x, x, x, x
3827 #define B(x) A(A(A(A(x))))
3828 int a^rr[] = {B(0)};
3831 TestTU TU
= TestTU::withCode(T
.code());
3832 auto AST
= TU
.build();
3833 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3836 EXPECT_EQ(H
->Definition
, "int arr[]");
3839 #if defined(__aarch64__)
3840 // FIXME: AARCH64 sanitizer buildbots are broken after 72142fbac4.
3841 #define PREDEFINEMACROS_TEST(x) DISABLED_##x
3843 #define PREDEFINEMACROS_TEST(x) x
3846 TEST(Hover
, PREDEFINEMACROS_TEST(GlobalVarEnumeralCastNoCrash
)) {
3847 Annotations
T(R
"cpp(
3848 using uintptr_t = __UINTPTR_TYPE__;
3849 enum Test : uintptr_t {};
3850 unsigned global_var;
3852 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));
3856 TestTU TU
= TestTU::withCode(T
.code());
3857 TU
.PredefineMacros
= true;
3858 auto AST
= TU
.build();
3859 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3861 EXPECT_EQ(*HI
->Value
, "&global_var");
3864 TEST(Hover
, PREDEFINEMACROS_TEST(GlobalVarIntCastNoCrash
)) {
3865 Annotations
T(R
"cpp(
3866 using uintptr_t = __UINTPTR_TYPE__;
3867 unsigned global_var;
3869 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);
3873 TestTU TU
= TestTU::withCode(T
.code());
3874 TU
.PredefineMacros
= true;
3875 auto AST
= TU
.build();
3876 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3878 EXPECT_EQ(*HI
->Value
, "&global_var");
3881 TEST(Hover
, Typedefs
) {
3882 Annotations
T(R
"cpp(
3883 template <bool X, typename T, typename F>
3884 struct cond { using type = T; };
3885 template <typename T, typename F>
3886 struct cond<false, T, F> { using type = F; };
3888 template <bool X, typename T, typename F>
3889 using type = typename cond<X, T, F>::type;
3892 using f^oo = type<true, int, double>;
3896 TestTU TU
= TestTU::withCode(T
.code());
3897 auto AST
= TU
.build();
3898 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3900 ASSERT_TRUE(H
&& H
->Type
);
3901 EXPECT_EQ(H
->Type
->Type
, "int");
3902 EXPECT_EQ(H
->Definition
, "using foo = type<true, int, double>");
3905 TEST(Hover
, EvaluateMacros
) {
3906 llvm::StringRef PredefinedCXX
= R
"cpp(
3908 #define SizeOf sizeof
3909 #define AlignOf alignof
3913 using u64 = unsigned long long;
3914 // calculate (a ** b) % p
3915 constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
3919 ret = (ret * a) % p;
3925 #define last_n_digit(x, y, n) \
3926 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))
3927 #define declare_struct(X, name, value) \
3929 constexpr auto name() { return value; } \
3931 #define gnu_statement_expression(value) \
3933 declare_struct(Widget, getter, value); \
3934 Widget().getter(); \
3936 #define define_lambda_begin(lambda, ...) \
3938 #define define_lambda_end() }
3940 #define left_bracket [
3941 #define right_bracket ]
3942 #define dg_left_bracket <:
3943 #define dg_right_bracket :>
3944 #define array_decl(type, name, size) type name left_bracket size right_bracket
3948 llvm::StringRef Code
;
3949 const std::function
<void(std::optional
<HoverInfo
>, size_t /*Id*/)>
3957 [](std::optional
<HoverInfo
> HI
, size_t) {
3958 EXPECT_EQ(HI
->Value
, "42 (0x2a)");
3959 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("int"));
3967 [](std::optional
<HoverInfo
> HI
, size_t) {
3968 EXPECT_TRUE(HI
->Value
);
3969 EXPECT_TRUE(HI
->Type
);
3970 // Don't validate type or value of `sizeof` and `alignof` as we're
3971 // getting different values or desugared types on different
3972 // platforms. Same as below.
3984 [](std::optional
<HoverInfo
> HI
, size_t) {
3985 EXPECT_TRUE(HI
->Value
);
3986 EXPECT_TRUE(HI
->Type
);
3991 // 2**32 == 4294967296
3992 last_n_di^git(2, 32, 6);
3995 [](std::optional
<HoverInfo
> HI
, size_t) {
3996 EXPECT_EQ(HI
->Value
, "967296 (0xec280)");
3997 EXPECT_EQ(HI
->Type
, "u64");
4002 gnu_statement_exp^ression(42);
4005 [](std::optional
<HoverInfo
> HI
, size_t) {
4006 EXPECT_EQ(HI
->Value
, "42 (0x2a)");
4007 EXPECT_EQ(HI
->Type
, "int");
4015 [](std::optional
<HoverInfo
> HI
, size_t) {
4016 EXPECT_EQ(HI
->Value
, "2");
4017 EXPECT_EQ(HI
->Type
, "int");
4025 [](std::optional
<HoverInfo
> HI
, size_t) {
4026 EXPECT_FALSE(HI
->Value
) << HI
->Value
;
4027 EXPECT_FALSE(HI
->Type
) << HI
->Type
;
4035 [](std::optional
<HoverInfo
> HI
, size_t) {
4036 EXPECT_EQ(HI
->Value
, "2");
4037 EXPECT_EQ(HI
->Type
, "int");
4042 arra^y_decl(int, vector, 10);
4043 vector left_b^racket 3 right_b^racket;
4044 vector dg_le^ft_bracket 3 dg_righ^t_bracket;
4047 [](std::optional
<HoverInfo
> HI
, size_t Id
) {
4050 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("int[10]"));
4056 EXPECT_FALSE(HI
->Type
) << HI
->Type
;
4057 EXPECT_FALSE(HI
->Value
) << HI
->Value
;
4060 ASSERT_TRUE(false) << "Unhandled id: " << Id
;
4066 constexpr auto value = define_lamb^da_begin(lambda, int, char)
4067 // Check if the expansion range is right.
4068 return ^last_n_digit(10, 3, 3)^;
4069 define_lam^bda_end();
4072 [](std::optional
<HoverInfo
> HI
, size_t Id
) {
4075 EXPECT_FALSE(HI
->Value
);
4076 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("const (lambda)"));
4079 EXPECT_EQ(HI
->Value
, "0");
4080 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("u64"));
4086 EXPECT_FALSE(HI
->Type
) << HI
->Type
;
4087 EXPECT_FALSE(HI
->Value
) << HI
->Value
;
4090 ASSERT_TRUE(false) << "Unhandled id: " << Id
;
4097 Cfg
.Hover
.ShowAKA
= false;
4098 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
4099 for (const auto &C
: Cases
) {
4101 (PredefinedCXX
+ "void function() {\n" + C
.Code
+ "}\n").str());
4102 auto TU
= TestTU::withCode(Code
.code());
4103 TU
.ExtraArgs
.push_back("-std=c++17");
4104 auto AST
= TU
.build();
4105 for (auto [Index
, Position
] : llvm::enumerate(Code
.points())) {
4106 C
.Validator(getHover(AST
, Position
, format::getLLVMStyle(), nullptr),
4112 #define alignof _Alignof
4114 al^ignof(struct { int x; char y[10]; });
4118 auto TU
= TestTU::withCode(C
.code());
4119 TU
.Filename
= "TestTU.c";
4123 auto AST
= TU
.build();
4124 auto H
= getHover(AST
, C
.point(), format::getLLVMStyle(), nullptr);
4127 EXPECT_TRUE(H
->Value
);
4128 EXPECT_TRUE(H
->Type
);
4131 } // namespace clangd
4132 } // namespace clang