1 //===-- HoverTests.cpp ----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "Annotations.h"
14 #include "TestIndex.h"
16 #include "index/MemIndex.h"
17 #include "clang/AST/Attr.h"
18 #include "clang/Format/Format.h"
19 #include "clang/Index/IndexSymbol.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Twine.h"
23 #include "gtest/gtest.h"
33 using PassMode
= HoverInfo::PassType::PassMode
;
35 std::string
guard(llvm::StringRef Code
) {
36 return "#pragma once\n" + Code
.str();
39 TEST(Hover
, Structured
) {
41 const char *const Code
;
42 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
50 HI
.NamespaceScope
= "";
52 HI
.Kind
= index::SymbolKind::Function
;
53 HI
.Documentation
= "Best foo ever.";
54 HI
.Definition
= "void foo()";
55 HI
.ReturnType
= "void";
57 HI
.Parameters
.emplace();
61 namespace ns1 { namespace ns2 {
67 HI
.NamespaceScope
= "ns1::ns2::";
69 HI
.Kind
= index::SymbolKind::Function
;
70 HI
.Documentation
= "Best foo ever.";
71 HI
.Definition
= "void foo()";
72 HI
.ReturnType
= "void";
74 HI
.Parameters
.emplace();
78 namespace ns1 { namespace ns2 {
86 HI
.NamespaceScope
= "ns1::ns2::";
87 HI
.LocalScope
= "Foo::";
89 HI
.Kind
= index::SymbolKind::Field
;
90 HI
.Definition
= "char bar";
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";
136 // Local to class method.
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";
154 // Predefined variable
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]";
168 // Predefined variable (dependent)
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[]";
181 // Anon namespace and local scope.
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";
201 // Struct definition shows size.
206 HI
.NamespaceScope
= "";
208 HI
.Kind
= index::SymbolKind::Struct
;
209 HI
.Definition
= "struct X {}";
213 // Variable with template type
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>";
225 // Implicit template instantiation
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>
253 class 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")},
307 // Pointers to lambdas
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
},
329 // Lambda parameter with decltype reference
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
},
350 // Lambda parameter with decltype
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
},
394 // Local variable in lambda
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";
408 // Partially-specialized class template. (formerly type-parameter-0-0)
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 *> {}";
419 // Constructor of partially-specialized class template
421 template<typename, typename=void> struct X;
422 template<typename T> struct X<T*>{ [[^X]](); };
425 HI
.NamespaceScope
= "";
427 HI
.LocalScope
= "X<T *>::"; // FIXME: X<T *, void>::
428 HI
.Kind
= index::SymbolKind::Constructor
;
429 HI
.Definition
= "X()";
430 HI
.Parameters
.emplace();
431 HI
.AccessSpecifier
= "public";
433 {"class X { [[^~]]X(); };", // FIXME: Should be [[~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 {}";
461 // auto on structured bindings
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)";
516 // auto on template instantiation
518 template<typename T> class Foo{};
520 [[au^to]] x = Foo<int>();
525 HI
.Kind
= index::SymbolKind::TypeAlias
;
526 HI
.Definition
= "Foo<int>";
528 // auto on specialized template
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>";
541 // constrained template parameter
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"
616 // function-like macro
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";
698 HI
.Value
= "5"; // Numeric on the enumerator name, no hex as small.
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)"; // Symbolic on an expression.
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>";
812 {// Falls back to primary template, when the type is not instantiated.
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 *>";
827 // FIXME: Maybe force instantiation to make use of real template
829 HI
.Documentation
= "comment from primary";
831 {// Template Type Parameter
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";
844 {// TemplateTemplate Type Parameter
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";
857 {// NonType Template Parameter
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";
945 {// Field type initializer.
947 struct X { int x = 2; };
952 HI
.Kind
= index::SymbolKind::Variable
;
953 HI
.NamespaceScope
= "";
954 HI
.Definition
= "X x";
957 {// Don't crash on null types.
958 R
"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
961 HI
.Kind
= index::SymbolKind::Variable
;
962 HI
.NamespaceScope
= "";
964 HI
.Type
= "NULL TYPE";
965 // Bindings are in theory public members of an anonymous struct.
966 HI
.AccessSpecifier
= "public";
968 {// Extra info for function call.
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};
989 {// make_unique-like function call
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};
1062 {// Literal passed to function call
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};
1078 {// Expression passed to function call
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};
1128 {// Extra info for method call.
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};
1177 {// Dont crash on invalid decl
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";
1207 {// No crash on InitListExpr.
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]";
1222 {// Var template decl
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
}};
1236 {// Var template decl specialization
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"};
1270 {// Canonical template type
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
}};
1286 {// TypeAlias Template
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
}};
1301 {// TypeAlias Template
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"}; // FIXME: should be 'T'
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]"};
1333 {// Incomplete array
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[]"};
1347 {// Dependent size array
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]"};
1365 {// Bitfield offset, size and padding
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
);
1390 TestTU TU
= TestTU::withCode(T
.code());
1391 TU
.ExtraArgs
.push_back("-std=c++20");
1392 // Types might be different depending on the target triplet, we chose a
1393 // fixed one to make sure tests passes on different platform.
1394 TU
.ExtraArgs
.push_back("--target=x86_64-pc-linux-gnu");
1395 auto AST
= TU
.build();
1397 Cfg
.Hover
.ShowAKA
= true;
1398 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
1400 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
1403 Expected
.SymRange
= T
.range();
1404 Case
.ExpectedBuilder(Expected
);
1406 EXPECT_EQ(H
->NamespaceScope
, Expected
.NamespaceScope
);
1407 EXPECT_EQ(H
->LocalScope
, Expected
.LocalScope
);
1408 EXPECT_EQ(H
->Name
, Expected
.Name
);
1409 EXPECT_EQ(H
->Kind
, Expected
.Kind
);
1410 EXPECT_EQ(H
->Documentation
, Expected
.Documentation
);
1411 EXPECT_EQ(H
->Definition
, Expected
.Definition
);
1412 EXPECT_EQ(H
->Type
, Expected
.Type
);
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
);
1418 EXPECT_EQ(H
->Size
, Expected
.Size
);
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
);
1427 TEST(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
);
1448 TestTU TU
= TestTU::withCode(T
.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
);
1460 TEST(Hover
, CallPassType
) {
1461 const llvm::StringRef CodePrefix
= R
"cpp(
1463 class Derived : public Base {};
1467 CustomClass(const Base &x) {}
1468 CustomClass(int &x) {}
1469 CustomClass(float x) {}
1470 CustomClass(int x, int y) {}
1473 void int_by_ref(int &x) {}
1474 void int_by_const_ref(const int &x) {}
1475 void int_by_value(int x) {}
1476 void base_by_ref(Base &x) {}
1477 void base_by_const_ref(const Base &x) {}
1478 void base_by_value(Base x) {}
1479 void float_by_value(float x) {}
1480 void 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
;
1495 HoverInfo::PassType::PassMode PassBy
;
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},
1508 // Custom class tests
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},
1517 // Custom class constructor tests
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
);
1537 TestTU TU
= TestTU::withCode(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
);
1547 TEST(Hover
, NoHover
) {
1548 llvm::StringRef Tests
[] = {
1551 // FIXME: "decltype(auto)" should be a single hover
1552 "decltype(au^to) x = 0;",
1553 // FIXME: not supported yet
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
);
1587 TestTU TU
= TestTU::withCode(T
.code());
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";
1804 // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is
1805 // of struct type and omitted.
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";
1971 // NOTE MACRO doesn't have expansion since it technically isn't
1979 int main() ^[[MACRO]]
1983 HI
.Kind
= index::SymbolKind::Macro
;
1985 R
"cpp(#define MACRO \
1992 R
"cpp(// Forward class declaration
1999 HI
.Kind
= index::SymbolKind::Class
;
2000 HI
.NamespaceScope
= "";
2001 HI
.Definition
= "class Foo {}";
2002 HI
.Documentation
= "Forward class declaration";
2005 R
"cpp(// Function declaration
2007 void g() { [[f^oo]](); }
2012 HI
.Kind
= index::SymbolKind::Function
;
2013 HI
.NamespaceScope
= "";
2014 HI
.Type
= "void ()";
2015 HI
.Definition
= "void foo()";
2016 HI
.Documentation
= "Function declaration";
2017 HI
.ReturnType
= "void";
2018 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
2021 R
"cpp(// Enum declaration
2026 [[Hel^lo]] hello = ONE;
2031 HI
.Kind
= index::SymbolKind::Enum
;
2032 HI
.NamespaceScope
= "";
2033 HI
.Definition
= "enum Hello {}";
2034 HI
.Documentation
= "Enum declaration";
2042 Hello hello = [[O^NE]];
2047 HI
.Kind
= index::SymbolKind::EnumConstant
;
2048 HI
.NamespaceScope
= "";
2049 HI
.LocalScope
= "Hello::";
2050 HI
.Type
= "enum Hello";
2051 HI
.Definition
= "ONE";
2055 R
"cpp(// C++20's using enum
2061 Hello hello = [[O^NE]];
2066 HI
.Kind
= index::SymbolKind::EnumConstant
;
2067 HI
.NamespaceScope
= "";
2068 HI
.LocalScope
= "Hello::";
2069 HI
.Type
= "enum Hello";
2070 HI
.Definition
= "ONE";
2074 R
"cpp(// Enumerator in anonymous enum
2079 int hello = [[O^NE]];
2084 HI
.Kind
= index::SymbolKind::EnumConstant
;
2085 HI
.NamespaceScope
= "";
2086 // FIXME: This should be `(anon enum)::`
2088 HI
.Type
= "enum (unnamed)";
2089 HI
.Definition
= "ONE";
2093 R
"cpp(// Global variable
2094 static int hey = 10;
2101 HI
.Kind
= index::SymbolKind::Variable
;
2102 HI
.NamespaceScope
= "";
2104 HI
.Definition
= "static int hey = 10";
2105 HI
.Documentation
= "Global variable";
2106 // FIXME: Value shouldn't be set in this case
2107 HI
.Value
= "10 (0xa)";
2110 R
"cpp(// Global variable in namespace
2112 static long long hey = -36637162602497;
2120 HI
.Kind
= index::SymbolKind::Variable
;
2121 HI
.NamespaceScope
= "ns1::";
2122 HI
.Type
= "long long";
2123 HI
.Definition
= "static long long hey = -36637162602497";
2124 HI
.Value
= "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits
2127 R
"cpp(// Field in anonymous struct
2137 HI
.Kind
= index::SymbolKind::Field
;
2138 HI
.NamespaceScope
= "";
2139 HI
.LocalScope
= "(anonymous struct)::";
2141 HI
.Definition
= "int hello";
2144 R
"cpp(// Templated function
2145 template <typename T>
2149 void g() { auto x = [[f^oo]]<int>(); }
2153 HI
.Kind
= index::SymbolKind::Function
;
2154 HI
.NamespaceScope
= "";
2156 HI
.Definition
= "template <> int foo<int>()";
2157 HI
.Documentation
= "Templated function";
2158 HI
.ReturnType
= "int";
2159 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
2160 // FIXME: We should populate template parameters with arguments in
2161 // case of instantiations.
2164 R
"cpp(// Anonymous union
2170 void g() { struct outer o; o.v.[[d^ef]]++; }
2174 HI
.Kind
= index::SymbolKind::Field
;
2175 HI
.NamespaceScope
= "";
2176 HI
.LocalScope
= "outer::(anonymous union)::";
2178 HI
.Definition
= "int def";
2181 R
"cpp(// documentation from index
2182 int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
2184 void g() { [[ind^exSymbol]](); }
2187 HI
.Name
= "indexSymbol";
2188 HI
.Kind
= index::SymbolKind::Function
;
2189 HI
.NamespaceScope
= "";
2190 HI
.Type
= "void ()";
2191 HI
.Definition
= "void indexSymbol()";
2192 HI
.ReturnType
= "void";
2193 HI
.Parameters
= std::vector
<HoverInfo::Param
>{};
2194 HI
.Documentation
= "comment from index";
2197 R
"cpp(// Simple initialization with auto
2204 HI
.Kind
= index::SymbolKind::TypeAlias
;
2205 HI
.Definition
= "int";
2208 R
"cpp(// Simple initialization with const auto
2210 const ^[[auto]] i = 1;
2215 HI
.Kind
= index::SymbolKind::TypeAlias
;
2216 HI
.Definition
= "int";
2219 R
"cpp(// Simple initialization with const auto&
2221 const ^[[auto]]& i = 1;
2226 HI
.Kind
= index::SymbolKind::TypeAlias
;
2227 HI
.Definition
= "int";
2230 R
"cpp(// Simple initialization with auto&
2238 HI
.Kind
= index::SymbolKind::TypeAlias
;
2239 HI
.Definition
= "int";
2242 R
"cpp(// Simple initialization with auto*
2250 HI
.Kind
= index::SymbolKind::TypeAlias
;
2251 HI
.Definition
= "int";
2254 R
"cpp(// Simple initialization with auto from pointer
2262 HI
.Kind
= index::SymbolKind::TypeAlias
;
2263 HI
.Definition
= "int *";
2266 R
"cpp(// Auto with initializer list.
2270 class initializer_list {};
2273 ^[[auto]] i = {1,2};
2278 HI
.Kind
= index::SymbolKind::TypeAlias
;
2279 HI
.Definition
= "std::initializer_list<int>";
2282 R
"cpp(// User defined conversion to auto
2284 operator ^[[auto]]() const { return 10; }
2289 HI
.Kind
= index::SymbolKind::TypeAlias
;
2290 HI
.Definition
= "int";
2293 R
"cpp(// Simple initialization with decltype(auto)
2295 ^[[decltype]](auto) i = 1;
2299 HI
.Name
= "decltype";
2300 HI
.Kind
= index::SymbolKind::TypeAlias
;
2301 HI
.Definition
= "int";
2304 R
"cpp(// Simple initialization with const decltype(auto)
2307 ^[[decltype]](auto) i = j;
2311 HI
.Name
= "decltype";
2312 HI
.Kind
= index::SymbolKind::TypeAlias
;
2313 HI
.Definition
= "const int";
2316 R
"cpp(// Simple initialization with const& decltype(auto)
2320 ^[[decltype]](auto) i = j;
2324 HI
.Name
= "decltype";
2325 HI
.Kind
= index::SymbolKind::TypeAlias
;
2326 HI
.Definition
= "const int &";
2329 R
"cpp(// Simple initialization with & decltype(auto)
2333 ^[[decltype]](auto) i = j;
2337 HI
.Name
= "decltype";
2338 HI
.Kind
= index::SymbolKind::TypeAlias
;
2339 HI
.Definition
= "int &";
2342 R
"cpp(// simple trailing return type
2343 ^[[auto]] main() -> int {
2349 HI
.Kind
= index::SymbolKind::TypeAlias
;
2350 HI
.Definition
= "int";
2353 R
"cpp(// auto function return with trailing type
2355 ^[[auto]] test() -> decltype(Bar()) {
2361 HI
.Kind
= index::SymbolKind::TypeAlias
;
2362 HI
.Definition
= "Bar";
2363 HI
.Documentation
= "auto function return with trailing type";
2366 R
"cpp(// trailing return type
2368 auto test() -> ^[[decltype]](Bar()) {
2373 HI
.Name
= "decltype";
2374 HI
.Kind
= index::SymbolKind::TypeAlias
;
2375 HI
.Definition
= "Bar";
2376 HI
.Documentation
= "trailing return type";
2379 R
"cpp(// auto in function return
2387 HI
.Kind
= index::SymbolKind::TypeAlias
;
2388 HI
.Definition
= "Bar";
2389 HI
.Documentation
= "auto in function return";
2392 R
"cpp(// auto& in function return
2401 HI
.Kind
= index::SymbolKind::TypeAlias
;
2402 HI
.Definition
= "Bar";
2403 HI
.Documentation
= "auto& in function return";
2406 R
"cpp(// auto* in function return
2415 HI
.Kind
= index::SymbolKind::TypeAlias
;
2416 HI
.Definition
= "Bar";
2417 HI
.Documentation
= "auto* in function return";
2420 R
"cpp(// const auto& in function return
2422 const ^[[auto]]& test() {
2429 HI
.Kind
= index::SymbolKind::TypeAlias
;
2430 HI
.Definition
= "Bar";
2431 HI
.Documentation
= "const auto& in function return";
2434 R
"cpp(// decltype(auto) in function return
2436 ^[[decltype]](auto) test() {
2441 HI
.Name
= "decltype";
2442 HI
.Kind
= index::SymbolKind::TypeAlias
;
2443 HI
.Definition
= "Bar";
2444 HI
.Documentation
= "decltype(auto) in function return";
2447 R
"cpp(// decltype(auto) reference in function return
2448 ^[[decltype]](auto) test() {
2454 HI
.Name
= "decltype";
2455 HI
.Kind
= index::SymbolKind::TypeAlias
;
2456 HI
.Definition
= "int &";
2459 R
"cpp(// decltype lvalue reference
2462 ^[[decltype]](I) J = I;
2466 HI
.Name
= "decltype";
2467 HI
.Kind
= index::SymbolKind::TypeAlias
;
2468 HI
.Definition
= "int";
2471 R
"cpp(// decltype lvalue reference
2475 ^[[decltype]](K) J = I;
2479 HI
.Name
= "decltype";
2480 HI
.Kind
= index::SymbolKind::TypeAlias
;
2481 HI
.Definition
= "int &";
2484 R
"cpp(// decltype lvalue reference parenthesis
2487 ^[[decltype]]((I)) J = I;
2491 HI
.Name
= "decltype";
2492 HI
.Kind
= index::SymbolKind::TypeAlias
;
2493 HI
.Definition
= "int &";
2496 R
"cpp(// decltype rvalue reference
2499 ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
2503 HI
.Name
= "decltype";
2504 HI
.Kind
= index::SymbolKind::TypeAlias
;
2505 HI
.Definition
= "int &&";
2508 R
"cpp(// decltype rvalue reference function call
2512 ^[[decltype]](bar()) J = bar();
2516 HI
.Name
= "decltype";
2517 HI
.Kind
= index::SymbolKind::TypeAlias
;
2518 HI
.Definition
= "int &&";
2521 R
"cpp(// decltype of function with trailing return type.
2523 auto test() -> decltype(Bar()) {
2527 ^[[decltype]](test()) i = test();
2531 HI
.Name
= "decltype";
2532 HI
.Kind
= index::SymbolKind::TypeAlias
;
2533 HI
.Definition
= "Bar";
2535 "decltype of function with trailing return type.";
2538 R
"cpp(// decltype of var with decltype.
2542 ^[[decltype]](J) K = J;
2546 HI
.Name
= "decltype";
2547 HI
.Kind
= index::SymbolKind::TypeAlias
;
2548 HI
.Definition
= "int";
2551 R
"cpp(// decltype of dependent type
2552 template <typename T>
2554 using Y = ^[[decltype]](T::Z);
2558 HI
.Name
= "decltype";
2559 HI
.Kind
= index::SymbolKind::TypeAlias
;
2560 HI
.Definition
= "<dependent type>";
2563 R
"cpp(// More complicated structured types.
2565 ^[[auto]] (*foo)() = bar;
2569 HI
.Kind
= index::SymbolKind::TypeAlias
;
2570 HI
.Definition
= "int";
2573 R
"cpp(// Should not crash when evaluating the initializer.
2575 void test() { Test && [[te^st]] = {}; }
2579 HI
.Kind
= index::SymbolKind::Variable
;
2580 HI
.NamespaceScope
= "";
2581 HI
.LocalScope
= "test::";
2582 HI
.Type
= "Test &&";
2583 HI
.Definition
= "Test &&test = {}";
2586 R
"cpp(// Shouldn't crash when evaluating the initializer.
2587 struct Bar {}; // error-ok
2588 struct Foo { void foo(Bar x = y); }
2589 void Foo::foo(Bar [[^x]]) {})cpp",
2592 HI
.Kind
= index::SymbolKind::Parameter
;
2593 HI
.NamespaceScope
= "";
2594 HI
.LocalScope
= "Foo::foo::";
2596 HI
.Definition
= "Bar x = <recovery - expr>()";
2599 R
"cpp(// auto on alias
2600 typedef int int_type;
2601 ^[[auto]] x = int_type();
2605 HI
.Kind
= index::SymbolKind::TypeAlias
;
2606 HI
.Definition
= "int_type // aka: int";
2609 R
"cpp(// auto on alias
2611 typedef cls cls_type;
2612 ^[[auto]] y = cls_type();
2616 HI
.Kind
= index::SymbolKind::TypeAlias
;
2617 HI
.Definition
= "cls_type // aka: cls";
2618 HI
.Documentation
= "auto on alias";
2621 R
"cpp(// auto on alias
2624 ^[[auto]] z = templ<int>();
2628 HI
.Kind
= index::SymbolKind::TypeAlias
;
2629 HI
.Definition
= "templ<int>";
2630 HI
.Documentation
= "auto on alias";
2633 R
"cpp(// Undeduced auto declaration
2634 template<typename T>
2641 HI
.Kind
= index::SymbolKind::TypeAlias
;
2642 HI
.Definition
= "/* not deduced */";
2645 R
"cpp(// Undeduced auto return type
2646 template<typename T>
2653 HI
.Kind
= index::SymbolKind::TypeAlias
;
2654 HI
.Definition
= "/* not deduced */";
2657 R
"cpp(// Template auto parameter
2658 template<[[a^uto]] T>
2663 // FIXME: not sure this is what we want, but this
2664 // is what we currently get with getDeducedType
2666 HI
.Kind
= index::SymbolKind::TypeAlias
;
2667 HI
.Definition
= "/* not deduced */";
2670 R
"cpp(// Undeduced decltype(auto) return type
2671 template<typename T>
2672 ^[[decltype]](auto) foo() {
2677 HI
.Name
= "decltype";
2678 HI
.Kind
= index::SymbolKind::TypeAlias
;
2679 HI
.Definition
= "/* not deduced */";
2682 R
"cpp(// should not crash.
2683 template <class T> struct cls {
2687 auto test = cls<int>().[[m^ethod]]();
2690 HI
.Definition
= "int method()";
2691 HI
.Kind
= index::SymbolKind::InstanceMethod
;
2692 HI
.NamespaceScope
= "";
2693 HI
.LocalScope
= "cls<int>::";
2695 HI
.Parameters
.emplace();
2696 HI
.ReturnType
= "int";
2700 R
"cpp(// type of nested templates.
2701 template <class T> struct cls {};
2702 cls<cls<cls<int>>> [[fo^o]];
2705 HI
.Definition
= "cls<cls<cls<int>>> foo";
2706 HI
.Kind
= index::SymbolKind::Variable
;
2707 HI
.NamespaceScope
= "";
2709 HI
.Type
= "cls<cls<cls<int>>>";
2712 R
"cpp(// type of nested templates.
2713 template <class T> struct cls {};
2714 [[cl^s]]<cls<cls<int>>> foo;
2717 HI
.Definition
= "template <> struct cls<cls<cls<int>>> {}";
2718 HI
.Kind
= index::SymbolKind::Struct
;
2719 HI
.NamespaceScope
= "";
2720 HI
.Name
= "cls<cls<cls<int>>>";
2721 HI
.Documentation
= "type of nested templates.";
2724 R
"cpp(// type with decltype
2726 decltype(a) [[b^]] = a;)cpp",
2728 HI
.Definition
= "decltype(a) b = a";
2729 HI
.Kind
= index::SymbolKind::Variable
;
2730 HI
.NamespaceScope
= "";
2735 R
"cpp(// type with decltype
2738 decltype(c) [[b^]] = a;)cpp",
2740 HI
.Definition
= "decltype(c) b = a";
2741 HI
.Kind
= index::SymbolKind::Variable
;
2742 HI
.NamespaceScope
= "";
2747 R
"cpp(// type with decltype
2749 const decltype(a) [[b^]] = a;)cpp",
2751 HI
.Definition
= "const decltype(a) b = a";
2752 HI
.Kind
= index::SymbolKind::Variable
;
2753 HI
.NamespaceScope
= "";
2758 R
"cpp(// type with decltype
2760 auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
2762 HI
.Definition
= "auto foo(decltype(a) x) -> decltype(a)";
2763 HI
.Kind
= index::SymbolKind::Function
;
2764 HI
.NamespaceScope
= "";
2766 // FIXME: Handle composite types with decltype with a printing
2768 HI
.Type
= {"auto (decltype(a)) -> decltype(a)",
2769 "auto (int) -> int"};
2770 HI
.ReturnType
= "int";
2771 HI
.Parameters
= {{{"int"}, std::string("x"), std::nullopt
}};
2774 R
"cpp(// sizeof expr
2776 (void)[[size^of]](char);
2779 HI
.Name
= "expression";
2780 HI
.Type
= "unsigned long";
2784 R
"cpp(// alignof expr
2786 (void)[[align^of]](char);
2789 HI
.Name
= "expression";
2790 HI
.Type
= "unsigned long";
2795 template <typename T = int>
2796 void foo(const T& = T()) {
2801 HI
.Kind
= index::SymbolKind::Function
;
2802 HI
.Type
= "void (const int &)";
2803 HI
.ReturnType
= "void";
2805 {{"const int &"}, std::nullopt
, std::string("T()")}};
2806 HI
.Definition
= "template <> void foo<int>(const int &)";
2807 HI
.NamespaceScope
= "";
2810 R
"cpp(// should not crash
2818 HI
.Kind
= index::SymbolKind::Field
;
2819 HI
.LocalScope
= "ObjC::";
2820 HI
.NamespaceScope
= "";
2821 HI
.Definition
= "char data";
2827 @interface Interface
2828 @property(retain) [[MYOb^ject]] *x;
2832 HI
.Name
= "MYObject";
2833 HI
.Kind
= index::SymbolKind::Class
;
2834 HI
.NamespaceScope
= "";
2835 HI
.Definition
= "@interface MYObject\n@end";
2841 @interface Interface
2842 - (void)doWith:([[MYOb^ject]] *)object;
2846 HI
.Name
= "MYObject";
2847 HI
.Kind
= index::SymbolKind::Class
;
2848 HI
.NamespaceScope
= "";
2849 HI
.Definition
= "@interface MYObject\n@end";
2864 HI
.Definition
= "ns::Foo *";
2867 R
"cpp(// this expr for template class
2869 template <typename T>
2879 HI
.Definition
= "const Foo<T> *";
2882 R
"cpp(// this expr for specialization class
2884 template <typename T> class Foo {};
2895 HI
.Definition
= "Foo<int> *";
2898 R
"cpp(// this expr for partial specialization struct
2900 template <typename T, typename F> struct Foo {};
2901 template <typename F>
2902 struct Foo<int, F> {
2911 HI
.Definition
= "const Foo<int, F> *";
2917 @interface MYObject (Private)
2918 @property(nonatomic, assign) int privateField;
2921 int someFunction() {
2922 MYObject *obj = [MYObject sharedInstance];
2923 return obj.[[private^Field]];
2927 HI
.Name
= "privateField";
2928 HI
.Kind
= index::SymbolKind::InstanceProperty
;
2929 HI
.LocalScope
= "MYObject(Private)::";
2930 HI
.NamespaceScope
= "";
2931 HI
.Definition
= "@property(nonatomic, assign, unsafe_unretained, "
2932 "readwrite) int privateField;";
2936 @protocol MYProtocol
2937 @property(nonatomic, assign) int prop1;
2940 int someFunction() {
2941 id<MYProtocol> obj = 0;
2942 return obj.[[pro^p1]];
2947 HI
.Kind
= index::SymbolKind::InstanceProperty
;
2948 HI
.LocalScope
= "MYProtocol::";
2949 HI
.NamespaceScope
= "";
2950 HI
.Definition
= "@property(nonatomic, assign, unsafe_unretained, "
2951 "readwrite) int prop1;";
2955 @protocol MYProtocol
2960 @interface MYObject (Ext) <[[MYProt^ocol]]>
2964 HI
.Name
= "MYProtocol";
2965 HI
.Kind
= index::SymbolKind::Protocol
;
2966 HI
.NamespaceScope
= "";
2967 HI
.Definition
= "@protocol MYProtocol\n@end";
2973 @implementation Foo(Private)
2974 + (int)somePrivateMethod {
2975 int [[res^ult]] = 2;
2982 HI
.Definition
= "int result = 2";
2983 HI
.Kind
= index::SymbolKind::Variable
;
2985 HI
.LocalScope
= "+[Foo(Private) somePrivateMethod]::";
2986 HI
.NamespaceScope
= "";
2994 - (int)variadicArgMethod:(id)first, ... {
2995 int [[res^ult]] = 0;
3002 HI
.Definition
= "int result = 0";
3003 HI
.Kind
= index::SymbolKind::Variable
;
3005 HI
.LocalScope
= "-[Foo variadicArgMethod:, ...]::";
3006 HI
.NamespaceScope
= "";
3009 // Should not crash.
3011 typedef struct MyRect {} MyRect;
3014 @property(nonatomic) MyRect frame;
3023 v.frame = [[foo^bar]]();
3028 HI
.Kind
= index::SymbolKind::Function
;
3029 HI
.NamespaceScope
= "";
3030 HI
.Definition
= "MyRect foobar()";
3031 HI
.Type
= {"MyRect ()", "MyRect ()"};
3032 HI
.ReturnType
= {"MyRect", "MyRect"};
3033 HI
.Parameters
.emplace();
3036 void foo(int * __attribute__(([[non^null]], noescape)) );
3039 HI
.Name
= "nonnull";
3040 HI
.Kind
= index::SymbolKind::Unknown
; // FIXME: no suitable value
3041 HI
.Definition
= "__attribute__((nonnull))";
3042 HI
.Documentation
= Attr::getDocumentation(attr::NonNull
).str();
3047 struct strong_ordering {
3049 constexpr operator int() const { return n; }
3050 static const strong_ordering equal, greater, less;
3052 constexpr strong_ordering strong_ordering::equal = {0};
3053 constexpr strong_ordering strong_ordering::greater = {1};
3054 constexpr strong_ordering strong_ordering::less = {-1};
3061 auto operator<=>(const Foo&) const = default;
3064 bool x = Foo(1) [[!^=]] Foo(2);
3067 HI
.Type
= "bool (const Foo &) const noexcept";
3069 HI
.Name
= "operator==";
3070 HI
.Parameters
= {{{"const Foo &"}, std::nullopt
, std::nullopt
}};
3071 HI
.ReturnType
= "bool";
3072 HI
.Kind
= index::SymbolKind::InstanceMethod
;
3073 HI
.LocalScope
= "Foo::";
3074 HI
.NamespaceScope
= "";
3076 "bool operator==(const Foo &) const noexcept = default";
3077 HI
.Documentation
= "Foo spaceship";
3081 // Create a tiny index, so tests above can verify documentation is fetched.
3082 Symbol IndexSym
= func("indexSymbol");
3083 IndexSym
.Documentation
= "comment from index";
3084 SymbolSlab::Builder Symbols
;
3085 Symbols
.insert(IndexSym
);
3087 MemIndex::build(std::move(Symbols
).build(), RefSlab(), RelationSlab());
3089 for (const auto &Case
: Cases
) {
3090 SCOPED_TRACE(Case
.Code
);
3092 Annotations
T(Case
.Code
);
3093 TestTU TU
= TestTU::withCode(T
.code());
3094 TU
.ExtraArgs
.push_back("-std=c++20");
3095 TU
.ExtraArgs
.push_back("-xobjective-c++");
3097 TU
.ExtraArgs
.push_back("-Wno-gnu-designator");
3098 // Types might be different depending on the target triplet, we chose a
3099 // fixed one to make sure tests passes on different platform.
3100 TU
.ExtraArgs
.push_back("--target=x86_64-pc-linux-gnu");
3101 auto AST
= TU
.build();
3103 Cfg
.Hover
.ShowAKA
= true;
3104 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
3105 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), Index
.get());
3108 Expected
.SymRange
= T
.range();
3109 Case
.ExpectedBuilder(Expected
);
3111 SCOPED_TRACE(H
->present().asPlainText());
3112 EXPECT_EQ(H
->NamespaceScope
, Expected
.NamespaceScope
);
3113 EXPECT_EQ(H
->LocalScope
, Expected
.LocalScope
);
3114 EXPECT_EQ(H
->Name
, Expected
.Name
);
3115 EXPECT_EQ(H
->Kind
, Expected
.Kind
);
3116 EXPECT_EQ(H
->Documentation
, Expected
.Documentation
);
3117 EXPECT_EQ(H
->Definition
, Expected
.Definition
);
3118 EXPECT_EQ(H
->Type
, Expected
.Type
);
3119 EXPECT_EQ(H
->ReturnType
, Expected
.ReturnType
);
3120 EXPECT_EQ(H
->Parameters
, Expected
.Parameters
);
3121 EXPECT_EQ(H
->TemplateParameters
, Expected
.TemplateParameters
);
3122 EXPECT_EQ(H
->SymRange
, Expected
.SymRange
);
3123 EXPECT_EQ(H
->Value
, Expected
.Value
);
3127 TEST(Hover
, Providers
) {
3130 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
3131 } Cases
[] = {{R
"cpp(
3135 [](HoverInfo
&HI
) { HI
.Provider
= ""; }},
3140 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3145 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3150 [](HoverInfo
&HI
) { HI
.Provider
= ""; }},
3155 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3160 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3167 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3168 // Hover selects the underlying decl of the using decl
3176 [](HoverInfo
&HI
) { HI
.Provider
= "\"foo.h\""; }},
3179 using namespace fo^o;
3181 [](HoverInfo
&HI
) { HI
.Provider
= ""; }},
3184 for (const auto &Case
: Cases
) {
3185 Annotations Code
{Case
.Code
};
3186 SCOPED_TRACE(Code
.code());
3189 TU
.Filename
= "foo.cpp";
3190 TU
.Code
= Code
.code();
3191 TU
.AdditionalFiles
["foo.h"] = guard(R
"cpp(
3194 Foo& operator+(const Foo, const Foo);
3196 TU
.AdditionalFiles
["all.h"] = guard("#include \"foo.h\"");
3198 auto AST
= TU
.build();
3199 auto H
= getHover(AST
, Code
.point(), format::getLLVMStyle(), nullptr);
3202 Case
.ExpectedBuilder(Expected
);
3203 SCOPED_TRACE(H
->present().asMarkdown());
3204 EXPECT_EQ(H
->Provider
, Expected
.Provider
);
3208 TEST(Hover
, ParseProviderInfo
) {
3211 HIFoo
.Provider
= "\"foo.h\"";
3214 HIFooBar
.Name
= "foo";
3215 HIFooBar
.Provider
= "<bar.h>";
3218 llvm::StringRef ExpectedMarkdown
;
3219 } Cases
[] = {{HIFoo
, "### `foo` \nprovided by `\"foo.h\"`"},
3220 {HIFooBar
, "### `foo` \nprovided by `<bar.h>`"}};
3222 for (const auto &Case
: Cases
)
3223 EXPECT_EQ(Case
.HI
.present().asMarkdown(), Case
.ExpectedMarkdown
);
3226 TEST(Hover
, UsedSymbols
) {
3229 const std::function
<void(HoverInfo
&)> ExpectedBuilder
;
3230 } Cases
[] = {{R
"cpp(
3232 int fstBar = bar1();
3233 int another= bar1(0);
3234 int sndBar = bar2();
3239 HI
.UsedSymbolNames
= {"BAR", "Bar", "bar1", "bar2"};
3243 std::vector<int> vec;
3245 [](HoverInfo
&HI
) { HI
.UsedSymbolNames
= {"vector"}; }}};
3246 for (const auto &Case
: Cases
) {
3247 Annotations Code
{Case
.Code
};
3248 SCOPED_TRACE(Code
.code());
3251 TU
.Filename
= "foo.cpp";
3252 TU
.Code
= Code
.code();
3253 TU
.AdditionalFiles
["bar.h"] = guard(R
"cpp(
3260 TU
.AdditionalFiles
["system/vector"] = guard(R
"cpp(
3266 TU
.ExtraArgs
.push_back("-isystem" + testPath("system"));
3268 auto AST
= TU
.build();
3269 auto H
= getHover(AST
, Code
.point(), format::getLLVMStyle(), nullptr);
3272 Case
.ExpectedBuilder(Expected
);
3273 SCOPED_TRACE(H
->present().asMarkdown());
3274 EXPECT_EQ(H
->UsedSymbolNames
, Expected
.UsedSymbolNames
);
3278 TEST(Hover
, DocsFromIndex
) {
3279 Annotations
T(R
"cpp(
3280 template <typename T> class X {};
3287 TestTU TU
= TestTU::withCode(T
.code());
3288 auto AST
= TU
.build();
3290 IndexSym
.ID
= getSymbolID(&findDecl(AST
, "X"));
3291 IndexSym
.Documentation
= "comment from index";
3292 SymbolSlab::Builder Symbols
;
3293 Symbols
.insert(IndexSym
);
3295 MemIndex::build(std::move(Symbols
).build(), RefSlab(), RelationSlab());
3297 for (const auto &P
: T
.points()) {
3298 auto H
= getHover(AST
, P
, format::getLLVMStyle(), Index
.get());
3300 EXPECT_EQ(H
->Documentation
, IndexSym
.Documentation
);
3304 TEST(Hover
, DocsFromAST
) {
3305 Annotations
T(R
"cpp(
3307 template <typename T> class X {};
3309 template <typename T> void bar() {}
3311 template <typename T> T baz;
3316 au^to T = ba^z<X<int>>;
3320 TestTU TU
= TestTU::withCode(T
.code());
3321 auto AST
= TU
.build();
3322 for (const auto &P
: T
.points()) {
3323 auto H
= getHover(AST
, P
, format::getLLVMStyle(), nullptr);
3325 EXPECT_EQ(H
->Documentation
, "doc");
3329 TEST(Hover
, NoCrash
) {
3330 Annotations
T(R
"cpp(
3332 template<typename T> T foo(T);
3334 // Setter variable heuristic might fail if the callexpr is broken.
3335 struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");
3337 TestTU TU
= TestTU::withCode(T
.code());
3338 auto AST
= TU
.build();
3339 for (const auto &P
: T
.points())
3340 getHover(AST
, P
, format::getLLVMStyle(), nullptr);
3343 TEST(Hover
, NoCrashAPInt64
) {
3344 Annotations
T(R
"cpp(
3345 constexpr unsigned long value = -1; // wrap around
3346 void foo() { va^lue; }
3348 auto AST
= TestTU::withCode(T
.code()).build();
3349 getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3352 TEST(Hover
, DocsFromMostSpecial
) {
3353 Annotations
T(R
"cpp(
3355 template <typename T> class $doc1^X {};
3357 template <> class $doc2^X<int> {};
3359 template <typename T> class $doc3^X<T*> {};
3366 TestTU TU
= TestTU::withCode(T
.code());
3367 auto AST
= TU
.build();
3368 for (const auto *Comment
: {"doc1", "doc2", "doc3"}) {
3369 for (const auto &P
: T
.points(Comment
)) {
3370 auto H
= getHover(AST
, P
, format::getLLVMStyle(), nullptr);
3372 EXPECT_EQ(H
->Documentation
, Comment
);
3377 TEST(Hover
, Present
) {
3379 const std::function
<void(HoverInfo
&)> Builder
;
3380 llvm::StringRef ExpectedRender
;
3384 HI
.Kind
= index::SymbolKind::Unknown
;
3391 HI
.Kind
= index::SymbolKind::NamespaceAlias
;
3394 R
"(namespace-alias foo)",
3398 HI
.Kind
= index::SymbolKind::Class
;
3400 HI
.TemplateParameters
= {
3401 {{"typename"}, std::string("T"), std::nullopt
},
3402 {{"typename"}, std::string("C"), std::string("bool")},
3404 HI
.Documentation
= "documentation";
3406 "template <typename T, typename C = bool> class Foo {}";
3408 HI
.NamespaceScope
.emplace();
3415 template <typename T, typename C = bool> class Foo {})",
3419 HI
.Kind
= index::SymbolKind::Function
;
3421 HI
.Type
= {"type", "c_type"};
3422 HI
.ReturnType
= {"ret_type", "can_ret_type"};
3423 HI
.Parameters
.emplace();
3425 HI
.Parameters
->push_back(P
);
3426 P
.Type
= {"type", "can_type"};
3427 HI
.Parameters
->push_back(P
);
3429 HI
.Parameters
->push_back(P
);
3430 P
.Default
= "default";
3431 HI
.Parameters
->push_back(P
);
3432 HI
.NamespaceScope
= "ns::";
3433 HI
.Definition
= "ret_type foo(params) {}";
3437 "→ ret_type (aka can_ret_type)\n"
3440 "- type (aka can_type)\n"
3441 "- type foo (aka can_type)\n"
3442 "- type foo = default (aka can_type)\n"
3444 "// In namespace ns\n"
3445 "ret_type foo(params) {}",
3449 HI
.Kind
= index::SymbolKind::Field
;
3450 HI
.LocalScope
= "test::Bar::";
3453 HI
.Type
= {"type", "can_type"};
3454 HI
.Definition
= "def";
3462 Type: type (aka can_type)
3465 Size: 4 bytes (+4 bytes padding), alignment 4 bytes
3472 HI
.Kind
= index::SymbolKind::Field
;
3473 HI
.LocalScope
= "test::Bar::";
3476 HI
.Type
= {"type", "can_type"};
3477 HI
.Definition
= "def";
3485 Type: type (aka can_type)
3487 Offset: 4 bytes and 3 bits
3488 Size: 25 bits (+4 bits padding), alignment 8 bytes
3495 HI
.Kind
= index::SymbolKind::Field
;
3496 HI
.AccessSpecifier
= "public";
3498 HI
.LocalScope
= "test::Bar::";
3499 HI
.Definition
= "def";
3508 HI
.Definition
= "size_t method()";
3509 HI
.AccessSpecifier
= "protected";
3510 HI
.Kind
= index::SymbolKind::InstanceMethod
;
3511 HI
.NamespaceScope
= "";
3512 HI
.LocalScope
= "cls<int>::";
3514 HI
.Parameters
.emplace();
3515 HI
.ReturnType
= {"size_t", "unsigned long"};
3516 HI
.Type
= {"size_t ()", "unsigned long ()"};
3518 R
"(instance-method method
3520 → size_t (aka unsigned long)
3523 protected: size_t method())",
3527 HI
.Definition
= "cls(int a, int b = 5)";
3528 HI
.AccessSpecifier
= "public";
3529 HI
.Kind
= index::SymbolKind::Constructor
;
3530 HI
.NamespaceScope
= "";
3531 HI
.LocalScope
= "cls";
3533 HI
.Parameters
.emplace();
3534 HI
.Parameters
->emplace_back();
3535 HI
.Parameters
->back().Type
= "int";
3536 HI
.Parameters
->back().Name
= "a";
3537 HI
.Parameters
->emplace_back();
3538 HI
.Parameters
->back().Type
= "int";
3539 HI
.Parameters
->back().Name
= "b";
3540 HI
.Parameters
->back().Default
= "5";
3549 public: cls(int a, int b = 5))",
3553 HI
.Kind
= index::SymbolKind::Union
;
3554 HI
.AccessSpecifier
= "private";
3556 HI
.NamespaceScope
= "ns1::";
3557 HI
.Definition
= "union foo {}";
3562 private: union foo {})",
3566 HI
.Kind
= index::SymbolKind::Variable
;
3568 HI
.Definition
= "int foo = 3";
3569 HI
.LocalScope
= "test::Bar::";
3572 HI
.CalleeArgInfo
.emplace();
3573 HI
.CalleeArgInfo
->Name
= "arg_a";
3574 HI
.CalleeArgInfo
->Type
= "int";
3575 HI
.CalleeArgInfo
->Default
= "7";
3576 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
3589 HI
.Kind
= index::SymbolKind::Variable
;
3591 HI
.CalleeArgInfo
.emplace();
3592 HI
.CalleeArgInfo
->Type
= "int";
3593 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, false};
3601 HI
.Kind
= index::SymbolKind::Variable
;
3603 HI
.Definition
= "int foo = 3";
3604 HI
.LocalScope
= "test::Bar::";
3607 HI
.CalleeArgInfo
.emplace();
3608 HI
.CalleeArgInfo
->Name
= "arg_a";
3609 HI
.CalleeArgInfo
->Type
= "int";
3610 HI
.CalleeArgInfo
->Default
= "7";
3611 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Ref
, false};
3617 Passed by reference as arg_a
3624 HI
.Kind
= index::SymbolKind::Variable
;
3626 HI
.Definition
= "int foo = 3";
3627 HI
.LocalScope
= "test::Bar::";
3630 HI
.CalleeArgInfo
.emplace();
3631 HI
.CalleeArgInfo
->Name
= "arg_a";
3632 HI
.CalleeArgInfo
->Type
= {"alias_int", "int"};
3633 HI
.CalleeArgInfo
->Default
= "7";
3634 HI
.CallPassType
= HoverInfo::PassType
{PassMode::Value
, true};
3640 Passed as arg_a (converted to alias_int)
3647 HI
.Kind
= index::SymbolKind::Macro
;
3648 HI
.Name
= "PLUS_ONE";
3649 HI
.Definition
= "#define PLUS_ONE(X) (X+1)\n\n"
3655 #define PLUS_ONE(X) (X+1)
3662 HI
.Kind
= index::SymbolKind::Variable
;
3664 HI
.Definition
= "int foo = 3";
3665 HI
.LocalScope
= "test::Bar::";
3668 HI
.CalleeArgInfo
.emplace();
3669 HI
.CalleeArgInfo
->Name
= "arg_a";
3670 HI
.CalleeArgInfo
->Type
= "int";
3671 HI
.CalleeArgInfo
->Default
= "7";
3672 HI
.CallPassType
= HoverInfo::PassType
{PassMode::ConstRef
, true};
3678 Passed by const reference as arg_a (converted to int)
3685 HI
.Name
= "stdio.h";
3686 HI
.Definition
= "/usr/include/stdio.h";
3690 /usr/include/stdio.h)",
3692 {[](HoverInfo
&HI
) {
3694 HI
.UsedSymbolNames
= {"Foo", "Bar", "Bar"};
3698 provides Foo, Bar, Bar)"},
3699 {[](HoverInfo
&HI
) {
3701 HI
.UsedSymbolNames
= {"Foo", "Bar", "Baz", "Foobar", "Qux", "Quux"};
3705 provides Foo, Bar, Baz, Foobar, Qux and 1 more)"}};
3707 for (const auto &C
: Cases
) {
3711 Cfg
.Hover
.ShowAKA
= true;
3712 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
3713 EXPECT_EQ(HI
.present().asPlainText(), C
.ExpectedRender
);
3717 TEST(Hover
, ParseDocumentation
) {
3719 llvm::StringRef Documentation
;
3720 llvm::StringRef ExpectedRenderMarkdown
;
3721 llvm::StringRef ExpectedRenderPlainText
;
3778 "Tests primality of `p`.",
3779 "Tests primality of `p`.",
3780 "Tests primality of `p`.",
3783 "'`' should not occur in `Code`",
3784 "'\\`' should not occur in `Code`",
3785 "'`' should not occur in `Code`",
3793 for (const auto &C
: Cases
) {
3794 markup::Document Output
;
3795 parseDocumentation(C
.Documentation
, Output
);
3797 EXPECT_EQ(Output
.asMarkdown(), C
.ExpectedRenderMarkdown
);
3798 EXPECT_EQ(Output
.asPlainText(), C
.ExpectedRenderPlainText
);
3802 // This is a separate test as headings don't create any differences in
3804 TEST(Hover
, PresentHeadings
) {
3806 HI
.Kind
= index::SymbolKind::Variable
;
3809 EXPECT_EQ(HI
.present().asMarkdown(), "### variable `foo`");
3812 // This is a separate test as rulers behave differently in markdown vs
3814 TEST(Hover
, PresentRulers
) {
3816 HI
.Kind
= index::SymbolKind::Variable
;
3819 HI
.Definition
= "def";
3821 llvm::StringRef ExpectedMarkdown
= //
3822 "### variable `foo` \n"
3831 EXPECT_EQ(HI
.present().asMarkdown(), ExpectedMarkdown
);
3833 llvm::StringRef ExpectedPlaintext
= R
"pt(variable foo
3838 EXPECT_EQ(HI
.present().asPlainText(), ExpectedPlaintext
);
3841 TEST(Hover
, SpaceshipTemplateNoCrash
) {
3842 Annotations
T(R
"cpp(
3844 struct strong_ordering {
3846 constexpr operator int() const { return n; }
3847 static const strong_ordering equal, greater, less;
3849 constexpr strong_ordering strong_ordering::equal = {0};
3850 constexpr strong_ordering strong_ordering::greater = {1};
3851 constexpr strong_ordering strong_ordering::less = {-1};
3854 template <typename T>
3857 friend auto operator<=>(S, S) = default;
3859 static_assert(S<void>() =^= S<void>());
3862 TestTU TU
= TestTU::withCode(T
.code());
3863 TU
.ExtraArgs
.push_back("-std=c++20");
3864 auto AST
= TU
.build();
3865 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3866 EXPECT_EQ(HI
->Documentation
, "Foo bar baz");
3869 TEST(Hover
, ForwardStructNoCrash
) {
3870 Annotations
T(R
"cpp(
3873 auto baz = (Fo^o*)&bar;
3876 TestTU TU
= TestTU::withCode(T
.code());
3877 auto AST
= TU
.build();
3878 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3880 EXPECT_EQ(*HI
->Value
, "&bar");
3883 TEST(Hover
, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls
) {
3885 const char *const Code
;
3886 const std::optional
<std::string
> HoverValue
;
3889 // error-ok testing behavior on invalid decl
3891 void foo(Foo p^aram = nullptr);
3896 void foo(Foo *p^aram = nullptr);
3901 for (const auto &C
: Cases
) {
3902 Annotations
T(C
.Code
);
3903 TestTU TU
= TestTU::withCode(T
.code());
3904 auto AST
= TU
.build();
3905 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3907 ASSERT_EQ(HI
->Value
, C
.HoverValue
);
3911 TEST(Hover
, DisableShowAKA
) {
3912 Annotations
T(R
"cpp(
3918 Cfg
.Hover
.ShowAKA
= false;
3919 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
3921 TestTU TU
= TestTU::withCode(T
.code());
3922 TU
.ExtraArgs
.push_back("-std=c++17");
3923 auto AST
= TU
.build();
3924 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3927 EXPECT_EQ(H
->Type
, HoverInfo::PrintedType("m_int"));
3930 TEST(Hover
, HideBigInitializers
) {
3931 Annotations
T(R
"cpp(
3932 #define A(x) x, x, x, x
3933 #define B(x) A(A(A(A(x))))
3934 int a^rr[] = {B(0)};
3937 TestTU TU
= TestTU::withCode(T
.code());
3938 auto AST
= TU
.build();
3939 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3942 EXPECT_EQ(H
->Definition
, "int arr[]");
3945 #if defined(__aarch64__)
3946 // FIXME: AARCH64 sanitizer buildbots are broken after 72142fbac4.
3947 #define PREDEFINEMACROS_TEST(x) DISABLED_##x
3949 #define PREDEFINEMACROS_TEST(x) x
3952 TEST(Hover
, PREDEFINEMACROS_TEST(GlobalVarEnumeralCastNoCrash
)) {
3953 Annotations
T(R
"cpp(
3954 using uintptr_t = __UINTPTR_TYPE__;
3955 enum Test : uintptr_t {};
3956 unsigned global_var;
3958 Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));
3962 TestTU TU
= TestTU::withCode(T
.code());
3963 TU
.PredefineMacros
= true;
3964 auto AST
= TU
.build();
3965 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3967 EXPECT_EQ(*HI
->Value
, "&global_var");
3970 TEST(Hover
, PREDEFINEMACROS_TEST(GlobalVarIntCastNoCrash
)) {
3971 Annotations
T(R
"cpp(
3972 using uintptr_t = __UINTPTR_TYPE__;
3973 unsigned global_var;
3975 uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);
3979 TestTU TU
= TestTU::withCode(T
.code());
3980 TU
.PredefineMacros
= true;
3981 auto AST
= TU
.build();
3982 auto HI
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
3984 EXPECT_EQ(*HI
->Value
, "&global_var");
3987 TEST(Hover
, Typedefs
) {
3988 Annotations
T(R
"cpp(
3989 template <bool X, typename T, typename F>
3990 struct cond { using type = T; };
3991 template <typename T, typename F>
3992 struct cond<false, T, F> { using type = F; };
3994 template <bool X, typename T, typename F>
3995 using type = typename cond<X, T, F>::type;
3998 using f^oo = type<true, int, double>;
4002 TestTU TU
= TestTU::withCode(T
.code());
4003 auto AST
= TU
.build();
4004 auto H
= getHover(AST
, T
.point(), format::getLLVMStyle(), nullptr);
4006 ASSERT_TRUE(H
&& H
->Type
);
4007 EXPECT_EQ(H
->Type
->Type
, "int");
4008 EXPECT_EQ(H
->Definition
, "using foo = type<true, int, double>");
4011 TEST(Hover
, EvaluateMacros
) {
4012 llvm::StringRef PredefinedCXX
= R
"cpp(
4014 #define SizeOf sizeof
4015 #define AlignOf alignof
4019 using u64 = unsigned long long;
4020 // calculate (a ** b) % p
4021 constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {
4025 ret = (ret * a) % p;
4031 #define last_n_digit(x, y, n) \
4032 pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))
4033 #define declare_struct(X, name, value) \
4035 constexpr auto name() { return value; } \
4037 #define gnu_statement_expression(value) \
4039 declare_struct(Widget, getter, value); \
4040 Widget().getter(); \
4042 #define define_lambda_begin(lambda, ...) \
4044 #define define_lambda_end() }
4046 #define left_bracket [
4047 #define right_bracket ]
4048 #define dg_left_bracket <:
4049 #define dg_right_bracket :>
4050 #define array_decl(type, name, size) type name left_bracket size right_bracket
4054 llvm::StringRef Code
;
4055 const std::function
<void(std::optional
<HoverInfo
>, size_t /*Id*/)>
4063 [](std::optional
<HoverInfo
> HI
, size_t) {
4064 EXPECT_EQ(HI
->Value
, "42 (0x2a)");
4065 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("int"));
4073 [](std::optional
<HoverInfo
> HI
, size_t) {
4074 EXPECT_TRUE(HI
->Value
);
4075 EXPECT_TRUE(HI
->Type
);
4076 // Don't validate type or value of `sizeof` and `alignof` as we're
4077 // getting different values or desugared types on different
4078 // platforms. Same as below.
4090 [](std::optional
<HoverInfo
> HI
, size_t) {
4091 EXPECT_TRUE(HI
->Value
);
4092 EXPECT_TRUE(HI
->Type
);
4097 // 2**32 == 4294967296
4098 last_n_di^git(2, 32, 6);
4101 [](std::optional
<HoverInfo
> HI
, size_t) {
4102 EXPECT_EQ(HI
->Value
, "967296 (0xec280)");
4103 EXPECT_EQ(HI
->Type
, "u64");
4108 gnu_statement_exp^ression(42);
4111 [](std::optional
<HoverInfo
> HI
, size_t) {
4112 EXPECT_EQ(HI
->Value
, "42 (0x2a)");
4113 EXPECT_EQ(HI
->Type
, "int");
4121 [](std::optional
<HoverInfo
> HI
, size_t) {
4122 EXPECT_EQ(HI
->Value
, "2");
4123 EXPECT_EQ(HI
->Type
, "int");
4131 [](std::optional
<HoverInfo
> HI
, size_t) {
4132 EXPECT_FALSE(HI
->Value
) << HI
->Value
;
4133 EXPECT_FALSE(HI
->Type
) << HI
->Type
;
4141 [](std::optional
<HoverInfo
> HI
, size_t) {
4142 EXPECT_EQ(HI
->Value
, "2");
4143 EXPECT_EQ(HI
->Type
, "int");
4148 arra^y_decl(int, vector, 10);
4149 vector left_b^racket 3 right_b^racket;
4150 vector dg_le^ft_bracket 3 dg_righ^t_bracket;
4153 [](std::optional
<HoverInfo
> HI
, size_t Id
) {
4156 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("int[10]"));
4162 EXPECT_FALSE(HI
->Type
) << HI
->Type
;
4163 EXPECT_FALSE(HI
->Value
) << HI
->Value
;
4166 ASSERT_TRUE(false) << "Unhandled id: " << Id
;
4172 constexpr auto value = define_lamb^da_begin(lambda, int, char)
4173 // Check if the expansion range is right.
4174 return ^last_n_digit(10, 3, 3)^;
4175 define_lam^bda_end();
4178 [](std::optional
<HoverInfo
> HI
, size_t Id
) {
4181 EXPECT_FALSE(HI
->Value
);
4182 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("const (lambda)"));
4185 EXPECT_EQ(HI
->Value
, "0");
4186 EXPECT_EQ(HI
->Type
, HoverInfo::PrintedType("u64"));
4192 EXPECT_FALSE(HI
->Type
) << HI
->Type
;
4193 EXPECT_FALSE(HI
->Value
) << HI
->Value
;
4196 ASSERT_TRUE(false) << "Unhandled id: " << Id
;
4203 Cfg
.Hover
.ShowAKA
= false;
4204 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
4205 for (const auto &C
: Cases
) {
4207 (PredefinedCXX
+ "void function() {\n" + C
.Code
+ "}\n").str());
4208 auto TU
= TestTU::withCode(Code
.code());
4209 TU
.ExtraArgs
.push_back("-std=c++17");
4210 auto AST
= TU
.build();
4211 for (auto [Index
, Position
] : llvm::enumerate(Code
.points())) {
4212 C
.Validator(getHover(AST
, Position
, format::getLLVMStyle(), nullptr),
4218 #define alignof _Alignof
4220 al^ignof(struct { int x; char y[10]; });
4224 auto TU
= TestTU::withCode(C
.code());
4225 TU
.Filename
= "TestTU.c";
4229 auto AST
= TU
.build();
4230 auto H
= getHover(AST
, C
.point(), format::getLLVMStyle(), nullptr);
4233 EXPECT_TRUE(H
->Value
);
4234 EXPECT_TRUE(H
->Type
);
4237 } // namespace clangd
4238 } // namespace clang