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"
35std::string guard(llvm::StringRef
Code) {
36 return "#pragma once\n" +
Code.str();
39TEST(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";
96 HI.AccessSpecifier =
"private";
106 HI.NamespaceScope = "";
107 HI.LocalScope =
"Foo::";
109 HI.Kind = index::SymbolKind::Field;
110 HI.Definition =
"char bar";
115 HI.AccessSpecifier =
"public";
125 HI.NamespaceScope = "";
126 HI.LocalScope =
"Foo::";
128 HI.Kind = index::SymbolKind::Field;
129 HI.Definition =
"int x : 1";
134 HI.AccessSpecifier =
"public";
138 namespace ns1 { namespace ns2 {
147 HI.NamespaceScope = "ns1::ns2::";
148 HI.LocalScope =
"Foo::foo::";
150 HI.Kind = index::SymbolKind::Variable;
151 HI.Definition =
"int bar";
161 HI.Name = "__func__";
162 HI.Kind = index::SymbolKind::Variable;
164 "Name of the current function (predefined variable)";
165 HI.Value =
"\"foo\"";
166 HI.Type =
"const char[4]";
170 template<int> void foo() {
175 HI.Name = "__func__";
176 HI.Kind = index::SymbolKind::Variable;
178 "Name of the current function (predefined variable)";
179 HI.Type =
"const char[]";
183 namespace ns1 { namespace {
190 HI.NamespaceScope = "ns1::";
191 HI.LocalScope =
"(anonymous struct)::";
193 HI.Kind = index::SymbolKind::Field;
194 HI.Definition =
"char bar";
199 HI.AccessSpecifier =
"public";
206 HI.NamespaceScope = "";
208 HI.Kind = index::SymbolKind::Struct;
209 HI.Definition =
"struct X {}";
215 template <typename T, class... Ts> class Foo { public: Foo(int); };
216 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
219 HI.NamespaceScope = "";
221 HI.Kind = index::SymbolKind::Variable;
222 HI.Definition =
"Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
223 HI.Type =
"Foo<int, char, bool>";
227 template <typename T> class vector{};
228 [[vec^tor]]<int> foo;
231 HI.NamespaceScope = "";
232 HI.Name =
"vector<int>";
233 HI.Kind = index::SymbolKind::Class;
234 HI.Definition =
"template <> class vector<int> {}";
238 template <template<typename, bool...> class C,
242 class... Ts> class Foo final {};
243 template <template<typename, bool...> class T>
247 HI.NamespaceScope = "";
249 HI.Kind = index::SymbolKind::Class;
251 R
"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
252 bool Q = false, class... Ts>
253class Foo final {})cpp";
254 HI.TemplateParameters = {
255 {{"template <typename, bool...> class"},
258 {{
"typename"}, std::nullopt, std::string(
"char")},
259 {{
"int"}, std::nullopt, std::string(
"0")},
260 {{
"bool"}, std::string(
"Q"), std::string(
"false")},
261 {{
"class..."}, std::string(
"Ts"), std::nullopt},
266 template <template<typename, bool...> class C,
270 class... Ts> void foo();
271 template<typename, bool...> class Foo;
278 HI.NamespaceScope = "";
280 HI.Kind = index::SymbolKind::Function;
281 HI.Definition =
"template <> void foo<Foo, char, 0, false, <>>()";
282 HI.ReturnType =
"void";
284 HI.Parameters.emplace();
288 template<typename, bool...> class Foo {};
289 Foo<bool, true, false> foo(int, bool T = false);
296 HI.NamespaceScope = "";
298 HI.Kind = index::SymbolKind::Function;
299 HI.Definition =
"Foo<bool, true, false> foo(int, bool T = false)";
300 HI.ReturnType =
"Foo<bool, true, false>";
301 HI.Type =
"Foo<bool, true, false> (int, bool)";
303 {{
"int"}, std::nullopt, std::nullopt},
304 {{
"bool"}, std::string(
"T"), std::string(
"false")},
310 auto lamb = [](int T, bool B) -> bool { return T && B; };
316 HI.NamespaceScope = "";
317 HI.LocalScope =
"foo::";
319 HI.Kind = index::SymbolKind::Variable;
320 HI.Definition =
"auto *c = &b";
321 HI.Type =
"(lambda) **";
322 HI.ReturnType =
"bool";
324 {{
"int"}, std::string(
"T"), std::nullopt},
325 {{
"bool"}, std::string(
"B"), std::nullopt},
331 auto lamb = [](int T, bool B) -> bool { return T && B; };
332 void foo(decltype(lamb)& bar) {
337 HI.NamespaceScope = "";
338 HI.LocalScope =
"foo::";
340 HI.Kind = index::SymbolKind::Parameter;
341 HI.Definition =
"decltype(lamb) &bar";
342 HI.Type = {
"decltype(lamb) &",
"(lambda) &"};
343 HI.ReturnType =
"bool";
345 {{
"int"}, std::string(
"T"), std::nullopt},
346 {{
"bool"}, std::string(
"B"), std::nullopt},
352 auto lamb = [](int T, bool B) -> bool { return T && B; };
353 void foo(decltype(lamb) bar) {
358 HI.NamespaceScope = "";
359 HI.LocalScope =
"foo::";
361 HI.Kind = index::SymbolKind::Parameter;
362 HI.Definition =
"decltype(lamb) bar";
363 HI.Type =
"class (lambda)";
364 HI.ReturnType =
"bool";
366 {{
"int"}, std::string(
"T"), std::nullopt},
367 {{
"bool"}, std::string(
"B"), std::nullopt},
376 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
377 bool res = [[lam^b]](bar, false);
381 HI.NamespaceScope = "";
382 HI.LocalScope =
"foo::";
384 HI.Kind = index::SymbolKind::Variable;
385 HI.Definition =
"auto lamb = [&bar](int T, bool B) -> bool {}";
386 HI.Type =
"class (lambda)";
387 HI.ReturnType =
"bool";
389 {{
"int"}, std::string(
"T"), std::nullopt},
390 {{
"bool"}, std::string(
"B"), std::nullopt},
397 auto lamb = []{int [[te^st]];};
401 HI.NamespaceScope = "";
402 HI.LocalScope =
"foo::(anonymous class)::operator()::";
404 HI.Kind = index::SymbolKind::Variable;
405 HI.Definition =
"int test";
410 template <typename T> class X;
411 template <typename T> class [[^X]]<T*> {};
415 HI.NamespaceScope =
"";
416 HI.Kind = index::SymbolKind::Class;
417 HI.Definition =
"template <typename T> class X<T *> {}";
421 template<typename, typename=void> struct X;
422 template<typename T> struct X<T*>{ [[^X]](); };
425 HI.NamespaceScope = "";
427 HI.LocalScope =
"X<T *>::";
428 HI.Kind = index::SymbolKind::Constructor;
429 HI.Definition =
"X()";
430 HI.Parameters.emplace();
431 HI.AccessSpecifier =
"public";
433 {
"class X { [[^~]]X(); };",
435 HI.NamespaceScope =
"";
437 HI.LocalScope =
"X::";
438 HI.Kind = index::SymbolKind::Destructor;
439 HI.Definition =
"~X()";
440 HI.Parameters.emplace();
441 HI.AccessSpecifier =
"private";
443 {
"class X { [[op^erator]] int(); };",
445 HI.NamespaceScope =
"";
446 HI.Name =
"operator int";
447 HI.LocalScope =
"X::";
448 HI.Kind = index::SymbolKind::ConversionFunction;
449 HI.Definition =
"operator int()";
450 HI.Parameters.emplace();
451 HI.AccessSpecifier =
"private";
453 {
"class X { operator [[^X]](); };",
455 HI.NamespaceScope =
"";
457 HI.Kind = index::SymbolKind::Class;
458 HI.Definition =
"class X {}";
464 struct S { int x; float y; };
465 [[au^to]] [x, y] = S();
470 HI.Kind = index::SymbolKind::TypeAlias;
482 HI.Kind = index::SymbolKind::TypeAlias;
483 HI.Definition =
"/* not deduced */";
487 template <class T> concept F = true;
492 HI.Kind = index::SymbolKind::TypeAlias;
493 HI.Definition =
"int";
496 template <class T> concept F = true;
500 HI.NamespaceScope = "";
502 HI.Kind = index::SymbolKind::Concept;
503 HI.Definition =
"template <class T>\nconcept F = true";
508 [[au^to]] lamb = []{};
513 HI.Kind = index::SymbolKind::TypeAlias;
514 HI.Definition =
"class(lambda)";
518 template<typename T> class Foo{};
520 [[au^to]] x = Foo<int>();
525 HI.Kind = index::SymbolKind::TypeAlias;
526 HI.Definition =
"Foo<int>";
530 template<typename T> class Foo{};
531 template<> class Foo<int>{};
533 [[au^to]] x = Foo<int>();
538 HI.Kind = index::SymbolKind::TypeAlias;
539 HI.Definition =
"Foo<int>";
543 template<class T> concept Fooable = true;
544 template<[[Foo^able]] T>
548 HI.NamespaceScope = "";
550 HI.Kind = index::SymbolKind::Concept;
551 HI.Definition =
"template <class T>\nconcept Fooable = true";
554 template<class T> concept Fooable = true;
555 template<Fooable [[T^T]]>
561 HI.AccessSpecifier =
"public";
562 HI.NamespaceScope =
"";
563 HI.LocalScope =
"bar::";
564 HI.Kind = index::SymbolKind::TemplateTypeParm;
565 HI.Definition =
"Fooable TT";
568 template<class T> concept Fooable = true;
569 void bar([[Foo^able]] auto t) {}
572 HI.NamespaceScope = "";
574 HI.Kind = index::SymbolKind::Concept;
575 HI.Definition =
"template <class T>\nconcept Fooable = true";
579 template<class T> concept Fooable = true;
580 auto X = [[Fooa^ble]]<int>;
583 HI.NamespaceScope = "";
585 HI.Kind = index::SymbolKind::Concept;
586 HI.Definition =
"template <class T>\nconcept Fooable = true";
597 HI.Kind = index::SymbolKind::Macro;
598 HI.Definition =
"#define MACRO";
608 HI.Kind = index::SymbolKind::Macro;
609 HI.Value =
"41 (0x29)";
611 HI.Definition =
"#define MACRO 41\n\n"
619 #define MACRO(x,y,z) void foo(x, y, z)
620 [[MAC^RO]](int, double d, bool z = false);
624 HI.Kind = index::SymbolKind::Macro;
625 HI.Definition =
"#define MACRO(x, y, z) void foo(x, y, z)\n\n"
627 "void foo(int, double d, bool z = false)";
632 #define STRINGIFY_AUX(s) #s
633 #define STRINGIFY(s) STRINGIFY_AUX(s)
634 #define DECL_STR(NAME, VALUE) const char *v_##NAME = STRINGIFY(VALUE)
637 [[DECL^_STR]](foo, FOO);
640 HI.Name = "DECL_STR";
641 HI.Kind = index::SymbolKind::Macro;
642 HI.Type = HoverInfo::PrintedType(
"const char *");
643 HI.Definition =
"#define DECL_STR(NAME, VALUE) const char *v_##NAME = "
644 "STRINGIFY(VALUE)\n\n"
646 "const char *v_foo = \"41\"";
651 constexpr int add(int a, int b) { return a + b; }
652 int [[b^ar]] = add(1, 2);
656 HI.Definition =
"int bar = add(1, 2)";
657 HI.Kind = index::SymbolKind::Variable;
659 HI.NamespaceScope =
"";
663 int [[b^ar]] = sizeof(char);
667 HI.Definition =
"int bar = sizeof(char)";
668 HI.Kind = index::SymbolKind::Variable;
670 HI.NamespaceScope =
"";
674 template<int a, int b> struct Add {
675 static constexpr int result = a + b;
677 int [[ba^r]] = Add<1, 2>::result;
681 HI.Definition =
"int bar = Add<1, 2>::result";
682 HI.Kind = index::SymbolKind::Variable;
684 HI.NamespaceScope =
"";
688 enum Color { RED = -123, GREEN = 5, };
689 Color x = [[GR^EEN]];
693 HI.NamespaceScope =
"";
694 HI.LocalScope =
"Color::";
695 HI.Definition =
"GREEN = 5";
696 HI.Kind = index::SymbolKind::EnumConstant;
697 HI.Type =
"enum Color";
701 enum Color { RED = -123, GREEN = 5, };
707 HI.NamespaceScope =
"";
708 HI.Definition =
"Color x = RED";
709 HI.Kind = index::SymbolKind::Variable;
711 HI.Value =
"RED (0xffffff85)";
714 template<int a, int b> struct Add {
715 static constexpr int result = a + b;
717 int bar = Add<1, 2>::[[resu^lt]];
721 HI.Definition =
"static constexpr int result = a + b";
722 HI.Kind = index::SymbolKind::StaticProperty;
723 HI.Type =
"const int";
724 HI.NamespaceScope =
"";
725 HI.LocalScope =
"Add<1, 2>::";
727 HI.AccessSpecifier =
"public";
731 constexpr my_int answer() { return 40 + 2; }
732 int x = [[ans^wer]]();
736 HI.Definition =
"constexpr my_int answer()";
737 HI.Kind = index::SymbolKind::Function;
738 HI.Type = {
"my_int ()",
"int ()"};
739 HI.ReturnType = {
"my_int",
"int"};
740 HI.Parameters.emplace();
741 HI.NamespaceScope =
"";
742 HI.Value =
"42 (0x2a)";
745 const char *[[ba^r]] = "1234";
749 HI.Definition =
"const char *bar = \"1234\"";
750 HI.Kind = index::SymbolKind::Variable;
751 HI.Type =
"const char *";
752 HI.NamespaceScope =
"";
753 HI.Value =
"&\"1234\"[0]";
755 {R
"cpp(// Should not crash
756 template <typename T>
761 template <typename A>
762 void boom(int name) {
763 new Tmpl<A>([[na^me]]);
767 HI.Definition =
"int name";
768 HI.Kind = index::SymbolKind::Parameter;
770 HI.NamespaceScope =
"";
771 HI.LocalScope =
"boom::";
774 R
"cpp(// Should not print inline or anon namespaces.
776 inline namespace in_ns {
780 inline namespace in_ns2 {
789 ns::a::b::[[F^oo]] x;
795 HI.Kind = index::SymbolKind::Class;
796 HI.NamespaceScope =
"ns::a::b::";
797 HI.Definition =
"class Foo {}";
801 template <typename T> class Foo {};
804 [[^auto]] x = Foo<X>();
809 HI.Kind = index::SymbolKind::TypeAlias;
810 HI.Definition =
"Foo<X>";
814 // comment from primary
815 template <typename T> class Foo {};
816 // comment from specialization
817 template <typename T> class Foo<T*> {};
819 [[Fo^o]]<int*> *x = nullptr;
823 HI.Name = "Foo<int *>";
824 HI.Kind = index::SymbolKind::Class;
825 HI.NamespaceScope =
"";
826 HI.Definition =
"template <> class Foo<int *>";
829 HI.Documentation =
"comment from primary";
833 template <typename [[^T]] = int> void foo();
837 HI.Kind = index::SymbolKind::TemplateTypeParm;
838 HI.NamespaceScope =
"";
839 HI.Definition =
"typename T = int";
840 HI.LocalScope =
"foo::";
841 HI.Type =
"typename";
842 HI.AccessSpecifier =
"public";
846 template <template<typename> class [[^T]]> void foo();
850 HI.Kind = index::SymbolKind::TemplateTemplateParm;
851 HI.NamespaceScope =
"";
852 HI.Definition =
"template <typename> class T";
853 HI.LocalScope =
"foo::";
854 HI.Type =
"template <typename> class";
855 HI.AccessSpecifier =
"public";
859 template <int [[^T]] = 5> void foo();
863 HI.Kind = index::SymbolKind::NonTypeTemplateParm;
864 HI.NamespaceScope =
"";
865 HI.Definition =
"int T = 5";
866 HI.LocalScope =
"foo::";
868 HI.AccessSpecifier =
"public";
873 struct X { int Y; float [[^y]]() { return Y; } };
877 HI.Kind = index::SymbolKind::InstanceMethod;
878 HI.NamespaceScope =
"";
879 HI.Definition =
"float y()";
880 HI.LocalScope =
"X::";
881 HI.Documentation =
"Trivial accessor for `Y`.";
882 HI.Type =
"float ()";
883 HI.ReturnType =
"float";
884 HI.Parameters.emplace();
885 HI.AccessSpecifier =
"public";
889 struct X { int Y; void [[^setY]](float v) { Y = v; } };
893 HI.Kind = index::SymbolKind::InstanceMethod;
894 HI.NamespaceScope =
"";
895 HI.Definition =
"void setY(float v)";
896 HI.LocalScope =
"X::";
897 HI.Documentation =
"Trivial setter for `Y`.";
898 HI.Type =
"void (float)";
899 HI.ReturnType =
"void";
900 HI.Parameters.emplace();
901 HI.Parameters->emplace_back();
902 HI.Parameters->back().Type =
"float";
903 HI.Parameters->back().Name =
"v";
904 HI.AccessSpecifier =
"public";
908 struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };
912 HI.Kind = index::SymbolKind::InstanceMethod;
913 HI.NamespaceScope =
"";
914 HI.Definition =
"X &setY(float v)";
915 HI.LocalScope =
"X::";
916 HI.Documentation =
"Trivial setter for `Y`.";
917 HI.Type =
"X &(float)";
918 HI.ReturnType =
"X &";
919 HI.Parameters.emplace();
920 HI.Parameters->emplace_back();
921 HI.Parameters->back().Type =
"float";
922 HI.Parameters->back().Name =
"v";
923 HI.AccessSpecifier =
"public";
927 namespace std { template<typename T> T&& move(T&& t); }
928 struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } };
932 HI.Kind = index::SymbolKind::InstanceMethod;
933 HI.NamespaceScope =
"";
934 HI.Definition =
"void setY(float v)";
935 HI.LocalScope =
"X::";
936 HI.Documentation =
"Trivial setter for `Y`.";
937 HI.Type =
"void (float)";
938 HI.ReturnType =
"void";
939 HI.Parameters.emplace();
940 HI.Parameters->emplace_back();
941 HI.Parameters->back().Type =
"float";
942 HI.Parameters->back().Name =
"v";
943 HI.AccessSpecifier =
"public";
947 struct X { int x = 2; };
952 HI.Kind = index::SymbolKind::Variable;
953 HI.NamespaceScope =
"";
954 HI.Definition =
"X x";
958 R
"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
961 HI.Kind = index::SymbolKind::Variable;
962 HI.NamespaceScope =
"";
964 HI.Type =
"NULL TYPE";
966 HI.AccessSpecifier =
"public";
970 Unknown [[^abc]] = invalid;
975 HI.Kind = index::SymbolKind::Variable;
976 HI.NamespaceScope =
"";
977 HI.Definition =
"int abc = <recovery - expr>()";
979 HI.AccessSpecifier =
"public";
983 void fun(int arg_a, int &arg_b) {};
991 HI.Kind = index::SymbolKind::Variable;
992 HI.NamespaceScope =
"";
993 HI.Definition =
"int b = 2";
994 HI.LocalScope =
"code::";
997 HI.CalleeArgInfo.emplace();
998 HI.CalleeArgInfo->Name =
"arg_b";
999 HI.CalleeArgInfo->Type =
"int &";
1000 HI.CallPassType = HoverInfo::PassType{PassMode::Ref,
false};
1005 explicit Foo(int arg_a) {}
1007 template<class T, class... Args>
1008 T make(Args&&... args)
1015 auto foo = make<Foo>([[^a]]);
1020 HI.Kind = index::SymbolKind::Variable;
1021 HI.NamespaceScope =
"";
1022 HI.Definition =
"int a = 1";
1023 HI.LocalScope =
"code::";
1026 HI.CalleeArgInfo.emplace();
1027 HI.CalleeArgInfo->Name =
"arg_a";
1028 HI.CalleeArgInfo->Type =
"int";
1029 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
1033 void foobar(const float &arg);
1041 HI.Kind = index::SymbolKind::Variable;
1042 HI.NamespaceScope =
"";
1043 HI.Definition =
"int a = 0";
1044 HI.LocalScope =
"main::";
1047 HI.CalleeArgInfo.emplace();
1048 HI.CalleeArgInfo->Name =
"arg";
1049 HI.CalleeArgInfo->Type =
"const float &";
1050 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
1055 explicit Foo(const float& arg) {}
1064 HI.Kind = index::SymbolKind::Variable;
1065 HI.NamespaceScope =
"";
1066 HI.Definition =
"int a = 0";
1067 HI.LocalScope =
"main::";
1070 HI.CalleeArgInfo.emplace();
1071 HI.CalleeArgInfo->Name =
"arg";
1072 HI.CalleeArgInfo->Type =
"const float &";
1073 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
1077 void fun(int arg_a, const int &arg_b) {};
1084 HI.Name = "literal";
1085 HI.Kind = index::SymbolKind::Unknown;
1086 HI.CalleeArgInfo.emplace();
1087 HI.CalleeArgInfo->Name =
"arg_b";
1088 HI.CalleeArgInfo->Type =
"const int &";
1089 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
false};
1093 void fun(int arg_a, const int &arg_b) {};
1100 HI.Name = "expression";
1101 HI.Kind = index::SymbolKind::Unknown;
1104 HI.CalleeArgInfo.emplace();
1105 HI.CalleeArgInfo->Name =
"arg_b";
1106 HI.CalleeArgInfo->Type =
"const int &";
1107 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
false};
1111 int add(int lhs, int rhs);
1117 HI.Name = "expression";
1118 HI.Kind = index::SymbolKind::Unknown;
1121 HI.CalleeArgInfo.emplace();
1122 HI.CalleeArgInfo->Name =
"lhs";
1123 HI.CalleeArgInfo->Type =
"int";
1124 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
1128 void foobar(const float &arg);
1134 HI.Name = "literal";
1135 HI.Kind = index::SymbolKind::Unknown;
1136 HI.CalleeArgInfo.emplace();
1137 HI.CalleeArgInfo->Name =
"arg";
1138 HI.CalleeArgInfo->Type =
"const float &";
1139 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
1145 void fun(int arg_a = 3, int arg_b = 4) {}
1155 HI.Kind = index::SymbolKind::Variable;
1156 HI.NamespaceScope =
"";
1157 HI.Definition =
"int a = 1";
1158 HI.LocalScope =
"code::";
1161 HI.CalleeArgInfo.emplace();
1162 HI.CalleeArgInfo->Name =
"arg_a";
1163 HI.CalleeArgInfo->Type =
"int";
1164 HI.CalleeArgInfo->Default =
"3";
1165 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
1180 HI.Kind = index::SymbolKind::Variable;
1181 HI.NamespaceScope =
"";
1182 HI.Definition =
"const int x = 0";
1183 HI.LocalScope =
"bar::";
1185 HI.Type =
"const int";
1186 HI.CalleeArgInfo.emplace();
1187 HI.CalleeArgInfo->Type =
"Foo";
1188 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
true};
1198 HI.Kind = index::SymbolKind::Field;
1199 HI.NamespaceScope =
"";
1200 HI.Definition =
"int xx";
1201 HI.LocalScope =
"Foo::";
1203 HI.AccessSpecifier =
"public";
1213 HI.Kind = index::SymbolKind::Field;
1214 HI.NamespaceScope =
"";
1215 HI.Definition =
"int yy";
1216 HI.LocalScope =
"Foo::";
1218 HI.AccessSpecifier =
"public";
1225 constexpr Foo k2 = {
1226 ^[[{]]1} // FIXME: why the hover range is 1 character?
1230 HI.Name = "expression";
1231 HI.Kind = index::SymbolKind::Unknown;
1232 HI.Type =
"int[10]";
1239 template <int Size> m_int ^[[arr]][Size];
1243 HI.Kind = index::SymbolKind::Variable;
1244 HI.Type = {
"m_int[Size]",
"int[Size]"};
1245 HI.NamespaceScope =
"";
1246 HI.Definition =
"template <int Size> m_int arr[Size]";
1247 HI.TemplateParameters = {{{
"int"}, {
"Size"}, std::nullopt}};
1253 template <int Size> m_int arr[Size];
1255 template <> m_int ^[[arr]]<4>[4];
1259 HI.Kind = index::SymbolKind::Variable;
1260 HI.Type = {
"m_int[4]",
"int[4]"};
1261 HI.NamespaceScope =
"";
1262 HI.Definition =
"m_int arr[4]";
1266 template<typename T>
1272 TestHover<int>::Type ^[[a]];
1277 HI.NamespaceScope =
"";
1278 HI.LocalScope =
"code::";
1279 HI.Definition =
"TestHover<int>::Type a";
1280 HI.Kind = index::SymbolKind::Variable;
1281 HI.Type = {
"TestHover<int>::Type",
"int"};
1285 template<typename T>
1286 void ^[[foo]](T arg) {}
1290 HI.Kind = index::SymbolKind::Function;
1291 HI.NamespaceScope =
"";
1292 HI.Definition =
"template <typename T> void foo(T arg)";
1293 HI.Type =
"void (T)";
1294 HI.ReturnType =
"void";
1295 HI.Parameters = {{{
"T"}, std::string(
"arg"), std::nullopt}};
1296 HI.TemplateParameters = {
1297 {{
"typename"}, std::string(
"T"), std::nullopt}};
1301 template<typename T>
1302 using ^[[alias]] = T;
1306 HI.NamespaceScope =
"";
1308 HI.Kind = index::SymbolKind::TypeAlias;
1309 HI.Definition =
"template <typename T> using alias = T";
1311 HI.TemplateParameters = {
1312 {{
"typename"}, std::string(
"T"), std::nullopt}};
1316 template<typename T>
1319 template<typename T>
1320 using ^[[AA]] = A<T>;
1324 HI.NamespaceScope =
"";
1326 HI.Kind = index::SymbolKind::TypeAlias;
1327 HI.Definition =
"template <typename T> using AA = A<T>";
1328 HI.Type = {
"A<T>",
"T"};
1329 HI.TemplateParameters = {
1330 {{
"typename"}, std::string(
"T"), std::nullopt}};
1340 HI.NamespaceScope =
"";
1342 HI.Kind = index::SymbolKind::Variable;
1343 HI.Definition =
"m_int arr[10]";
1344 HI.Type = {
"m_int[10]",
"int[10]"};
1350 extern m_int ^[[arr]][];
1354 HI.NamespaceScope =
"";
1356 HI.Kind = index::SymbolKind::Variable;
1357 HI.Definition =
"extern m_int arr[]";
1358 HI.Type = {
"m_int[]",
"int[]"};
1366 m_int ^[[arr]][Size];
1371 HI.NamespaceScope =
"";
1372 HI.LocalScope =
"Test<Size>::";
1373 HI.AccessSpecifier =
"public";
1374 HI.Kind = index::SymbolKind::Field;
1375 HI.Definition =
"m_int arr[Size]";
1376 HI.Type = {
"m_int[Size]",
"int[Size]"};
1387 HI.NamespaceScope = "";
1388 HI.LocalScope =
"Foo::";
1390 HI.Kind = index::SymbolKind::Field;
1391 HI.Definition =
"char y : 1";
1397 HI.AccessSpecifier =
"public";
1399 for (
const auto &Case : Cases) {
1400 SCOPED_TRACE(Case.Code);
1402 Annotations
T(Case.Code);
1404 TU.ExtraArgs.push_back(
"-std=c++20");
1407 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
1408 auto AST = TU.build();
1411 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
1413 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1419 EXPECT_EQ(H->NamespaceScope,
Expected.NamespaceScope);
1420 EXPECT_EQ(H->LocalScope,
Expected.LocalScope);
1423 EXPECT_EQ(H->Documentation,
Expected.Documentation);
1424 EXPECT_EQ(H->Definition,
Expected.Definition);
1426 EXPECT_EQ(H->ReturnType,
Expected.ReturnType);
1427 EXPECT_EQ(H->Parameters,
Expected.Parameters);
1428 EXPECT_EQ(H->TemplateParameters,
Expected.TemplateParameters);
1429 EXPECT_EQ(H->SymRange,
Expected.SymRange);
1430 EXPECT_EQ(H->Value,
Expected.Value);
1432 EXPECT_EQ(H->Offset,
Expected.Offset);
1433 EXPECT_EQ(H->Align,
Expected.Align);
1434 EXPECT_EQ(H->AccessSpecifier,
Expected.AccessSpecifier);
1435 EXPECT_EQ(H->CalleeArgInfo,
Expected.CalleeArgInfo);
1436 EXPECT_EQ(H->CallPassType,
Expected.CallPassType);
1440TEST(Hover, DefinitionLanuage) {
1442 const char *
const Code;
1443 const std::string ClangLanguageFlag;
1444 const char *
const ExpectedDefinitionLanguage;
1445 } Cases[] = {{R
"cpp(
1446 void [[some^Global]]() {}
1450 void [[some^Global]]() {}
1452 "-xobjective-c++",
"objective-cpp"},
1454 void [[some^Global]]() {}
1456 "-xobjective-c",
"objective-c"}};
1457 for (
const auto &Case : Cases) {
1458 SCOPED_TRACE(Case.Code);
1460 Annotations
T(Case.Code);
1462 if (!Case.ClangLanguageFlag.empty())
1463 TU.ExtraArgs.push_back(Case.ClangLanguageFlag);
1464 auto AST = TU.build();
1466 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1469 EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage);
1473TEST(Hover, CallPassType) {
1474 const llvm::StringRef CodePrefix = R
"cpp(
1476class Derived : public Base {};
1480 CustomClass(const Base &x) {}
1481 CustomClass(int &x) {}
1482 CustomClass(float x) {}
1483 CustomClass(int x, int y) {}
1486void int_by_ref(int &x) {}
1487void int_by_const_ref(const int &x) {}
1488void int_by_value(int x) {}
1489void base_by_ref(Base &x) {}
1490void base_by_const_ref(const Base &x) {}
1491void base_by_value(Base x) {}
1492void float_by_value(float x) {}
1493void custom_by_value(CustomClass x) {}
1497 int &int_ref = int_x;
1498 const int &int_const_ref = int_x;
1500 const Base &base_const_ref = base;
1504 const llvm::StringRef CodeSuffix =
"}";
1507 const char *
const Code;
1512 {
"int_by_value([[^int_x]]);", PassMode::Value,
false},
1513 {
"int_by_value([[^123]]);", PassMode::Value,
false},
1514 {
"int_by_ref([[^int_x]]);", PassMode::Ref,
false},
1515 {
"int_by_const_ref([[^int_x]]);", PassMode::ConstRef,
false},
1516 {
"int_by_const_ref([[^123]]);", PassMode::ConstRef,
false},
1517 {
"int_by_value([[^int_ref]]);", PassMode::Value,
false},
1518 {
"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef,
false},
1519 {
"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef,
false},
1520 {
"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef,
false},
1522 {
"base_by_ref([[^base]]);", PassMode::Ref,
false},
1523 {
"base_by_const_ref([[^base]]);", PassMode::ConstRef,
false},
1524 {
"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef,
false},
1525 {
"base_by_value([[^base]]);", PassMode::Value,
false},
1526 {
"base_by_value([[^base_const_ref]]);", PassMode::Value,
false},
1527 {
"base_by_ref([[^derived]]);", PassMode::Ref,
false},
1528 {
"base_by_const_ref([[^derived]]);", PassMode::ConstRef,
false},
1529 {
"base_by_value([[^derived]]);", PassMode::Value,
false},
1531 {
"CustomClass c1([[^base]]);", PassMode::ConstRef,
false},
1532 {
"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef,
false},
1533 {
"CustomClass c3([[^int_x]]);", PassMode::Ref,
false},
1534 {
"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value,
false},
1536 {
"float_by_value([[^int_x]]);", PassMode::Value,
true},
1537 {
"float_by_value([[^int_ref]]);", PassMode::Value,
true},
1538 {
"float_by_value([[^int_const_ref]]);", PassMode::Value,
true},
1539 {
"float_by_value([[^123.0f]]);", PassMode::Value,
false},
1540 {
"float_by_value([[^123]]);", PassMode::Value,
true},
1541 {
"custom_by_value([[^int_x]]);", PassMode::Ref,
true},
1542 {
"custom_by_value([[^float_x]]);", PassMode::Value,
true},
1543 {
"custom_by_value([[^base]]);", PassMode::ConstRef,
true},
1545 for (
const auto &Test : Tests) {
1546 SCOPED_TRACE(Test.Code);
1548 const auto Code = (CodePrefix + Test.Code + CodeSuffix).str();
1549 Annotations
T(
Code);
1551 TU.ExtraArgs.push_back(
"-std=c++17");
1552 auto AST = TU.build();
1553 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1555 EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy);
1556 EXPECT_EQ(H->CallPassType->Converted, Test.Converted);
1560TEST(Hover, NoHover) {
1561 llvm::StringRef Tests[] = {
1565 "decltype(au^to) x = 0;",
1567 R
"cpp(// Lambda auto parameter
1568 auto lamb = [](a^uto){};
1570 R"cpp(// non-named decls don't get hover. Don't crash!
1571 ^static_assert(1, "");
1573 R"cpp(// non-evaluatable expr
1574 template <typename T> void foo() {
1575 (void)[[size^of]](T);
1577 R"cpp(// should not crash on invalid semantic form of init-list-expr.
1583 constexpr Foo s = ^{
1589 "auto x = ^(int){42};",
1593 "auto x = ^nullptr;",
1596 for (
const auto &Test : Tests) {
1599 Annotations
T(Test);
1601 TU.ExtraArgs.push_back(
"-std=c++17");
1602 auto AST = TU.build();
1603 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1610 const char *
const Code;
1611 const std::function<void(HoverInfo &)> ExpectedBuilder;
1613 {
"auto x = [['^A']]; // character literal",
1615 HI.Name =
"expression";
1617 HI.Value =
"65 (0x41)";
1619 {
"auto s = ^[[\"Hello, world!\"]]; // string literal",
1621 HI.Name =
"string-literal";
1623 HI.Type =
"const char[14]";
1626 R
"cpp(// Local variable
1630 int test1 = bonjour;
1634 HI.Name = "bonjour";
1635 HI.Kind = index::SymbolKind::Variable;
1636 HI.NamespaceScope =
"";
1637 HI.LocalScope =
"main::";
1639 HI.Definition =
"int bonjour";
1642 R
"cpp(// Local variable in method
1651 HI.Name = "bonjour";
1652 HI.Kind = index::SymbolKind::Variable;
1653 HI.NamespaceScope =
"";
1654 HI.LocalScope =
"s::method::";
1656 HI.Definition =
"int bonjour";
1664 ns1::[[My^Class]]* Params;
1668 HI.Name = "MyClass";
1669 HI.Kind = index::SymbolKind::Struct;
1670 HI.NamespaceScope =
"ns1::";
1671 HI.Definition =
"struct MyClass {}";
1679 ns1::[[My^Class]]* Params;
1683 HI.Name = "MyClass";
1684 HI.Kind = index::SymbolKind::Class;
1685 HI.NamespaceScope =
"ns1::";
1686 HI.Definition =
"class MyClass {}";
1691 union MyUnion { int x; int y; };
1694 ns1::[[My^Union]] Params;
1698 HI.Name = "MyUnion";
1699 HI.Kind = index::SymbolKind::Union;
1700 HI.NamespaceScope =
"ns1::";
1701 HI.Definition =
"union MyUnion {}";
1704 R
"cpp(// Function definition via pointer
1707 auto *X = &^[[foo]];
1712 HI.Kind = index::SymbolKind::Function;
1713 HI.NamespaceScope =
"";
1714 HI.Type =
"void (int)";
1715 HI.Definition =
"void foo(int)";
1716 HI.Documentation =
"Function definition via pointer";
1717 HI.ReturnType =
"void";
1719 {{
"int"}, std::nullopt, std::nullopt},
1723 R
"cpp(// Function declaration via call
1726 return ^[[foo]](42);
1731 HI.Kind = index::SymbolKind::Function;
1732 HI.NamespaceScope =
"";
1733 HI.Type =
"int (int)";
1734 HI.Definition =
"int foo(int)";
1735 HI.Documentation =
"Function declaration via call";
1736 HI.ReturnType =
"int";
1738 {{
"int"}, std::nullopt, std::nullopt},
1743 struct Foo { int x; };
1751 HI.Kind = index::SymbolKind::Field;
1752 HI.NamespaceScope =
"";
1753 HI.LocalScope =
"Foo::";
1755 HI.Definition =
"int x";
1758 R
"cpp(// Field with initialization
1759 struct Foo { int x = 5; };
1767 HI.Kind = index::SymbolKind::Field;
1768 HI.NamespaceScope =
"";
1769 HI.LocalScope =
"Foo::";
1771 HI.Definition =
"int x = 5";
1774 R
"cpp(// Static field
1775 struct Foo { static int x; };
1782 HI.Kind = index::SymbolKind::StaticProperty;
1783 HI.NamespaceScope =
"";
1784 HI.LocalScope =
"Foo::";
1786 HI.Definition =
"static int x";
1789 R
"cpp(// Field, member initializer
1792 Foo() : ^[[x]](0) {}
1797 HI.Kind = index::SymbolKind::Field;
1798 HI.NamespaceScope =
"";
1799 HI.LocalScope =
"Foo::";
1801 HI.Definition =
"int x";
1804 R
"cpp(// Field, GNU old-style field designator
1805 struct Foo { int x; };
1807 Foo bar = { ^[[x]] : 1 };
1812 HI.Kind = index::SymbolKind::Field;
1813 HI.NamespaceScope =
"";
1814 HI.LocalScope =
"Foo::";
1816 HI.Definition =
"int x";
1821 R
"cpp(// Field, field designator
1822 struct Foo { int x; int y; };
1824 Foo bar = { .^[[x]] = 2, .y = 2 };
1829 HI.Kind = index::SymbolKind::Field;
1830 HI.NamespaceScope =
"";
1831 HI.LocalScope =
"Foo::";
1833 HI.Definition =
"int x";
1836 R
"cpp(// Method call
1837 struct Foo { int x(); };
1845 HI.Kind = index::SymbolKind::InstanceMethod;
1846 HI.NamespaceScope =
"";
1847 HI.LocalScope =
"Foo::";
1849 HI.Definition =
"int x()";
1850 HI.ReturnType =
"int";
1851 HI.Parameters = std::vector<HoverInfo::Param>{};
1854 R
"cpp(// Static method call
1855 struct Foo { static int x(); };
1862 HI.Kind = index::SymbolKind::StaticMethod;
1863 HI.NamespaceScope =
"";
1864 HI.LocalScope =
"Foo::";
1866 HI.Definition =
"static int x()";
1867 HI.ReturnType =
"int";
1868 HI.Parameters = std::vector<HoverInfo::Param>{};
1879 HI.Kind = index::SymbolKind::TypeAlias;
1880 HI.NamespaceScope =
"";
1881 HI.Definition =
"typedef int Foo";
1883 HI.Documentation =
"Typedef";
1886 R
"cpp(// Typedef with embedded definition
1887 typedef struct Bar {} Foo;
1894 HI.Kind = index::SymbolKind::TypeAlias;
1895 HI.NamespaceScope =
"";
1896 HI.Definition =
"typedef struct Bar Foo";
1897 HI.Type =
"struct Bar";
1898 HI.Documentation =
"Typedef with embedded definition";
1903 struct Foo { static void bar(); };
1905 int main() { ^[[ns]]::Foo::bar(); }
1909 HI.Kind = index::SymbolKind::Namespace;
1910 HI.NamespaceScope =
"";
1911 HI.Definition =
"namespace ns {}";
1914 R
"cpp(// Anonymous namespace
1918 } // anonymous namespace
1920 int main() { ns::[[f^oo]]++; }
1924 HI.Kind = index::SymbolKind::Variable;
1925 HI.NamespaceScope =
"ns::";
1927 HI.Definition =
"int foo";
1930 R
"cpp(// Function definition via using declaration
1941 HI.Kind = index::SymbolKind::Function;
1942 HI.NamespaceScope =
"ns::";
1943 HI.Type =
"void ()";
1944 HI.Definition =
"void foo()";
1945 HI.Documentation =
"";
1946 HI.ReturnType =
"void";
1947 HI.Parameters = std::vector<HoverInfo::Param>{};
1950 R
"cpp( // using declaration and two possible function declarations
1951 namespace ns { void foo(int); void foo(char); }
1953 template <typename T> void bar() { [[f^oo]](T{}); }
1957 HI.Kind = index::SymbolKind::Using;
1958 HI.NamespaceScope =
"";
1959 HI.Definition =
"using ns::foo";
1964 int main() { return ^[[MACRO]]; }
1970 HI.Kind = index::SymbolKind::Macro;
1971 HI.Definition =
"#define MACRO 0\n\n"
1978 #define MACRO2 ^[[MACRO]]
1982 HI.Kind = index::SymbolKind::Macro;
1983 HI.Definition =
"#define MACRO 0";
1992 int main() ^[[MACRO]]
1996 HI.Kind = index::SymbolKind::Macro;
1998 R
"cpp(#define MACRO \
2009 R"cpp(// Forward class declaration
2016 HI.Kind = index::SymbolKind::Class;
2017 HI.NamespaceScope =
"";
2018 HI.Definition =
"class Foo {}";
2019 HI.Documentation =
"Forward class declaration";
2022 R
"cpp(// Function declaration
2024 void g() { [[f^oo]](); }
2029 HI.Kind = index::SymbolKind::Function;
2030 HI.NamespaceScope =
"";
2031 HI.Type =
"void ()";
2032 HI.Definition =
"void foo()";
2033 HI.Documentation =
"Function declaration";
2034 HI.ReturnType =
"void";
2035 HI.Parameters = std::vector<HoverInfo::Param>{};
2038 R
"cpp(// Enum declaration
2043 [[Hel^lo]] hello = ONE;
2048 HI.Kind = index::SymbolKind::Enum;
2049 HI.NamespaceScope =
"";
2050 HI.Definition =
"enum Hello {}";
2051 HI.Documentation =
"Enum declaration";
2059 Hello hello = [[O^NE]];
2064 HI.Kind = index::SymbolKind::EnumConstant;
2065 HI.NamespaceScope =
"";
2066 HI.LocalScope =
"Hello::";
2067 HI.Type =
"enum Hello";
2068 HI.Definition =
"ONE";
2072 R
"cpp(// C++20's using enum
2078 Hello hello = [[O^NE]];
2083 HI.Kind = index::SymbolKind::EnumConstant;
2084 HI.NamespaceScope =
"";
2085 HI.LocalScope =
"Hello::";
2086 HI.Type =
"enum Hello";
2087 HI.Definition =
"ONE";
2091 R
"cpp(// Enumerator in anonymous enum
2096 int hello = [[O^NE]];
2101 HI.Kind = index::SymbolKind::EnumConstant;
2102 HI.NamespaceScope =
"";
2105 HI.Type =
"enum (unnamed)";
2106 HI.Definition =
"ONE";
2110 R
"cpp(// Global variable
2111 static int hey = 10;
2118 HI.Kind = index::SymbolKind::Variable;
2119 HI.NamespaceScope =
"";
2121 HI.Definition =
"static int hey = 10";
2122 HI.Documentation =
"Global variable";
2124 HI.Value =
"10 (0xa)";
2127 R
"cpp(// Global variable in namespace
2129 static long long hey = -36637162602497;
2137 HI.Kind = index::SymbolKind::Variable;
2138 HI.NamespaceScope =
"ns1::";
2139 HI.Type =
"long long";
2140 HI.Definition =
"static long long hey = -36637162602497";
2141 HI.Value =
"-36637162602497 (0xffffdeadbeefffff)";
2144 R
"cpp(// Field in anonymous struct
2154 HI.Kind = index::SymbolKind::Field;
2155 HI.NamespaceScope =
"";
2156 HI.LocalScope =
"(anonymous struct)::";
2158 HI.Definition =
"int hello";
2161 R
"cpp(// Templated function
2162 template <typename T>
2166 void g() { auto x = [[f^oo]]<int>(); }
2170 HI.Kind = index::SymbolKind::Function;
2171 HI.NamespaceScope =
"";
2173 HI.Definition =
"template <> int foo<int>()";
2174 HI.Documentation =
"Templated function";
2175 HI.ReturnType =
"int";
2176 HI.Parameters = std::vector<HoverInfo::Param>{};
2181 R
"cpp(// Anonymous union
2187 void g() { struct outer o; o.v.[[d^ef]]++; }
2191 HI.Kind = index::SymbolKind::Field;
2192 HI.NamespaceScope =
"";
2193 HI.LocalScope =
"outer::(anonymous union)::";
2195 HI.Definition =
"int def";
2198 R
"cpp(// documentation from index
2199 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
2201 void g() { [[ind^exSymbol]](); }
2204 HI.Name = "indexSymbol";
2205 HI.Kind = index::SymbolKind::Function;
2206 HI.NamespaceScope =
"";
2207 HI.Type =
"void ()";
2208 HI.Definition =
"void indexSymbol()";
2209 HI.ReturnType =
"void";
2210 HI.Parameters = std::vector<HoverInfo::Param>{};
2211 HI.Documentation =
"comment from index";
2214 R
"cpp(// Simple initialization with auto
2221 HI.Kind = index::SymbolKind::TypeAlias;
2222 HI.Definition =
"int";
2225 R
"cpp(// Simple initialization with const auto
2227 const ^[[auto]] i = 1;
2232 HI.Kind = index::SymbolKind::TypeAlias;
2233 HI.Definition =
"int";
2236 R
"cpp(// Simple initialization with const auto&
2238 const ^[[auto]]& i = 1;
2243 HI.Kind = index::SymbolKind::TypeAlias;
2244 HI.Definition =
"int";
2247 R
"cpp(// Simple initialization with auto&
2255 HI.Kind = index::SymbolKind::TypeAlias;
2256 HI.Definition =
"int";
2259 R
"cpp(// Simple initialization with auto*
2267 HI.Kind = index::SymbolKind::TypeAlias;
2268 HI.Definition =
"int";
2271 R
"cpp(// Simple initialization with auto from pointer
2279 HI.Kind = index::SymbolKind::TypeAlias;
2280 HI.Definition =
"int *";
2283 R
"cpp(// Auto with initializer list.
2287 class initializer_list { const _E *a, *b; };
2290 ^[[auto]] i = {1,2};
2295 HI.Kind = index::SymbolKind::TypeAlias;
2296 HI.Definition =
"std::initializer_list<int>";
2299 R
"cpp(// User defined conversion to auto
2301 operator ^[[auto]]() const { return 10; }
2306 HI.Kind = index::SymbolKind::TypeAlias;
2307 HI.Definition =
"int";
2310 R
"cpp(// Simple initialization with decltype(auto)
2312 ^[[decltype]](auto) i = 1;
2316 HI.Name = "decltype";
2317 HI.Kind = index::SymbolKind::TypeAlias;
2318 HI.Definition =
"int";
2321 R
"cpp(// Simple initialization with const decltype(auto)
2324 ^[[decltype]](auto) i = j;
2328 HI.Name = "decltype";
2329 HI.Kind = index::SymbolKind::TypeAlias;
2330 HI.Definition =
"const int";
2333 R
"cpp(// Simple initialization with const& decltype(auto)
2337 ^[[decltype]](auto) i = j;
2341 HI.Name = "decltype";
2342 HI.Kind = index::SymbolKind::TypeAlias;
2343 HI.Definition =
"const int &";
2346 R
"cpp(// Simple initialization with & decltype(auto)
2350 ^[[decltype]](auto) i = j;
2354 HI.Name = "decltype";
2355 HI.Kind = index::SymbolKind::TypeAlias;
2356 HI.Definition =
"int &";
2359 R
"cpp(// simple trailing return type
2360 ^[[auto]] main() -> int {
2366 HI.Kind = index::SymbolKind::TypeAlias;
2367 HI.Definition =
"int";
2370 R
"cpp(// auto function return with trailing type
2372 ^[[auto]] test() -> decltype(Bar()) {
2378 HI.Kind = index::SymbolKind::TypeAlias;
2379 HI.Definition =
"Bar";
2380 HI.Documentation =
"auto function return with trailing type";
2383 R
"cpp(// trailing return type
2385 auto test() -> ^[[decltype]](Bar()) {
2390 HI.Name = "decltype";
2391 HI.Kind = index::SymbolKind::TypeAlias;
2392 HI.Definition =
"Bar";
2393 HI.Documentation =
"trailing return type";
2396 R
"cpp(// auto in function return
2404 HI.Kind = index::SymbolKind::TypeAlias;
2405 HI.Definition =
"Bar";
2406 HI.Documentation =
"auto in function return";
2409 R
"cpp(// auto& in function return
2418 HI.Kind = index::SymbolKind::TypeAlias;
2419 HI.Definition =
"Bar";
2420 HI.Documentation =
"auto& in function return";
2423 R
"cpp(// auto* in function return
2432 HI.Kind = index::SymbolKind::TypeAlias;
2433 HI.Definition =
"Bar";
2434 HI.Documentation =
"auto* in function return";
2437 R
"cpp(// const auto& in function return
2439 const ^[[auto]]& test() {
2446 HI.Kind = index::SymbolKind::TypeAlias;
2447 HI.Definition =
"Bar";
2448 HI.Documentation =
"const auto& in function return";
2451 R
"cpp(// decltype(auto) in function return
2453 ^[[decltype]](auto) test() {
2458 HI.Name = "decltype";
2459 HI.Kind = index::SymbolKind::TypeAlias;
2460 HI.Definition =
"Bar";
2461 HI.Documentation =
"decltype(auto) in function return";
2464 R
"cpp(// decltype(auto) reference in function return
2465 ^[[decltype]](auto) test() {
2471 HI.Name = "decltype";
2472 HI.Kind = index::SymbolKind::TypeAlias;
2473 HI.Definition =
"int &";
2476 R
"cpp(// decltype lvalue reference
2479 ^[[decltype]](I) J = I;
2483 HI.Name = "decltype";
2484 HI.Kind = index::SymbolKind::TypeAlias;
2485 HI.Definition =
"int";
2488 R
"cpp(// decltype lvalue reference
2492 ^[[decltype]](K) J = I;
2496 HI.Name = "decltype";
2497 HI.Kind = index::SymbolKind::TypeAlias;
2498 HI.Definition =
"int &";
2501 R
"cpp(// decltype lvalue reference parenthesis
2504 ^[[decltype]]((I)) J = I;
2508 HI.Name = "decltype";
2509 HI.Kind = index::SymbolKind::TypeAlias;
2510 HI.Definition =
"int &";
2513 R
"cpp(// decltype rvalue reference
2516 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
2520 HI.Name = "decltype";
2521 HI.Kind = index::SymbolKind::TypeAlias;
2522 HI.Definition =
"int &&";
2525 R
"cpp(// decltype rvalue reference function call
2529 ^[[decltype]](bar()) J = bar();
2533 HI.Name = "decltype";
2534 HI.Kind = index::SymbolKind::TypeAlias;
2535 HI.Definition =
"int &&";
2538 R
"cpp(// decltype of function with trailing return type.
2540 auto test() -> decltype(Bar()) {
2544 ^[[decltype]](test()) i = test();
2548 HI.Name = "decltype";
2549 HI.Kind = index::SymbolKind::TypeAlias;
2550 HI.Definition =
"Bar";
2552 "decltype of function with trailing return type.";
2555 R
"cpp(// decltype of var with decltype.
2559 ^[[decltype]](J) K = J;
2563 HI.Name = "decltype";
2564 HI.Kind = index::SymbolKind::TypeAlias;
2565 HI.Definition =
"int";
2568 R
"cpp(// decltype of dependent type
2569 template <typename T>
2571 using Y = ^[[decltype]](T::Z);
2575 HI.Name = "decltype";
2576 HI.Kind = index::SymbolKind::TypeAlias;
2577 HI.Definition =
"<dependent type>";
2580 R
"cpp(// More complicated structured types.
2582 ^[[auto]] (*foo)() = bar;
2586 HI.Kind = index::SymbolKind::TypeAlias;
2587 HI.Definition =
"int";
2590 R
"cpp(// Should not crash when evaluating the initializer.
2592 void test() { Test && [[te^st]] = {}; }
2596 HI.Kind = index::SymbolKind::Variable;
2597 HI.NamespaceScope =
"";
2598 HI.LocalScope =
"test::";
2599 HI.Type =
"Test &&";
2600 HI.Definition =
"Test &&test = {}";
2603 R
"cpp(// Shouldn't crash when evaluating the initializer.
2604 struct Bar {}; // error-ok
2605 struct Foo { void foo(Bar x = y); }
2606 void Foo::foo(Bar [[^x]]) {})cpp",
2609 HI.Kind = index::SymbolKind::Parameter;
2610 HI.NamespaceScope =
"";
2611 HI.LocalScope =
"Foo::foo::";
2613 HI.Definition =
"Bar x = <recovery - expr>()";
2616 R
"cpp(// auto on alias
2617 typedef int int_type;
2618 ^[[auto]] x = int_type();
2622 HI.Kind = index::SymbolKind::TypeAlias;
2623 HI.Definition =
"int_type // aka: int";
2626 R
"cpp(// auto on alias
2628 typedef cls cls_type;
2629 ^[[auto]] y = cls_type();
2633 HI.Kind = index::SymbolKind::TypeAlias;
2634 HI.Definition =
"cls_type // aka: cls";
2635 HI.Documentation =
"auto on alias";
2638 R
"cpp(// auto on alias
2641 ^[[auto]] z = templ<int>();
2645 HI.Kind = index::SymbolKind::TypeAlias;
2646 HI.Definition =
"templ<int>";
2647 HI.Documentation =
"auto on alias";
2650 R
"cpp(// Undeduced auto declaration
2651 template<typename T>
2658 HI.Kind = index::SymbolKind::TypeAlias;
2659 HI.Definition =
"/* not deduced */";
2662 R
"cpp(// Undeduced auto return type
2663 template<typename T>
2670 HI.Kind = index::SymbolKind::TypeAlias;
2671 HI.Definition =
"/* not deduced */";
2674 R
"cpp(// Template auto parameter
2675 template<[[a^uto]] T>
2683 HI.Kind = index::SymbolKind::TypeAlias;
2684 HI.Definition =
"/* not deduced */";
2687 R
"cpp(// Undeduced decltype(auto) return type
2688 template<typename T>
2689 ^[[decltype]](auto) foo() {
2694 HI.Name = "decltype";
2695 HI.Kind = index::SymbolKind::TypeAlias;
2696 HI.Definition =
"/* not deduced */";
2699 R
"cpp(// should not crash.
2700 template <class T> struct cls {
2704 auto test = cls<int>().[[m^ethod]]();
2707 HI.Definition = "int method()";
2708 HI.Kind = index::SymbolKind::InstanceMethod;
2709 HI.NamespaceScope =
"";
2710 HI.LocalScope =
"cls<int>::";
2712 HI.Parameters.emplace();
2713 HI.ReturnType =
"int";
2717 R
"cpp(// type of nested templates.
2718 template <class T> struct cls {};
2719 cls<cls<cls<int>>> [[fo^o]];
2722 HI.Definition = "cls<cls<cls<int>>> foo";
2723 HI.Kind = index::SymbolKind::Variable;
2724 HI.NamespaceScope =
"";
2726 HI.Type =
"cls<cls<cls<int>>>";
2729 R
"cpp(// type of nested templates.
2730 template <class T> struct cls {};
2731 [[cl^s]]<cls<cls<int>>> foo;
2734 HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
2735 HI.Kind = index::SymbolKind::Struct;
2736 HI.NamespaceScope =
"";
2737 HI.Name =
"cls<cls<cls<int>>>";
2738 HI.Documentation =
"type of nested templates.";
2741 R
"cpp(// type with decltype
2743 decltype(a) [[b^]] = a;)cpp",
2745 HI.Definition = "decltype(a) b = a";
2746 HI.Kind = index::SymbolKind::Variable;
2747 HI.NamespaceScope =
"";
2752 R
"cpp(// type with decltype
2755 decltype(c) [[b^]] = a;)cpp",
2757 HI.Definition = "decltype(c) b = a";
2758 HI.Kind = index::SymbolKind::Variable;
2759 HI.NamespaceScope =
"";
2764 R
"cpp(// type with decltype
2766 const decltype(a) [[b^]] = a;)cpp",
2768 HI.Definition = "const decltype(a) b = a";
2769 HI.Kind = index::SymbolKind::Variable;
2770 HI.NamespaceScope =
"";
2775 R
"cpp(// type with decltype
2777 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
2779 HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
2780 HI.Kind = index::SymbolKind::Function;
2781 HI.NamespaceScope =
"";
2785 HI.Type = {
"auto (decltype(a)) -> decltype(a)",
2786 "auto (int) -> int"};
2787 HI.ReturnType =
"int";
2788 HI.Parameters = {{{
"int"}, std::string(
"x"), std::nullopt}};
2791 R
"cpp(// sizeof expr
2793 (void)[[size^of]](char);
2796 HI.Name = "expression";
2797 HI.Type =
"unsigned long";
2801 R
"cpp(// alignof expr
2803 (void)[[align^of]](char);
2806 HI.Name = "expression";
2807 HI.Type =
"unsigned long";
2812 template <typename T = int>
2813 void foo(const T& = T()) {
2818 HI.Kind = index::SymbolKind::Function;
2819 HI.Type =
"void (const int &)";
2820 HI.ReturnType =
"void";
2822 {{
"const int &"}, std::nullopt, std::string(
"T()")}};
2823 HI.Definition =
"template <> void foo<int>(const int &)";
2824 HI.NamespaceScope =
"";
2827 R
"cpp(// should not crash
2835 HI.Kind = index::SymbolKind::Field;
2836 HI.LocalScope =
"ObjC::";
2837 HI.NamespaceScope =
"";
2838 HI.Definition =
"char data";
2844 @interface Interface
2845 @property(retain) [[MYOb^ject]] *x;
2849 HI.Name = "MYObject";
2850 HI.Kind = index::SymbolKind::Class;
2851 HI.NamespaceScope =
"";
2852 HI.Definition =
"@interface MYObject\n@end";
2858 @interface Interface
2859 - (void)doWith:([[MYOb^ject]] *)object;
2863 HI.Name = "MYObject";
2864 HI.Kind = index::SymbolKind::Class;
2865 HI.NamespaceScope =
"";
2866 HI.Definition =
"@interface MYObject\n@end";
2881 HI.Definition =
"ns::Foo *";
2884 R
"cpp(// this expr for template class
2886 template <typename T>
2896 HI.Definition =
"const Foo<T> *";
2899 R
"cpp(// this expr for specialization class
2901 template <typename T> class Foo {};
2912 HI.Definition =
"Foo<int> *";
2915 R
"cpp(// this expr for partial specialization struct
2917 template <typename T, typename F> struct Foo {};
2918 template <typename F>
2919 struct Foo<int, F> {
2928 HI.Definition =
"const Foo<int, F> *";
2934 @interface MYObject (Private)
2935 @property(nonatomic, assign) int privateField;
2938 int someFunction() {
2939 MYObject *obj = [MYObject sharedInstance];
2940 return obj.[[private^Field]];
2944 HI.Name = "privateField";
2945 HI.Kind = index::SymbolKind::InstanceProperty;
2946 HI.LocalScope =
"MYObject(Private)::";
2947 HI.NamespaceScope =
"";
2948 HI.Definition =
"@property(nonatomic, assign, unsafe_unretained, "
2949 "readwrite) int privateField;";
2953 @protocol MYProtocol
2954 @property(nonatomic, assign) int prop1;
2957 int someFunction() {
2958 id<MYProtocol> obj = 0;
2959 return obj.[[pro^p1]];
2964 HI.Kind = index::SymbolKind::InstanceProperty;
2965 HI.LocalScope =
"MYProtocol::";
2966 HI.NamespaceScope =
"";
2967 HI.Definition =
"@property(nonatomic, assign, unsafe_unretained, "
2968 "readwrite) int prop1;";
2972 @protocol MYProtocol
2977 @interface MYObject (Ext) <[[MYProt^ocol]]>
2981 HI.Name = "MYProtocol";
2982 HI.Kind = index::SymbolKind::Protocol;
2983 HI.NamespaceScope =
"";
2984 HI.Definition =
"@protocol MYProtocol\n@end";
2990 @implementation Foo(Private)
2991 + (int)somePrivateMethod {
2992 int [[res^ult]] = 2;
2999 HI.Definition =
"int result = 2";
3000 HI.Kind = index::SymbolKind::Variable;
3002 HI.LocalScope =
"+[Foo(Private) somePrivateMethod]::";
3003 HI.NamespaceScope =
"";
3011 - (int)variadicArgMethod:(id)first, ... {
3012 int [[res^ult]] = 0;
3019 HI.Definition =
"int result = 0";
3020 HI.Kind = index::SymbolKind::Variable;
3022 HI.LocalScope =
"-[Foo variadicArgMethod:, ...]::";
3023 HI.NamespaceScope =
"";
3028 typedef struct MyRect {} MyRect;
3031 @property(nonatomic) MyRect frame;
3040 v.frame = [[foo^bar]]();
3045 HI.Kind = index::SymbolKind::Function;
3046 HI.NamespaceScope =
"";
3047 HI.Definition =
"MyRect foobar()";
3048 HI.Type = {
"MyRect ()",
"MyRect ()"};
3049 HI.ReturnType = {
"MyRect",
"MyRect"};
3050 HI.Parameters.emplace();
3053 void foo(int * __attribute__(([[non^null]], noescape)) );
3056 HI.Name = "nonnull";
3057 HI.Kind = index::SymbolKind::Unknown;
3058 HI.Definition =
"__attribute__((nonnull))";
3059 HI.Documentation = Attr::getDocumentation(attr::NonNull).str();
3064 struct strong_ordering {
3066 constexpr operator int() const { return n; }
3067 static const strong_ordering equal, greater, less;
3069 constexpr strong_ordering strong_ordering::equal = {0};
3070 constexpr strong_ordering strong_ordering::greater = {1};
3071 constexpr strong_ordering strong_ordering::less = {-1};
3078 auto operator<=>(const Foo&) const = default;
3081 bool x = Foo(1) [[!^=]] Foo(2);
3084 HI.Type = "bool (const Foo &) const noexcept";
3086 HI.Name =
"operator==";
3087 HI.Parameters = {{{
"const Foo &"}, std::nullopt, std::nullopt}};
3088 HI.ReturnType =
"bool";
3089 HI.Kind = index::SymbolKind::InstanceMethod;
3090 HI.LocalScope =
"Foo::";
3091 HI.NamespaceScope =
"";
3093 "bool operator==(const Foo &) const noexcept = default";
3094 HI.Documentation =
"";
3099 Symbol IndexSym =
func(
"indexSymbol");
3100 IndexSym.Documentation =
"comment from index";
3106 for (
const auto &Case : Cases) {
3107 SCOPED_TRACE(Case.Code);
3109 Annotations
T(Case.Code);
3111 TU.ExtraArgs.push_back(
"-std=c++20");
3112 TU.ExtraArgs.push_back(
"-xobjective-c++");
3114 TU.ExtraArgs.push_back(
"-Wno-gnu-designator");
3117 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
3118 auto AST = TU.build();
3121 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
3122 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(), Index.get());
3128 SCOPED_TRACE(H->present().asPlainText());
3129 EXPECT_EQ(H->NamespaceScope,
Expected.NamespaceScope);
3130 EXPECT_EQ(H->LocalScope,
Expected.LocalScope);
3133 EXPECT_EQ(H->Documentation,
Expected.Documentation);
3134 EXPECT_EQ(H->Definition,
Expected.Definition);
3136 EXPECT_EQ(H->ReturnType,
Expected.ReturnType);
3137 EXPECT_EQ(H->Parameters,
Expected.Parameters);
3138 EXPECT_EQ(H->TemplateParameters,
Expected.TemplateParameters);
3139 EXPECT_EQ(H->SymRange,
Expected.SymRange);
3140 EXPECT_EQ(H->Value,
Expected.Value);
3144TEST(Hover, Providers) {
3147 const std::function<void(HoverInfo &)> ExpectedBuilder;
3148 } Cases[] = {{R
"cpp(
3152 [](HoverInfo &HI) { HI.Provider = ""; }},
3157 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3162 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3167 [](HoverInfo &HI) { HI.Provider = ""; }},
3172 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3177 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3184 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3193 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3196 using namespace fo^o;
3198 [](HoverInfo &HI) { HI.Provider = ""; }},
3201 for (
const auto &Case : Cases) {
3202 Annotations
Code{Case.Code};
3203 SCOPED_TRACE(
Code.code());
3206 TU.Filename =
"foo.cpp";
3207 TU.Code =
Code.code();
3208 TU.AdditionalFiles[
"foo.h"] = guard(R
"cpp(
3211 Foo& operator+(const Foo, const Foo);
3213 TU.AdditionalFiles["all.h"] = guard(
"#include \"foo.h\"");
3215 auto AST = TU.build();
3216 auto H =
getHover(
AST,
Code.point(), format::getLLVMStyle(),
nullptr);
3220 SCOPED_TRACE(H->present().asMarkdown());
3221 EXPECT_EQ(H->Provider,
Expected.Provider);
3225TEST(Hover, ParseProviderInfo) {
3228 HIFoo.Provider =
"\"foo.h\"";
3231 HIFooBar.Name =
"foo";
3232 HIFooBar.Provider =
"<bar.h>";
3235 llvm::StringRef ExpectedMarkdown;
3236 } Cases[] = {{HIFoo,
"### `foo` \nprovided by `\"foo.h\"`"},
3237 {HIFooBar,
"### `foo` \nprovided by `<bar.h>`"}};
3239 for (
const auto &Case : Cases)
3240 EXPECT_EQ(Case.HI.present().asMarkdown(), Case.ExpectedMarkdown);
3243TEST(Hover, UsedSymbols) {
3246 const std::function<void(HoverInfo &)> ExpectedBuilder;
3247 } Cases[] = {{R
"cpp(
3249 int fstBar = bar1();
3250 int another= bar1(0);
3251 int sndBar = bar2();
3256 HI.UsedSymbolNames = {"BAR",
"Bar",
"bar1",
"bar2"};
3260 std::vector<int> vec;
3262 [](HoverInfo &HI) { HI.UsedSymbolNames = {"vector"}; }}};
3263 for (
const auto &Case : Cases) {
3264 Annotations
Code{Case.Code};
3265 SCOPED_TRACE(
Code.code());
3268 TU.Filename =
"foo.cpp";
3269 TU.Code =
Code.code();
3270 TU.AdditionalFiles[
"bar.h"] = guard(R
"cpp(
3277 TU.AdditionalFiles["system/vector"] = guard(R
"cpp(
3283 TU.ExtraArgs.push_back("-isystem" +
testPath(
"system"));
3285 auto AST = TU.build();
3286 auto H =
getHover(
AST,
Code.point(), format::getLLVMStyle(),
nullptr);
3290 SCOPED_TRACE(H->present().asMarkdown());
3291 EXPECT_EQ(H->UsedSymbolNames,
Expected.UsedSymbolNames);
3295TEST(Hover, DocsFromIndex) {
3296 Annotations
T(R
"cpp(
3297 template <typename T> class X {};
3305 auto AST = TU.build();
3308 IndexSym.Documentation =
"comment from index";
3314 for (
const auto &P :
T.points()) {
3315 auto H =
getHover(
AST, P, format::getLLVMStyle(), Index.get());
3317 EXPECT_EQ(H->Documentation, IndexSym.Documentation);
3321TEST(Hover, DocsFromAST) {
3322 Annotations
T(R
"cpp(
3324 template <typename T> class X {};
3326 template <typename T> void bar() {}
3328 template <typename T> T baz;
3333 au^to T = ba^z<X<int>>;
3338 auto AST = TU.build();
3339 for (
const auto &P :
T.points()) {
3340 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3342 EXPECT_EQ(H->Documentation,
"doc");
3346TEST(Hover, NoCrash) {
3347 Annotations
T(R
"cpp(
3349 template<typename T> T foo(T);
3351 // Setter variable heuristic might fail if the callexpr is broken.
3352 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");
3355 auto AST = TU.build();
3356 for (
const auto &P :
T.points())
3357 getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3360TEST(Hover, NoCrashAPInt64) {
3361 Annotations
T(R
"cpp(
3362 constexpr unsigned long value = -1; // wrap around
3363 void foo() { va^lue; }
3366 getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3369TEST(Hover, NoCrashInt128) {
3370 Annotations
T(R
"cpp(
3371 constexpr __int128_t value = -4;
3372 void foo() { va^lue; }
3376 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
3377 auto AST = TU.build();
3378 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3380 EXPECT_EQ(H->Value,
"-4 (0xfffffffc)");
3383TEST(Hover, DocsFromMostSpecial) {
3384 Annotations
T(R
"cpp(
3386 template <typename T> class $doc1^X {};
3388 template <> class $doc2^X<int> {};
3390 template <typename T> class $doc3^X<T*> {};
3398 auto AST = TU.build();
3399 for (
const auto *Comment : {
"doc1",
"doc2",
"doc3"}) {
3400 for (
const auto &P :
T.points(Comment)) {
3401 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3403 EXPECT_EQ(H->Documentation, Comment);
3408TEST(Hover, Present) {
3410 const std::function<void(HoverInfo &)>
Builder;
3411 llvm::StringRef ExpectedRender;
3415 HI.Kind = index::SymbolKind::Unknown;
3422 HI.Kind = index::SymbolKind::NamespaceAlias;
3425 R
"(namespace-alias foo)",
3429 HI.Kind = index::SymbolKind::Class;
3431 HI.TemplateParameters = {
3432 {{"typename"}, std::string(
"T"), std::nullopt},
3433 {{
"typename"}, std::string(
"C"), std::string(
"bool")},
3435 HI.Documentation =
"documentation";
3437 "template <typename T, typename C = bool> class Foo {}";
3439 HI.NamespaceScope.emplace();
3446template <typename T, typename C = bool> class Foo {})",
3450 HI.Kind = index::SymbolKind::Function;
3452 HI.Type = {
"type",
"c_type"};
3453 HI.ReturnType = {
"ret_type",
"can_ret_type"};
3454 HI.Parameters.emplace();
3456 HI.Parameters->push_back(P);
3457 P.Type = {
"type",
"can_type"};
3458 HI.Parameters->push_back(P);
3460 HI.Parameters->push_back(P);
3461 P.Default =
"default";
3462 HI.Parameters->push_back(P);
3463 HI.NamespaceScope =
"ns::";
3464 HI.Definition =
"ret_type foo(params) {}";
3468 "→ ret_type (aka can_ret_type)\n"
3471 "- type (aka can_type)\n"
3472 "- type foo (aka can_type)\n"
3473 "- type foo = default (aka can_type)\n"
3475 "// In namespace ns\n"
3476 "ret_type foo(params) {}",
3480 HI.Kind = index::SymbolKind::Field;
3481 HI.LocalScope =
"test::Bar::";
3484 HI.Type = {
"type",
"can_type"};
3485 HI.Definition =
"def";
3493Type: type (aka can_type)
3496Size: 4 bytes (+4 bytes padding), alignment 4 bytes
3503 HI.Kind = index::SymbolKind::Field;
3504 HI.LocalScope = "test::Bar::";
3507 HI.Type = {
"type",
"can_type"};
3508 HI.Definition =
"def";
3516Type: type (aka can_type)
3518Offset: 4 bytes and 3 bits
3519Size: 25 bits (+4 bits padding), alignment 8 bytes
3526 HI.Kind = index::SymbolKind::Field;
3527 HI.AccessSpecifier = "public";
3529 HI.LocalScope =
"test::Bar::";
3530 HI.Definition =
"def";
3539 HI.Definition = "size_t method()";
3540 HI.AccessSpecifier =
"protected";
3541 HI.Kind = index::SymbolKind::InstanceMethod;
3542 HI.NamespaceScope =
"";
3543 HI.LocalScope =
"cls<int>::";
3545 HI.Parameters.emplace();
3546 HI.ReturnType = {
"size_t",
"unsigned long"};
3547 HI.Type = {
"size_t ()",
"unsigned long ()"};
3549 R
"(instance-method method
3551→ size_t (aka unsigned long)
3554protected: size_t method())",
3558 HI.Definition = "cls(int a, int b = 5)";
3559 HI.AccessSpecifier =
"public";
3560 HI.Kind = index::SymbolKind::Constructor;
3561 HI.NamespaceScope =
"";
3562 HI.LocalScope =
"cls";
3564 HI.Parameters.emplace();
3565 HI.Parameters->emplace_back();
3566 HI.Parameters->back().Type =
"int";
3567 HI.Parameters->back().Name =
"a";
3568 HI.Parameters->emplace_back();
3569 HI.Parameters->back().Type =
"int";
3570 HI.Parameters->back().Name =
"b";
3571 HI.Parameters->back().Default =
"5";
3580public: cls(int a, int b = 5))",
3584 HI.Kind = index::SymbolKind::Union;
3585 HI.AccessSpecifier = "private";
3587 HI.NamespaceScope =
"ns1::";
3588 HI.Definition =
"union foo {}";
3593private: union foo {})",
3597 HI.Kind = index::SymbolKind::Variable;
3599 HI.Definition =
"int foo = 3";
3600 HI.LocalScope =
"test::Bar::";
3603 HI.CalleeArgInfo.emplace();
3604 HI.CalleeArgInfo->Name =
"arg_a";
3605 HI.CalleeArgInfo->Type =
"int";
3606 HI.CalleeArgInfo->Default =
"7";
3607 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
3620 HI.Kind = index::SymbolKind::Variable;
3622 HI.CalleeArgInfo.emplace();
3623 HI.CalleeArgInfo->Type =
"int";
3624 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
3632 HI.Kind = index::SymbolKind::Variable;
3634 HI.Definition =
"int foo = 3";
3635 HI.LocalScope =
"test::Bar::";
3638 HI.CalleeArgInfo.emplace();
3639 HI.CalleeArgInfo->Name =
"arg_a";
3640 HI.CalleeArgInfo->Type =
"int";
3641 HI.CalleeArgInfo->Default =
"7";
3642 HI.CallPassType = HoverInfo::PassType{PassMode::Ref,
false};
3648Passed by reference as arg_a
3655 HI.Kind = index::SymbolKind::Variable;
3657 HI.Definition =
"int foo = 3";
3658 HI.LocalScope =
"test::Bar::";
3661 HI.CalleeArgInfo.emplace();
3662 HI.CalleeArgInfo->Name =
"arg_a";
3663 HI.CalleeArgInfo->Type = {
"alias_int",
"int"};
3664 HI.CalleeArgInfo->Default =
"7";
3665 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
3671Passed as arg_a (converted to alias_int)
3678 HI.Kind = index::SymbolKind::Macro;
3679 HI.Name = "PLUS_ONE";
3680 HI.Definition =
"#define PLUS_ONE(X) (X+1)\n\n"
3686#define PLUS_ONE(X) (X+1)
3693 HI.Kind = index::SymbolKind::Variable;
3695 HI.Definition =
"int foo = 3";
3696 HI.LocalScope =
"test::Bar::";
3699 HI.CalleeArgInfo.emplace();
3700 HI.CalleeArgInfo->Name =
"arg_a";
3701 HI.CalleeArgInfo->Type =
"int";
3702 HI.CalleeArgInfo->Default =
"7";
3703 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
true};
3709Passed by const reference as arg_a (converted to int)
3716 HI.Name = "stdio.h";
3717 HI.Definition =
"/usr/include/stdio.h";
3721/usr/include/stdio.h)",
3723 {[](HoverInfo &HI) {
3725 HI.UsedSymbolNames = {
"Foo",
"Bar",
"Bar"};
3729provides Foo, Bar, Bar)"},
3730 {[](HoverInfo &HI) {
3732 HI.UsedSymbolNames = {
"Foo",
"Bar",
"Baz",
"Foobar",
"Qux",
"Quux"};
3736provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}};
3738 for (
const auto &
C : Cases) {
3743 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
3744 EXPECT_EQ(HI.present().asPlainText(),
C.ExpectedRender);
3748TEST(Hover, ParseDocumentation) {
3750 llvm::StringRef Documentation;
3751 llvm::StringRef ExpectedRenderMarkdown;
3752 llvm::StringRef ExpectedRenderPlainText;
3809 "Tests primality of `p`.",
3810 "Tests primality of `p`.",
3811 "Tests primality of `p`.",
3814 "'`' should not occur in `Code`",
3815 "'\\`' should not occur in `Code`",
3816 "'`' should not occur in `Code`",
3824 for (
const auto &
C : Cases) {
3828 EXPECT_EQ(
Output.asMarkdown(),
C.ExpectedRenderMarkdown);
3829 EXPECT_EQ(
Output.asPlainText(),
C.ExpectedRenderPlainText);
3835TEST(Hover, PresentHeadings) {
3837 HI.Kind = index::SymbolKind::Variable;
3840 EXPECT_EQ(HI.present().asMarkdown(),
"### variable `foo`");
3845TEST(Hover, PresentRulers) {
3847 HI.Kind = index::SymbolKind::Variable;
3850 HI.Definition =
"def";
3852 llvm::StringRef ExpectedMarkdown =
3853 "### variable `foo` \n"
3862 EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
3864 llvm::StringRef ExpectedPlaintext = R
"pt(variable foo
3869 EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
3872TEST(Hover, SpaceshipTemplateNoCrash) {
3873 Annotations T(R"cpp(
3875 struct strong_ordering {
3877 constexpr operator int() const { return n; }
3878 static const strong_ordering equal, greater, less;
3880 constexpr strong_ordering strong_ordering::equal = {0};
3881 constexpr strong_ordering strong_ordering::greater = {1};
3882 constexpr strong_ordering strong_ordering::less = {-1};
3885 template <typename T>
3888 friend auto operator<=>(S, S) = default;
3890 static_assert(S<void>() =^= S<void>());
3894 TU.ExtraArgs.push_back("-std=c++20");
3895 auto AST = TU.build();
3896 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3897 EXPECT_EQ(HI->Documentation,
"");
3900TEST(Hover, ForwardStructNoCrash) {
3901 Annotations
T(R
"cpp(
3904 auto baz = (Fo^o*)&bar;
3908 auto AST = TU.build();
3909 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3911 EXPECT_EQ(*HI->Value,
"&bar");
3914TEST(Hover, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls) {
3916 const char *
const Code;
3917 const std::optional<std::string> HoverValue;
3920 // error-ok testing behavior on invalid decl
3922 void foo(Foo p^aram = nullptr);
3927 void foo(Foo *p^aram = nullptr);
3932 for (
const auto &
C : Cases) {
3933 Annotations
T(
C.Code);
3935 auto AST = TU.build();
3936 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3938 ASSERT_EQ(HI->Value,
C.HoverValue);
3942TEST(Hover, DisableShowAKA) {
3943 Annotations
T(R
"cpp(
3950 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
3953 TU.ExtraArgs.push_back(
"-std=c++17");
3954 auto AST = TU.build();
3955 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3958 EXPECT_EQ(H->Type, HoverInfo::PrintedType(
"m_int"));
3961TEST(Hover, HideBigInitializers) {
3962 Annotations
T(R
"cpp(
3963 #define A(x) x, x, x, x
3964 #define B(x) A(A(A(A(x))))
3965 int a^rr[] = {B(0)};
3969 auto AST = TU.build();
3970 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3973 EXPECT_EQ(H->Definition,
"int arr[]");
3976#if defined(__aarch64__)
3978#define PREDEFINEMACROS_TEST(x) DISABLED_##x
3980#define PREDEFINEMACROS_TEST(x) x
3984 Annotations
T(R
"cpp(
3985 using uintptr_t = __UINTPTR_TYPE__;
3986 enum Test : uintptr_t {};
3987 unsigned global_var;
3989 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));
3994 TU.PredefineMacros = true;
3995 auto AST = TU.build();
3996 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3998 EXPECT_EQ(*HI->Value,
"&global_var");
4002 Annotations
T(R
"cpp(
4003 using uintptr_t = __UINTPTR_TYPE__;
4004 unsigned global_var;
4006 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);
4011 TU.PredefineMacros = true;
4012 auto AST = TU.build();
4013 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4015 EXPECT_EQ(*HI->Value,
"&global_var");
4018TEST(Hover, Typedefs) {
4019 Annotations
T(R
"cpp(
4020 template <bool X, typename T, typename F>
4021 struct cond { using type = T; };
4022 template <typename T, typename F>
4023 struct cond<false, T, F> { using type = F; };
4025 template <bool X, typename T, typename F>
4026 using type = typename cond<X, T, F>::type;
4029 using f^oo = type<true, int, double>;
4034 auto AST = TU.build();
4035 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4037 ASSERT_TRUE(H && H->Type);
4038 EXPECT_EQ(H->Type->Type,
"int");
4039 EXPECT_EQ(H->Definition,
"using foo = type<true, int, double>");
4042TEST(Hover, EvaluateMacros) {
4043 llvm::StringRef PredefinedCXX = R
"cpp(
4045#define SizeOf sizeof
4046#define AlignOf alignof
4050using u64 = unsigned long long;
4051// calculate (a ** b) % p
4052constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
4056 ret = (ret * a) % p;
4062#define last_n_digit(x, y, n) \
4063 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))
4064#define declare_struct(X, name, value) \
4066 constexpr auto name() { return value; } \
4068#define gnu_statement_expression(value) \
4070 declare_struct(Widget, getter, value); \
4071 Widget().getter(); \
4073#define define_lambda_begin(lambda, ...) \
4075#define define_lambda_end() }
4077#define left_bracket [
4078#define right_bracket ]
4079#define dg_left_bracket <:
4080#define dg_right_bracket :>
4081#define array_decl(type, name, size) type name left_bracket size right_bracket
4085 llvm::StringRef
Code;
4086 const std::function<void(std::optional<HoverInfo>,
size_t )>
4094 [](std::optional<HoverInfo> HI, size_t) {
4095 EXPECT_EQ(HI->Value,
"42 (0x2a)");
4096 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"int"));
4104 [](std::optional<HoverInfo> HI, size_t) {
4105 EXPECT_TRUE(HI->Value);
4106 EXPECT_TRUE(HI->Type);
4121 [](std::optional<HoverInfo> HI, size_t) {
4122 EXPECT_TRUE(HI->Value);
4123 EXPECT_TRUE(HI->Type);
4128 // 2**32 == 4294967296
4129 last_n_di^git(2, 32, 6);
4132 [](std::optional<HoverInfo> HI, size_t) {
4133 EXPECT_EQ(HI->Value,
"967296 (0xec280)");
4134 EXPECT_EQ(HI->Type,
"u64");
4139 gnu_statement_exp^ression(42);
4142 [](std::optional<HoverInfo> HI, size_t) {
4143 EXPECT_EQ(HI->Value,
"42 (0x2a)");
4144 EXPECT_EQ(HI->Type,
"int");
4152 [](std::optional<HoverInfo> HI, size_t) {
4153 EXPECT_EQ(HI->Value,
"2");
4154 EXPECT_EQ(HI->Type,
"int");
4162 [](std::optional<HoverInfo> HI, size_t) {
4163 EXPECT_FALSE(HI->Value) << HI->Value;
4164 EXPECT_FALSE(HI->Type) << HI->Type;
4172 [](std::optional<HoverInfo> HI, size_t) {
4173 EXPECT_EQ(HI->Value,
"2");
4174 EXPECT_EQ(HI->Type,
"int");
4179 arra^y_decl(int, vector, 10);
4180 vector left_b^racket 3 right_b^racket;
4181 vector dg_le^ft_bracket 3 dg_righ^t_bracket;
4184 [](std::optional<HoverInfo> HI,
size_t Id) {
4187 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"int[10]"));
4193 EXPECT_FALSE(HI->Type) << HI->Type;
4194 EXPECT_FALSE(HI->Value) << HI->Value;
4197 ASSERT_TRUE(
false) <<
"Unhandled id: " <<
Id;
4203 constexpr auto value = define_lamb^da_begin(lambda, int, char)
4204 // Check if the expansion range is right.
4205 return ^last_n_digit(10, 3, 3)^;
4206 define_lam^bda_end();
4209 [](std::optional<HoverInfo> HI,
size_t Id) {
4212 EXPECT_FALSE(HI->Value);
4213 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"const (lambda)"));
4216 EXPECT_EQ(HI->Value,
"0");
4217 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"u64"));
4223 EXPECT_FALSE(HI->Type) << HI->Type;
4224 EXPECT_FALSE(HI->Value) << HI->Value;
4227 ASSERT_TRUE(
false) <<
"Unhandled id: " <<
Id;
4235 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
4236 for (
const auto &
C : Cases) {
4238 (PredefinedCXX +
"void function() {\n" +
C.Code +
"}\n").str());
4240 TU.ExtraArgs.push_back(
"-std=c++17");
4241 auto AST = TU.build();
4242 for (
auto [Index, Position] : llvm::enumerate(
Code.points())) {
4243 C.Validator(
getHover(
AST, Position, format::getLLVMStyle(),
nullptr),
4249 #define alignof _Alignof
4251 al^ignof(struct { int x; char y[10]; });
4256 TU.Filename =
"TestTU.c";
4260 auto AST = TU.build();
4261 auto H =
getHover(
AST,
C.point(), format::getLLVMStyle(),
nullptr);
4264 EXPECT_TRUE(H->Value);
4265 EXPECT_TRUE(H->Type);
CodeCompletionBuilder Builder
#define PREDEFINEMACROS_TEST(x)
std::vector< const char * > Expected
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Symbol func(llvm::StringRef Name)
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
std::optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, const format::FormatStyle &Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
TEST(BackgroundQueueTest, Priority)
void parseDocumentation(llvm::StringRef Input, markup::Document &Output)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
bool ShowAKA
Whether hover show a.k.a type.
struct clang::clangd::Config::@7 Hover
Configures hover feature.
static TestTU withCode(llvm::StringRef Code)