18#include "clang/AST/Attr.h"
19#include "clang/Format/Format.h"
20#include "clang/Index/IndexSymbol.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/ADT/Twine.h"
24#include "gtest/gtest.h"
36std::string guard(llvm::StringRef Code) {
37 return "#pragma once\n" + Code.str();
42 const char *
const Code;
43 const std::function<void(
HoverInfo &)> ExpectedBuilder;
51 HI.NamespaceScope = "";
53 HI.Kind = index::SymbolKind::Function;
54 HI.Documentation =
"Best foo ever.";
55 HI.Definition =
"void foo()";
56 HI.ReturnType =
"void";
58 HI.Parameters.emplace();
62 void [[fo^o]](auto x) {}
65 HI.NamespaceScope = "";
67 HI.Kind = index::SymbolKind::Function;
68 HI.Documentation =
"Best foo ever.";
69 HI.Definition =
"void foo(auto x)";
70 HI.ReturnType =
"void";
71 HI.Type =
"void (auto)";
72 HI.TemplateParameters = {
73 {{
"class"}, std::string(
"x:auto"), std::nullopt},
76 {{
"auto"}, std::string(
"x"), std::nullopt},
85 HI.NamespaceScope = "";
87 HI.Kind = index::SymbolKind::Function;
88 HI.Documentation =
"Best foo ever.";
89 HI.Definition =
"template <class T> void foo(T x)";
90 HI.ReturnType =
"void";
92 HI.TemplateParameters = {
93 {{
"class"}, std::string(
"T"), std::nullopt},
96 {{
"T"}, std::string(
"x"), std::nullopt},
102 void [[fo^o]](T x, auto y) {}
105 HI.NamespaceScope = "";
107 HI.Kind = index::SymbolKind::Function;
108 HI.Documentation =
"Best foo ever.";
109 HI.Definition =
"template <class T> void foo(T x, auto y)";
110 HI.ReturnType =
"void";
111 HI.Type =
"void (T, auto)";
112 HI.TemplateParameters = {
113 {{
"class"}, std::string(
"T"), std::nullopt},
114 {{
"class"}, std::string(
"y:auto"), std::nullopt},
117 {{
"T"}, std::string(
"x"), std::nullopt},
118 {{
"auto"}, std::string(
"y"), std::nullopt},
122 template<typename T1, typename T2>
123 concept C = requires () { true; };
127 void [[fo^o]](T x) {}
130 HI.NamespaceScope = "";
132 HI.Kind = index::SymbolKind::Function;
133 HI.Documentation =
"Best foo ever.";
134 HI.Definition =
"template <C<int> T> void foo(T x)";
135 HI.ReturnType =
"void";
136 HI.Type =
"void (T)";
137 HI.TemplateParameters = {
138 {{
"class"}, std::string(
"T"), std::nullopt},
141 {{
"T"}, std::string(
"x"), std::nullopt},
145 template<typename T1, typename T2>
146 concept C = requires () { true; };
149 void [[fo^o]](C<int> auto x) {}
152 HI.NamespaceScope = "";
154 HI.Kind = index::SymbolKind::Function;
155 HI.Documentation =
"Best foo ever.";
156 HI.Definition =
"void foo(C<int> auto x)";
157 HI.ReturnType =
"void";
158 HI.Type =
"void (C<int> auto)";
159 HI.TemplateParameters = {
160 {{
"class"}, std::string(
"x:auto"), std::nullopt},
163 {{
"C<int> auto"}, std::string(
"x"), std::nullopt},
167 template<typename T1, typename T2>
168 concept C = requires () { true; };
172 void [[fo^o]](T x, C<int> auto y) {}
175 HI.NamespaceScope = "";
177 HI.Kind = index::SymbolKind::Function;
178 HI.Documentation =
"Best foo ever.";
179 HI.Definition =
"template <C<int> T> void foo(T x, C<int> auto y)";
180 HI.ReturnType =
"void";
181 HI.Type =
"void (T, C<int> auto)";
182 HI.TemplateParameters = {
183 {{
"class"}, std::string(
"T"), std::nullopt},
184 {{
"class"}, std::string(
"y:auto"), std::nullopt},
187 {{
"T"}, std::string(
"x"), std::nullopt},
188 {{
"C<int> auto"}, std::string(
"y"), std::nullopt},
193 namespace ns1 { namespace ns2 {
199 HI.NamespaceScope =
"ns1::ns2::";
201 HI.Kind = index::SymbolKind::Function;
202 HI.Documentation =
"Best foo ever.";
203 HI.Definition =
"void foo()";
204 HI.ReturnType =
"void";
206 HI.Parameters.emplace();
210 namespace ns1 { namespace ns2 {
218 HI.NamespaceScope = "ns1::ns2::";
219 HI.LocalScope =
"Foo::";
221 HI.Kind = index::SymbolKind::Field;
222 HI.Definition =
"char bar";
228 HI.AccessSpecifier =
"private";
238 HI.NamespaceScope = "";
239 HI.LocalScope =
"Foo::";
241 HI.Kind = index::SymbolKind::Field;
242 HI.Definition =
"char bar";
247 HI.AccessSpecifier =
"public";
257 HI.NamespaceScope = "";
258 HI.LocalScope =
"Foo::";
260 HI.Kind = index::SymbolKind::Field;
261 HI.Definition =
"int x : 1";
266 HI.AccessSpecifier =
"public";
270 namespace ns1 { namespace ns2 {
279 HI.NamespaceScope = "ns1::ns2::";
280 HI.LocalScope =
"Foo::foo::";
282 HI.Kind = index::SymbolKind::Variable;
283 HI.Definition =
"int bar";
293 HI.Name = "__func__";
294 HI.Kind = index::SymbolKind::Variable;
296 "Name of the current function (predefined variable)";
297 HI.Value =
"\"foo\"";
298 HI.Type =
"const char[4]";
302 template<int> void foo() {
307 HI.Name = "__func__";
308 HI.Kind = index::SymbolKind::Variable;
310 "Name of the current function (predefined variable)";
311 HI.Type =
"const char[]";
315 namespace ns1 { namespace {
322 HI.NamespaceScope = "ns1::";
323 HI.LocalScope =
"(anonymous struct)::";
325 HI.Kind = index::SymbolKind::Field;
326 HI.Definition =
"char bar";
331 HI.AccessSpecifier =
"public";
338 HI.NamespaceScope = "";
340 HI.Kind = index::SymbolKind::Struct;
341 HI.Definition =
"struct X {}";
347 template <typename T, class... Ts> class Foo { public: Foo(int); };
348 Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
351 HI.NamespaceScope = "";
353 HI.Kind = index::SymbolKind::Variable;
354 HI.Definition =
"Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
355 HI.Type =
"Foo<int, char, bool>";
359 template <typename T> class vector{};
360 [[vec^tor]]<int> foo;
363 HI.NamespaceScope = "";
364 HI.Name =
"vector<int>";
365 HI.Kind = index::SymbolKind::Class;
366 HI.Definition =
"template <> class vector<int> {}";
370 template <template<typename, bool...> class C,
374 class... Ts> class Foo final {};
375 template <template<typename, bool...> class T>
379 HI.NamespaceScope = "";
381 HI.Kind = index::SymbolKind::Class;
383 R
"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
384 bool Q = false, class... Ts>
385class Foo final {})cpp";
386 HI.TemplateParameters = {
387 {{"template <typename, bool...> class"},
390 {{
"typename"}, std::nullopt, std::string(
"char")},
391 {{
"int"}, std::nullopt, std::string(
"0")},
392 {{
"bool"}, std::string(
"Q"), std::string(
"false")},
393 {{
"class..."}, std::string(
"Ts"), std::nullopt},
398 template <template<typename, bool...> class C,
402 class... Ts> void foo();
403 template<typename, bool...> class Foo;
410 HI.NamespaceScope = "";
412 HI.Kind = index::SymbolKind::Function;
413 HI.Definition =
"template <> void foo<Foo, char, 0, false, <>>()";
414 HI.ReturnType =
"void";
416 HI.Parameters.emplace();
420 template<typename, bool...> class Foo {};
421 Foo<bool, true, false> foo(int, bool T = false);
428 HI.NamespaceScope = "";
430 HI.Kind = index::SymbolKind::Function;
431 HI.Definition =
"Foo<bool, true, false> foo(int, bool T = false)";
432 HI.ReturnType =
"Foo<bool, true, false>";
433 HI.Type =
"Foo<bool, true, false> (int, bool)";
435 {{
"int"}, std::nullopt, std::nullopt},
436 {{
"bool"}, std::string(
"T"), std::string(
"false")},
442 auto lamb = [](int T, bool B) -> bool { return T && B; };
448 HI.NamespaceScope = "";
449 HI.LocalScope =
"foo::";
451 HI.Kind = index::SymbolKind::Variable;
452 HI.Definition =
"auto *c = &b";
453 HI.Type =
"(lambda) **";
454 HI.ReturnType =
"bool";
456 {{
"int"}, std::string(
"T"), std::nullopt},
457 {{
"bool"}, std::string(
"B"), std::nullopt},
463 auto lamb = [](int T, bool B) -> bool { return T && B; };
464 void foo(decltype(lamb)& bar) {
469 HI.NamespaceScope = "";
470 HI.LocalScope =
"foo::";
472 HI.Kind = index::SymbolKind::Parameter;
473 HI.Definition =
"decltype(lamb) &bar";
474 HI.Type =
"(lambda) &";
475 HI.ReturnType =
"bool";
477 {{
"int"}, std::string(
"T"), std::nullopt},
478 {{
"bool"}, std::string(
"B"), std::nullopt},
484 auto lamb = [](int T, bool B) -> bool { return T && B; };
485 void foo(decltype(lamb) bar) {
490 HI.NamespaceScope = "";
491 HI.LocalScope =
"foo::";
493 HI.Kind = index::SymbolKind::Parameter;
494 HI.Definition =
"decltype(lamb) bar";
495 HI.Type =
"class (lambda)";
496 HI.ReturnType =
"bool";
498 {{
"int"}, std::string(
"T"), std::nullopt},
499 {{
"bool"}, std::string(
"B"), std::nullopt},
508 auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
509 bool res = [[lam^b]](bar, false);
513 HI.NamespaceScope = "";
514 HI.LocalScope =
"foo::";
516 HI.Kind = index::SymbolKind::Variable;
517 HI.Definition =
"auto lamb = [&bar](int T, bool B) -> bool {}";
518 HI.Type =
"class (lambda)";
519 HI.ReturnType =
"bool";
521 {{
"int"}, std::string(
"T"), std::nullopt},
522 {{
"bool"}, std::string(
"B"), std::nullopt},
529 auto lamb = []{int [[te^st]];};
533 HI.NamespaceScope = "";
534 HI.LocalScope =
"foo::(anonymous class)::operator()::";
536 HI.Kind = index::SymbolKind::Variable;
537 HI.Definition =
"int test";
542 template <typename T> class X;
543 template <typename T> class [[^X]]<T*> {};
547 HI.NamespaceScope =
"";
548 HI.Kind = index::SymbolKind::Class;
549 HI.Definition =
"template <typename T> class X<T *> {}";
553 template<typename, typename=void> struct X;
554 template<typename T> struct X<T*>{ [[^X]](); };
557 HI.NamespaceScope = "";
559 HI.LocalScope =
"X<T *>::";
560 HI.Kind = index::SymbolKind::Constructor;
561 HI.Definition =
"X()";
562 HI.Parameters.emplace();
563 HI.AccessSpecifier =
"public";
565 {
"class X { [[^~]]X(); };",
567 HI.NamespaceScope =
"";
569 HI.LocalScope =
"X::";
570 HI.Kind = index::SymbolKind::Destructor;
571 HI.Definition =
"~X()";
572 HI.Parameters.emplace();
573 HI.AccessSpecifier =
"private";
575 {
"class X { [[op^erator]] int(); };",
577 HI.NamespaceScope =
"";
578 HI.Name =
"operator int";
579 HI.LocalScope =
"X::";
580 HI.Kind = index::SymbolKind::ConversionFunction;
581 HI.Definition =
"operator int()";
582 HI.Parameters.emplace();
583 HI.AccessSpecifier =
"private";
585 {
"class X { operator [[^X]](); };",
587 HI.NamespaceScope =
"";
589 HI.Kind = index::SymbolKind::Class;
590 HI.Definition =
"class X {}";
596 struct S { int x; float y; };
597 [[au^to]] [x, y] = S();
602 HI.Kind = index::SymbolKind::TypeAlias;
614 HI.Kind = index::SymbolKind::TypeAlias;
619 template <class T> concept F = true;
624 HI.Kind = index::SymbolKind::TypeAlias;
625 HI.Definition =
"int";
628 template <class T> concept F = true;
632 HI.NamespaceScope = "";
634 HI.Kind = index::SymbolKind::Concept;
635 HI.Definition =
"template <class T>\nconcept F = true";
640 [[au^to]] lamb = []{};
645 HI.Kind = index::SymbolKind::TypeAlias;
646 HI.Definition =
"class(lambda)";
650 template<typename T> class Foo{};
652 [[au^to]] x = Foo<int>();
657 HI.Kind = index::SymbolKind::TypeAlias;
658 HI.Definition =
"Foo<int>";
662 template<typename T> class Foo{};
663 template<> class Foo<int>{};
665 [[au^to]] x = Foo<int>();
670 HI.Kind = index::SymbolKind::TypeAlias;
671 HI.Definition =
"Foo<int>";
675 template<class T> concept Fooable = true;
676 template<[[Foo^able]] T>
680 HI.NamespaceScope = "";
682 HI.Kind = index::SymbolKind::Concept;
683 HI.Definition =
"template <class T>\nconcept Fooable = true";
686 template<class T> concept Fooable = true;
687 template<Fooable [[T^T]]>
693 HI.AccessSpecifier =
"public";
694 HI.NamespaceScope =
"";
695 HI.LocalScope =
"bar::";
696 HI.Kind = index::SymbolKind::TemplateTypeParm;
697 HI.Definition =
"Fooable TT";
700 template<class T> concept Fooable = true;
701 void bar([[Foo^able]] auto t) {}
704 HI.NamespaceScope = "";
706 HI.Kind = index::SymbolKind::Concept;
707 HI.Definition =
"template <class T>\nconcept Fooable = true";
711 template<class T> concept Fooable = true;
712 auto X = [[Fooa^ble]]<int>;
715 HI.NamespaceScope = "";
717 HI.Kind = index::SymbolKind::Concept;
718 HI.Definition =
"template <class T>\nconcept Fooable = true";
729 HI.Kind = index::SymbolKind::Macro;
730 HI.Definition =
"#define MACRO";
740 HI.Kind = index::SymbolKind::Macro;
741 HI.Value =
"41 (0x29)";
743 HI.Definition =
"#define MACRO 41\n\n"
751 #define MACRO(x,y,z) void foo(x, y, z)
752 [[MAC^RO]](int, double d, bool z = false);
756 HI.Kind = index::SymbolKind::Macro;
757 HI.Definition =
"#define MACRO(x, y, z) void foo(x, y, z)\n\n"
759 "void foo(int, double d, bool z = false)";
764 #define STRINGIFY_AUX(s) #s
765 #define STRINGIFY(s) STRINGIFY_AUX(s)
766 #define DECL_STR(NAME, VALUE) const char *v_##NAME = STRINGIFY(VALUE)
769 [[DECL^_STR]](foo, FOO);
772 HI.Name = "DECL_STR";
773 HI.Kind = index::SymbolKind::Macro;
775 HI.Definition =
"#define DECL_STR(NAME, VALUE) const char *v_##NAME = "
776 "STRINGIFY(VALUE)\n\n"
778 "const char *v_foo = \"41\"";
783 constexpr int add(int a, int b) { return a + b; }
784 int [[b^ar]] = add(1, 2);
788 HI.Definition =
"int bar = add(1, 2)";
789 HI.Kind = index::SymbolKind::Variable;
791 HI.NamespaceScope =
"";
795 int [[b^ar]] = sizeof(char);
799 HI.Definition =
"int bar = sizeof(char)";
800 HI.Kind = index::SymbolKind::Variable;
802 HI.NamespaceScope =
"";
806 template<int a, int b> struct Add {
807 static constexpr int result = a + b;
809 int [[ba^r]] = Add<1, 2>::result;
813 HI.Definition =
"int bar = Add<1, 2>::result";
814 HI.Kind = index::SymbolKind::Variable;
816 HI.NamespaceScope =
"";
820 enum Color { RED = -123, GREEN = 5, };
821 Color x = [[GR^EEN]];
825 HI.NamespaceScope =
"";
826 HI.LocalScope =
"Color::";
827 HI.Definition =
"GREEN = 5";
828 HI.Kind = index::SymbolKind::EnumConstant;
829 HI.Type =
"enum Color";
833 enum Color { RED = -123, GREEN = 5, };
839 HI.NamespaceScope =
"";
840 HI.Definition =
"Color x = RED";
841 HI.Kind = index::SymbolKind::Variable;
843 HI.Value =
"RED (0xffffff85)";
846 template<int a, int b> struct Add {
847 static constexpr int result = a + b;
849 int bar = Add<1, 2>::[[resu^lt]];
853 HI.Definition =
"static constexpr int result = a + b";
854 HI.Kind = index::SymbolKind::StaticProperty;
855 HI.Type =
"const int";
856 HI.NamespaceScope =
"";
857 HI.LocalScope =
"Add<1, 2>::";
859 HI.AccessSpecifier =
"public";
863 constexpr my_int answer() { return 40 + 2; }
864 int x = [[ans^wer]]();
868 HI.Definition =
"constexpr my_int answer()";
869 HI.Kind = index::SymbolKind::Function;
870 HI.Type = {
"my_int ()",
"int ()"};
871 HI.ReturnType = {
"my_int",
"int"};
872 HI.Parameters.emplace();
873 HI.NamespaceScope =
"";
874 HI.Value =
"42 (0x2a)";
877 const char *[[ba^r]] = "1234";
881 HI.Definition =
"const char *bar = \"1234\"";
882 HI.Kind = index::SymbolKind::Variable;
883 HI.Type =
"const char *";
884 HI.NamespaceScope =
"";
885 HI.Value =
"&\"1234\"[0]";
887 {R
"cpp(// Should not crash
888 template <typename T>
893 template <typename A>
894 void boom(int name) {
895 new Tmpl<A>([[na^me]]);
899 HI.Definition =
"int name";
900 HI.Kind = index::SymbolKind::Parameter;
902 HI.NamespaceScope =
"";
903 HI.LocalScope =
"boom::";
906 R
"cpp(// Should not print inline or anon namespaces.
908 inline namespace in_ns {
912 inline namespace in_ns2 {
921 ns::a::b::[[F^oo]] x;
927 HI.Kind = index::SymbolKind::Class;
928 HI.NamespaceScope =
"ns::a::b::";
929 HI.Definition =
"class Foo {}";
933 template <typename T> class Foo {};
936 [[^auto]] x = Foo<X>();
941 HI.Kind = index::SymbolKind::TypeAlias;
942 HI.Definition =
"Foo<X>";
946 // comment from primary
947 template <typename T> class Foo {};
948 // comment from specialization
949 template <typename T> class Foo<T*> {};
951 [[Fo^o]]<int*> *x = nullptr;
955 HI.Name = "Foo<int *>";
956 HI.Kind = index::SymbolKind::Class;
957 HI.NamespaceScope =
"";
958 HI.Definition =
"template <> class Foo<int *>";
961 HI.Documentation =
"comment from primary";
965 template <typename [[^T]] = int> void foo();
969 HI.Kind = index::SymbolKind::TemplateTypeParm;
970 HI.NamespaceScope =
"";
971 HI.Definition =
"typename T = int";
972 HI.LocalScope =
"foo::";
973 HI.Type =
"typename";
974 HI.AccessSpecifier =
"public";
978 template <template<typename> class [[^T]]> void foo();
982 HI.Kind = index::SymbolKind::TemplateTemplateParm;
983 HI.NamespaceScope =
"";
984 HI.Definition =
"template <typename> class T";
985 HI.LocalScope =
"foo::";
986 HI.Type =
"template <typename> class";
987 HI.AccessSpecifier =
"public";
991 template <int [[^T]] = 5> void foo();
995 HI.Kind = index::SymbolKind::NonTypeTemplateParm;
996 HI.NamespaceScope =
"";
997 HI.Definition =
"int T = 5";
998 HI.LocalScope =
"foo::";
1000 HI.AccessSpecifier =
"public";
1005 struct X { int Y; float [[^y]]() { return Y; } };
1009 HI.Kind = index::SymbolKind::InstanceMethod;
1010 HI.NamespaceScope =
"";
1011 HI.Definition =
"float y()";
1012 HI.LocalScope =
"X::";
1013 HI.Documentation =
"Trivial accessor for `Y`.";
1014 HI.Type =
"float ()";
1015 HI.ReturnType =
"float";
1016 HI.Parameters.emplace();
1017 HI.AccessSpecifier =
"public";
1024 float [[^y]]() { return Y; }
1029 HI.Kind = index::SymbolKind::InstanceMethod;
1030 HI.NamespaceScope =
"";
1031 HI.Definition =
"float y()";
1032 HI.LocalScope =
"X::";
1033 HI.Documentation =
"Trivial accessor for `Y`.\n\nAn int named Y";
1034 HI.Type =
"float ()";
1035 HI.ReturnType =
"float";
1036 HI.Parameters.emplace();
1037 HI.AccessSpecifier =
"public";
1041 struct X { int Y; void [[^setY]](float v) { Y = v; } };
1045 HI.Kind = index::SymbolKind::InstanceMethod;
1046 HI.NamespaceScope =
"";
1047 HI.Definition =
"void setY(float v)";
1048 HI.LocalScope =
"X::";
1049 HI.Documentation =
"Trivial setter for `Y`.";
1050 HI.Type =
"void (float)";
1051 HI.ReturnType =
"void";
1052 HI.Parameters.emplace();
1053 HI.Parameters->emplace_back();
1054 HI.Parameters->back().Type =
"float";
1055 HI.Parameters->back().Name =
"v";
1056 HI.AccessSpecifier =
"public";
1060 struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };
1064 HI.Kind = index::SymbolKind::InstanceMethod;
1065 HI.NamespaceScope =
"";
1066 HI.Definition =
"X &setY(float v)";
1067 HI.LocalScope =
"X::";
1068 HI.Documentation =
"Trivial setter for `Y`.";
1069 HI.Type =
"X &(float)";
1070 HI.ReturnType =
"X &";
1071 HI.Parameters.emplace();
1072 HI.Parameters->emplace_back();
1073 HI.Parameters->back().Type =
"float";
1074 HI.Parameters->back().Name =
"v";
1075 HI.AccessSpecifier =
"public";
1079 namespace std { template<typename T> T&& move(T&& t); }
1080 struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } };
1084 HI.Kind = index::SymbolKind::InstanceMethod;
1085 HI.NamespaceScope =
"";
1086 HI.Definition =
"void setY(float v)";
1087 HI.LocalScope =
"X::";
1088 HI.Documentation =
"Trivial setter for `Y`.";
1089 HI.Type =
"void (float)";
1090 HI.ReturnType =
"void";
1091 HI.Parameters.emplace();
1092 HI.Parameters->emplace_back();
1093 HI.Parameters->back().Type =
"float";
1094 HI.Parameters->back().Name =
"v";
1095 HI.AccessSpecifier =
"public";
1102 void [[^setY]](float v) { Y = v; }
1107 HI.Kind = index::SymbolKind::InstanceMethod;
1108 HI.NamespaceScope =
"";
1109 HI.Definition =
"void setY(float v)";
1110 HI.LocalScope =
"X::";
1111 HI.Documentation =
"Trivial setter for `Y`.\n\nAn int named Y";
1112 HI.Type =
"void (float)";
1113 HI.ReturnType =
"void";
1114 HI.Parameters.emplace();
1115 HI.Parameters->emplace_back();
1116 HI.Parameters->back().Type =
"float";
1117 HI.Parameters->back().Name =
"v";
1118 HI.AccessSpecifier =
"public";
1122 struct X { int x = 2; };
1127 HI.Kind = index::SymbolKind::Variable;
1128 HI.NamespaceScope =
"";
1129 HI.Definition =
"X x";
1133 R
"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
1136 HI.Kind = index::SymbolKind::Variable;
1137 HI.NamespaceScope =
"";
1139 HI.Type =
"NULL TYPE";
1141 HI.AccessSpecifier =
"public";
1145 Unknown [[^abc]] = invalid;
1150 HI.Kind = index::SymbolKind::Variable;
1151 HI.NamespaceScope =
"";
1152 HI.Definition =
"int abc";
1154 HI.AccessSpecifier =
"public";
1158 void fun(int arg_a, int &arg_b) {};
1166 HI.Kind = index::SymbolKind::Variable;
1167 HI.NamespaceScope =
"";
1168 HI.Definition =
"int b = 2";
1169 HI.LocalScope =
"code::";
1172 HI.CalleeArgInfo.emplace();
1173 HI.CalleeArgInfo->Name =
"arg_b";
1174 HI.CalleeArgInfo->Type =
"int &";
1180 explicit Foo(int arg_a) {}
1182 template<class T, class... Args>
1183 T make(Args&&... args)
1190 auto foo = make<Foo>([[^a]]);
1195 HI.Kind = index::SymbolKind::Variable;
1196 HI.NamespaceScope =
"";
1197 HI.Definition =
"int a = 1";
1198 HI.LocalScope =
"code::";
1201 HI.CalleeArgInfo.emplace();
1202 HI.CalleeArgInfo->Name =
"arg_a";
1203 HI.CalleeArgInfo->Type =
"int";
1208 void foobar(const float &arg);
1216 HI.Kind = index::SymbolKind::Variable;
1217 HI.NamespaceScope =
"";
1218 HI.Definition =
"int a = 0";
1219 HI.LocalScope =
"main::";
1222 HI.CalleeArgInfo.emplace();
1223 HI.CalleeArgInfo->Name =
"arg";
1224 HI.CalleeArgInfo->Type =
"const float &";
1230 explicit Foo(const float& arg) {}
1239 HI.Kind = index::SymbolKind::Variable;
1240 HI.NamespaceScope =
"";
1241 HI.Definition =
"int a = 0";
1242 HI.LocalScope =
"main::";
1245 HI.CalleeArgInfo.emplace();
1246 HI.CalleeArgInfo->Name =
"arg";
1247 HI.CalleeArgInfo->Type =
"const float &";
1252 void fun(int arg_a, const int &arg_b) {};
1259 HI.Name = "literal";
1260 HI.Kind = index::SymbolKind::Unknown;
1261 HI.CalleeArgInfo.emplace();
1262 HI.CalleeArgInfo->Name =
"arg_b";
1263 HI.CalleeArgInfo->Type =
"const int &";
1268 void fun(int arg_a, const int &arg_b) {};
1275 HI.Name = "expression";
1276 HI.Kind = index::SymbolKind::Unknown;
1279 HI.CalleeArgInfo.emplace();
1280 HI.CalleeArgInfo->Name =
"arg_b";
1281 HI.CalleeArgInfo->Type =
"const int &";
1286 int add(int lhs, int rhs);
1292 HI.Name = "expression";
1293 HI.Kind = index::SymbolKind::Unknown;
1296 HI.CalleeArgInfo.emplace();
1297 HI.CalleeArgInfo->Name =
"lhs";
1298 HI.CalleeArgInfo->Type =
"int";
1303 void foobar(const float &arg);
1309 HI.Name = "literal";
1310 HI.Kind = index::SymbolKind::Unknown;
1311 HI.CalleeArgInfo.emplace();
1312 HI.CalleeArgInfo->Name =
"arg";
1313 HI.CalleeArgInfo->Type =
"const float &";
1320 void fun(int arg_a = 3, int arg_b = 4) {}
1330 HI.Kind = index::SymbolKind::Variable;
1331 HI.NamespaceScope =
"";
1332 HI.Definition =
"int a = 1";
1333 HI.LocalScope =
"code::";
1336 HI.CalleeArgInfo.emplace();
1337 HI.CalleeArgInfo->Name =
"arg_a";
1338 HI.CalleeArgInfo->Type =
"int";
1339 HI.CalleeArgInfo->Default =
"3";
1355 HI.Kind = index::SymbolKind::Variable;
1356 HI.NamespaceScope =
"";
1357 HI.Definition =
"const int x = 0";
1358 HI.LocalScope =
"bar::";
1360 HI.Type =
"const int";
1361 HI.CalleeArgInfo.emplace();
1362 HI.CalleeArgInfo->Type =
"Foo";
1373 HI.Kind = index::SymbolKind::Field;
1374 HI.NamespaceScope =
"";
1375 HI.Definition =
"int xx";
1376 HI.LocalScope =
"Foo::";
1378 HI.AccessSpecifier =
"public";
1388 HI.Kind = index::SymbolKind::Field;
1389 HI.NamespaceScope =
"";
1390 HI.Definition =
"int yy";
1391 HI.LocalScope =
"Foo::";
1393 HI.AccessSpecifier =
"public";
1400 constexpr Foo k2 = {
1401 ^[[{]]1} // FIXME: why the hover range is 1 character?
1405 HI.Name = "expression";
1406 HI.Kind = index::SymbolKind::Unknown;
1407 HI.Type =
"int[10]";
1414 template <int Size> m_int ^[[arr]][Size];
1418 HI.Kind = index::SymbolKind::Variable;
1419 HI.Type = {
"m_int[Size]",
"int[Size]"};
1420 HI.NamespaceScope =
"";
1421 HI.Definition =
"template <int Size> m_int arr[Size]";
1422 HI.TemplateParameters = {{{
"int"}, {
"Size"}, std::nullopt}};
1428 template <int Size> m_int arr[Size];
1430 template <> m_int ^[[arr]]<4>[4];
1434 HI.Kind = index::SymbolKind::Variable;
1435 HI.Type = {
"m_int[4]",
"int[4]"};
1436 HI.NamespaceScope =
"";
1437 HI.Definition =
"m_int arr[4]";
1441 template<typename T>
1447 TestHover<int>::Type ^[[a]];
1452 HI.NamespaceScope =
"";
1453 HI.LocalScope =
"code::";
1454 HI.Definition =
"TestHover<int>::Type a";
1455 HI.Kind = index::SymbolKind::Variable;
1456 HI.Type = {
"TestHover<int>::Type",
"int"};
1460 template<typename T>
1461 void ^[[foo]](T arg) {}
1465 HI.Kind = index::SymbolKind::Function;
1466 HI.NamespaceScope =
"";
1467 HI.Definition =
"template <typename T> void foo(T arg)";
1468 HI.Type =
"void (T)";
1469 HI.ReturnType =
"void";
1470 HI.Parameters = {{{
"T"}, std::string(
"arg"), std::nullopt}};
1471 HI.TemplateParameters = {
1472 {{
"typename"}, std::string(
"T"), std::nullopt}};
1476 template<typename T>
1477 using ^[[alias]] = T;
1481 HI.NamespaceScope =
"";
1483 HI.Kind = index::SymbolKind::TypeAlias;
1484 HI.Definition =
"template <typename T> using alias = T";
1486 HI.TemplateParameters = {
1487 {{
"typename"}, std::string(
"T"), std::nullopt}};
1491 template<typename T>
1494 template<typename T>
1495 using ^[[AA]] = A<T>;
1499 HI.NamespaceScope =
"";
1501 HI.Kind = index::SymbolKind::TypeAlias;
1502 HI.Definition =
"template <typename T> using AA = A<T>";
1503 HI.Type = {
"A<T>",
"T"};
1504 HI.TemplateParameters = {
1505 {{
"typename"}, std::string(
"T"), std::nullopt}};
1515 HI.NamespaceScope =
"";
1517 HI.Kind = index::SymbolKind::Variable;
1518 HI.Definition =
"m_int arr[10]";
1519 HI.Type = {
"m_int[10]",
"int[10]"};
1525 extern m_int ^[[arr]][];
1529 HI.NamespaceScope =
"";
1531 HI.Kind = index::SymbolKind::Variable;
1532 HI.Definition =
"extern m_int arr[]";
1533 HI.Type = {
"m_int[]",
"int[]"};
1541 m_int ^[[arr]][Size];
1546 HI.NamespaceScope =
"";
1547 HI.LocalScope =
"Test<Size>::";
1548 HI.AccessSpecifier =
"public";
1549 HI.Kind = index::SymbolKind::Field;
1550 HI.Definition =
"m_int arr[Size]";
1551 HI.Type = {
"m_int[Size]",
"int[Size]"};
1562 HI.NamespaceScope = "";
1563 HI.LocalScope =
"Foo::";
1565 HI.Kind = index::SymbolKind::Field;
1566 HI.Definition =
"char y : 1";
1572 HI.AccessSpecifier =
"public";
1574 for (
const auto &Case : Cases) {
1575 SCOPED_TRACE(Case.Code);
1579 TU.ExtraArgs.push_back(
"-std=c++20");
1582 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
1583 auto AST = TU.build();
1588 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1592 Case.ExpectedBuilder(Expected);
1594 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
1595 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
1596 EXPECT_EQ(H->Name, Expected.Name);
1597 EXPECT_EQ(H->Kind, Expected.Kind);
1598 EXPECT_EQ(H->Documentation, Expected.Documentation);
1599 EXPECT_EQ(H->Definition, Expected.Definition);
1600 EXPECT_EQ(H->Type, Expected.Type);
1601 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
1602 EXPECT_EQ(H->Parameters, Expected.Parameters);
1603 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
1604 EXPECT_EQ(H->SymRange, Expected.SymRange);
1605 EXPECT_EQ(H->Value, Expected.Value);
1606 EXPECT_EQ(H->Size, Expected.Size);
1607 EXPECT_EQ(H->Offset, Expected.Offset);
1608 EXPECT_EQ(H->Align, Expected.Align);
1609 EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier);
1610 EXPECT_EQ(H->CalleeArgInfo, Expected.CalleeArgInfo);
1611 EXPECT_EQ(H->CallPassType, Expected.CallPassType);
1617 const char *
const Code;
1618 const std::string ClangLanguageFlag;
1619 const char *
const ExpectedDefinitionLanguage;
1620 } Cases[] = {{R
"cpp(
1621 void [[some^Global]]() {}
1625 void [[some^Global]]() {}
1627 "-xobjective-c++",
"objective-cpp"},
1629 void [[some^Global]]() {}
1631 "-xobjective-c",
"objective-c"}};
1632 for (
const auto &Case : Cases) {
1633 SCOPED_TRACE(Case.Code);
1637 if (!Case.ClangLanguageFlag.empty())
1638 TU.ExtraArgs.push_back(Case.ClangLanguageFlag);
1639 auto AST = TU.build();
1641 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1644 EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage);
1649 const llvm::StringRef CodePrefix = R
"cpp(
1651class Derived : public Base {};
1655 CustomClass(const Base &x) {}
1656 CustomClass(int &x) {}
1657 CustomClass(float x) {}
1658 CustomClass(int x, int y) {}
1661void int_by_ref(int &x) {}
1662void int_by_const_ref(const int &x) {}
1663void int_by_value(int x) {}
1664void base_by_ref(Base &x) {}
1665void base_by_const_ref(const Base &x) {}
1666void base_by_value(Base x) {}
1667void float_by_value(float x) {}
1668void custom_by_value(CustomClass x) {}
1672 int &int_ref = int_x;
1673 const int &int_const_ref = int_x;
1675 const Base &base_const_ref = base;
1679 const llvm::StringRef CodeSuffix =
"}";
1682 const char *
const Code;
1687 {
"int_by_value([[^int_x]]);", PassMode::Value,
false},
1688 {
"int_by_value([[^123]]);", PassMode::Value,
false},
1689 {
"int_by_ref([[^int_x]]);", PassMode::Ref,
false},
1690 {
"int_by_const_ref([[^int_x]]);", PassMode::ConstRef,
false},
1691 {
"int_by_const_ref([[^123]]);", PassMode::ConstRef,
false},
1692 {
"int_by_value([[^int_ref]]);", PassMode::Value,
false},
1693 {
"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef,
false},
1694 {
"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef,
false},
1695 {
"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef,
false},
1697 {
"base_by_ref([[^base]]);", PassMode::Ref,
false},
1698 {
"base_by_const_ref([[^base]]);", PassMode::ConstRef,
false},
1699 {
"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef,
false},
1700 {
"base_by_value([[^base]]);", PassMode::Value,
false},
1701 {
"base_by_value([[^base_const_ref]]);", PassMode::Value,
false},
1702 {
"base_by_ref([[^derived]]);", PassMode::Ref,
false},
1703 {
"base_by_const_ref([[^derived]]);", PassMode::ConstRef,
false},
1704 {
"base_by_value([[^derived]]);", PassMode::Value,
false},
1706 {
"CustomClass c1([[^base]]);", PassMode::ConstRef,
false},
1707 {
"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef,
false},
1708 {
"CustomClass c3([[^int_x]]);", PassMode::Ref,
false},
1709 {
"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value,
false},
1711 {
"float_by_value([[^int_x]]);", PassMode::Value,
true},
1712 {
"float_by_value([[^int_ref]]);", PassMode::Value,
true},
1713 {
"float_by_value([[^int_const_ref]]);", PassMode::Value,
true},
1714 {
"float_by_value([[^123.0f]]);", PassMode::Value,
false},
1715 {
"float_by_value([[^123]]);", PassMode::Value,
true},
1716 {
"custom_by_value([[^int_x]]);", PassMode::Ref,
true},
1717 {
"custom_by_value([[^float_x]]);", PassMode::Value,
true},
1718 {
"custom_by_value([[^base]]);", PassMode::ConstRef,
true},
1720 for (
const auto &Test : Tests) {
1721 SCOPED_TRACE(Test.Code);
1723 const auto Code = (CodePrefix + Test.Code + CodeSuffix).str();
1726 TU.ExtraArgs.push_back(
"-std=c++17");
1727 auto AST = TU.build();
1728 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1730 EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy);
1731 EXPECT_EQ(H->CallPassType->Converted, Test.Converted);
1736 llvm::StringRef Tests[] = {
1740 "decltype(au^to) x = 0;",
1742 R
"cpp(// Lambda auto parameter
1743 auto lamb = [](a^uto){};
1745 R"cpp(// non-named decls don't get hover. Don't crash!
1746 ^static_assert(1, "");
1748 R"cpp(// non-evaluatable expr
1749 template <typename T> void foo() {
1750 (void)[[size^of]](T);
1752 R"cpp(// should not crash on invalid semantic form of init-list-expr.
1758 constexpr Foo s = ^{
1764 "auto x = ^(int){42};",
1768 "auto x = ^nullptr;",
1771 for (
const auto &Test : Tests) {
1776 TU.ExtraArgs.push_back(
"-std=c++17");
1777 auto AST = TU.build();
1778 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1785 struct Foo { int x; };
1786 int y = __builtin_o^ffsetof(Foo, x);
1789 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
1791 EXPECT_EQ(H->Name,
"expression");
1792 EXPECT_EQ(H->Kind, index::SymbolKind::Unknown);
1797 const char *
const Code;
1798 const std::function<void(
HoverInfo &)> ExpectedBuilder;
1800 {
"auto x = [['^A']]; // character literal",
1802 HI.Name =
"expression";
1804 HI.Value =
"65 (0x41)";
1806 {
"auto s = ^[[\"Hello, world!\"]]; // string literal",
1808 HI.Name =
"string-literal";
1810 HI.Type =
"const char[14]";
1813 R
"cpp(// Local variable
1817 int test1 = bonjour;
1821 HI.Name = "bonjour";
1822 HI.Kind = index::SymbolKind::Variable;
1823 HI.NamespaceScope =
"";
1824 HI.LocalScope =
"main::";
1826 HI.Definition =
"int bonjour";
1829 R
"cpp(// Local variable in method
1838 HI.Name = "bonjour";
1839 HI.Kind = index::SymbolKind::Variable;
1840 HI.NamespaceScope =
"";
1841 HI.LocalScope =
"s::method::";
1843 HI.Definition =
"int bonjour";
1851 ns1::[[My^Class]]* Params;
1855 HI.Name = "MyClass";
1856 HI.Kind = index::SymbolKind::Struct;
1857 HI.NamespaceScope =
"ns1::";
1858 HI.Definition =
"struct MyClass {}";
1866 ns1::[[My^Class]]* Params;
1870 HI.Name = "MyClass";
1871 HI.Kind = index::SymbolKind::Class;
1872 HI.NamespaceScope =
"ns1::";
1873 HI.Definition =
"class MyClass {}";
1878 union MyUnion { int x; int y; };
1881 ns1::[[My^Union]] Params;
1885 HI.Name = "MyUnion";
1886 HI.Kind = index::SymbolKind::Union;
1887 HI.NamespaceScope =
"ns1::";
1888 HI.Definition =
"union MyUnion {}";
1891 R
"cpp(// Function definition via pointer
1894 auto *X = &^[[foo]];
1899 HI.Kind = index::SymbolKind::Function;
1900 HI.NamespaceScope =
"";
1901 HI.Type =
"void (int)";
1902 HI.Definition =
"void foo(int)";
1903 HI.Documentation =
"Function definition via pointer";
1904 HI.ReturnType =
"void";
1906 {{
"int"}, std::nullopt, std::nullopt},
1910 R
"cpp(// Function declaration via call
1913 return ^[[foo]](42);
1918 HI.Kind = index::SymbolKind::Function;
1919 HI.NamespaceScope =
"";
1920 HI.Type =
"int (int)";
1921 HI.Definition =
"int foo(int)";
1922 HI.Documentation =
"Function declaration via call";
1923 HI.ReturnType =
"int";
1925 {{
"int"}, std::nullopt, std::nullopt},
1930 struct Foo { int x; };
1938 HI.Kind = index::SymbolKind::Field;
1939 HI.NamespaceScope =
"";
1940 HI.LocalScope =
"Foo::";
1942 HI.Definition =
"int x";
1945 R
"cpp(// Field with initialization
1946 struct Foo { int x = 5; };
1954 HI.Kind = index::SymbolKind::Field;
1955 HI.NamespaceScope =
"";
1956 HI.LocalScope =
"Foo::";
1958 HI.Definition =
"int x = 5";
1961 R
"cpp(// Static field
1962 struct Foo { static int x; };
1969 HI.Kind = index::SymbolKind::StaticProperty;
1970 HI.NamespaceScope =
"";
1971 HI.LocalScope =
"Foo::";
1973 HI.Definition =
"static int x";
1976 R
"cpp(// Field, member initializer
1979 Foo() : ^[[x]](0) {}
1984 HI.Kind = index::SymbolKind::Field;
1985 HI.NamespaceScope =
"";
1986 HI.LocalScope =
"Foo::";
1988 HI.Definition =
"int x";
1991 R
"cpp(// Field, GNU old-style field designator
1992 struct Foo { int x; };
1994 Foo bar = { ^[[x]] : 1 };
1999 HI.Kind = index::SymbolKind::Field;
2000 HI.NamespaceScope =
"";
2001 HI.LocalScope =
"Foo::";
2003 HI.Definition =
"int x";
2008 R
"cpp(// Field, field designator
2009 struct Foo { int x; int y; };
2011 Foo bar = { .^[[x]] = 2, .y = 2 };
2016 HI.Kind = index::SymbolKind::Field;
2017 HI.NamespaceScope =
"";
2018 HI.LocalScope =
"Foo::";
2020 HI.Definition =
"int x";
2023 R
"cpp(// Field, offsetof
2024 struct Foo { int x; int y; };
2025 int z = __builtin_offsetof(Foo, ^[[x]]);
2029 HI.Kind = index::SymbolKind::Field;
2030 HI.NamespaceScope =
"";
2031 HI.LocalScope =
"Foo::";
2033 HI.Definition =
"int x";
2037 R
"cpp(// Outer field, nested offsetof designator
2038 struct Inner { int c; };
2039 struct A { Inner B; };
2040 int z = __builtin_offsetof(A, ^[[B]].c);
2044 HI.Kind = index::SymbolKind::Field;
2045 HI.NamespaceScope =
"";
2046 HI.LocalScope =
"A::";
2048 HI.Definition =
"Inner B";
2052 R
"cpp(// Inner field, nested offsetof designator
2053 struct Inner { int c; };
2054 struct A { Inner B; };
2055 int z = __builtin_offsetof(A, B.^[[c]]);
2059 HI.Kind = index::SymbolKind::Field;
2060 HI.NamespaceScope =
"";
2061 HI.LocalScope =
"Inner::";
2063 HI.Definition =
"int c";
2067 R
"cpp(// Method call
2068 struct Foo { int x(); };
2076 HI.Kind = index::SymbolKind::InstanceMethod;
2077 HI.NamespaceScope =
"";
2078 HI.LocalScope =
"Foo::";
2080 HI.Definition =
"int x()";
2081 HI.ReturnType =
"int";
2082 HI.Parameters = std::vector<HoverInfo::Param>{};
2085 R
"cpp(// Static method call
2086 struct Foo { static int x(); };
2093 HI.Kind = index::SymbolKind::StaticMethod;
2094 HI.NamespaceScope =
"";
2095 HI.LocalScope =
"Foo::";
2097 HI.Definition =
"static int x()";
2098 HI.ReturnType =
"int";
2099 HI.Parameters = std::vector<HoverInfo::Param>{};
2110 HI.Kind = index::SymbolKind::TypeAlias;
2111 HI.NamespaceScope =
"";
2112 HI.Definition =
"typedef int Foo";
2114 HI.Documentation =
"Typedef";
2117 R
"cpp(// Typedef with embedded definition
2118 typedef struct Bar {} Foo;
2125 HI.Kind = index::SymbolKind::TypeAlias;
2126 HI.NamespaceScope =
"";
2127 HI.Definition =
"typedef struct Bar Foo";
2128 HI.Type =
"struct Bar";
2129 HI.Documentation =
"Typedef with embedded definition";
2134 struct Foo { static void bar(); };
2136 int main() { ^[[ns]]::Foo::bar(); }
2140 HI.Kind = index::SymbolKind::Namespace;
2141 HI.NamespaceScope =
"";
2142 HI.Definition =
"namespace ns {}";
2145 R
"cpp(// Anonymous namespace
2149 } // anonymous namespace
2151 int main() { ns::[[f^oo]]++; }
2155 HI.Kind = index::SymbolKind::Variable;
2156 HI.NamespaceScope =
"ns::";
2158 HI.Definition =
"int foo";
2161 R
"cpp(// Function definition via using declaration
2172 HI.Kind = index::SymbolKind::Function;
2173 HI.NamespaceScope =
"ns::";
2174 HI.Type =
"void ()";
2175 HI.Definition =
"void foo()";
2176 HI.Documentation =
"";
2177 HI.ReturnType =
"void";
2178 HI.Parameters = std::vector<HoverInfo::Param>{};
2181 R
"cpp( // using declaration and two possible function declarations
2182 namespace ns { void foo(int); void foo(char); }
2184 template <typename T> void bar() { [[f^oo]](T{}); }
2188 HI.Kind = index::SymbolKind::Using;
2189 HI.NamespaceScope =
"";
2190 HI.Definition =
"using ns::foo";
2195 int main() { return ^[[MACRO]]; }
2201 HI.Kind = index::SymbolKind::Macro;
2202 HI.Definition =
"#define MACRO 0\n\n"
2209 #define MACRO2 ^[[MACRO]]
2213 HI.Kind = index::SymbolKind::Macro;
2214 HI.Definition =
"#define MACRO 0";
2223 int main() ^[[MACRO]]
2227 HI.Kind = index::SymbolKind::Macro;
2229 R
"cpp(#define MACRO \
2240 R"cpp(// Forward class declaration
2247 HI.Kind = index::SymbolKind::Class;
2248 HI.NamespaceScope =
"";
2249 HI.Definition =
"class Foo {}";
2250 HI.Documentation =
"Forward class declaration";
2253 R
"cpp(// Function declaration
2255 void g() { [[f^oo]](); }
2260 HI.Kind = index::SymbolKind::Function;
2261 HI.NamespaceScope =
"";
2262 HI.Type =
"void ()";
2263 HI.Definition =
"void foo()";
2264 HI.Documentation =
"Function declaration";
2265 HI.ReturnType =
"void";
2266 HI.Parameters = std::vector<HoverInfo::Param>{};
2269 R
"cpp(// Enum declaration
2274 [[Hel^lo]] hello = ONE;
2279 HI.Kind = index::SymbolKind::Enum;
2280 HI.NamespaceScope =
"";
2281 HI.Definition =
"enum Hello {}";
2282 HI.Documentation =
"Enum declaration";
2290 Hello hello = [[O^NE]];
2295 HI.Kind = index::SymbolKind::EnumConstant;
2296 HI.NamespaceScope =
"";
2297 HI.LocalScope =
"Hello::";
2298 HI.Type =
"enum Hello";
2299 HI.Definition =
"ONE";
2303 R
"cpp(// C++20's using enum
2309 Hello hello = [[O^NE]];
2314 HI.Kind = index::SymbolKind::EnumConstant;
2315 HI.NamespaceScope =
"";
2316 HI.LocalScope =
"Hello::";
2317 HI.Type =
"enum Hello";
2318 HI.Definition =
"ONE";
2322 R
"cpp(// Enumerator in anonymous enum
2327 int hello = [[O^NE]];
2332 HI.Kind = index::SymbolKind::EnumConstant;
2333 HI.NamespaceScope =
"";
2336 HI.Type =
"enum (unnamed)";
2337 HI.Definition =
"ONE";
2341 R
"cpp(// Global variable
2342 static int hey = 10;
2349 HI.Kind = index::SymbolKind::Variable;
2350 HI.NamespaceScope =
"";
2352 HI.Definition =
"static int hey = 10";
2353 HI.Documentation =
"Global variable";
2355 HI.Value =
"10 (0xa)";
2358 R
"cpp(// Global variable in namespace
2360 static long long hey = -36637162602497;
2368 HI.Kind = index::SymbolKind::Variable;
2369 HI.NamespaceScope =
"ns1::";
2370 HI.Type =
"long long";
2371 HI.Definition =
"static long long hey = -36637162602497";
2372 HI.Value =
"-36637162602497 (0xffffdeadbeefffff)";
2375 R
"cpp(// Field in anonymous struct
2385 HI.Kind = index::SymbolKind::Field;
2386 HI.NamespaceScope =
"";
2387 HI.LocalScope =
"(anonymous struct)::";
2389 HI.Definition =
"int hello";
2392 R
"cpp(// Templated function
2393 template <typename T>
2397 void g() { auto x = [[f^oo]]<int>(); }
2401 HI.Kind = index::SymbolKind::Function;
2402 HI.NamespaceScope =
"";
2404 HI.Definition =
"template <> int foo<int>()";
2405 HI.Documentation =
"Templated function";
2406 HI.ReturnType =
"int";
2407 HI.Parameters = std::vector<HoverInfo::Param>{};
2412 R
"cpp(// Anonymous union
2418 void g() { struct outer o; o.v.[[d^ef]]++; }
2422 HI.Kind = index::SymbolKind::Field;
2423 HI.NamespaceScope =
"";
2424 HI.LocalScope =
"outer::(anonymous union)::";
2426 HI.Definition =
"int def";
2429 R
"cpp(// documentation from index
2430 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
2432 void g() { [[ind^exSymbol]](); }
2435 HI.Name = "indexSymbol";
2436 HI.Kind = index::SymbolKind::Function;
2437 HI.NamespaceScope =
"";
2438 HI.Type =
"void ()";
2439 HI.Definition =
"void indexSymbol()";
2440 HI.ReturnType =
"void";
2441 HI.Parameters = std::vector<HoverInfo::Param>{};
2442 HI.Documentation =
"comment from index";
2445 R
"cpp(// Simple initialization with auto
2452 HI.Kind = index::SymbolKind::TypeAlias;
2453 HI.Definition =
"int";
2456 R
"cpp(// Simple initialization with const auto
2458 const ^[[auto]] i = 1;
2463 HI.Kind = index::SymbolKind::TypeAlias;
2464 HI.Definition =
"int";
2467 R
"cpp(// Simple initialization with const auto&
2469 const ^[[auto]]& i = 1;
2474 HI.Kind = index::SymbolKind::TypeAlias;
2475 HI.Definition =
"int";
2478 R
"cpp(// Simple initialization with auto&
2486 HI.Kind = index::SymbolKind::TypeAlias;
2487 HI.Definition =
"int";
2490 R
"cpp(// Simple initialization with auto*
2498 HI.Kind = index::SymbolKind::TypeAlias;
2499 HI.Definition =
"int";
2502 R
"cpp(// Simple initialization with auto from pointer
2510 HI.Kind = index::SymbolKind::TypeAlias;
2511 HI.Definition =
"int *";
2514 R
"cpp(// Auto with initializer list.
2518 class initializer_list { const _E *a, *b; };
2521 ^[[auto]] i = {1,2};
2526 HI.Kind = index::SymbolKind::TypeAlias;
2527 HI.Definition =
"std::initializer_list<int>";
2530 R
"cpp(// User defined conversion to auto
2532 operator ^[[auto]]() const { return 10; }
2537 HI.Kind = index::SymbolKind::TypeAlias;
2538 HI.Definition =
"int";
2541 R
"cpp(// Simple initialization with decltype(auto)
2543 ^[[decltype]](auto) i = 1;
2547 HI.Name = "decltype";
2548 HI.Kind = index::SymbolKind::TypeAlias;
2549 HI.Definition =
"int";
2552 R
"cpp(// Simple initialization with const decltype(auto)
2555 ^[[decltype]](auto) i = j;
2559 HI.Name = "decltype";
2560 HI.Kind = index::SymbolKind::TypeAlias;
2561 HI.Definition =
"const int";
2564 R
"cpp(// Simple initialization with const& decltype(auto)
2568 ^[[decltype]](auto) i = j;
2572 HI.Name = "decltype";
2573 HI.Kind = index::SymbolKind::TypeAlias;
2574 HI.Definition =
"const int &";
2577 R
"cpp(// Simple initialization with & decltype(auto)
2581 ^[[decltype]](auto) i = j;
2585 HI.Name = "decltype";
2586 HI.Kind = index::SymbolKind::TypeAlias;
2587 HI.Definition =
"int &";
2590 R
"cpp(// simple trailing return type
2591 ^[[auto]] main() -> int {
2597 HI.Kind = index::SymbolKind::TypeAlias;
2598 HI.Definition =
"int";
2601 R
"cpp(// auto function return with trailing type
2603 ^[[auto]] test() -> decltype(Bar()) {
2609 HI.Kind = index::SymbolKind::TypeAlias;
2610 HI.Definition =
"Bar";
2611 HI.Documentation =
"auto function return with trailing type";
2614 R
"cpp(// trailing return type
2616 auto test() -> ^[[decltype]](Bar()) {
2621 HI.Name = "decltype";
2622 HI.Kind = index::SymbolKind::TypeAlias;
2623 HI.Definition =
"Bar";
2624 HI.Documentation =
"trailing return type";
2627 R
"cpp(// auto in function return
2635 HI.Kind = index::SymbolKind::TypeAlias;
2636 HI.Definition =
"Bar";
2637 HI.Documentation =
"auto in function return";
2640 R
"cpp(// auto& in function return
2649 HI.Kind = index::SymbolKind::TypeAlias;
2650 HI.Definition =
"Bar";
2651 HI.Documentation =
"auto& in function return";
2654 R
"cpp(// auto* in function return
2663 HI.Kind = index::SymbolKind::TypeAlias;
2664 HI.Definition =
"Bar";
2665 HI.Documentation =
"auto* in function return";
2668 R
"cpp(// const auto& in function return
2670 const ^[[auto]]& test() {
2677 HI.Kind = index::SymbolKind::TypeAlias;
2678 HI.Definition =
"Bar";
2679 HI.Documentation =
"const auto& in function return";
2682 R
"cpp(// decltype(auto) in function return
2684 ^[[decltype]](auto) test() {
2689 HI.Name = "decltype";
2690 HI.Kind = index::SymbolKind::TypeAlias;
2691 HI.Definition =
"Bar";
2692 HI.Documentation =
"decltype(auto) in function return";
2695 R
"cpp(// decltype(auto) reference in function return
2696 ^[[decltype]](auto) test() {
2702 HI.Name = "decltype";
2703 HI.Kind = index::SymbolKind::TypeAlias;
2704 HI.Definition =
"int &";
2707 R
"cpp(// decltype lvalue reference
2710 ^[[decltype]](I) J = I;
2714 HI.Name = "decltype";
2715 HI.Kind = index::SymbolKind::TypeAlias;
2716 HI.Definition =
"int";
2719 R
"cpp(// decltype lvalue reference
2723 ^[[decltype]](K) J = I;
2727 HI.Name = "decltype";
2728 HI.Kind = index::SymbolKind::TypeAlias;
2729 HI.Definition =
"int &";
2732 R
"cpp(// decltype lvalue reference parenthesis
2735 ^[[decltype]]((I)) J = I;
2739 HI.Name = "decltype";
2740 HI.Kind = index::SymbolKind::TypeAlias;
2741 HI.Definition =
"int &";
2744 R
"cpp(// decltype rvalue reference
2747 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
2751 HI.Name = "decltype";
2752 HI.Kind = index::SymbolKind::TypeAlias;
2753 HI.Definition =
"int &&";
2756 R
"cpp(// decltype rvalue reference function call
2760 ^[[decltype]](bar()) J = bar();
2764 HI.Name = "decltype";
2765 HI.Kind = index::SymbolKind::TypeAlias;
2766 HI.Definition =
"int &&";
2769 R
"cpp(// decltype of function with trailing return type.
2771 auto test() -> decltype(Bar()) {
2775 ^[[decltype]](test()) i = test();
2779 HI.Name = "decltype";
2780 HI.Kind = index::SymbolKind::TypeAlias;
2781 HI.Definition =
"Bar";
2783 "decltype of function with trailing return type.";
2786 R
"cpp(// decltype of var with decltype.
2790 ^[[decltype]](J) K = J;
2794 HI.Name = "decltype";
2795 HI.Kind = index::SymbolKind::TypeAlias;
2796 HI.Definition =
"int";
2799 R
"cpp(// decltype of dependent type
2800 template <typename T>
2802 using Y = ^[[decltype]](T::Z);
2806 HI.Name = "decltype";
2807 HI.Kind = index::SymbolKind::TypeAlias;
2808 HI.Definition =
"<dependent type>";
2811 R
"cpp(// More complicated structured types.
2813 ^[[auto]] (*foo)() = bar;
2817 HI.Kind = index::SymbolKind::TypeAlias;
2818 HI.Definition =
"int";
2821 R
"cpp(// Should not crash when evaluating the initializer.
2823 void test() { Test && [[te^st]] = {}; }
2827 HI.Kind = index::SymbolKind::Variable;
2828 HI.NamespaceScope =
"";
2829 HI.LocalScope =
"test::";
2830 HI.Type =
"Test &&";
2831 HI.Definition =
"Test &&test = {}";
2834 R
"cpp(// Shouldn't crash when evaluating the initializer.
2835 struct Bar {}; // error-ok
2836 struct Foo { void foo(Bar x = y); }
2837 void Foo::foo(Bar [[^x]]) {})cpp",
2840 HI.Kind = index::SymbolKind::Parameter;
2841 HI.NamespaceScope =
"";
2842 HI.LocalScope =
"Foo::foo::";
2844 HI.Definition =
"Bar x = <recovery - expr>()";
2847 R
"cpp(// auto on alias
2848 typedef int int_type;
2849 ^[[auto]] x = int_type();
2853 HI.Kind = index::SymbolKind::TypeAlias;
2854 HI.Definition =
"int_type // aka: int";
2857 R
"cpp(// auto on alias
2859 typedef cls cls_type;
2860 ^[[auto]] y = cls_type();
2864 HI.Kind = index::SymbolKind::TypeAlias;
2865 HI.Definition =
"cls_type // aka: cls";
2866 HI.Documentation =
"auto on alias";
2869 R
"cpp(// auto on alias
2872 ^[[auto]] z = templ<int>();
2876 HI.Kind = index::SymbolKind::TypeAlias;
2877 HI.Definition =
"templ<int>";
2878 HI.Documentation =
"auto on alias";
2881 R
"cpp(// Undeduced auto declaration
2882 template<typename T>
2889 HI.Kind = index::SymbolKind::TypeAlias;
2890 HI.Definition =
"T";
2893 R
"cpp(// Undeduced auto return type
2894 template<typename T>
2901 HI.Kind = index::SymbolKind::TypeAlias;
2902 HI.Definition =
"/* not deduced */";
2905 R
"cpp(// Template auto parameter
2906 template<[[a^uto]] T>
2914 HI.Kind = index::SymbolKind::TypeAlias;
2915 HI.Definition =
"/* not deduced */";
2918 R
"cpp(// Undeduced decltype(auto) return type
2919 template<typename T>
2920 ^[[decltype]](auto) foo() {
2925 HI.Name = "decltype";
2926 HI.Kind = index::SymbolKind::TypeAlias;
2927 HI.Definition =
"/* not deduced */";
2930 R
"cpp(// should not crash.
2931 template <class T> struct cls {
2935 auto test = cls<int>().[[m^ethod]]();
2938 HI.Definition = "int method()";
2939 HI.Kind = index::SymbolKind::InstanceMethod;
2940 HI.NamespaceScope =
"";
2941 HI.LocalScope =
"cls<int>::";
2943 HI.Parameters.emplace();
2944 HI.ReturnType =
"int";
2948 R
"cpp(// type of nested templates.
2949 template <class T> struct cls {};
2950 cls<cls<cls<int>>> [[fo^o]];
2953 HI.Definition = "cls<cls<cls<int>>> foo";
2954 HI.Kind = index::SymbolKind::Variable;
2955 HI.NamespaceScope =
"";
2957 HI.Type =
"cls<cls<cls<int>>>";
2960 R
"cpp(// type of nested templates.
2961 template <class T> struct cls {};
2962 [[cl^s]]<cls<cls<int>>> foo;
2965 HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
2966 HI.Kind = index::SymbolKind::Struct;
2967 HI.NamespaceScope =
"";
2968 HI.Name =
"cls<cls<cls<int>>>";
2969 HI.Documentation =
"type of nested templates.";
2972 R
"cpp(// type with decltype
2974 decltype(a) [[b^]] = a;)cpp",
2976 HI.Definition = "decltype(a) b = a";
2977 HI.Kind = index::SymbolKind::Variable;
2978 HI.NamespaceScope =
"";
2983 R
"cpp(// type with decltype
2986 decltype(c) [[b^]] = a;)cpp",
2988 HI.Definition = "decltype(c) b = a";
2989 HI.Kind = index::SymbolKind::Variable;
2990 HI.NamespaceScope =
"";
2995 R
"cpp(// type with decltype
2997 const decltype(a) [[b^]] = a;)cpp",
2999 HI.Definition = "const decltype(a) b = a";
3000 HI.Kind = index::SymbolKind::Variable;
3001 HI.NamespaceScope =
"";
3003 HI.Type =
"const int";
3006 R
"cpp(// type with decltype
3008 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
3010 HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
3011 HI.Kind = index::SymbolKind::Function;
3012 HI.NamespaceScope =
"";
3014 HI.Type =
"auto (int) -> int";
3015 HI.ReturnType =
"int";
3016 HI.Parameters = {{{
"int"}, std::string(
"x"), std::nullopt}};
3019 R
"cpp(// sizeof expr
3021 (void)[[size^of]](char);
3024 HI.Name = "expression";
3025 HI.Type = {
"__size_t",
"unsigned long"};
3029 R
"cpp(// alignof expr
3031 (void)[[align^of]](char);
3034 HI.Name = "expression";
3035 HI.Type = {
"__size_t",
"unsigned long"};
3040 template <typename T = int>
3041 void foo(const T& = T()) {
3046 HI.Kind = index::SymbolKind::Function;
3047 HI.Type =
"void (const int &)";
3048 HI.ReturnType =
"void";
3050 {{
"const int &"}, std::nullopt, std::string(
"T()")}};
3051 HI.Definition =
"template <> void foo<int>(const int &)";
3052 HI.NamespaceScope =
"";
3055 R
"cpp(// should not crash
3063 HI.Kind = index::SymbolKind::Field;
3064 HI.LocalScope =
"ObjC::";
3065 HI.NamespaceScope =
"";
3066 HI.Definition =
"char data";
3072 @interface Interface
3073 @property(retain) [[MYOb^ject]] *x;
3077 HI.Name = "MYObject";
3078 HI.Kind = index::SymbolKind::Class;
3079 HI.NamespaceScope =
"";
3080 HI.Definition =
"@interface MYObject\n@end";
3086 @interface Interface
3087 - (void)doWith:([[MYOb^ject]] *)object;
3091 HI.Name = "MYObject";
3092 HI.Kind = index::SymbolKind::Class;
3093 HI.NamespaceScope =
"";
3094 HI.Definition =
"@interface MYObject\n@end";
3109 HI.Definition =
"ns::Foo *";
3112 R
"cpp(// this expr for template class
3114 template <typename T>
3124 HI.Definition =
"const ns::Foo<T> *";
3127 R
"cpp(// this expr for specialization class
3129 template <typename T> class Foo {};
3140 HI.Definition =
"ns::Foo<int> *";
3143 R
"cpp(// this expr for partial specialization struct
3145 template <typename T, typename F> struct Foo {};
3146 template <typename F>
3147 struct Foo<int, F> {
3156 HI.Definition =
"const ns::Foo<int, F> *";
3162 @interface MYObject (Private)
3163 @property(nonatomic, assign) int privateField;
3166 int someFunction() {
3167 MYObject *obj = [MYObject sharedInstance];
3168 return obj.[[private^Field]];
3172 HI.Name = "privateField";
3173 HI.Kind = index::SymbolKind::InstanceProperty;
3174 HI.LocalScope =
"MYObject(Private)::";
3175 HI.NamespaceScope =
"";
3176 HI.Definition =
"@property(nonatomic, assign, unsafe_unretained, "
3177 "readwrite) int privateField;";
3181 @protocol MYProtocol
3182 @property(nonatomic, assign) int prop1;
3185 int someFunction() {
3186 id<MYProtocol> obj = 0;
3187 return obj.[[pro^p1]];
3192 HI.Kind = index::SymbolKind::InstanceProperty;
3193 HI.LocalScope =
"MYProtocol::";
3194 HI.NamespaceScope =
"";
3195 HI.Definition =
"@property(nonatomic, assign, unsafe_unretained, "
3196 "readwrite) int prop1;";
3200 @protocol MYProtocol
3205 @interface MYObject (Ext) <[[MYProt^ocol]]>
3209 HI.Name = "MYProtocol";
3210 HI.Kind = index::SymbolKind::Protocol;
3211 HI.NamespaceScope =
"";
3212 HI.Definition =
"@protocol MYProtocol\n@end";
3218 @implementation Foo(Private)
3219 + (int)somePrivateMethod {
3220 int [[res^ult]] = 2;
3227 HI.Definition =
"int result = 2";
3228 HI.Kind = index::SymbolKind::Variable;
3230 HI.LocalScope =
"+[Foo(Private) somePrivateMethod]::";
3231 HI.NamespaceScope =
"";
3239 - (int)variadicArgMethod:(id)first, ... {
3240 int [[res^ult]] = 0;
3247 HI.Definition =
"int result = 0";
3248 HI.Kind = index::SymbolKind::Variable;
3250 HI.LocalScope =
"-[Foo variadicArgMethod:, ...]::";
3251 HI.NamespaceScope =
"";
3256 typedef struct MyRect {} MyRect;
3259 @property(nonatomic) MyRect frame;
3268 v.frame = [[foo^bar]]();
3273 HI.Kind = index::SymbolKind::Function;
3274 HI.NamespaceScope =
"";
3275 HI.Definition =
"MyRect foobar()";
3276 HI.Type = {
"MyRect ()",
"struct MyRect ()"};
3277 HI.ReturnType = {
"MyRect",
"struct MyRect"};
3278 HI.Parameters.emplace();
3281 void foo(int * __attribute__(([[non^null]], noescape)) );
3284 HI.Name = "nonnull";
3285 HI.Kind = index::SymbolKind::Unknown;
3286 HI.Definition =
"__attribute__((nonnull))";
3287 HI.Documentation = Attr::getDocumentation(attr::NonNull).str();
3292 struct strong_ordering {
3294 constexpr operator int() const { return n; }
3295 static const strong_ordering equal, greater, less;
3297 constexpr strong_ordering strong_ordering::equal = {0};
3298 constexpr strong_ordering strong_ordering::greater = {1};
3299 constexpr strong_ordering strong_ordering::less = {-1};
3306 auto operator<=>(const Foo&) const = default;
3309 bool x = Foo(1) [[!^=]] Foo(2);
3312 HI.Type = "bool (const Foo &) const noexcept";
3314 HI.Name =
"operator==";
3315 HI.Parameters = {{{
"const Foo &"}, std::nullopt, std::nullopt}};
3316 HI.ReturnType =
"bool";
3317 HI.Kind = index::SymbolKind::InstanceMethod;
3318 HI.LocalScope =
"Foo::";
3319 HI.NamespaceScope =
"";
3321 "bool operator==(const Foo &) const noexcept = default";
3322 HI.Documentation =
"";
3328 IndexSym.Documentation =
"comment from index";
3334 for (
const auto &Case : Cases) {
3335 SCOPED_TRACE(Case.Code);
3339 TU.ExtraArgs.push_back(
"-std=c++20");
3340 TU.ExtraArgs.push_back(
"-xobjective-c++");
3342 TU.ExtraArgs.push_back(
"-Wno-gnu-designator");
3345 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
3346 auto AST = TU.build();
3350 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(), Index.get());
3354 Case.ExpectedBuilder(Expected);
3357 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
3358 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
3359 EXPECT_EQ(H->Name, Expected.Name);
3360 EXPECT_EQ(H->Kind, Expected.Kind);
3361 EXPECT_EQ(H->Documentation, Expected.Documentation);
3362 EXPECT_EQ(H->Definition, Expected.Definition);
3363 EXPECT_EQ(H->Type, Expected.Type);
3364 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
3365 EXPECT_EQ(H->Parameters, Expected.Parameters);
3366 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
3367 EXPECT_EQ(H->SymRange, Expected.SymRange);
3368 EXPECT_EQ(H->Value, Expected.Value);
3375 const std::function<void(
HoverInfo &)> ExpectedBuilder;
3376 } Cases[] = {{R
"cpp(
3380 [](HoverInfo &HI) { HI.Provider = ""; }},
3385 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3390 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3395 [](HoverInfo &HI) { HI.Provider = ""; }},
3400 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3405 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3412 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3421 [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},
3424 using namespace fo^o;
3426 [](HoverInfo &HI) { HI.Provider = ""; }},
3429 for (
const auto &Case : Cases) {
3431 SCOPED_TRACE(Code.code());
3435 TU.Code = Code.code();
3436 TU.AdditionalFiles[
"foo.h"] = guard(R
"cpp(
3439 Foo& operator+(const Foo, const Foo);
3441 TU.AdditionalFiles["all.h"] = guard(
"#include \"foo.h\"");
3443 auto AST = TU.build();
3444 auto H =
getHover(
AST, Code.point(), format::getLLVMStyle(),
nullptr);
3447 Case.ExpectedBuilder(Expected);
3449 EXPECT_EQ(H->Provider, Expected.Provider);
3456 HIFoo.Provider =
"\"foo.h\"";
3459 HIFooBar.
Name =
"foo";
3460 HIFooBar.Provider =
"<bar.h>";
3463 llvm::StringRef ExpectedMarkdown;
3464 } Cases[] = {{HIFoo,
"### `foo`\n\nprovided by `\"foo.h\"`"},
3465 {HIFooBar,
"### `foo`\n\nprovided by `<bar.h>`"}};
3467 for (
const auto &Case : Cases)
3474 const std::function<void(
HoverInfo &)> ExpectedBuilder;
3475 } Cases[] = {{R
"cpp(
3477 int fstBar = bar1();
3478 int another= bar1(0);
3479 int sndBar = bar2();
3484 HI.UsedSymbolNames = {"BAR",
"Bar",
"bar1",
"bar2"};
3488 std::vector<int> vec;
3490 [](HoverInfo &HI) { HI.UsedSymbolNames = {"vector"}; }}};
3491 for (
const auto &Case : Cases) {
3493 SCOPED_TRACE(Code.code());
3497 TU.Code = Code.code();
3498 TU.AdditionalFiles[
"bar.h"] = guard(R
"cpp(
3505 TU.AdditionalFiles["system/vector"] = guard(R
"cpp(
3511 TU.ExtraArgs.push_back("-isystem" +
testPath(
"system"));
3513 auto AST = TU.build();
3514 auto H =
getHover(
AST, Code.point(), format::getLLVMStyle(),
nullptr);
3517 Case.ExpectedBuilder(Expected);
3519 EXPECT_EQ(H->UsedSymbolNames, Expected.UsedSymbolNames);
3525 template <typename T> class X {};
3533 auto AST = TU.build();
3536 IndexSym.Documentation =
"comment from index";
3542 for (
const auto &P :
T.points()) {
3543 auto H =
getHover(
AST, P, format::getLLVMStyle(), Index.get());
3545 EXPECT_EQ(H->Documentation, IndexSym.Documentation);
3552 template <typename T> class X {};
3554 template <typename T> void bar() {}
3556 template <typename T> T baz;
3561 au^to T = ba^z<X<int>>;
3566 auto AST = TU.build();
3567 for (
const auto &P :
T.points()) {
3568 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3570 EXPECT_EQ(H->Documentation,
"doc");
3577 template<typename T> T foo(T);
3579 // Setter variable heuristic might fail if the callexpr is broken.
3580 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");
3583 auto AST = TU.build();
3584 for (
const auto &P :
T.points())
3585 getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3590 constexpr unsigned long value = -1; // wrap around
3591 void foo() { va^lue; }
3594 getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3599 constexpr __int128_t value = -4;
3600 void foo() { va^lue; }
3604 TU.ExtraArgs.push_back(
"--target=x86_64-pc-linux-gnu");
3605 auto AST = TU.build();
3606 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
3608 EXPECT_EQ(H->Value,
"-4 (0xfffffffc)");
3614 template <typename T> class $doc1^X {};
3616 template <> class $doc2^X<int> {};
3618 template <typename T> class $doc3^X<T*> {};
3626 auto AST = TU.build();
3627 for (
const auto *Comment : {
"doc1",
"doc2",
"doc3"}) {
3628 for (
const auto &P :
T.points(Comment)) {
3629 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
3631 EXPECT_EQ(H->Documentation, Comment);
3638 const std::function<void(
HoverInfo &)> Builder;
3639 llvm::StringRef ExpectedMarkdownRender;
3640 llvm::StringRef ExpectedDoxygenRender;
3644 HI.Kind = index::SymbolKind::Unknown;
3652 HI.Kind = index::SymbolKind::NamespaceAlias;
3655 R
"(namespace-alias foo)",
3656 R"(### namespace-alias `foo`)",
3660 HI.Kind = index::SymbolKind::Class;
3662 HI.TemplateParameters = {
3663 {{"typename"}, std::string(
"T"), std::nullopt},
3664 {{
"typename"}, std::string(
"C"), std::string(
"bool")},
3666 HI.Documentation =
"documentation";
3668 "template <typename T, typename C = bool> class Foo {}";
3670 HI.NamespaceScope.emplace();
3678template <typename T, typename C = bool> class Foo {})",
3683template <typename T, typename C = bool> class Foo {}
3692### Template Parameters
3695- `typename C = bool`
3702 HI.Kind = index::SymbolKind::Function;
3704 HI.Type = {
"type",
"c_type"};
3705 HI.ReturnType = {
"ret_type",
"can_ret_type"};
3706 HI.Parameters.emplace();
3708 HI.Parameters->push_back(P);
3709 P.Type = {
"type",
"can_type"};
3710 HI.Parameters->push_back(P);
3712 HI.Parameters->push_back(P);
3713 P.Default =
"default";
3714 HI.Parameters->push_back(P);
3715 HI.NamespaceScope =
"ns::";
3716 HI.Definition =
"ret_type foo(params) {}";
3720 "→ ret_type (aka can_ret_type)\n\n"
3723 "- type (aka can_type)\n"
3724 "- type foo (aka can_type)\n"
3725 "- type foo = default (aka can_type)\n"
3727 "// In namespace ns\n"
3728 "ret_type foo(params) {}",
3734ret_type foo(params) {}
3741- `type (aka can_type)`
3742- `type foo (aka can_type)`
3743- `type foo = default (aka can_type)`
3748`ret_type (aka can_ret_type)`)",
3752 HI.Kind = index::SymbolKind::Field;
3753 HI.LocalScope = "test::Bar::";
3756 HI.Type = {
"type",
"can_type"};
3757 HI.Definition =
"def";
3765Type: type (aka can_type)
3771Size: 4 bytes (+4 bytes padding), alignment 4 bytes
3784Type: `type (aka can_type)`
3790Size: 4 bytes (+4 bytes padding), alignment 4 bytes)",
3794 HI.Kind = index::SymbolKind::Field;
3795 HI.LocalScope = "test::Bar::";
3798 HI.Type = {
"type",
"can_type"};
3799 HI.Definition =
"def";
3807Type: type (aka can_type)
3811Offset: 4 bytes and 3 bits
3813Size: 25 bits (+4 bits padding), alignment 8 bytes
3826Type: `type (aka can_type)`
3830Offset: 4 bytes and 3 bits
3832Size: 25 bits (+4 bits padding), alignment 8 bytes)",
3836 HI.Kind = index::SymbolKind::Field;
3837 HI.AccessSpecifier = "public";
3839 HI.LocalScope =
"test::Bar::";
3840 HI.Definition =
"def";
3856 HI.Definition = "size_t method()";
3857 HI.AccessSpecifier =
"protected";
3858 HI.Kind = index::SymbolKind::InstanceMethod;
3859 HI.NamespaceScope =
"";
3860 HI.LocalScope =
"cls<int>::";
3862 HI.Parameters.emplace();
3863 HI.ReturnType = {
"size_t",
"unsigned long"};
3864 HI.Type = {
"size_t ()",
"unsigned long ()"};
3866 R
"(instance-method method
3868→ size_t (aka unsigned long)
3871protected: size_t method())",
3872 R"(### instance-method
3877protected: size_t method()
3883`size_t (aka unsigned long)`)",
3887 HI.Definition = "cls(int a, int b = 5)";
3888 HI.AccessSpecifier =
"public";
3889 HI.Kind = index::SymbolKind::Constructor;
3890 HI.NamespaceScope =
"";
3891 HI.LocalScope =
"cls";
3893 HI.Parameters.emplace();
3894 HI.Parameters->emplace_back();
3895 HI.Parameters->back().Type =
"int";
3896 HI.Parameters->back().Name =
"a";
3897 HI.Parameters->emplace_back();
3898 HI.Parameters->back().Type =
"int";
3899 HI.Parameters->back().Name =
"b";
3900 HI.Parameters->back().Default =
"5";
3910public: cls(int a, int b = 5))",
3916public: cls(int a, int b = 5)
3927 HI.Kind = index::SymbolKind::Union;
3928 HI.AccessSpecifier = "private";
3930 HI.NamespaceScope =
"ns1::";
3931 HI.Definition =
"union foo {}";
3936private: union foo {})",
3942private: union foo {}
3947 HI.Kind = index::SymbolKind::Variable;
3949 HI.Definition =
"int foo = 3";
3950 HI.LocalScope =
"test::Bar::";
3953 HI.CalleeArgInfo.emplace();
3954 HI.CalleeArgInfo->Name =
"arg_a";
3955 HI.CalleeArgInfo->Type =
"int";
3956 HI.CalleeArgInfo->Default =
"7";
3986 HI.Kind = index::SymbolKind::Variable;
3988 HI.CalleeArgInfo.emplace();
3989 HI.CalleeArgInfo->Type =
"int";
3995 R"(### variable `foo`
4002 HI.Kind = index::SymbolKind::Variable;
4004 HI.Definition =
"int foo = 3";
4005 HI.LocalScope =
"test::Bar::";
4008 HI.CalleeArgInfo.emplace();
4009 HI.CalleeArgInfo->Name =
"arg_a";
4010 HI.CalleeArgInfo->Type =
"int";
4011 HI.CalleeArgInfo->Default =
"7";
4020Passed by reference as arg_a
4037Passed by reference as arg_a)",
4041 HI.Kind = index::SymbolKind::Variable;
4043 HI.Definition =
"int foo = 3";
4044 HI.LocalScope =
"test::Bar::";
4047 HI.CalleeArgInfo.emplace();
4048 HI.CalleeArgInfo->Name =
"arg_a";
4049 HI.CalleeArgInfo->Type = {
"alias_int",
"int"};
4050 HI.CalleeArgInfo->Default =
"7";
4059Passed as arg_a (converted to alias_int)
4076Passed as arg_a (converted to alias_int))",
4080 HI.Kind = index::SymbolKind::Macro;
4081 HI.Name = "PLUS_ONE";
4082 HI.Definition =
"#define PLUS_ONE(X) (X+1)\n\n"
4088#define PLUS_ONE(X) (X+1)
4096#define PLUS_ONE(X) (X+1)
4104 HI.Kind = index::SymbolKind::Variable;
4106 HI.Definition =
"int foo = 3";
4107 HI.LocalScope =
"test::Bar::";
4110 HI.CalleeArgInfo.emplace();
4111 HI.CalleeArgInfo->Name =
"arg_a";
4112 HI.CalleeArgInfo->Type =
"int";
4113 HI.CalleeArgInfo->Default =
"7";
4122Passed by const reference as arg_a (converted to int)
4139Passed by const reference as arg_a (converted to int))",
4143 HI.Name = "stdio.h";
4144 HI.Definition =
"/usr/include/stdio.h";
4145 HI.Kind = index::SymbolKind::IncludeDirective;
4149/usr/include/stdio.h)",
4152`/usr/include/stdio.h`)",
4157 HI.UsedSymbolNames = {
"Foo",
"Bar",
"Bar"};
4158 HI.Kind = index::SymbolKind::IncludeDirective;
4162provides Foo, Bar, Bar)",
4166provides `Foo`, `Bar`, `Bar`)",
4170 HI.UsedSymbolNames = {
"Foo",
"Bar",
"Baz",
"Foobar",
"Qux",
"Quux"};
4171 HI.Kind = index::SymbolKind::IncludeDirective;
4175provides Foo, Bar, Baz, Foobar, Qux and 1 more)",
4179provides `Foo`, `Bar`, `Baz`, `Foobar`, `Qux` and 1 more)"}};
4181 for (
const auto &C : Cases) {
4190 for (
const auto &C : Cases) {
4203 const std::function<void(
HoverInfo &)> Builder;
4204 llvm::StringRef ExpectedMarkdownRender;
4205 llvm::StringRef ExpectedDoxygenRender;
4208 HI.Kind = index::SymbolKind::Function;
4209 HI.Documentation =
"@brief brief doc\n\n"
4211 HI.Definition =
"void foo()";
4214 R
"(### function `foo`
4242 HI.Kind = index::SymbolKind::Function;
4243 HI.Documentation = "@brief brief doc\n\n"
4245 HI.Definition =
"int foo()";
4246 HI.ReturnType =
"int";
4249 R
"(### function `foo`
4284 HI.Kind = index::SymbolKind::Function;
4285 HI.Documentation = R"(@brief brief doc
4290As you see, notes are "inlined".
4291@warning this is a warning
4294@param a this is a param
4295@return it returns something
4296@retval 0 if successful
4297@retval 1 if failed)";
4298 HI.Definition = "int foo(int a)";
4299 HI.ReturnType =
"int";
4301 HI.Parameters.emplace();
4302 HI.Parameters->emplace_back();
4303 HI.Parameters->back().Type =
"int";
4304 HI.Parameters->back().Name =
"a";
4306 R
"(### function `foo`
4320As you see, notes are "inlined".
4321@warning this is a warning
4324@param a this is a param
4325@return it returns something
4326@retval 0 if successful
4348- `int a` - this is a param
4353`int` - it returns something
4355- `0` - if successful
4366As you see, notes are "inlined".
4371As well as warnings)"},
4373 HI.Kind = index::SymbolKind::Function;
4374 HI.Documentation = "@brief brief doc\n\n"
4375 "longer doc\n@param a this is a param\n@param b "
4376 "does not exist\n@return it returns something";
4377 HI.Definition =
"int foo(int a)";
4378 HI.ReturnType =
"int";
4380 HI.Parameters.emplace();
4381 HI.Parameters->emplace_back();
4382 HI.Parameters->back().Type =
"int";
4383 HI.Parameters->back().Name =
"a";
4385 R
"(### function `foo`
4397@param a this is a param
4398@param b does not exist
4399@return it returns something
4420- `int a` - this is a param
4425`int` - it returns something
4432 HI.Kind = index::SymbolKind::Function;
4433 HI.Documentation = "@brief brief doc\n"
4434 "@unknown command is treated as an inline command";
4435 HI.Definition =
"int foo(int a)";
4436 HI.ReturnType =
"int";
4438 HI.Parameters.emplace();
4439 HI.Parameters->emplace_back();
4440 HI.Parameters->back().Type =
"int";
4441 HI.Parameters->back().Name =
"a";
4443 R
"(### function `foo`
4453@unknown command is treated as an inline command
4470**@unknown** command is treated as an inline command
4483 for (
const auto &C : Cases) {
4492 for (
const auto &C : Cases) {
4505 llvm::StringRef Documentation;
4506 llvm::StringRef ExpectedRenderEscapedMarkdown;
4507 llvm::StringRef ExpectedRenderMarkdown;
4508 llvm::StringRef ExpectedRenderPlainText;
4618 "Tests primality of `p`.",
4619 "Tests primality of `p`.",
4620 "Tests primality of `p`.",
4621 "Tests primality of `p`.",
4624 "'`' should not occur in `Code`",
4625 "'\\`' should not occur in `Code`",
4626 "'`' should not occur in `Code`",
4627 "'`' should not occur in `Code`",
4636 R
"(@brief this is a typical use case
4640 R"(@brief this is a typical use case
4644 R"(@brief this is a typical use case
4648 R"(@brief this is a typical use case
4654 for (
const auto &C : Cases) {
4655 markup::Document Output;
4658 EXPECT_EQ(Output.asEscapedMarkdown(),
C.ExpectedRenderEscapedMarkdown);
4659 EXPECT_EQ(Output.asMarkdown(),
C.ExpectedRenderMarkdown);
4660 EXPECT_EQ(Output.asPlainText(),
C.ExpectedRenderPlainText);
4668 HI.
Kind = index::SymbolKind::Variable;
4678 HI.
Kind = index::SymbolKind::Variable;
4681 HI.Definition =
"def";
4683 llvm::StringRef ExpectedMarkdown =
4684 "### variable `foo`\n"
4695 llvm::StringRef ExpectedDoxygenMarkdown =
4710 llvm::StringRef ExpectedPlaintext = R
"pt(variable foo
4721 struct strong_ordering {
4723 constexpr operator int() const { return n; }
4724 static const strong_ordering equal, greater, less;
4726 constexpr strong_ordering strong_ordering::equal = {0};
4727 constexpr strong_ordering strong_ordering::greater = {1};
4728 constexpr strong_ordering strong_ordering::less = {-1};
4731 template <typename T>
4734 friend auto operator<=>(S, S) = default;
4736 static_assert(S<void>() =^= S<void>());
4740 TU.ExtraArgs.push_back("-std=c++20");
4741 auto AST = TU.build();
4742 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4743 EXPECT_EQ(HI->Documentation,
"");
4750 auto baz = (Fo^o*)&bar;
4754 auto AST = TU.build();
4755 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4757 EXPECT_EQ(*HI->Value,
"&bar");
4760TEST(
Hover, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls) {
4762 const char *
const Code;
4763 const std::optional<std::string> HoverValue;
4766 // error-ok testing behavior on invalid decl
4768 void foo(Foo p^aram = nullptr);
4773 void foo(Foo *p^aram = nullptr);
4778 for (
const auto &C : Cases) {
4781 auto AST = TU.build();
4782 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4784 ASSERT_EQ(HI->Value,
C.HoverValue);
4799 TU.ExtraArgs.push_back(
"-std=c++17");
4800 auto AST = TU.build();
4801 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4809 #define A(x) x, x, x, x
4810 #define B(x) A(A(A(A(x))))
4811 int a^rr[] = {B(0)};
4815 auto AST = TU.build();
4816 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4819 EXPECT_EQ(H->Definition,
"int arr[]");
4822#if defined(__aarch64__)
4824#define PREDEFINEMACROS_TEST(x) DISABLED_##x
4826#define PREDEFINEMACROS_TEST(x) x
4831 using uintptr_t = __UINTPTR_TYPE__;
4832 enum Test : uintptr_t {};
4833 unsigned global_var;
4835 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));
4840 TU.PredefineMacros = true;
4841 auto AST = TU.build();
4842 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4844 EXPECT_EQ(*HI->Value,
"&global_var");
4849 using uintptr_t = __UINTPTR_TYPE__;
4850 unsigned global_var;
4852 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);
4857 TU.PredefineMacros = true;
4858 auto AST = TU.build();
4859 auto HI =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4861 EXPECT_EQ(*HI->Value,
"&global_var");
4866 template <bool X, typename T, typename F>
4867 struct cond { using type = T; };
4868 template <typename T, typename F>
4869 struct cond<false, T, F> { using type = F; };
4871 template <bool X, typename T, typename F>
4872 using type = typename cond<X, T, F>::type;
4875 using f^oo = type<true, int, double>;
4880 auto AST = TU.build();
4881 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
4883 ASSERT_TRUE(H && H->Type);
4884 EXPECT_EQ(H->Type->Type,
"int");
4885 EXPECT_EQ(H->Definition,
"using foo = type<true, int, double>");
4889 llvm::StringRef PredefinedCXX = R
"cpp(
4891#define SizeOf sizeof
4892#define AlignOf alignof
4896using u64 = unsigned long long;
4897// calculate (a ** b) % p
4898constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
4902 ret = (ret * a) % p;
4908#define last_n_digit(x, y, n) \
4909 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))
4910#define declare_struct(X, name, value) \
4912 constexpr auto name() { return value; } \
4914#define gnu_statement_expression(value) \
4916 declare_struct(Widget, getter, value); \
4917 Widget().getter(); \
4919#define define_lambda_begin(lambda, ...) \
4921#define define_lambda_end() }
4923#define left_bracket [
4924#define right_bracket ]
4925#define dg_left_bracket <:
4926#define dg_right_bracket :>
4927#define array_decl(type, name, size) type name left_bracket size right_bracket
4931 llvm::StringRef Code;
4932 const std::function<void(std::optional<HoverInfo>,
size_t )>
4940 [](std::optional<HoverInfo> HI, size_t) {
4941 EXPECT_EQ(HI->Value,
"42 (0x2a)");
4950 [](std::optional<HoverInfo> HI, size_t) {
4951 EXPECT_TRUE(HI->Value);
4952 EXPECT_TRUE(HI->Type);
4967 [](std::optional<HoverInfo> HI, size_t) {
4968 EXPECT_TRUE(HI->Value);
4969 EXPECT_TRUE(HI->Type);
4974 // 2**32 == 4294967296
4975 last_n_di^git(2, 32, 6);
4978 [](std::optional<HoverInfo> HI, size_t) {
4979 EXPECT_EQ(HI->Value,
"967296 (0xec280)");
4980 EXPECT_EQ(HI->Type,
"u64");
4985 gnu_statement_exp^ression(42);
4988 [](std::optional<HoverInfo> HI, size_t) {
4989 EXPECT_EQ(HI->Value,
"42 (0x2a)");
4990 EXPECT_EQ(HI->Type,
"int");
4998 [](std::optional<HoverInfo> HI, size_t) {
4999 EXPECT_EQ(HI->Value,
"2");
5000 EXPECT_EQ(HI->Type,
"int");
5008 [](std::optional<HoverInfo> HI, size_t) {
5009 EXPECT_FALSE(HI->Value) << HI->Value;
5010 EXPECT_FALSE(HI->Type) << HI->Type;
5018 [](std::optional<HoverInfo> HI, size_t) {
5019 EXPECT_EQ(HI->Value,
"2");
5020 EXPECT_EQ(HI->Type,
"int");
5025 arra^y_decl(int, vector, 10);
5026 vector left_b^racket 3 right_b^racket;
5027 vector dg_le^ft_bracket 3 dg_righ^t_bracket;
5030 [](std::optional<HoverInfo> HI,
size_t Id) {
5039 EXPECT_FALSE(HI->Type) << HI->Type;
5040 EXPECT_FALSE(HI->Value) << HI->Value;
5043 ASSERT_TRUE(
false) <<
"Unhandled id: " << Id;
5049 constexpr auto value = define_lamb^da_begin(lambda, int, char)
5050 // Check if the expansion range is right.
5051 return ^last_n_digit(10, 3, 3)^;
5052 define_lam^bda_end();
5055 [](std::optional<HoverInfo> HI,
size_t Id) {
5058 EXPECT_FALSE(HI->Value);
5062 EXPECT_EQ(HI->Value,
"0");
5069 EXPECT_FALSE(HI->Type) << HI->Type;
5070 EXPECT_FALSE(HI->Value) << HI->Value;
5073 ASSERT_TRUE(
false) <<
"Unhandled id: " << Id;
5082 for (
const auto &C : Cases) {
5084 (PredefinedCXX +
"void function() {\n" +
C.Code +
"}\n").str());
5086 TU.ExtraArgs.push_back(
"-std=c++17");
5087 auto AST = TU.build();
5088 for (
auto [Index,
Position] : llvm::enumerate(Code.points())) {
5095 #define alignof _Alignof
5097 al^ignof(struct { int x; char y[10]; });
5102 TU.Filename =
"TestTU.c";
5106 auto AST = TU.build();
5107 auto H =
getHover(
AST,
C.point(), format::getLLVMStyle(),
nullptr);
5110 EXPECT_TRUE(H->Value);
5111 EXPECT_TRUE(H->Type);
5115 const char *
const Code =
5117 #define C(A) A##A // Concatenate
5118 #define E(A) C(A) // Expand
5119 #define Z0032 00000000000000000000000000000000
5120 #define Z0064 E(Z0032)
5121 #define Z0128 E(Z0064)
5122 #define Z0256 E(Z0128)
5123 #define Z0512 E(Z0256)
5124 #define Z1024 E(Z0512)
5125 #define Z2048 E(Z1024)
5126 #define Z4096 E(Z2048) // 4096 zeroes
5127 int main() { return [[^Z4096]]; }
5131 uint32_t MacroContentsLimit;
5132 const std::string ExpectedDefinition;
5135 {2048,
"#define Z4096 E(Z2048)"},
5137 {8192, std::string(
"#define Z4096 E(Z2048)\n\n") +
5138 std::string(
"// Expands to\n") + std::string(4096,
'0')},
5140 for (
const auto &Case : Cases) {
5145 auto AST = TU.build();
5149 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
5152 EXPECT_EQ(H->Definition, Case.ExpectedDefinition);
5158 const char *
const Code;
5159 const std::function<void(
HoverInfo &)> ExpectedBuilder;
5160 std::string ExpectedRender;
5162 {R
"cpp(/// Function doc
5163 void foo(int [[^a]]);
5167 HI.Kind = index::SymbolKind::Parameter;
5168 HI.NamespaceScope =
"";
5169 HI.LocalScope =
"foo::";
5171 HI.Definition =
"int a";
5172 HI.Documentation =
"";
5174 "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nType: `int`"},
5175 {R
"cpp(/// Function doc
5177 void foo(int [[^a]]);
5181 HI.Kind = index::SymbolKind::Parameter;
5182 HI.NamespaceScope =
"";
5183 HI.LocalScope =
"foo::";
5185 HI.Definition =
"int a";
5186 HI.Documentation =
"this is doc for a";
5188 "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nthis is doc "
5189 "for a\n\n---\nType: `int`"},
5190 {R
"cpp(/// Function doc
5192 void foo(int [[^a]], int b);
5196 HI.Kind = index::SymbolKind::Parameter;
5197 HI.NamespaceScope =
"";
5198 HI.LocalScope =
"foo::";
5200 HI.Definition =
"int a";
5201 HI.Documentation =
"";
5203 "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nType: `int`"},
5204 {R
"cpp(/// Function doc
5206 void foo(int a, int [[^b]]);
5210 HI.Kind = index::SymbolKind::Parameter;
5211 HI.NamespaceScope =
"";
5212 HI.LocalScope =
"foo::";
5214 HI.Definition =
"int b";
5215 HI.Documentation =
"this is doc for \\p b";
5217 "### param\n\n---\n```cpp\n// In foo\nint b\n```\n\n---\nthis is doc "
5218 "for `b`\n\n---\nType: `int`"},
5219 {R
"cpp(/// Function doc
5221 template <typename T>
5222 void foo(T a, T [[^b]]);
5226 HI.Kind = index::SymbolKind::Parameter;
5227 HI.NamespaceScope =
"";
5228 HI.LocalScope =
"foo::";
5230 HI.Definition =
"T b";
5231 HI.Documentation =
"this is doc for \\p b";
5233 "### param\n\n---\n```cpp\n// In foo\nT b\n```\n\n---\nthis is doc for "
5234 "`b`\n\n---\nType: `T`"},
5235 {R
"cpp(/// Function doc
5237 void foo(int a, int [[^b]]);
5241 HI.Kind = index::SymbolKind::Parameter;
5242 HI.NamespaceScope =
"";
5243 HI.LocalScope =
"foo::";
5245 HI.Definition =
"int b";
5247 "this is <b>doc</b> <html-tag attribute/> <another-html-tag "
5248 "attribute=\"value\">for</another-html-tag> \\p b";
5250 "### param\n\n---\n```cpp\n// In foo\nint b\n```\n\n---\nthis is "
5251 "\\<b>doc\\</b> \\<html-tag attribute/> \\<another-html-tag "
5252 "attribute=\"value\">for\\</another-html-tag> `b`\n\n---\nType: `int`"},
5253 {R
"cpp(/// Function doc
5256 void foo(int [[^a]]);
5260 HI.Kind = index::SymbolKind::Parameter;
5261 HI.NamespaceScope =
"";
5262 HI.LocalScope =
"foo::";
5264 HI.Definition =
"int a";
5265 HI.Documentation =
"the next command is an\n @unknown command.";
5267 "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nthe next "
5268 "command is an\n**@unknown** command.\n\n---\nType: `int`"},
5273 IndexSym.Documentation =
"comment from index";
5279 for (
const auto &Case : Cases) {
5280 SCOPED_TRACE(Case.Code);
5284 auto AST = TU.build();
5289 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(), Index.get());
5293 Case.ExpectedBuilder(Expected);
5296 EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
5297 EXPECT_EQ(H->LocalScope, Expected.LocalScope);
5298 EXPECT_EQ(H->Name, Expected.Name);
5299 EXPECT_EQ(H->Kind, Expected.Kind);
5300 EXPECT_EQ(H->Documentation, Expected.Documentation);
5301 EXPECT_EQ(H->Definition, Expected.Definition);
5302 EXPECT_EQ(H->Type, Expected.Type);
5303 EXPECT_EQ(H->ReturnType, Expected.ReturnType);
5304 EXPECT_EQ(H->Parameters, Expected.Parameters);
5305 EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
5306 EXPECT_EQ(H->SymRange, Expected.SymRange);
5307 EXPECT_EQ(H->Value, Expected.Value);
5311static void configureHLSL(
TestTU &TU,
bool EnableMatrix =
false) {
5312 TU.Filename =
"TestTU.hlsl";
5313 TU.ExtraArgs.push_back(
"-x");
5314 TU.ExtraArgs.push_back(
"hlsl");
5316 TU.ExtraArgs.push_back(
"-fenable-matrix");
5317 TU.ExtraArgs.push_back(
"--target=dxil-pc-shadermodel6.3-library");
5320TEST(
Hover, HLSLVectorAndMatrixSwizzle) {
5322 const char *
const Code;
5323 const std::function<void(
HoverInfo &)> ExpectedBuilder;
5327 typedef float float3 __attribute__((ext_vector_type(3)));
5330 float3 s = v.^[[xyz]];
5339 typedef float float3 __attribute__((ext_vector_type(3)));
5340 typedef float float2 __attribute__((ext_vector_type(2)));
5343 float2 s = v.^[[xy]];
5352 typedef float float4x4 __attribute__((matrix_type(4, 4)));
5355 float e = m.^[[_m00]];
5364 for (
const auto &Case : Cases) {
5365 SCOPED_TRACE(Case.Code);
5368 configureHLSL(TU,
true);
5369 auto AST = TU.build();
5370 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
5374 Case.ExpectedBuilder(Expected);
5376 EXPECT_EQ(H->Name, Expected.Name);
5377 EXPECT_EQ(H->Type, Expected.Type);
5378 EXPECT_EQ(H->SymRange, Expected.SymRange);
5382TEST(
Hover, HLSLInvalidMatrixSwizzleNoCrash) {
5384 typedef float float2x2 __attribute__((matrix_type(2, 2)));
5387 float bad = m.^[[_m22]]; // out of bounds for a 2x2 matrix /*error-ok*/
5391 configureHLSL(TU, true);
5392 auto AST = TU.build();
5393 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
5397TEST(
Hover, HLSLInvalidVectorSwizzleNoCrash) {
5399 typedef float float3 __attribute__((ext_vector_type(3)));
5402 float bad = v.^[[w]]; // 'w' is not a valid component for a 3-component vector /*error-ok*/
5407 auto AST = TU.build();
5408 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
5414 const char *
const Code;
5415 const char *
const ExpectedName;
5417 bool ExpectDocumentation;
5420 [numthreads(1, 1, 1)]
5423 for (int i = 0; i < 4; i++) {}
5426 "unroll",
true,
true},
5428 [numthreads(1, 1, 1)]
5431 for (int i = 0; i < 4; i++) {}
5434 "loop",
true,
true},
5436 [numthreads(1, 1, 1)]
5442 "branch",
true,
false},
5444 [numthreads(1, 1, 1)]
5450 "flatten",
true,
false},
5453 [[^likely]] if (true) {}
5456 "likely",
false,
false},
5459 [[^unlikely]] if (true) {}
5462 "unlikely",
false,
false},
5473 "fallthrough",
false,
false},
5475 for (
const auto &Case : Cases) {
5476 SCOPED_TRACE(Case.Code);
5478 Annotations::Markers().setRangeBegin(
"{{").setRangeEnd(
"}}"));
5483 TU.ExtraArgs.push_back(
"-std=c++20");
5484 auto AST = TU.build();
5485 auto H =
getHover(
AST,
T.point(), format::getLLVMStyle(),
nullptr);
5487 EXPECT_EQ(H->Name, Case.ExpectedName);
5488 if (Case.ExpectDocumentation) {
5489 EXPECT_FALSE(H->Documentation.empty());
5493TEST(
Hover, HLSLRegisterAttributeRange) {
5495 Texture2D tex : [[^register]]([[^t1]]);
5501 auto AST = TU.build();
5503 for (
const auto &P :
T.points()) {
5504 auto H =
getHover(
AST, P, format::getLLVMStyle(),
nullptr);
5507 EXPECT_EQ(H->Name,
"register");
5508 EXPECT_FALSE(H->Documentation.empty());
#define PREDEFINEMACROS_TEST(x)
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
An efficient structure of storing large set of symbol references in memory.
SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
WithContextValue extends Context::current() with a single value.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
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)
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccessCheck P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Settings that express user/project preferences and control clangd behavior.
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
@ Markdown
Treat comments as Markdown.
@ Doxygen
Treat comments as doxygen.
struct clang::clangd::Config::@124253042262101241326257264241307221112313102042 Hover
Configures hover feature.
bool ShowAKA
Whether hover show a.k.a type.
uint32_t MacroContentsLimit
Limit the number of characters returned when hovering a macro; 0 is no limit.
Represents parameters of a function, a template or a macro.
Contains pretty-printed type and desugared type.
Contains detailed information about a Symbol.
std::optional< Range > SymRange
std::string Name
Name of the symbol, does not contain any "::".
Ensure we have enough bits to represent all SymbolTag values.
static TestTU withCode(llvm::StringRef Code)