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 void fun(int arg_a, int &arg_b) {};
978 HI.Kind = index::SymbolKind::Variable;
979 HI.NamespaceScope =
"";
980 HI.Definition =
"int b = 2";
981 HI.LocalScope =
"code::";
984 HI.CalleeArgInfo.emplace();
985 HI.CalleeArgInfo->Name =
"arg_b";
986 HI.CalleeArgInfo->Type =
"int &";
987 HI.CallPassType = HoverInfo::PassType{PassMode::Ref,
false};
992 explicit Foo(int arg_a) {}
994 template<class T, class... Args>
995 T make(Args&&... args)
1002 auto foo = make<Foo>([[^a]]);
1007 HI.Kind = index::SymbolKind::Variable;
1008 HI.NamespaceScope =
"";
1009 HI.Definition =
"int a = 1";
1010 HI.LocalScope =
"code::";
1013 HI.CalleeArgInfo.emplace();
1014 HI.CalleeArgInfo->Name =
"arg_a";
1015 HI.CalleeArgInfo->Type =
"int";
1016 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
1020 void foobar(const float &arg);
1028 HI.Kind = index::SymbolKind::Variable;
1029 HI.NamespaceScope =
"";
1030 HI.Definition =
"int a = 0";
1031 HI.LocalScope =
"main::";
1034 HI.CalleeArgInfo.emplace();
1035 HI.CalleeArgInfo->Name =
"arg";
1036 HI.CalleeArgInfo->Type =
"const float &";
1037 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
1042 explicit Foo(const float& arg) {}
1051 HI.Kind = index::SymbolKind::Variable;
1052 HI.NamespaceScope =
"";
1053 HI.Definition =
"int a = 0";
1054 HI.LocalScope =
"main::";
1057 HI.CalleeArgInfo.emplace();
1058 HI.CalleeArgInfo->Name =
"arg";
1059 HI.CalleeArgInfo->Type =
"const float &";
1060 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
1064 void fun(int arg_a, const int &arg_b) {};
1071 HI.Name = "literal";
1072 HI.Kind = index::SymbolKind::Unknown;
1073 HI.CalleeArgInfo.emplace();
1074 HI.CalleeArgInfo->Name =
"arg_b";
1075 HI.CalleeArgInfo->Type =
"const int &";
1076 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
false};
1080 void fun(int arg_a, const int &arg_b) {};
1087 HI.Name = "expression";
1088 HI.Kind = index::SymbolKind::Unknown;
1091 HI.CalleeArgInfo.emplace();
1092 HI.CalleeArgInfo->Name =
"arg_b";
1093 HI.CalleeArgInfo->Type =
"const int &";
1094 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
false};
1098 int add(int lhs, int rhs);
1104 HI.Name = "expression";
1105 HI.Kind = index::SymbolKind::Unknown;
1108 HI.CalleeArgInfo.emplace();
1109 HI.CalleeArgInfo->Name =
"lhs";
1110 HI.CalleeArgInfo->Type =
"int";
1111 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
1115 void foobar(const float &arg);
1121 HI.Name = "literal";
1122 HI.Kind = index::SymbolKind::Unknown;
1123 HI.CalleeArgInfo.emplace();
1124 HI.CalleeArgInfo->Name =
"arg";
1125 HI.CalleeArgInfo->Type =
"const float &";
1126 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
1132 void fun(int arg_a = 3, int arg_b = 4) {}
1142 HI.Kind = index::SymbolKind::Variable;
1143 HI.NamespaceScope =
"";
1144 HI.Definition =
"int a = 1";
1145 HI.LocalScope =
"code::";
1148 HI.CalleeArgInfo.emplace();
1149 HI.CalleeArgInfo->Name =
"arg_a";
1150 HI.CalleeArgInfo->Type =
"int";
1151 HI.CalleeArgInfo->Default =
"3";
1152 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
1167 HI.Kind = index::SymbolKind::Variable;
1168 HI.NamespaceScope =
"";
1169 HI.Definition =
"const int x = 0";
1170 HI.LocalScope =
"bar::";
1172 HI.Type =
"const int";
1173 HI.CalleeArgInfo.emplace();
1174 HI.CalleeArgInfo->Type =
"Foo";
1175 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
true};
1185 HI.Kind = index::SymbolKind::Field;
1186 HI.NamespaceScope =
"";
1187 HI.Definition =
"int xx";
1188 HI.LocalScope =
"Foo::";
1190 HI.AccessSpecifier =
"public";
1200 HI.Kind = index::SymbolKind::Field;
1201 HI.NamespaceScope =
"";
1202 HI.Definition =
"int yy";
1203 HI.LocalScope =
"Foo::";
1205 HI.AccessSpecifier =
"public";
1212 constexpr Foo k2 = {
1213 ^[[{]]1} // FIXME: why the hover range is 1 character?
1217 HI.Name = "expression";
1218 HI.Kind = index::SymbolKind::Unknown;
1219 HI.Type =
"int[10]";
1226 template <int Size> m_int ^[[arr]][Size];
1230 HI.Kind = index::SymbolKind::Variable;
1231 HI.Type = {
"m_int[Size]",
"int[Size]"};
1232 HI.NamespaceScope =
"";
1233 HI.Definition =
"template <int Size> m_int arr[Size]";
1234 HI.TemplateParameters = {{{
"int"}, {
"Size"}, std::nullopt}};
1240 template <int Size> m_int arr[Size];
1242 template <> m_int ^[[arr]]<4>[4];
1246 HI.Kind = index::SymbolKind::Variable;
1247 HI.Type = {
"m_int[4]",
"int[4]"};
1248 HI.NamespaceScope =
"";
1249 HI.Definition =
"m_int arr[4]";
1253 template<typename T>
1259 TestHover<int>::Type ^[[a]];
1264 HI.NamespaceScope =
"";
1265 HI.LocalScope =
"code::";
1266 HI.Definition =
"TestHover<int>::Type a";
1267 HI.Kind = index::SymbolKind::Variable;
1268 HI.Type = {
"TestHover<int>::Type",
"int"};
1272 template<typename T>
1273 void ^[[foo]](T arg) {}
1277 HI.Kind = index::SymbolKind::Function;
1278 HI.NamespaceScope =
"";
1279 HI.Definition =
"template <typename T> void foo(T arg)";
1280 HI.Type =
"void (T)";
1281 HI.ReturnType =
"void";
1282 HI.Parameters = {{{
"T"}, std::string(
"arg"), std::nullopt}};
1283 HI.TemplateParameters = {
1284 {{
"typename"}, std::string(
"T"), std::nullopt}};
1288 template<typename T>
1289 using ^[[alias]] = T;
1293 HI.NamespaceScope =
"";
1295 HI.Kind = index::SymbolKind::TypeAlias;
1296 HI.Definition =
"template <typename T> using alias = T";
1298 HI.TemplateParameters = {
1299 {{
"typename"}, std::string(
"T"), std::nullopt}};
1303 template<typename T>
1306 template<typename T>
1307 using ^[[AA]] = A<T>;
1311 HI.NamespaceScope =
"";
1313 HI.Kind = index::SymbolKind::TypeAlias;
1314 HI.Definition =
"template <typename T> using AA = A<T>";
1315 HI.Type = {
"A<T>",
"type-parameter-0-0"};
1316 HI.TemplateParameters = {
1317 {{
"typename"}, std::string(
"T"), std::nullopt}};
1327 HI.NamespaceScope =
"";
1329 HI.Kind = index::SymbolKind::Variable;
1330 HI.Definition =
"m_int arr[10]";
1331 HI.Type = {
"m_int[10]",
"int[10]"};
1337 extern m_int ^[[arr]][];
1341 HI.NamespaceScope =
"";
1343 HI.Kind = index::SymbolKind::Variable;
1344 HI.Definition =
"extern m_int arr[]";
1345 HI.Type = {
"m_int[]",
"int[]"};
1353 m_int ^[[arr]][Size];
1358 HI.NamespaceScope =
"";
1359 HI.LocalScope =
"Test<Size>::";
1360 HI.AccessSpecifier =
"public";
1361 HI.Kind = index::SymbolKind::Field;
1362 HI.Definition =
"m_int arr[Size]";
1363 HI.Type = {
"m_int[Size]",
"int[Size]"};
1374 HI.NamespaceScope = "";
1375 HI.LocalScope =
"Foo::";
1377 HI.Kind = index::SymbolKind::Field;
1378 HI.Definition =
"char y : 1";
1384 HI.AccessSpecifier =
"public";
1386 for (
const auto &Case : Cases) {
1387 SCOPED_TRACE(Case.Code);
1389 Annotations T(Case.Code);
1391 TU.ExtraArgs.push_back(
"-std=c++20");
1394 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
1395 auto AST = TU.build();
1398 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
1400 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
1406 EXPECT_EQ(H->NamespaceScope,
Expected.NamespaceScope);
1407 EXPECT_EQ(H->LocalScope,
Expected.LocalScope);
1410 EXPECT_EQ(H->Documentation,
Expected.Documentation);
1411 EXPECT_EQ(H->Definition,
Expected.Definition);
1413 EXPECT_EQ(H->ReturnType,
Expected.ReturnType);
1414 EXPECT_EQ(H->Parameters,
Expected.Parameters);
1415 EXPECT_EQ(H->TemplateParameters,
Expected.TemplateParameters);
1416 EXPECT_EQ(H->SymRange,
Expected.SymRange);
1417 EXPECT_EQ(H->Value,
Expected.Value);
1419 EXPECT_EQ(H->Offset,
Expected.Offset);
1420 EXPECT_EQ(H->Align,
Expected.Align);
1421 EXPECT_EQ(H->AccessSpecifier,
Expected.AccessSpecifier);
1422 EXPECT_EQ(H->CalleeArgInfo,
Expected.CalleeArgInfo);
1423 EXPECT_EQ(H->CallPassType,
Expected.CallPassType);
1427TEST(Hover, DefinitionLanuage) {
1429 const char *
const Code;
1430 const std::string ClangLanguageFlag;
1431 const char *
const ExpectedDefinitionLanguage;
1432 } Cases[] = {{R
"cpp(
1433 void [[some^Global]]() {}
1437 void [[some^Global]]() {}
1439 "-xobjective-c++",
"objective-cpp"},
1441 void [[some^Global]]() {}
1443 "-xobjective-c",
"objective-c"}};
1444 for (
const auto &Case : Cases) {
1445 SCOPED_TRACE(Case.Code);
1447 Annotations T(Case.Code);
1449 if (!Case.ClangLanguageFlag.empty())
1450 TU.ExtraArgs.push_back(Case.ClangLanguageFlag);
1451 auto AST = TU.build();
1453 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
1456 EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage);
1460TEST(Hover, CallPassType) {
1461 const llvm::StringRef CodePrefix = R
"cpp(
1463class Derived : public Base {};
1467 CustomClass(const Base &x) {}
1468 CustomClass(int &x) {}
1469 CustomClass(float x) {}
1470 CustomClass(int x, int y) {}
1473void int_by_ref(int &x) {}
1474void int_by_const_ref(const int &x) {}
1475void int_by_value(int x) {}
1476void base_by_ref(Base &x) {}
1477void base_by_const_ref(const Base &x) {}
1478void base_by_value(Base x) {}
1479void float_by_value(float x) {}
1480void custom_by_value(CustomClass x) {}
1484 int &int_ref = int_x;
1485 const int &int_const_ref = int_x;
1487 const Base &base_const_ref = base;
1491 const llvm::StringRef CodeSuffix =
"}";
1494 const char *
const Code;
1499 {
"int_by_value([[^int_x]]);", PassMode::Value,
false},
1500 {
"int_by_value([[^123]]);", PassMode::Value,
false},
1501 {
"int_by_ref([[^int_x]]);", PassMode::Ref,
false},
1502 {
"int_by_const_ref([[^int_x]]);", PassMode::ConstRef,
false},
1503 {
"int_by_const_ref([[^123]]);", PassMode::ConstRef,
false},
1504 {
"int_by_value([[^int_ref]]);", PassMode::Value,
false},
1505 {
"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef,
false},
1506 {
"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef,
false},
1507 {
"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef,
false},
1509 {
"base_by_ref([[^base]]);", PassMode::Ref,
false},
1510 {
"base_by_const_ref([[^base]]);", PassMode::ConstRef,
false},
1511 {
"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef,
false},
1512 {
"base_by_value([[^base]]);", PassMode::Value,
false},
1513 {
"base_by_value([[^base_const_ref]]);", PassMode::Value,
false},
1514 {
"base_by_ref([[^derived]]);", PassMode::Ref,
false},
1515 {
"base_by_const_ref([[^derived]]);", PassMode::ConstRef,
false},
1516 {
"base_by_value([[^derived]]);", PassMode::Value,
false},
1518 {
"CustomClass c1([[^base]]);", PassMode::ConstRef,
false},
1519 {
"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef,
false},
1520 {
"CustomClass c3([[^int_x]]);", PassMode::Ref,
false},
1521 {
"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value,
false},
1523 {
"float_by_value([[^int_x]]);", PassMode::Value,
true},
1524 {
"float_by_value([[^int_ref]]);", PassMode::Value,
true},
1525 {
"float_by_value([[^int_const_ref]]);", PassMode::Value,
true},
1526 {
"float_by_value([[^123.0f]]);", PassMode::Value,
false},
1527 {
"float_by_value([[^123]]);", PassMode::Value,
true},
1528 {
"custom_by_value([[^int_x]]);", PassMode::Ref,
true},
1529 {
"custom_by_value([[^float_x]]);", PassMode::Value,
true},
1530 {
"custom_by_value([[^base]]);", PassMode::ConstRef,
true},
1532 for (
const auto &Test : Tests) {
1533 SCOPED_TRACE(Test.Code);
1535 const auto Code = (CodePrefix + Test.Code + CodeSuffix).str();
1536 Annotations T(
Code);
1538 TU.ExtraArgs.push_back(
"-std=c++17");
1539 auto AST = TU.build();
1540 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
1542 EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy);
1543 EXPECT_EQ(H->CallPassType->Converted, Test.Converted);
1547TEST(Hover, NoHover) {
1548 llvm::StringRef Tests[] = {
1552 "decltype(au^to) x = 0;",
1554 R
"cpp(// Lambda auto parameter
1555 auto lamb = [](a^uto){};
1557 R"cpp(// non-named decls don't get hover. Don't crash!
1558 ^static_assert(1, "");
1560 R"cpp(// non-evaluatable expr
1561 template <typename T> void foo() {
1562 (void)[[size^of]](T);
1564 R"cpp(// should not crash on invalid semantic form of init-list-expr.
1570 constexpr Foo s = ^{
1576 "auto x = ^(int){42};",
1580 "auto x = ^nullptr;",
1583 for (
const auto &Test : Tests) {
1586 Annotations T(Test);
1588 TU.ExtraArgs.push_back(
"-std=c++17");
1589 auto AST = TU.build();
1590 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
1597 const char *
const Code;
1598 const std::function<void(HoverInfo &)> ExpectedBuilder;
1600 {
"auto x = [['^A']]; // character literal",
1602 HI.Name =
"expression";
1604 HI.Value =
"65 (0x41)";
1606 {
"auto s = ^[[\"Hello, world!\"]]; // string literal",
1608 HI.Name =
"string-literal";
1610 HI.Type =
"const char[14]";
1613 R
"cpp(// Local variable
1617 int test1 = bonjour;
1621 HI.Name = "bonjour";
1622 HI.Kind = index::SymbolKind::Variable;
1623 HI.NamespaceScope =
"";
1624 HI.LocalScope =
"main::";
1626 HI.Definition =
"int bonjour";
1629 R
"cpp(// Local variable in method
1638 HI.Name = "bonjour";
1639 HI.Kind = index::SymbolKind::Variable;
1640 HI.NamespaceScope =
"";
1641 HI.LocalScope =
"s::method::";
1643 HI.Definition =
"int bonjour";
1651 ns1::[[My^Class]]* Params;
1655 HI.Name = "MyClass";
1656 HI.Kind = index::SymbolKind::Struct;
1657 HI.NamespaceScope =
"ns1::";
1658 HI.Definition =
"struct MyClass {}";
1666 ns1::[[My^Class]]* Params;
1670 HI.Name = "MyClass";
1671 HI.Kind = index::SymbolKind::Class;
1672 HI.NamespaceScope =
"ns1::";
1673 HI.Definition =
"class MyClass {}";
1678 union MyUnion { int x; int y; };
1681 ns1::[[My^Union]] Params;
1685 HI.Name = "MyUnion";
1686 HI.Kind = index::SymbolKind::Union;
1687 HI.NamespaceScope =
"ns1::";
1688 HI.Definition =
"union MyUnion {}";
1691 R
"cpp(// Function definition via pointer
1694 auto *X = &^[[foo]];
1699 HI.Kind = index::SymbolKind::Function;
1700 HI.NamespaceScope =
"";
1701 HI.Type =
"void (int)";
1702 HI.Definition =
"void foo(int)";
1703 HI.Documentation =
"Function definition via pointer";
1704 HI.ReturnType =
"void";
1706 {{
"int"}, std::nullopt, std::nullopt},
1710 R
"cpp(// Function declaration via call
1713 return ^[[foo]](42);
1718 HI.Kind = index::SymbolKind::Function;
1719 HI.NamespaceScope =
"";
1720 HI.Type =
"int (int)";
1721 HI.Definition =
"int foo(int)";
1722 HI.Documentation =
"Function declaration via call";
1723 HI.ReturnType =
"int";
1725 {{
"int"}, std::nullopt, std::nullopt},
1730 struct Foo { int x; };
1738 HI.Kind = index::SymbolKind::Field;
1739 HI.NamespaceScope =
"";
1740 HI.LocalScope =
"Foo::";
1742 HI.Definition =
"int x";
1745 R
"cpp(// Field with initialization
1746 struct Foo { int x = 5; };
1754 HI.Kind = index::SymbolKind::Field;
1755 HI.NamespaceScope =
"";
1756 HI.LocalScope =
"Foo::";
1758 HI.Definition =
"int x = 5";
1761 R
"cpp(// Static field
1762 struct Foo { static int x; };
1769 HI.Kind = index::SymbolKind::StaticProperty;
1770 HI.NamespaceScope =
"";
1771 HI.LocalScope =
"Foo::";
1773 HI.Definition =
"static int x";
1776 R
"cpp(// Field, member initializer
1779 Foo() : ^[[x]](0) {}
1784 HI.Kind = index::SymbolKind::Field;
1785 HI.NamespaceScope =
"";
1786 HI.LocalScope =
"Foo::";
1788 HI.Definition =
"int x";
1791 R
"cpp(// Field, GNU old-style field designator
1792 struct Foo { int x; };
1794 Foo bar = { ^[[x]] : 1 };
1799 HI.Kind = index::SymbolKind::Field;
1800 HI.NamespaceScope =
"";
1801 HI.LocalScope =
"Foo::";
1803 HI.Definition =
"int x";
1808 R
"cpp(// Field, field designator
1809 struct Foo { int x; int y; };
1811 Foo bar = { .^[[x]] = 2, .y = 2 };
1816 HI.Kind = index::SymbolKind::Field;
1817 HI.NamespaceScope =
"";
1818 HI.LocalScope =
"Foo::";
1820 HI.Definition =
"int x";
1823 R
"cpp(// Method call
1824 struct Foo { int x(); };
1832 HI.Kind = index::SymbolKind::InstanceMethod;
1833 HI.NamespaceScope =
"";
1834 HI.LocalScope =
"Foo::";
1836 HI.Definition =
"int x()";
1837 HI.ReturnType =
"int";
1838 HI.Parameters = std::vector<HoverInfo::Param>{};
1841 R
"cpp(// Static method call
1842 struct Foo { static int x(); };
1849 HI.Kind = index::SymbolKind::StaticMethod;
1850 HI.NamespaceScope =
"";
1851 HI.LocalScope =
"Foo::";
1853 HI.Definition =
"static int x()";
1854 HI.ReturnType =
"int";
1855 HI.Parameters = std::vector<HoverInfo::Param>{};
1866 HI.Kind = index::SymbolKind::TypeAlias;
1867 HI.NamespaceScope =
"";
1868 HI.Definition =
"typedef int Foo";
1870 HI.Documentation =
"Typedef";
1873 R
"cpp(// Typedef with embedded definition
1874 typedef struct Bar {} Foo;
1881 HI.Kind = index::SymbolKind::TypeAlias;
1882 HI.NamespaceScope =
"";
1883 HI.Definition =
"typedef struct Bar Foo";
1884 HI.Type =
"struct Bar";
1885 HI.Documentation =
"Typedef with embedded definition";
1890 struct Foo { static void bar(); };
1892 int main() { ^[[ns]]::Foo::bar(); }
1896 HI.Kind = index::SymbolKind::Namespace;
1897 HI.NamespaceScope =
"";
1898 HI.Definition =
"namespace ns {}";
1901 R
"cpp(// Anonymous namespace
1905 } // anonymous namespace
1907 int main() { ns::[[f^oo]]++; }
1911 HI.Kind = index::SymbolKind::Variable;
1912 HI.NamespaceScope =
"ns::";
1914 HI.Definition =
"int foo";
1917 R
"cpp(// Function definition via using declaration
1928 HI.Kind = index::SymbolKind::Function;
1929 HI.NamespaceScope =
"ns::";
1930 HI.Type =
"void ()";
1931 HI.Definition =
"void foo()";
1932 HI.Documentation =
"";
1933 HI.ReturnType =
"void";
1934 HI.Parameters = std::vector<HoverInfo::Param>{};
1937 R
"cpp( // using declaration and two possible function declarations
1938 namespace ns { void foo(int); void foo(char); }
1940 template <typename T> void bar() { [[f^oo]](T{}); }
1944 HI.Kind = index::SymbolKind::Using;
1945 HI.NamespaceScope =
"";
1946 HI.Definition =
"using ns::foo";
1951 int main() { return ^[[MACRO]]; }
1957 HI.Kind = index::SymbolKind::Macro;
1958 HI.Definition =
"#define MACRO 0\n\n"
1965 #define MACRO2 ^[[MACRO]]
1969 HI.Kind = index::SymbolKind::Macro;
1970 HI.Definition =
"#define MACRO 0";
1979 int main() ^[[MACRO]]
1983 HI.Kind = index::SymbolKind::Macro;
1985 R
"cpp(#define MACRO \
1996 R"cpp(// Forward class declaration
2003 HI.Kind = index::SymbolKind::Class;
2004 HI.NamespaceScope =
"";
2005 HI.Definition =
"class Foo {}";
2006 HI.Documentation =
"Forward class declaration";
2009 R
"cpp(// Function declaration
2011 void g() { [[f^oo]](); }
2016 HI.Kind = index::SymbolKind::Function;
2017 HI.NamespaceScope =
"";
2018 HI.Type =
"void ()";
2019 HI.Definition =
"void foo()";
2020 HI.Documentation =
"Function declaration";
2021 HI.ReturnType =
"void";
2022 HI.Parameters = std::vector<HoverInfo::Param>{};
2025 R
"cpp(// Enum declaration
2030 [[Hel^lo]] hello = ONE;
2035 HI.Kind = index::SymbolKind::Enum;
2036 HI.NamespaceScope =
"";
2037 HI.Definition =
"enum Hello {}";
2038 HI.Documentation =
"Enum declaration";
2046 Hello hello = [[O^NE]];
2051 HI.Kind = index::SymbolKind::EnumConstant;
2052 HI.NamespaceScope =
"";
2053 HI.LocalScope =
"Hello::";
2054 HI.Type =
"enum Hello";
2055 HI.Definition =
"ONE";
2059 R
"cpp(// C++20's using enum
2065 Hello hello = [[O^NE]];
2070 HI.Kind = index::SymbolKind::EnumConstant;
2071 HI.NamespaceScope =
"";
2072 HI.LocalScope =
"Hello::";
2073 HI.Type =
"enum Hello";
2074 HI.Definition =
"ONE";
2078 R
"cpp(// Enumerator in anonymous enum
2083 int hello = [[O^NE]];
2088 HI.Kind = index::SymbolKind::EnumConstant;
2089 HI.NamespaceScope =
"";
2092 HI.Type =
"enum (unnamed)";
2093 HI.Definition =
"ONE";
2097 R
"cpp(// Global variable
2098 static int hey = 10;
2105 HI.Kind = index::SymbolKind::Variable;
2106 HI.NamespaceScope =
"";
2108 HI.Definition =
"static int hey = 10";
2109 HI.Documentation =
"Global variable";
2111 HI.Value =
"10 (0xa)";
2114 R
"cpp(// Global variable in namespace
2116 static long long hey = -36637162602497;
2124 HI.Kind = index::SymbolKind::Variable;
2125 HI.NamespaceScope =
"ns1::";
2126 HI.Type =
"long long";
2127 HI.Definition =
"static long long hey = -36637162602497";
2128 HI.Value =
"-36637162602497 (0xffffdeadbeefffff)";
2131 R
"cpp(// Field in anonymous struct
2141 HI.Kind = index::SymbolKind::Field;
2142 HI.NamespaceScope =
"";
2143 HI.LocalScope =
"(anonymous struct)::";
2145 HI.Definition =
"int hello";
2148 R
"cpp(// Templated function
2149 template <typename T>
2153 void g() { auto x = [[f^oo]]<int>(); }
2157 HI.Kind = index::SymbolKind::Function;
2158 HI.NamespaceScope =
"";
2160 HI.Definition =
"template <> int foo<int>()";
2161 HI.Documentation =
"Templated function";
2162 HI.ReturnType =
"int";
2163 HI.Parameters = std::vector<HoverInfo::Param>{};
2168 R
"cpp(// Anonymous union
2174 void g() { struct outer o; o.v.[[d^ef]]++; }
2178 HI.Kind = index::SymbolKind::Field;
2179 HI.NamespaceScope =
"";
2180 HI.LocalScope =
"outer::(anonymous union)::";
2182 HI.Definition =
"int def";
2185 R
"cpp(// documentation from index
2186 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
2188 void g() { [[ind^exSymbol]](); }
2191 HI.Name = "indexSymbol";
2192 HI.Kind = index::SymbolKind::Function;
2193 HI.NamespaceScope =
"";
2194 HI.Type =
"void ()";
2195 HI.Definition =
"void indexSymbol()";
2196 HI.ReturnType =
"void";
2197 HI.Parameters = std::vector<HoverInfo::Param>{};
2198 HI.Documentation =
"comment from index";
2201 R
"cpp(// Simple initialization with auto
2208 HI.Kind = index::SymbolKind::TypeAlias;
2209 HI.Definition =
"int";
2212 R
"cpp(// Simple initialization with const auto
2214 const ^[[auto]] i = 1;
2219 HI.Kind = index::SymbolKind::TypeAlias;
2220 HI.Definition =
"int";
2223 R
"cpp(// Simple initialization with const auto&
2225 const ^[[auto]]& i = 1;
2230 HI.Kind = index::SymbolKind::TypeAlias;
2231 HI.Definition =
"int";
2234 R
"cpp(// Simple initialization with auto&
2242 HI.Kind = index::SymbolKind::TypeAlias;
2243 HI.Definition =
"int";
2246 R
"cpp(// Simple initialization with auto*
2254 HI.Kind = index::SymbolKind::TypeAlias;
2255 HI.Definition =
"int";
2258 R
"cpp(// Simple initialization with auto from pointer
2266 HI.Kind = index::SymbolKind::TypeAlias;
2267 HI.Definition =
"int *";
2270 R
"cpp(// Auto with initializer list.
2274 class initializer_list {};
2277 ^[[auto]] i = {1,2};
2282 HI.Kind = index::SymbolKind::TypeAlias;
2283 HI.Definition =
"std::initializer_list<int>";
2286 R
"cpp(// User defined conversion to auto
2288 operator ^[[auto]]() const { return 10; }
2293 HI.Kind = index::SymbolKind::TypeAlias;
2294 HI.Definition =
"int";
2297 R
"cpp(// Simple initialization with decltype(auto)
2299 ^[[decltype]](auto) i = 1;
2303 HI.Name = "decltype";
2304 HI.Kind = index::SymbolKind::TypeAlias;
2305 HI.Definition =
"int";
2308 R
"cpp(// Simple initialization with const decltype(auto)
2311 ^[[decltype]](auto) i = j;
2315 HI.Name = "decltype";
2316 HI.Kind = index::SymbolKind::TypeAlias;
2317 HI.Definition =
"const int";
2320 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 & decltype(auto)
2337 ^[[decltype]](auto) i = j;
2341 HI.Name = "decltype";
2342 HI.Kind = index::SymbolKind::TypeAlias;
2343 HI.Definition =
"int &";
2346 R
"cpp(// simple trailing return type
2347 ^[[auto]] main() -> int {
2353 HI.Kind = index::SymbolKind::TypeAlias;
2354 HI.Definition =
"int";
2357 R
"cpp(// auto function return with trailing type
2359 ^[[auto]] test() -> decltype(Bar()) {
2365 HI.Kind = index::SymbolKind::TypeAlias;
2366 HI.Definition =
"Bar";
2367 HI.Documentation =
"auto function return with trailing type";
2370 R
"cpp(// trailing return type
2372 auto test() -> ^[[decltype]](Bar()) {
2377 HI.Name = "decltype";
2378 HI.Kind = index::SymbolKind::TypeAlias;
2379 HI.Definition =
"Bar";
2380 HI.Documentation =
"trailing return type";
2383 R
"cpp(// auto in function return
2391 HI.Kind = index::SymbolKind::TypeAlias;
2392 HI.Definition =
"Bar";
2393 HI.Documentation =
"auto in function return";
2396 R
"cpp(// auto& in function return
2405 HI.Kind = index::SymbolKind::TypeAlias;
2406 HI.Definition =
"Bar";
2407 HI.Documentation =
"auto& in function return";
2410 R
"cpp(// auto* in function return
2419 HI.Kind = index::SymbolKind::TypeAlias;
2420 HI.Definition =
"Bar";
2421 HI.Documentation =
"auto* in function return";
2424 R
"cpp(// const auto& in function return
2426 const ^[[auto]]& test() {
2433 HI.Kind = index::SymbolKind::TypeAlias;
2434 HI.Definition =
"Bar";
2435 HI.Documentation =
"const auto& in function return";
2438 R
"cpp(// decltype(auto) in function return
2440 ^[[decltype]](auto) test() {
2445 HI.Name = "decltype";
2446 HI.Kind = index::SymbolKind::TypeAlias;
2447 HI.Definition =
"Bar";
2448 HI.Documentation =
"decltype(auto) in function return";
2451 R
"cpp(// decltype(auto) reference in function return
2452 ^[[decltype]](auto) test() {
2458 HI.Name = "decltype";
2459 HI.Kind = index::SymbolKind::TypeAlias;
2460 HI.Definition =
"int &";
2463 R
"cpp(// decltype lvalue reference
2466 ^[[decltype]](I) J = I;
2470 HI.Name = "decltype";
2471 HI.Kind = index::SymbolKind::TypeAlias;
2472 HI.Definition =
"int";
2475 R
"cpp(// decltype lvalue reference
2479 ^[[decltype]](K) J = I;
2483 HI.Name = "decltype";
2484 HI.Kind = index::SymbolKind::TypeAlias;
2485 HI.Definition =
"int &";
2488 R
"cpp(// decltype lvalue reference parenthesis
2491 ^[[decltype]]((I)) J = I;
2495 HI.Name = "decltype";
2496 HI.Kind = index::SymbolKind::TypeAlias;
2497 HI.Definition =
"int &";
2500 R
"cpp(// decltype rvalue reference
2503 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
2507 HI.Name = "decltype";
2508 HI.Kind = index::SymbolKind::TypeAlias;
2509 HI.Definition =
"int &&";
2512 R
"cpp(// decltype rvalue reference function call
2516 ^[[decltype]](bar()) J = bar();
2520 HI.Name = "decltype";
2521 HI.Kind = index::SymbolKind::TypeAlias;
2522 HI.Definition =
"int &&";
2525 R
"cpp(// decltype of function with trailing return type.
2527 auto test() -> decltype(Bar()) {
2531 ^[[decltype]](test()) i = test();
2535 HI.Name = "decltype";
2536 HI.Kind = index::SymbolKind::TypeAlias;
2537 HI.Definition =
"Bar";
2539 "decltype of function with trailing return type.";
2542 R
"cpp(// decltype of var with decltype.
2546 ^[[decltype]](J) K = J;
2550 HI.Name = "decltype";
2551 HI.Kind = index::SymbolKind::TypeAlias;
2552 HI.Definition =
"int";
2555 R
"cpp(// decltype of dependent type
2556 template <typename T>
2558 using Y = ^[[decltype]](T::Z);
2562 HI.Name = "decltype";
2563 HI.Kind = index::SymbolKind::TypeAlias;
2564 HI.Definition =
"<dependent type>";
2567 R
"cpp(// More complicated structured types.
2569 ^[[auto]] (*foo)() = bar;
2573 HI.Kind = index::SymbolKind::TypeAlias;
2574 HI.Definition =
"int";
2577 R
"cpp(// Should not crash when evaluating the initializer.
2579 void test() { Test && [[te^st]] = {}; }
2583 HI.Kind = index::SymbolKind::Variable;
2584 HI.NamespaceScope =
"";
2585 HI.LocalScope =
"test::";
2586 HI.Type =
"Test &&";
2587 HI.Definition =
"Test &&test = {}";
2590 R
"cpp(// Shouldn't crash when evaluating the initializer.
2591 struct Bar {}; // error-ok
2592 struct Foo { void foo(Bar x = y); }
2593 void Foo::foo(Bar [[^x]]) {})cpp",
2596 HI.Kind = index::SymbolKind::Parameter;
2597 HI.NamespaceScope =
"";
2598 HI.LocalScope =
"Foo::foo::";
2600 HI.Definition =
"Bar x = <recovery - expr>()";
2603 R
"cpp(// auto on alias
2604 typedef int int_type;
2605 ^[[auto]] x = int_type();
2609 HI.Kind = index::SymbolKind::TypeAlias;
2610 HI.Definition =
"int_type // aka: int";
2613 R
"cpp(// auto on alias
2615 typedef cls cls_type;
2616 ^[[auto]] y = cls_type();
2620 HI.Kind = index::SymbolKind::TypeAlias;
2621 HI.Definition =
"cls_type // aka: cls";
2622 HI.Documentation =
"auto on alias";
2625 R
"cpp(// auto on alias
2628 ^[[auto]] z = templ<int>();
2632 HI.Kind = index::SymbolKind::TypeAlias;
2633 HI.Definition =
"templ<int>";
2634 HI.Documentation =
"auto on alias";
2637 R
"cpp(// Undeduced auto declaration
2638 template<typename T>
2645 HI.Kind = index::SymbolKind::TypeAlias;
2646 HI.Definition =
"/* not deduced */";
2649 R
"cpp(// Undeduced auto return type
2650 template<typename T>
2657 HI.Kind = index::SymbolKind::TypeAlias;
2658 HI.Definition =
"/* not deduced */";
2661 R
"cpp(// Template auto parameter
2662 template<[[a^uto]] T>
2670 HI.Kind = index::SymbolKind::TypeAlias;
2671 HI.Definition =
"/* not deduced */";
2674 R
"cpp(// Undeduced decltype(auto) return type
2675 template<typename T>
2676 ^[[decltype]](auto) foo() {
2681 HI.Name = "decltype";
2682 HI.Kind = index::SymbolKind::TypeAlias;
2683 HI.Definition =
"/* not deduced */";
2686 R
"cpp(// should not crash.
2687 template <class T> struct cls {
2691 auto test = cls<int>().[[m^ethod]]();
2694 HI.Definition = "int method()";
2695 HI.Kind = index::SymbolKind::InstanceMethod;
2696 HI.NamespaceScope =
"";
2697 HI.LocalScope =
"cls<int>::";
2699 HI.Parameters.emplace();
2700 HI.ReturnType =
"int";
2704 R
"cpp(// type of nested templates.
2705 template <class T> struct cls {};
2706 cls<cls<cls<int>>> [[fo^o]];
2709 HI.Definition = "cls<cls<cls<int>>> foo";
2710 HI.Kind = index::SymbolKind::Variable;
2711 HI.NamespaceScope =
"";
2713 HI.Type =
"cls<cls<cls<int>>>";
2716 R
"cpp(// type of nested templates.
2717 template <class T> struct cls {};
2718 [[cl^s]]<cls<cls<int>>> foo;
2721 HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
2722 HI.Kind = index::SymbolKind::Struct;
2723 HI.NamespaceScope =
"";
2724 HI.Name =
"cls<cls<cls<int>>>";
2725 HI.Documentation =
"type of nested templates.";
2728 R
"cpp(// type with decltype
2730 decltype(a) [[b^]] = a;)cpp",
2732 HI.Definition = "decltype(a) b = a";
2733 HI.Kind = index::SymbolKind::Variable;
2734 HI.NamespaceScope =
"";
2739 R
"cpp(// type with decltype
2742 decltype(c) [[b^]] = a;)cpp",
2744 HI.Definition = "decltype(c) b = a";
2745 HI.Kind = index::SymbolKind::Variable;
2746 HI.NamespaceScope =
"";
2751 R
"cpp(// type with decltype
2753 const decltype(a) [[b^]] = a;)cpp",
2755 HI.Definition = "const decltype(a) b = a";
2756 HI.Kind = index::SymbolKind::Variable;
2757 HI.NamespaceScope =
"";
2762 R
"cpp(// type with decltype
2764 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
2766 HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
2767 HI.Kind = index::SymbolKind::Function;
2768 HI.NamespaceScope =
"";
2772 HI.Type = {
"auto (decltype(a)) -> decltype(a)",
2773 "auto (int) -> int"};
2774 HI.ReturnType =
"int";
2775 HI.Parameters = {{{
"int"}, std::string(
"x"), std::nullopt}};
2778 R
"cpp(// sizeof expr
2780 (void)[[size^of]](char);
2783 HI.Name = "expression";
2784 HI.Type =
"unsigned long";
2788 R
"cpp(// alignof expr
2790 (void)[[align^of]](char);
2793 HI.Name = "expression";
2794 HI.Type =
"unsigned long";
2799 template <typename T = int>
2800 void foo(const T& = T()) {
2805 HI.Kind = index::SymbolKind::Function;
2806 HI.Type =
"void (const int &)";
2807 HI.ReturnType =
"void";
2809 {{
"const int &"}, std::nullopt, std::string(
"T()")}};
2810 HI.Definition =
"template <> void foo<int>(const int &)";
2811 HI.NamespaceScope =
"";
2814 R
"cpp(// should not crash
2822 HI.Kind = index::SymbolKind::Field;
2823 HI.LocalScope =
"ObjC::";
2824 HI.NamespaceScope =
"";
2825 HI.Definition =
"char data";
2831 @interface Interface
2832 @property(retain) [[MYOb^ject]] *x;
2836 HI.Name = "MYObject";
2837 HI.Kind = index::SymbolKind::Class;
2838 HI.NamespaceScope =
"";
2839 HI.Definition =
"@interface MYObject\n@end";
2845 @interface Interface
2846 - (void)doWith:([[MYOb^ject]] *)object;
2850 HI.Name = "MYObject";
2851 HI.Kind = index::SymbolKind::Class;
2852 HI.NamespaceScope =
"";
2853 HI.Definition =
"@interface MYObject\n@end";
2868 HI.Definition =
"ns::Foo *";
2871 R
"cpp(// this expr for template class
2873 template <typename T>
2883 HI.Definition =
"const Foo<T> *";
2886 R
"cpp(// this expr for specialization class
2888 template <typename T> class Foo {};
2899 HI.Definition =
"Foo<int> *";
2902 R
"cpp(// this expr for partial specialization struct
2904 template <typename T, typename F> struct Foo {};
2905 template <typename F>
2906 struct Foo<int, F> {
2915 HI.Definition =
"const Foo<int, F> *";
2921 @interface MYObject (Private)
2922 @property(nonatomic, assign) int privateField;
2925 int someFunction() {
2926 MYObject *obj = [MYObject sharedInstance];
2927 return obj.[[private^Field]];
2931 HI.Name = "privateField";
2932 HI.Kind = index::SymbolKind::InstanceProperty;
2933 HI.LocalScope =
"MYObject(Private)::";
2934 HI.NamespaceScope =
"";
2935 HI.Definition =
"@property(nonatomic, assign, unsafe_unretained, "
2936 "readwrite) int privateField;";
2940 @protocol MYProtocol
2941 @property(nonatomic, assign) int prop1;
2944 int someFunction() {
2945 id<MYProtocol> obj = 0;
2946 return obj.[[pro^p1]];
2951 HI.Kind = index::SymbolKind::InstanceProperty;
2952 HI.LocalScope =
"MYProtocol::";
2953 HI.NamespaceScope =
"";
2954 HI.Definition =
"@property(nonatomic, assign, unsafe_unretained, "
2955 "readwrite) int prop1;";
2959 @protocol MYProtocol
2964 @interface MYObject (Ext) <[[MYProt^ocol]]>
2968 HI.Name = "MYProtocol";
2969 HI.Kind = index::SymbolKind::Protocol;
2970 HI.NamespaceScope =
"";
2971 HI.Definition =
"@protocol MYProtocol\n@end";
2977 @implementation Foo(Private)
2978 + (int)somePrivateMethod {
2979 int [[res^ult]] = 2;
2986 HI.Definition =
"int result = 2";
2987 HI.Kind = index::SymbolKind::Variable;
2989 HI.LocalScope =
"+[Foo(Private) somePrivateMethod]::";
2990 HI.NamespaceScope =
"";
2998 - (int)variadicArgMethod:(id)first, ... {
2999 int [[res^ult]] = 0;
3006 HI.Definition =
"int result = 0";
3007 HI.Kind = index::SymbolKind::Variable;
3009 HI.LocalScope =
"-[Foo variadicArgMethod:, ...]::";
3010 HI.NamespaceScope =
"";
3015 typedef struct MyRect {} MyRect;
3018 @property(nonatomic) MyRect frame;
3027 v.frame = [[foo^bar]]();
3032 HI.Kind = index::SymbolKind::Function;
3033 HI.NamespaceScope =
"";
3034 HI.Definition =
"MyRect foobar()";
3035 HI.Type = {
"MyRect ()",
"MyRect ()"};
3036 HI.ReturnType = {
"MyRect",
"MyRect"};
3037 HI.Parameters.emplace();
3040 void foo(int * __attribute__(([[non^null]], noescape)) );
3043 HI.Name = "nonnull";
3044 HI.Kind = index::SymbolKind::Unknown;
3045 HI.Definition =
"__attribute__((nonnull))";
3046 HI.Documentation = Attr::getDocumentation(attr::NonNull).str();
3051 struct strong_ordering {
3053 constexpr operator int() const { return n; }
3054 static const strong_ordering equal, greater, less;
3056 constexpr strong_ordering strong_ordering::equal = {0};
3057 constexpr strong_ordering strong_ordering::greater = {1};
3058 constexpr strong_ordering strong_ordering::less = {-1};
3065 auto operator<=>(const Foo&) const = default;
3068 bool x = Foo(1) [[!^=]] Foo(2);
3071 HI.Type = "bool (const Foo &) const noexcept";
3073 HI.Name =
"operator==";
3074 HI.Parameters = {{{
"const Foo &"}, std::nullopt, std::nullopt}};
3075 HI.ReturnType =
"bool";
3076 HI.Kind = index::SymbolKind::InstanceMethod;
3077 HI.LocalScope =
"Foo::";
3078 HI.NamespaceScope =
"";
3080 "bool operator==(const Foo &) const noexcept = default";
3081 HI.Documentation =
"Foo spaceship";
3086 Symbol IndexSym =
func(
"indexSymbol");
3087 IndexSym.Documentation =
"comment from index";
3093 for (
const auto &Case : Cases) {
3094 SCOPED_TRACE(Case.Code);
3096 Annotations T(Case.Code);
3098 TU.ExtraArgs.push_back(
"-std=c++20");
3099 TU.ExtraArgs.push_back(
"-xobjective-c++");
3101 TU.ExtraArgs.push_back(
"-Wno-gnu-designator");
3104 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
3105 auto AST = TU.build();
3108 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
3109 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(), Index.get());
3115 SCOPED_TRACE(H->present().asPlainText());
3116 EXPECT_EQ(H->NamespaceScope,
Expected.NamespaceScope);
3117 EXPECT_EQ(H->LocalScope,
Expected.LocalScope);
3120 EXPECT_EQ(H->Documentation,
Expected.Documentation);
3121 EXPECT_EQ(H->Definition,
Expected.Definition);
3123 EXPECT_EQ(H->ReturnType,
Expected.ReturnType);
3124 EXPECT_EQ(H->Parameters,
Expected.Parameters);
3125 EXPECT_EQ(H->TemplateParameters,
Expected.TemplateParameters);
3126 EXPECT_EQ(H->SymRange,
Expected.SymRange);
3127 EXPECT_EQ(H->Value,
Expected.Value);
3131TEST(Hover, Providers) {
3134 const std::function<void(HoverInfo &)> ExpectedBuilder;
3135 } Cases[] = {{R
"cpp(
3139 [](HoverInfo &HI) { HI.Provider = ""; }},
3144 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3149 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3154 [](HoverInfo &HI) { HI.Provider = ""; }},
3159 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3164 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3171 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3180 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3183 using namespace fo^o;
3185 [](HoverInfo &HI) { HI.Provider = ""; }},
3188 for (
const auto &Case : Cases) {
3189 Annotations
Code{Case.Code};
3190 SCOPED_TRACE(
Code.code());
3193 TU.Filename =
"foo.cpp";
3194 TU.Code =
Code.code();
3195 TU.AdditionalFiles[
"foo.h"] = guard(R
"cpp(
3198 Foo& operator+(const Foo, const Foo);
3200 TU.AdditionalFiles["all.h"] = guard(
"#include \"foo.h\"");
3202 auto AST = TU.build();
3203 auto H =
getHover(
AST,
Code.point(), format::getLLVMStyle(),
nullptr);
3207 SCOPED_TRACE(H->present().asMarkdown());
3208 EXPECT_EQ(H->Provider,
Expected.Provider);
3212TEST(Hover, ParseProviderInfo) {
3215 HIFoo.Provider =
"\"foo.h\"";
3218 HIFooBar.Name =
"foo";
3219 HIFooBar.Provider =
"<bar.h>";
3222 llvm::StringRef ExpectedMarkdown;
3223 } Cases[] = {{HIFoo,
"### `foo` \nprovided by `\"foo.h\"`"},
3224 {HIFooBar,
"### `foo` \nprovided by `<bar.h>`"}};
3226 for (
const auto &Case : Cases)
3227 EXPECT_EQ(Case.HI.present().asMarkdown(), Case.ExpectedMarkdown);
3230TEST(Hover, UsedSymbols) {
3233 const std::function<void(HoverInfo &)> ExpectedBuilder;
3234 } Cases[] = {{R
"cpp(
3236 int fstBar = bar1();
3237 int another= bar1(0);
3238 int sndBar = bar2();
3243 HI.UsedSymbolNames = {"BAR",
"Bar",
"bar1",
"bar2"};
3247 std::vector<int> vec;
3249 [](HoverInfo &HI) { HI.UsedSymbolNames = {"vector"}; }}};
3250 for (
const auto &Case : Cases) {
3251 Annotations
Code{Case.Code};
3252 SCOPED_TRACE(
Code.code());
3255 TU.Filename =
"foo.cpp";
3256 TU.Code =
Code.code();
3257 TU.AdditionalFiles[
"bar.h"] = guard(R
"cpp(
3264 TU.AdditionalFiles["system/vector"] = guard(R
"cpp(
3270 TU.ExtraArgs.push_back("-isystem" +
testPath(
"system"));
3272 auto AST = TU.build();
3273 auto H =
getHover(
AST,
Code.point(), format::getLLVMStyle(),
nullptr);
3277 SCOPED_TRACE(H->present().asMarkdown());
3278 EXPECT_EQ(H->UsedSymbolNames,
Expected.UsedSymbolNames);
3282TEST(Hover, DocsFromIndex) {
3283 Annotations T(R
"cpp(
3284 template <typename T> class X {};
3292 auto AST = TU.build();
3295 IndexSym.Documentation =
"comment from index";
3301 for (
const auto &P : T.points()) {
3302 auto H =
getHover(
AST, P, format::getLLVMStyle(), Index.get());
3304 EXPECT_EQ(H->Documentation, IndexSym.Documentation);
3308TEST(Hover, DocsFromAST) {
3309 Annotations T(R
"cpp(
3311 template <typename T> class X {};
3313 template <typename T> void bar() {}
3315 template <typename T> T baz;
3320 au^to T = ba^z<X<int>>;
3325 auto AST = TU.build();
3326 for (
const auto &P : T.points()) {
3327 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3329 EXPECT_EQ(H->Documentation,
"doc");
3333TEST(Hover, NoCrash) {
3334 Annotations T(R
"cpp(
3336 template<typename T> T foo(T);
3338 // Setter variable heuristic might fail if the callexpr is broken.
3339 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");
3342 auto AST = TU.build();
3343 for (
const auto &P : T.points())
3344 getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3347TEST(Hover, NoCrashAPInt64) {
3348 Annotations T(R
"cpp(
3349 constexpr unsigned long value = -1; // wrap around
3350 void foo() { va^lue; }
3353 getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3356TEST(Hover, NoCrashInt128) {
3357 Annotations T(R
"cpp(
3358 constexpr __int128_t value = -4;
3359 void foo() { va^lue; }
3363 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
3364 auto AST = TU.build();
3365 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3367 EXPECT_EQ(H->Value,
"-4 (0xfffffffc)");
3370TEST(Hover, DocsFromMostSpecial) {
3371 Annotations T(R
"cpp(
3373 template <typename T> class $doc1^X {};
3375 template <> class $doc2^X<int> {};
3377 template <typename T> class $doc3^X<T*> {};
3385 auto AST = TU.build();
3386 for (
const auto *Comment : {
"doc1",
"doc2",
"doc3"}) {
3387 for (
const auto &P : T.points(Comment)) {
3388 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3390 EXPECT_EQ(H->Documentation, Comment);
3395TEST(Hover, Present) {
3397 const std::function<void(HoverInfo &)>
Builder;
3398 llvm::StringRef ExpectedRender;
3402 HI.Kind = index::SymbolKind::Unknown;
3409 HI.Kind = index::SymbolKind::NamespaceAlias;
3412 R
"(namespace-alias foo)",
3416 HI.Kind = index::SymbolKind::Class;
3418 HI.TemplateParameters = {
3419 {{"typename"}, std::string(
"T"), std::nullopt},
3420 {{
"typename"}, std::string(
"C"), std::string(
"bool")},
3422 HI.Documentation =
"documentation";
3424 "template <typename T, typename C = bool> class Foo {}";
3426 HI.NamespaceScope.emplace();
3433template <typename T, typename C = bool> class Foo {})",
3437 HI.Kind = index::SymbolKind::Function;
3439 HI.Type = {
"type",
"c_type"};
3440 HI.ReturnType = {
"ret_type",
"can_ret_type"};
3441 HI.Parameters.emplace();
3443 HI.Parameters->push_back(P);
3444 P.Type = {
"type",
"can_type"};
3445 HI.Parameters->push_back(P);
3447 HI.Parameters->push_back(P);
3448 P.Default =
"default";
3449 HI.Parameters->push_back(P);
3450 HI.NamespaceScope =
"ns::";
3451 HI.Definition =
"ret_type foo(params) {}";
3455 "→ ret_type (aka can_ret_type)\n"
3458 "- type (aka can_type)\n"
3459 "- type foo (aka can_type)\n"
3460 "- type foo = default (aka can_type)\n"
3462 "// In namespace ns\n"
3463 "ret_type foo(params) {}",
3467 HI.Kind = index::SymbolKind::Field;
3468 HI.LocalScope =
"test::Bar::";
3471 HI.Type = {
"type",
"can_type"};
3472 HI.Definition =
"def";
3480Type: type (aka can_type)
3483Size: 4 bytes (+4 bytes padding), alignment 4 bytes
3490 HI.Kind = index::SymbolKind::Field;
3491 HI.LocalScope = "test::Bar::";
3494 HI.Type = {
"type",
"can_type"};
3495 HI.Definition =
"def";
3503Type: type (aka can_type)
3505Offset: 4 bytes and 3 bits
3506Size: 25 bits (+4 bits padding), alignment 8 bytes
3513 HI.Kind = index::SymbolKind::Field;
3514 HI.AccessSpecifier = "public";
3516 HI.LocalScope =
"test::Bar::";
3517 HI.Definition =
"def";
3526 HI.Definition = "size_t method()";
3527 HI.AccessSpecifier =
"protected";
3528 HI.Kind = index::SymbolKind::InstanceMethod;
3529 HI.NamespaceScope =
"";
3530 HI.LocalScope =
"cls<int>::";
3532 HI.Parameters.emplace();
3533 HI.ReturnType = {
"size_t",
"unsigned long"};
3534 HI.Type = {
"size_t ()",
"unsigned long ()"};
3536 R
"(instance-method method
3538→ size_t (aka unsigned long)
3541protected: size_t method())",
3545 HI.Definition = "cls(int a, int b = 5)";
3546 HI.AccessSpecifier =
"public";
3547 HI.Kind = index::SymbolKind::Constructor;
3548 HI.NamespaceScope =
"";
3549 HI.LocalScope =
"cls";
3551 HI.Parameters.emplace();
3552 HI.Parameters->emplace_back();
3553 HI.Parameters->back().Type =
"int";
3554 HI.Parameters->back().Name =
"a";
3555 HI.Parameters->emplace_back();
3556 HI.Parameters->back().Type =
"int";
3557 HI.Parameters->back().Name =
"b";
3558 HI.Parameters->back().Default =
"5";
3567public: cls(int a, int b = 5))",
3571 HI.Kind = index::SymbolKind::Union;
3572 HI.AccessSpecifier = "private";
3574 HI.NamespaceScope =
"ns1::";
3575 HI.Definition =
"union foo {}";
3580private: union foo {})",
3584 HI.Kind = index::SymbolKind::Variable;
3586 HI.Definition =
"int foo = 3";
3587 HI.LocalScope =
"test::Bar::";
3590 HI.CalleeArgInfo.emplace();
3591 HI.CalleeArgInfo->Name =
"arg_a";
3592 HI.CalleeArgInfo->Type =
"int";
3593 HI.CalleeArgInfo->Default =
"7";
3594 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
3607 HI.Kind = index::SymbolKind::Variable;
3609 HI.CalleeArgInfo.emplace();
3610 HI.CalleeArgInfo->Type =
"int";
3611 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
false};
3619 HI.Kind = index::SymbolKind::Variable;
3621 HI.Definition =
"int foo = 3";
3622 HI.LocalScope =
"test::Bar::";
3625 HI.CalleeArgInfo.emplace();
3626 HI.CalleeArgInfo->Name =
"arg_a";
3627 HI.CalleeArgInfo->Type =
"int";
3628 HI.CalleeArgInfo->Default =
"7";
3629 HI.CallPassType = HoverInfo::PassType{PassMode::Ref,
false};
3635Passed by reference as arg_a
3642 HI.Kind = index::SymbolKind::Variable;
3644 HI.Definition =
"int foo = 3";
3645 HI.LocalScope =
"test::Bar::";
3648 HI.CalleeArgInfo.emplace();
3649 HI.CalleeArgInfo->Name =
"arg_a";
3650 HI.CalleeArgInfo->Type = {
"alias_int",
"int"};
3651 HI.CalleeArgInfo->Default =
"7";
3652 HI.CallPassType = HoverInfo::PassType{PassMode::Value,
true};
3658Passed as arg_a (converted to alias_int)
3665 HI.Kind = index::SymbolKind::Macro;
3666 HI.Name = "PLUS_ONE";
3667 HI.Definition =
"#define PLUS_ONE(X) (X+1)\n\n"
3673#define PLUS_ONE(X) (X+1)
3680 HI.Kind = index::SymbolKind::Variable;
3682 HI.Definition =
"int foo = 3";
3683 HI.LocalScope =
"test::Bar::";
3686 HI.CalleeArgInfo.emplace();
3687 HI.CalleeArgInfo->Name =
"arg_a";
3688 HI.CalleeArgInfo->Type =
"int";
3689 HI.CalleeArgInfo->Default =
"7";
3690 HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef,
true};
3696Passed by const reference as arg_a (converted to int)
3703 HI.Name = "stdio.h";
3704 HI.Definition =
"/usr/include/stdio.h";
3708/usr/include/stdio.h)",
3710 {[](HoverInfo &HI) {
3712 HI.UsedSymbolNames = {
"Foo",
"Bar",
"Bar"};
3716provides Foo, Bar, Bar)"},
3717 {[](HoverInfo &HI) {
3719 HI.UsedSymbolNames = {
"Foo",
"Bar",
"Baz",
"Foobar",
"Qux",
"Quux"};
3723provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}};
3725 for (
const auto &
C : Cases) {
3730 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
3731 EXPECT_EQ(HI.present().asPlainText(),
C.ExpectedRender);
3735TEST(Hover, ParseDocumentation) {
3737 llvm::StringRef Documentation;
3738 llvm::StringRef ExpectedRenderMarkdown;
3739 llvm::StringRef ExpectedRenderPlainText;
3796 "Tests primality of `p`.",
3797 "Tests primality of `p`.",
3798 "Tests primality of `p`.",
3801 "'`' should not occur in `Code`",
3802 "'\\`' should not occur in `Code`",
3803 "'`' should not occur in `Code`",
3811 for (
const auto &
C : Cases) {
3815 EXPECT_EQ(
Output.asMarkdown(),
C.ExpectedRenderMarkdown);
3816 EXPECT_EQ(
Output.asPlainText(),
C.ExpectedRenderPlainText);
3822TEST(Hover, PresentHeadings) {
3824 HI.Kind = index::SymbolKind::Variable;
3827 EXPECT_EQ(HI.present().asMarkdown(),
"### variable `foo`");
3832TEST(Hover, PresentRulers) {
3834 HI.Kind = index::SymbolKind::Variable;
3837 HI.Definition =
"def";
3839 llvm::StringRef ExpectedMarkdown =
3840 "### variable `foo` \n"
3849 EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
3851 llvm::StringRef ExpectedPlaintext = R
"pt(variable foo
3856 EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
3859TEST(Hover, SpaceshipTemplateNoCrash) {
3860 Annotations T(R"cpp(
3862 struct strong_ordering {
3864 constexpr operator int() const { return n; }
3865 static const strong_ordering equal, greater, less;
3867 constexpr strong_ordering strong_ordering::equal = {0};
3868 constexpr strong_ordering strong_ordering::greater = {1};
3869 constexpr strong_ordering strong_ordering::less = {-1};
3872 template <typename T>
3875 friend auto operator<=>(S, S) = default;
3877 static_assert(S<void>() =^= S<void>());
3881 TU.ExtraArgs.push_back("-std=c++20");
3882 auto AST = TU.build();
3883 auto HI =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3884 EXPECT_EQ(HI->Documentation,
"Foo bar baz");
3887TEST(Hover, ForwardStructNoCrash) {
3888 Annotations T(R
"cpp(
3891 auto baz = (Fo^o*)&bar;
3895 auto AST = TU.build();
3896 auto HI =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3898 EXPECT_EQ(*HI->Value,
"&bar");
3901TEST(Hover, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls) {
3903 const char *
const Code;
3904 const std::optional<std::string> HoverValue;
3907 // error-ok testing behavior on invalid decl
3909 void foo(Foo p^aram = nullptr);
3914 void foo(Foo *p^aram = nullptr);
3919 for (
const auto &
C : Cases) {
3920 Annotations T(
C.Code);
3922 auto AST = TU.build();
3923 auto HI =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3925 ASSERT_EQ(HI->Value,
C.HoverValue);
3929TEST(Hover, DisableShowAKA) {
3930 Annotations T(R
"cpp(
3937 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
3940 TU.ExtraArgs.push_back(
"-std=c++17");
3941 auto AST = TU.build();
3942 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3945 EXPECT_EQ(H->Type, HoverInfo::PrintedType(
"m_int"));
3948TEST(Hover, HideBigInitializers) {
3949 Annotations T(R
"cpp(
3950 #define A(x) x, x, x, x
3951 #define B(x) A(A(A(A(x))))
3952 int a^rr[] = {B(0)};
3956 auto AST = TU.build();
3957 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3960 EXPECT_EQ(H->Definition,
"int arr[]");
3963#if defined(__aarch64__)
3965#define PREDEFINEMACROS_TEST(x) DISABLED_##x
3967#define PREDEFINEMACROS_TEST(x) x
3971 Annotations T(R
"cpp(
3972 using uintptr_t = __UINTPTR_TYPE__;
3973 enum Test : uintptr_t {};
3974 unsigned global_var;
3976 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));
3981 TU.PredefineMacros = true;
3982 auto AST = TU.build();
3983 auto HI =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
3985 EXPECT_EQ(*HI->Value,
"&global_var");
3989 Annotations T(R
"cpp(
3990 using uintptr_t = __UINTPTR_TYPE__;
3991 unsigned global_var;
3993 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);
3998 TU.PredefineMacros = true;
3999 auto AST = TU.build();
4000 auto HI =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
4002 EXPECT_EQ(*HI->Value,
"&global_var");
4005TEST(Hover, Typedefs) {
4006 Annotations T(R
"cpp(
4007 template <bool X, typename T, typename F>
4008 struct cond { using type = T; };
4009 template <typename T, typename F>
4010 struct cond<false, T, F> { using type = F; };
4012 template <bool X, typename T, typename F>
4013 using type = typename cond<X, T, F>::type;
4016 using f^oo = type<true, int, double>;
4021 auto AST = TU.build();
4022 auto H =
getHover(
AST, T.point(), format::getLLVMStyle(),
nullptr);
4024 ASSERT_TRUE(H && H->Type);
4025 EXPECT_EQ(H->Type->Type,
"int");
4026 EXPECT_EQ(H->Definition,
"using foo = type<true, int, double>");
4029TEST(Hover, EvaluateMacros) {
4030 llvm::StringRef PredefinedCXX = R
"cpp(
4032#define SizeOf sizeof
4033#define AlignOf alignof
4037using u64 = unsigned long long;
4038// calculate (a ** b) % p
4039constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
4043 ret = (ret * a) % p;
4049#define last_n_digit(x, y, n) \
4050 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))
4051#define declare_struct(X, name, value) \
4053 constexpr auto name() { return value; } \
4055#define gnu_statement_expression(value) \
4057 declare_struct(Widget, getter, value); \
4058 Widget().getter(); \
4060#define define_lambda_begin(lambda, ...) \
4062#define define_lambda_end() }
4064#define left_bracket [
4065#define right_bracket ]
4066#define dg_left_bracket <:
4067#define dg_right_bracket :>
4068#define array_decl(type, name, size) type name left_bracket size right_bracket
4072 llvm::StringRef
Code;
4073 const std::function<void(std::optional<HoverInfo>,
size_t )>
4081 [](std::optional<HoverInfo> HI, size_t) {
4082 EXPECT_EQ(HI->Value,
"42 (0x2a)");
4083 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"int"));
4091 [](std::optional<HoverInfo> HI, size_t) {
4092 EXPECT_TRUE(HI->Value);
4093 EXPECT_TRUE(HI->Type);
4108 [](std::optional<HoverInfo> HI, size_t) {
4109 EXPECT_TRUE(HI->Value);
4110 EXPECT_TRUE(HI->Type);
4115 // 2**32 == 4294967296
4116 last_n_di^git(2, 32, 6);
4119 [](std::optional<HoverInfo> HI, size_t) {
4120 EXPECT_EQ(HI->Value,
"967296 (0xec280)");
4121 EXPECT_EQ(HI->Type,
"u64");
4126 gnu_statement_exp^ression(42);
4129 [](std::optional<HoverInfo> HI, size_t) {
4130 EXPECT_EQ(HI->Value,
"42 (0x2a)");
4131 EXPECT_EQ(HI->Type,
"int");
4139 [](std::optional<HoverInfo> HI, size_t) {
4140 EXPECT_EQ(HI->Value,
"2");
4141 EXPECT_EQ(HI->Type,
"int");
4149 [](std::optional<HoverInfo> HI, size_t) {
4150 EXPECT_FALSE(HI->Value) << HI->Value;
4151 EXPECT_FALSE(HI->Type) << HI->Type;
4159 [](std::optional<HoverInfo> HI, size_t) {
4160 EXPECT_EQ(HI->Value,
"2");
4161 EXPECT_EQ(HI->Type,
"int");
4166 arra^y_decl(int, vector, 10);
4167 vector left_b^racket 3 right_b^racket;
4168 vector dg_le^ft_bracket 3 dg_righ^t_bracket;
4171 [](std::optional<HoverInfo> HI,
size_t Id) {
4174 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"int[10]"));
4180 EXPECT_FALSE(HI->Type) << HI->Type;
4181 EXPECT_FALSE(HI->Value) << HI->Value;
4184 ASSERT_TRUE(
false) <<
"Unhandled id: " <<
Id;
4190 constexpr auto value = define_lamb^da_begin(lambda, int, char)
4191 // Check if the expansion range is right.
4192 return ^last_n_digit(10, 3, 3)^;
4193 define_lam^bda_end();
4196 [](std::optional<HoverInfo> HI,
size_t Id) {
4199 EXPECT_FALSE(HI->Value);
4200 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"const (lambda)"));
4203 EXPECT_EQ(HI->Value,
"0");
4204 EXPECT_EQ(HI->Type, HoverInfo::PrintedType(
"u64"));
4210 EXPECT_FALSE(HI->Type) << HI->Type;
4211 EXPECT_FALSE(HI->Value) << HI->Value;
4214 ASSERT_TRUE(
false) <<
"Unhandled id: " <<
Id;
4222 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
4223 for (
const auto &
C : Cases) {
4225 (PredefinedCXX +
"void function() {\n" +
C.Code +
"}\n").str());
4227 TU.ExtraArgs.push_back(
"-std=c++17");
4228 auto AST = TU.build();
4229 for (
auto [Index, Position] : llvm::enumerate(
Code.points())) {
4230 C.Validator(
getHover(
AST, Position, format::getLLVMStyle(),
nullptr),
4236 #define alignof _Alignof
4238 al^ignof(struct { int x; char y[10]; });
4243 TU.Filename =
"TestTU.c";
4247 auto AST = TU.build();
4248 auto H =
getHover(
AST,
C.point(), format::getLLVMStyle(),
nullptr);
4251 EXPECT_TRUE(H->Value);
4252 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)