16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/ScopedPrinter.h"
18#include "llvm/Support/raw_ostream.h"
19#include "gmock/gmock.h"
20#include "gtest/gtest.h"
36using ::testing::ElementsAre;
37using ::testing::IsEmpty;
39constexpr InlayHintOptions DefaultOptsForTests{2};
41std::vector<InlayHint> hintsOfKind(ParsedAST &
AST, InlayHintKind Kind,
42 InlayHintOptions Opts) {
43 std::vector<InlayHint> Result;
45 if (Hint.kind == Kind)
46 Result.push_back(Hint);
55 std::string RangeName;
58 friend llvm::raw_ostream &
operator<<(llvm::raw_ostream &Stream,
59 const ExpectedHint &Hint) {
60 return Stream << Hint.Label <<
"@$" << Hint.RangeName;
64MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) {
65 llvm::StringRef ExpectedView(Expected.Label);
66 std::string ResultLabel = arg.joinLabels();
67 if (ResultLabel != ExpectedView.trim(
" ") ||
68 arg.paddingLeft != ExpectedView.starts_with(
" ") ||
69 arg.paddingRight != ExpectedView.ends_with(
" ")) {
70 *result_listener <<
"label is '" << ResultLabel <<
"'";
73 if (arg.range != Code.range(Expected.RangeName)) {
74 *result_listener <<
"range is " << llvm::to_string(arg.range) <<
" but $"
75 << Expected.RangeName <<
" is "
76 << llvm::to_string(Code.range(Expected.RangeName));
86 C.InlayHints.Parameters =
false;
87 C.InlayHints.DeducedTypes =
false;
88 C.InlayHints.Designators =
false;
89 C.InlayHints.BlockEnd =
false;
90 C.InlayHints.DefaultArguments =
false;
94template <
typename... ExpectedHints>
95void assertHintsWithHeader(
InlayHintKind Kind, llvm::StringRef AnnotatedSource,
97 ExpectedHints... Expected) {
100 TU.ExtraArgs.push_back(
"-std=c++23");
101 TU.HeaderCode = HeaderContent;
102 auto AST = TU.build();
104 EXPECT_THAT(hintsOfKind(
AST, Kind, Opts),
105 ElementsAre(HintMatcher(Expected, Source)...));
112template <
typename... ExpectedHints>
113void assertHints(
InlayHintKind Kind, llvm::StringRef AnnotatedSource,
115 return assertHintsWithHeader(Kind, AnnotatedSource,
"", Opts,
116 std::move(Expected)...);
120template <
typename...
T>
void ignore(T &&...) {}
122template <
typename... ExpectedHints>
123void assertParameterHints(llvm::StringRef AnnotatedSource,
124 ExpectedHints... Expected) {
125 ignore(Expected.Side =
Left...);
130template <
typename... ExpectedHints>
131void assertTypeHints(llvm::StringRef AnnotatedSource,
132 ExpectedHints... Expected) {
133 ignore(Expected.Side =
Right...);
138template <
typename... ExpectedHints>
139void assertDesignatorHints(llvm::StringRef AnnotatedSource,
140 ExpectedHints... Expected) {
148template <
typename... ExpectedHints>
149void assertBlockEndHintsWithOpts(llvm::StringRef AnnotatedSource,
151 ExpectedHints... Expected) {
158template <
typename... ExpectedHints>
159void assertBlockEndHints(llvm::StringRef AnnotatedSource,
160 ExpectedHints... Expected) {
161 assertBlockEndHintsWithOpts(AnnotatedSource, DefaultOptsForTests,
165TEST(ParameterHints, Smoke) {
166 assertParameterHints(R
"cpp(
172 ExpectedHint{"param: ",
"param"});
175TEST(ParameterHints, NoName) {
177 assertParameterHints(R
"cpp(
185TEST(ParameterHints, NoNameConstReference) {
187 assertParameterHints(R
"cpp(
188 void foo(const int&);
195TEST(ParameterHints, NoNameReference) {
197 assertParameterHints(R
"cpp(
204 ExpectedHint{"&: ",
"param"});
207TEST(ParameterHints, NoNameRValueReference) {
209 assertParameterHints(R
"cpp(
217TEST(ParameterHints, NoNameVariadicDeclaration) {
219 assertParameterHints(R
"cpp(
220 template <typename... Args>
221 void foo(Args&& ...);
228TEST(ParameterHints, NoNameVariadicForwarded) {
231 assertParameterHints(R
"cpp(
232 namespace std { template <typename T> T&& forward(T&); }
234 template <typename... Args>
235 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
242TEST(ParameterHints, NoNameVariadicPlain) {
244 assertParameterHints(R
"cpp(
246 template <typename... Args>
247 void bar(Args&&... args) { return foo(args...); }
254TEST(ParameterHints, NameInDefinition) {
256 assertParameterHints(R
"cpp(
261 void foo(int param) {};
263 ExpectedHint{"param: ",
"param"});
266TEST(ParameterHints, NamePartiallyInDefinition) {
268 assertParameterHints(R
"cpp(
269 void foo(int, int b);
271 foo($param1[[42]], $param2[[42]]);
273 void foo(int a, int) {};
275 ExpectedHint{"a: ",
"param1"},
276 ExpectedHint{
"b: ",
"param2"});
279TEST(ParameterHints, NameInDefinitionVariadic) {
281 assertParameterHints(R
"cpp(
283 template <typename... Args>
284 void bar(Args... args) {
288 bar($param1[[42]], $param2[[42]]);
290 void foo(int a, int b) {};
292 ExpectedHint{"a: ",
"param1"},
293 ExpectedHint{
"b: ",
"param2"});
296TEST(ParameterHints, NameMismatch) {
298 assertParameterHints(R
"cpp(
303 void foo(int bad) {};
305 ExpectedHint{"good: ",
"good"});
308TEST(ParameterHints, NameConstReference) {
310 assertParameterHints(R
"cpp(
311 void foo(const int& param);
316 ExpectedHint{"param: ",
"param"});
319TEST(ParameterHints, NameTypeAliasConstReference) {
321 assertParameterHints(R
"cpp(
322 using alias = const int&;
323 void foo(alias param);
329 ExpectedHint{"param: ",
"param"});
332TEST(ParameterHints, NameReference) {
334 assertParameterHints(R
"cpp(
335 void foo(int& param);
341 ExpectedHint{"¶m: ",
"param"});
344TEST(ParameterHints, NameTypeAliasReference) {
346 assertParameterHints(R
"cpp(
348 void foo(alias param);
354 ExpectedHint{"¶m: ",
"param"});
357TEST(ParameterHints, NameRValueReference) {
359 assertParameterHints(R
"cpp(
360 void foo(int&& param);
365 ExpectedHint{"param: ",
"param"});
368TEST(ParameterHints, VariadicForwardedConstructor) {
371 assertParameterHints(R
"cpp(
372 namespace std { template <typename T> T&& forward(T&); }
373 struct S { S(int a); };
374 template <typename T, typename... Args>
375 T bar(Args&&... args) { return T{std::forward<Args>(args)...}; }
381 ExpectedHint{"a: ",
"param"});
384TEST(ParameterHints, VariadicPlainConstructor) {
386 assertParameterHints(R
"cpp(
387 struct S { S(int a); };
388 template <typename T, typename... Args>
389 T bar(Args&&... args) { return T{args...}; }
395 ExpectedHint{"a: ",
"param"});
398TEST(ParameterHints, VariadicForwardedNewConstructor) {
401 assertParameterHints(R
"cpp(
402 namespace std { template <typename T> T&& forward(T&); }
403 struct S { S(int a); };
404 template <typename T, typename... Args>
405 T* bar(Args&&... args) { return new T{std::forward<Args>(args)...}; }
411 ExpectedHint{"a: ",
"param"});
414TEST(ParameterHints, VariadicPlainNewConstructor) {
416 assertParameterHints(R
"cpp(
417 struct S { S(int a); };
418 template <typename T, typename... Args>
419 T* bar(Args&&... args) { return new T{args...}; }
425 ExpectedHint{"a: ",
"param"});
428TEST(ParameterHints, VariadicForwarded) {
431 assertParameterHints(R
"cpp(
432 namespace std { template <typename T> T&& forward(T&); }
434 template <typename... Args>
435 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
441 ExpectedHint{"a: ",
"param"});
444TEST(ParameterHints, VariadicPlain) {
446 assertParameterHints(R
"cpp(
448 template <typename... Args>
449 void bar(Args&&... args) { return foo(args...); }
454 ExpectedHint{"a: ",
"param"});
457TEST(ParameterHints, VariadicPlainWithPackFirst) {
460 assertParameterHints(R
"cpp(
462 template <typename... Args, typename Arg>
463 void bar(Arg, Args&&... args) { return foo(args...); }
465 bar(1, $param[[42]]);
468 ExpectedHint{"a: ",
"param"});
471TEST(ParameterHints, VariadicSplitTwolevel) {
475 assertParameterHints(R
"cpp(
476 namespace std { template <typename T> T&& forward(T&); }
477 void baz(int, int b, double);
478 template <typename... Args>
479 void foo(int a, Args&&... args) {
480 return baz(1, std::forward<Args>(args)..., 1.0);
482 template <typename... Args>
483 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
485 bar($param1[[32]], $param2[[42]]);
488 ExpectedHint{"a: ",
"param1"},
489 ExpectedHint{
"b: ",
"param2"});
492TEST(ParameterHints, VariadicNameFromSpecialization) {
495 assertParameterHints(R
"cpp(
497 template <typename... Args>
498 void bar(Args... args) {
502 void bar<int>(int b);
507 ExpectedHint{"b: ",
"param"});
510TEST(ParameterHints, VariadicNameFromSpecializationRecursive) {
513 assertParameterHints(R
"cpp(
515 template <typename... Args>
516 void foo(Args... args) {
519 template <typename... Args>
520 void bar(Args... args) {
524 void foo<int>(int b);
529 ExpectedHint{"b: ",
"param"});
532TEST(ParameterHints, VariadicOverloaded) {
536 assertParameterHints(
538 namespace std { template <typename T> T&& forward(T&); }
539 void baz(int b, int c);
540 void baz(int bb, int cc, int dd);
541 template <typename... Args>
542 void foo(int a, Args&&... args) {
543 return baz(std::forward<Args>(args)...);
545 template <typename... Args>
546 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
548 bar($param1[[32]], $param2[[42]], $param3[[52]]);
549 bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
552 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"},
553 ExpectedHint{
"c: ",
"param3"}, ExpectedHint{
"a: ",
"param4"},
554 ExpectedHint{
"bb: ",
"param5"}, ExpectedHint{
"cc: ",
"param6"},
555 ExpectedHint{
"dd: ",
"param7"});
558TEST(ParameterHints, VariadicRecursive) {
560 assertParameterHints(
564 template <typename Head, typename... Tail>
565 void foo(Head head, Tail... tail) {
569 template <typename... Args>
570 void bar(Args... args) {
580TEST(ParameterHints, VariadicVarargs) {
582 assertParameterHints(R
"cpp(
583 void foo(int fixed, ...);
584 template <typename... Args>
585 void bar(Args&&... args) {
590 bar($fixed[[41]], 42, 43);
595TEST(ParameterHints, VariadicTwolevelUnresolved) {
597 assertParameterHints(R
"cpp(
598 template <typename... Args>
599 void foo(int fixed, Args&& ... args);
600 template <typename... Args>
601 void bar(Args&&... args) {
606 bar($fixed[[41]], 42, 43);
609 ExpectedHint{"fixed: ",
"fixed"});
612TEST(ParameterHints, VariadicTwoCalls) {
614 assertParameterHints(
616 void f1(int a, int b);
617 void f2(int c, int d);
621 template <typename... Args>
622 void foo(Args... args) {
631 foo($param1[[1]], $param2[[2]]);
634 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"});
637TEST(ParameterHints, VariadicInfinite) {
639 assertParameterHints(
641 template <typename... Args>
644 template <typename... Args>
645 void bar(Args... args) {
649 template <typename... Args>
650 void foo(Args... args) {
660TEST(ParameterHints, VariadicDuplicatePack) {
662 assertParameterHints(
664 void foo(int a, int b, int c, int);
666 template <typename... Args>
667 void bar(int, Args... args, int d) {
671 template <typename... Args>
672 void baz(Args... args, Args... args2) {
673 bar<Args..., int>(1, args..., args2...);
677 baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
680 ExpectedHint{"a: ",
"p1"}, ExpectedHint{
"b: ",
"p2"},
681 ExpectedHint{
"c: ",
"p3"}, ExpectedHint{
"d: ",
"p4"});
684TEST(ParameterHints, VariadicEmplace) {
687 assertParameterHints(
689 namespace std { template <typename T> T&& forward(T&); }
690 using size_t = decltype(sizeof(0));
691 void *operator new(size_t, void *);
697 template <typename T>
699 template <typename T, typename... Args>
700 void construct(T* ptr, Args&&... args) {
701 ::new ((void*)ptr) T{std::forward<Args>(args)...};
704 template <typename T>
706 template <typename... Args>
707 void emplace(Args&&... args) {
709 auto ptr = a.template allocate<T>();
710 a.construct(ptr, std::forward<Args>(args)...);
715 c.emplace($param1[[1]]);
716 c.emplace($param2[[2]], $param3[[3]]);
719 ExpectedHint{"A: ",
"param1"}, ExpectedHint{
"B: ",
"param2"},
720 ExpectedHint{
"C: ",
"param3"});
723TEST(ParameterHints, VariadicReferenceHint) {
724 assertParameterHints(R
"cpp(
726 template <typename... Args>
727 void bar(Args... args) { return foo(args...); }
736TEST(ParameterHints, VariadicReferenceHintForwardingRef) {
737 assertParameterHints(R"cpp(
739 template <typename... Args>
740 void bar(Args&&... args) { return foo(args...); }
747 ExpectedHint{"&: ",
"param"});
750TEST(ParameterHints, VariadicReferenceHintForwardingRefStdForward) {
751 assertParameterHints(R
"cpp(
752 namespace std { template <typename T> T&& forward(T&); }
754 template <typename... Args>
755 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
761 ExpectedHint{"&: ",
"param"});
764TEST(ParameterHints, VariadicNoReferenceHintForwardingRefStdForward) {
765 assertParameterHints(R
"cpp(
766 namespace std { template <typename T> T&& forward(T&); }
768 template <typename... Args>
769 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
778TEST(ParameterHints, VariadicNoReferenceHintUnresolvedForward) {
779 assertParameterHints(R"cpp(
780 template <typename... Args>
781 void foo(Args&&... args);
789TEST(ParameterHints, MatchingNameVariadicForwarded) {
792 assertParameterHints(R
"cpp(
793 namespace std { template <typename T> T&& forward(T&); }
795 template <typename... Args>
796 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
804TEST(ParameterHints, MatchingNameVariadicPlain) {
806 assertParameterHints(R
"cpp(
808 template <typename... Args>
809 void bar(Args&&... args) { return foo(args...); }
819 assertParameterHints(R
"cpp(
821 void operator+(S lhs, S rhs);
829TEST(ParameterHints, FunctionCallOperator) {
830 assertParameterHints(R"cpp(
832 void operator()(int x);
836 static void operator()(int x, int y);
839 auto l1 = [](int x) {};
840 auto l2 = [](int x) static {};
844 s.operator()($2[[1]]);
845 s.operator()($3[[1]], $4[[2]]);
846 S::operator()($5[[1]], $6[[2]]);
849 l1.operator()($8[[1]]);
851 l2.operator()($10[[1]]);
853 void (*ptr)(int a, int b) = &S::operator();
854 ptr($11[[1]], $12[[2]]);
857 ExpectedHint{"x: ",
"1"}, ExpectedHint{
"x: ",
"2"},
858 ExpectedHint{
"x: ",
"3"}, ExpectedHint{
"y: ",
"4"},
859 ExpectedHint{
"x: ",
"5"}, ExpectedHint{
"y: ",
"6"},
860 ExpectedHint{
"x: ",
"7"}, ExpectedHint{
"x: ",
"8"},
861 ExpectedHint{
"x: ",
"9"}, ExpectedHint{
"x: ",
"10"},
862 ExpectedHint{
"a: ",
"11"}, ExpectedHint{
"b: ",
"12"});
865TEST(ParameterHints, DeducingThis) {
866 assertParameterHints(R
"cpp(
868 template <typename This>
869 auto operator()(this This &&Self, int Param) {
873 auto function(this auto &Self, int Param) {
880 s.function($2[[42]]);
882 auto lambda = [](this auto &Self, char C) -> void {
888 ExpectedHint{"Param: ",
"1"},
889 ExpectedHint{
"Param: ",
"2"},
890 ExpectedHint{
"Param: ",
"3"}, ExpectedHint{
"C: ",
"4"});
893TEST(ParameterHints, DependentDeducingThis) {
894 assertParameterHints(R
"cpp(
895 template <typename T>
897 void f1(this S& obj);
898 void f2(this S& obj, int x, int y);
901 s.f2($x[[42]], $y[[43]]);
905 ExpectedHint{"x: ",
"x"}, ExpectedHint{
"y: ",
"y"});
908TEST(ParameterHints, Macros) {
913 assertParameterHints(R
"cpp(
915 #define ExpandsToCall() foo(42)
923 assertParameterHints(R
"cpp(
925 void foo(double param);
930 ExpectedHint{"param: ",
"param"});
933 assertParameterHints(R
"cpp(
935 #define ASSERT(expr) if (!expr) abort()
938 ASSERT(foo($param[[42]]) == 0);
941 ExpectedHint{"param: ",
"param"});
944 assertParameterHints(R
"cpp(
945 void foo(double x, double y);
946 #define CONSTANTS 3.14, 2.72
953TEST(ParameterHints, ConstructorParens) {
954 assertParameterHints(R"cpp(
962 ExpectedHint{"param: ",
"param"});
965TEST(ParameterHints, ConstructorBraces) {
966 assertParameterHints(R
"cpp(
974 ExpectedHint{"param: ",
"param"});
977TEST(ParameterHints, ConstructorStdInitList) {
979 assertParameterHints(R
"cpp(
981 template <typename E> class initializer_list { const E *a, *b; };
984 S(std::initializer_list<int> param);
992TEST(ParameterHints, MemberInit) {
993 assertParameterHints(R"cpp(
999 T() : member($param[[42]]) {}
1002 ExpectedHint{"param: ",
"param"});
1005TEST(ParameterHints, ImplicitConstructor) {
1006 assertParameterHints(R
"cpp(
1012 // Do not show hint for implicit constructor call in argument.
1014 // Do not show hint for implicit constructor call in return.
1020TEST(ParameterHints, FunctionPointer) {
1021 assertParameterHints(
1023 void (*f1)(int param);
1024 void (__stdcall *f2)(int param);
1025 using f3_t = void(*)(int param);
1027 using f4_t = void(__stdcall *)(int param);
1029 __attribute__((noreturn)) f4_t f5;
1035 // This one runs into an edge case in clang's type model
1036 // and we can't extract the parameter name. But at least
1037 // we shouldn't crash.
1041 ExpectedHint{"param: ",
"f1"}, ExpectedHint{
"param: ",
"f2"},
1042 ExpectedHint{
"param: ",
"f3"}, ExpectedHint{
"param: ",
"f4"});
1045TEST(ParameterHints, ArgMatchesParam) {
1046 assertParameterHints(R
"cpp(
1047 void foo(int param);
1049 static const int param = 42;
1053 // Do not show redundant "param: param".
1055 // But show it if the argument is qualified.
1056 foo($param[[S::param]]);
1061 // Do not show "param: param" for member-expr.
1066 ExpectedHint{"param: ",
"param"});
1069TEST(ParameterHints, ArgMatchesParamReference) {
1070 assertParameterHints(R
"cpp(
1071 void foo(int& param);
1072 void foo2(const int& param);
1075 // show reference hint on mutable reference
1076 foo($param[[param]]);
1077 // but not on const reference
1081 ExpectedHint{"&: ",
"param"});
1084TEST(ParameterHints, LeadingUnderscore) {
1085 assertParameterHints(R
"cpp(
1086 void foo(int p1, int _p2, int __p3);
1088 foo($p1[[41]], $p2[[42]], $p3[[43]]);
1091 ExpectedHint{"p1: ",
"p1"}, ExpectedHint{
"p2: ",
"p2"},
1092 ExpectedHint{
"p3: ",
"p3"});
1095TEST(ParameterHints, DependentCalls) {
1096 assertParameterHints(R
"cpp(
1097 template <typename T>
1098 void nonmember(T par1);
1100 template <typename T>
1102 void member(T par2);
1103 static void static_member(T par3);
1106 void overload(int anInt);
1107 void overload(double aDouble);
1109 template <typename T>
1111 void bar(A<T> a, T t) {
1112 nonmember($par1[[t]]);
1113 a.member($par2[[t]]);
1114 A<T>::static_member($par3[[t]]);
1115 // We don't want to arbitrarily pick between
1116 // "anInt" or "aDouble", so just show no hint.
1121 ExpectedHint{"par1: ",
"par1"},
1122 ExpectedHint{
"par2: ",
"par2"},
1123 ExpectedHint{
"par3: ",
"par3"});
1126TEST(ParameterHints, VariadicFunction) {
1127 assertParameterHints(R
"cpp(
1128 template <typename... T>
1129 void foo(int fixed, T... variadic);
1132 foo($fixed[[41]], 42, 43);
1135 ExpectedHint{"fixed: ",
"fixed"});
1138TEST(ParameterHints, VarargsFunction) {
1139 assertParameterHints(R
"cpp(
1140 void foo(int fixed, ...);
1143 foo($fixed[[41]], 42, 43);
1146 ExpectedHint{"fixed: ",
"fixed"});
1149TEST(ParameterHints, CopyOrMoveConstructor) {
1151 assertParameterHints(R
"cpp(
1165TEST(ParameterHints, UserDefinedLiteral) {
1167 assertParameterHints(R
"cpp(
1168 long double operator"" _w(long double param);
1175TEST(ParameterHints, ParamNameComment) {
1178 assertParameterHints(R
"cpp(
1179 void foo(int param);
1182 foo( /* param = */ 42);
1186 foo(/*param=*/Z(a));
1187 foo($macro[[Z(a)]]);
1188 foo(/* the answer */$param[[42]]);
1191 ExpectedHint{"param: ",
"macro"},
1192 ExpectedHint{
"param: ",
"param"});
1195TEST(ParameterHints, SetterFunctions) {
1196 assertParameterHints(R
"cpp(
1198 void setParent(S* parent);
1199 void set_parent(S* parent);
1200 void setTimeout(int timeoutMillis);
1201 void setTimeoutMillis(int timeout_millis);
1205 // Parameter name matches setter name - omit hint.
1206 s.setParent(nullptr);
1207 // Support snake_case
1208 s.set_parent(nullptr);
1209 // Parameter name may contain extra info - show hint.
1210 s.setTimeout($timeoutMillis[[120]]);
1211 // FIXME: Ideally we'd want to omit this.
1212 s.setTimeoutMillis($timeout_millis[[120]]);
1215 ExpectedHint{"timeoutMillis: ",
"timeoutMillis"},
1216 ExpectedHint{
"timeout_millis: ",
"timeout_millis"});
1219TEST(ParameterHints, BuiltinFunctions) {
1221 assertParameterHints(R
"cpp(
1222 namespace std { template <typename T> T&& forward(T&); }
1230TEST(ParameterHints, IncludeAtNonGlobalScope) {
1232 void bar() { foo(42); }
1236 void foo(int param);
1242 Workspace.addSource("foo.inc", FooInc.code());
1243 Workspace.addMainFile(
"foo.cc", FooCC.code());
1245 auto AST = Workspace.openFile(
"foo.cc");
1246 ASSERT_TRUE(
bool(
AST));
1254TEST(ParameterHints, Issue220359_NoCrash) {
1255 assertParameterHints(R
"cpp(
1259 template <typename... Args>
1260 void f(Args... args) {
1269TEST(TypeHints, Smoke) {
1270 assertTypeHints(R"cpp(
1271 auto $waldo[[waldo]] = 42;
1273 ExpectedHint{": int",
"waldo"});
1276TEST(TypeHints, Decorations) {
1277 assertTypeHints(R
"cpp(
1279 auto* $var1[[var1]] = &x;
1280 auto&& $var2[[var2]] = x;
1281 const auto& $var3[[var3]] = x;
1283 ExpectedHint{": int *",
"var1"},
1284 ExpectedHint{
": int &",
"var2"},
1285 ExpectedHint{
": const int &",
"var3"});
1288TEST(TypeHints, DecltypeAuto) {
1289 assertTypeHints(R
"cpp(
1292 decltype(auto) $z[[z]] = y;
1294 ExpectedHint{": int &",
"z"});
1297TEST(TypeHints, NoQualifiers) {
1298 assertTypeHints(R
"cpp(
1303 auto $x[[x]] = foo();
1306 template <typename T>
1309 S2::Inner<int> bar();
1310 auto $y[[y]] = bar();
1314 ExpectedHint{": S1",
"x"}, ExpectedHint{
": Inner<int>",
"y"});
1317TEST(TypeHints, Lambda) {
1320 assertTypeHints(R
"cpp(
1323 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1324 return a + cap + init;
1328 ExpectedHint{": (lambda)",
"L"},
1329 ExpectedHint{
": int",
"init"}, ExpectedHint{
"-> int",
"ret"});
1333 assertTypeHints(
"auto $L[[x]] = <:$ret[[:>]]{return 42;};",
1334 ExpectedHint{
": (lambda)",
"L"},
1335 ExpectedHint{
"-> int",
"ret"});
1339 assertTypeHints(R
"cpp(
1341 []() $ret[[noexcept]] {};
1342 [] $retNoParams[[noexcept]] {};
1345 ExpectedHint{"-> void",
"ret"},
1346 ExpectedHint{
"-> void",
"retNoParams"});
1352TEST(TypeHints, StructuredBindings_PublicStruct) {
1353 assertTypeHints(R
"cpp(
1354 // Struct with public fields.
1360 auto [$x[[x]], $y[[y]]] = foo();
1362 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
1365TEST(TypeHints, StructuredBindings_Array) {
1366 assertTypeHints(R
"cpp(
1368 auto [$x[[x]], $y[[y]]] = arr;
1370 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
1373TEST(TypeHints, StructuredBindings_TupleLike) {
1374 assertTypeHints(R
"cpp(
1381 template <typename T>
1382 struct tuple_size {};
1384 struct tuple_size<IntPair> {
1385 constexpr static unsigned value = 2;
1387 template <unsigned I, typename T>
1388 struct tuple_element {};
1389 template <unsigned I>
1390 struct tuple_element<I, IntPair> {
1394 template <unsigned I>
1395 int get(const IntPair& p) {
1396 if constexpr (I == 0) {
1398 } else if constexpr (I == 1) {
1403 auto [$x[[x]], $y[[y]]] = bar();
1405 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
1408TEST(TypeHints, StructuredBindings_NoInitializer) {
1409 assertTypeHints(R
"cpp(
1410 // No initializer (ill-formed).
1411 // Do not show useless "NULL TYPE" hint.
1412 auto [x, y]; /*error-ok*/
1416TEST(TypeHints, InvalidType) {
1417 assertTypeHints(R"cpp(
1418 auto x = (unknown_type)42; /*error-ok*/
1419 auto *y = (unknown_ptr)nullptr;
1423TEST(TypeHints, ReturnTypeDeduction) {
1426 auto f1(int x$ret1a[[)]]; // Hint forward declaration too
1427 auto f1(int x$ret1b[[)]] { return x + 1; }
1429 // Include pointer operators in hint
1431 auto& f2($ret2[[)]] { return s; }
1433 // Do not hint `auto` for trailing return type.
1436 // Do not hint when a trailing return type is specified.
1437 auto f4() -> auto* { return "foo"; }
1439 auto f5($noreturn[[)]] {}
1441 auto f6() $retNoexcept[[noexcept]] { return 42; }
1443 // `auto` conversion operator
1445 operator auto($retConv[[)]] { return 42; }
1448 // FIXME: Dependent types do not work yet.
1449 template <typename T>
1451 auto method() { return T(); }
1454 ExpectedHint{"-> int",
"ret1a"}, ExpectedHint{
"-> int",
"ret1b"},
1455 ExpectedHint{
"-> int &",
"ret2"}, ExpectedHint{
"-> void",
"noreturn"},
1456 ExpectedHint{
"-> int",
"retNoexcept"}, ExpectedHint{
"-> int",
"retConv"});
1459TEST(TypeHints, DependentType) {
1460 assertTypeHints(R
"cpp(
1461 template <typename T>
1463 // The hint would just be "auto" and we can't do any better.
1464 auto var1 = arg.method();
1465 // FIXME: It would be nice to show "T" as the hint.
1466 auto $var2[[var2]] = arg;
1469 template <typename T>
1474 ExpectedHint{": T",
"var2"});
1477TEST(TypeHints, LongTypeName) {
1478 assertTypeHints(R
"cpp(
1479 template <typename, typename, typename>
1481 struct MultipleWords {};
1482 A<MultipleWords, MultipleWords, MultipleWords> foo();
1483 // Omit type hint past a certain length (currently 32)
1493 template <typename, typename, typename>
1495 struct MultipleWords {};
1496 A<MultipleWords, MultipleWords, MultipleWords> foo();
1497 // Should have type hint with TypeNameLimit = 0
1498 auto $var[[var]] = foo();
1500 ExpectedHint{": A<MultipleWords, MultipleWords, MultipleWords>",
"var"});
1503TEST(TypeHints, DefaultTemplateArgs) {
1504 assertTypeHints(R
"cpp(
1505 template <typename, typename = int>
1508 auto $var[[var]] = foo();
1510 auto [$binding[[value]]] = bar;
1512 ExpectedHint{": A<float>",
"var"},
1513 ExpectedHint{
": A<float>",
"binding"});
1516TEST(DefaultArguments, Smoke) {
1520 Cfg.InlayHints.DeducedTypes =
false;
1521 Cfg.InlayHints.Designators =
false;
1522 Cfg.InlayHints.BlockEnd =
false;
1524 Cfg.InlayHints.DefaultArguments =
true;
1527 const auto *Code = R
"cpp(
1528 int foo(int A = 4) { return A; }
1529 int bar(int A, int B = 1, bool C = foo($default1[[)]]) { return A; }
1530 int A = bar($explicit[[2]]$default2[[)]];
1532 void baz(int = 5) { if (false) baz($unnamed[[)]]; };
1536 ExpectedHint{"A: 4",
"default1",
Left},
1537 ExpectedHint{
", B: 1, C: foo()",
"default2",
Left},
1538 ExpectedHint{
"5",
"unnamed",
Left});
1541 ExpectedHint{
"A: ",
"explicit",
Left});
1544TEST(DefaultArguments, WithoutParameterNames) {
1547 Cfg.InlayHints.DeducedTypes =
false;
1548 Cfg.InlayHints.Designators =
false;
1549 Cfg.InlayHints.BlockEnd =
false;
1551 Cfg.InlayHints.DefaultArguments =
true;
1554 const auto *Code = R
"cpp(
1560 Foo(int, Baz baz = //
1561 Baz{$abbreviated[[}]]
1568 Foo foo1(1$paren[[)]];
1569 Foo foo2{2$brace1[[}]];
1570 Foo foo3 = {3$brace2[[}]];
1571 auto foo4 = Foo{4$brace3[[}]];
1576 ExpectedHint{"...",
"abbreviated",
Left},
1577 ExpectedHint{
", Baz{}",
"paren",
Left},
1578 ExpectedHint{
", Baz{}",
"brace1",
Left},
1579 ExpectedHint{
", Baz{}",
"brace2",
Left},
1580 ExpectedHint{
", Baz{}",
"brace3",
Left});
1585TEST(TypeHints, Deduplication) {
1586 assertTypeHints(R
"cpp(
1587 template <typename T>
1589 auto $var[[var]] = 42;
1591 template void foo<int>();
1592 template void foo<float>();
1594 ExpectedHint{": int",
"var"});
1597TEST(TypeHints, SinglyInstantiatedTemplate) {
1598 assertTypeHints(R
"cpp(
1599 auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
1600 int m = x("foo", 3);
1602 ExpectedHint{": (lambda)",
"lambda"},
1603 ExpectedHint{
": const char *",
"param"});
1606 assertTypeHints(R
"cpp(
1607 int x(auto $a[[a]], auto... b, auto c) { return 42; }
1608 int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
1610 ExpectedHint{": void *",
"a"});
1613TEST(TypeHints, Aliased) {
1617 TU.ExtraArgs.push_back(
"-xc");
1618 auto AST = TU.build();
1624TEST(TypeHints, CallingConvention) {
1629 []($lambda[[)]]__cdecl {};
1633 TU.ExtraArgs.push_back("--target=x86_64-w64-mingw32");
1634 TU.PredefineMacros =
true;
1635 auto AST = TU.build();
1639 ElementsAre(HintMatcher(ExpectedHint{
"-> void",
"lambda"}, Source)));
1642TEST(TypeHints, Decltype) {
1643 assertTypeHints(R
"cpp(
1644 $a[[decltype(0)]] a;
1645 $b[[decltype(a)]] b;
1646 const $c[[decltype(0)]] &c = b;
1648 // Don't show for dependent type
1650 constexpr decltype(T{}) d;
1652 $e[[decltype(0)]] e();
1653 auto f() -> $f[[decltype(0)]];
1655 template <class, class> struct Foo;
1656 using G = Foo<$g[[decltype(0)]], float>;
1658 auto $h[[h]] = $i[[decltype(0)]]{};
1664 ExpectedHint{": int",
"a"}, ExpectedHint{
": int",
"b"},
1665 ExpectedHint{
": int",
"c"}, ExpectedHint{
": int",
"e"},
1666 ExpectedHint{
": int",
"f"}, ExpectedHint{
": int",
"g"},
1667 ExpectedHint{
": int",
"h"}, ExpectedHint{
": int",
"i"});
1670TEST(TypeHints, SubstTemplateParameterAliases) {
1671 llvm::StringRef Header = R
"cpp(
1672 template <class T> struct allocator {};
1674 template <class T, class A>
1675 struct vector_base {
1679 template <class T, class A>
1680 struct internal_iterator_type_template_we_dont_expect {};
1682 struct my_iterator {};
1684 template <class T, class A = allocator<T>>
1685 struct vector : vector_base<T, A> {
1686 using base = vector_base<T, A>;
1687 typedef T value_type;
1688 typedef base::pointer pointer;
1689 using allocator_type = A;
1690 using size_type = int;
1691 using iterator = internal_iterator_type_template_we_dont_expect<T, A>;
1692 using non_template_iterator = my_iterator;
1694 value_type& operator[](int index) { return elements[index]; }
1695 const value_type& at(int index) const { return elements[index]; }
1696 pointer data() { return &elements[0]; }
1697 allocator_type get_allocator() { return A(); }
1698 size_type size() const { return 10; }
1699 iterator begin() { return iterator(); }
1700 non_template_iterator end() { return non_template_iterator(); }
1706 llvm::StringRef VectorIntPtr = R"cpp(
1707 vector<int *> array;
1708 auto $no_modifier[[x]] = array[3];
1709 auto* $ptr_modifier[[ptr]] = &array[3];
1710 auto& $ref_modifier[[ref]] = array[3];
1711 auto& $at[[immutable]] = array.at(3);
1713 auto $data[[data]] = array.data();
1714 auto $allocator[[alloc]] = array.get_allocator();
1715 auto $size[[size]] = array.size();
1716 auto $begin[[begin]] = array.begin();
1717 auto $end[[end]] = array.end();
1720 assertHintsWithHeader(
1722 ExpectedHint{": int *",
"no_modifier"},
1723 ExpectedHint{
": int **",
"ptr_modifier"},
1724 ExpectedHint{
": int *&",
"ref_modifier"},
1725 ExpectedHint{
": int *const &",
"at"}, ExpectedHint{
": int **",
"data"},
1726 ExpectedHint{
": allocator<int *>",
"allocator"},
1727 ExpectedHint{
": size_type",
"size"}, ExpectedHint{
": iterator",
"begin"},
1728 ExpectedHint{
": non_template_iterator",
"end"});
1730 llvm::StringRef VectorInt = R
"cpp(
1732 auto $no_modifier[[by_value]] = array[3];
1733 auto* $ptr_modifier[[ptr]] = &array[3];
1734 auto& $ref_modifier[[ref]] = array[3];
1735 auto& $at[[immutable]] = array.at(3);
1737 auto $data[[data]] = array.data();
1738 auto $allocator[[alloc]] = array.get_allocator();
1739 auto $size[[size]] = array.size();
1740 auto $begin[[begin]] = array.begin();
1741 auto $end[[end]] = array.end();
1744 assertHintsWithHeader(
1746 ExpectedHint{": int",
"no_modifier"},
1747 ExpectedHint{
": int *",
"ptr_modifier"},
1748 ExpectedHint{
": int &",
"ref_modifier"},
1749 ExpectedHint{
": const int &",
"at"}, ExpectedHint{
": int *",
"data"},
1750 ExpectedHint{
": allocator<int>",
"allocator"},
1751 ExpectedHint{
": size_type",
"size"}, ExpectedHint{
": iterator",
"begin"},
1752 ExpectedHint{
": non_template_iterator",
"end"});
1754 llvm::StringRef TypeAlias = R
"cpp(
1755 // If the type alias is not of substituted template parameter type,
1756 // do not show desugared type.
1757 using VeryLongLongTypeName = my_iterator;
1758 using Short = VeryLongLongTypeName;
1760 auto $short_name[[my_value]] = Short();
1762 // Same applies with templates.
1763 template <typename T, typename A>
1764 using basic_static_vector = vector<T, A>;
1765 template <typename T>
1766 using static_vector = basic_static_vector<T, allocator<T>>;
1768 auto $vector_name[[vec]] = static_vector<int>();
1772 DefaultOptsForTests,
1773 ExpectedHint{": Short",
"short_name"},
1774 ExpectedHint{
": static_vector<int>",
"vector_name"});
1777TEST(DesignatorHints, Basic) {
1778 assertDesignatorHints(R
"cpp(
1779 struct S { int x, y, z; };
1780 S s {$x[[1]], $y[[2+2]]};
1782 int x[] = {$0[[0]], $1[[1]]};
1784 ExpectedHint{".x=",
"x"}, ExpectedHint{
".y=",
"y"},
1785 ExpectedHint{
"[0]=",
"0"}, ExpectedHint{
"[1]=",
"1"});
1788TEST(DesignatorHints, Nested) {
1789 assertDesignatorHints(R
"cpp(
1790 struct Inner { int x, y; };
1791 struct Outer { Inner a, b; };
1792 Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
1794 ExpectedHint{".a=",
"a"}, ExpectedHint{
".x=",
"x"},
1795 ExpectedHint{
".y=",
"y"}, ExpectedHint{
".b.x=",
"bx"});
1798TEST(DesignatorHints, AnonymousRecord) {
1799 assertDesignatorHints(R
"cpp(
1811 ExpectedHint{".x.y=",
"xy"});
1814TEST(DesignatorHints, Suppression) {
1815 assertDesignatorHints(R
"cpp(
1816 struct Point { int a, b, c, d, e, f, g, h; };
1817 Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
1819 ExpectedHint{".e=",
"e"});
1822TEST(DesignatorHints, StdArray) {
1825 assertDesignatorHints(R
"cpp(
1826 template <typename T, int N> struct Array { T __elements[N]; };
1827 Array<int, 2> x = {$0[[0]], $1[[1]]};
1829 ExpectedHint{"[0]=",
"0"}, ExpectedHint{
"[1]=",
"1"});
1832TEST(DesignatorHints, OnlyAggregateInit) {
1833 assertDesignatorHints(R
"cpp(
1834 struct Copyable { int x; } c;
1837 struct Constructible { Constructible(int x); };
1838 Constructible x{42};
1842TEST(DesignatorHints, NoCrash) {
1843 assertDesignatorHints(R
"cpp(
1846 struct Foo {int a; int b;};
1848 Foo f{A(), $b[[1]]};
1851 ExpectedHint{".b=",
"b"});
1854TEST(DesignatorHints, ParenInit) {
1855 assertDesignatorHints(R
"cpp(
1861 S s ($x[[1]], $y[[2+2]], $z[[4]]);
1863 ExpectedHint{".x=",
"x"}, ExpectedHint{
".y=",
"y"},
1864 ExpectedHint{
".z=",
"z"});
1867TEST(DesignatorHints, ParenInitDerived) {
1868 assertDesignatorHints(R
"cpp(
1878 S2 s2 ({$a[[0]], $b[[0]]}, $c[[0]], $d[[0]]);
1881 ExpectedHint{
".a=",
"a"}, ExpectedHint{
".b=",
"b"},
1882 ExpectedHint{
".c=",
"c"}, ExpectedHint{
".d=",
"d"});
1885TEST(DesignatorHints, ParenInitTemplate) {
1886 assertDesignatorHints(R
"cpp(
1887 template <typename T>
1894 struct S2 : S1<S2> {
1901 S2 sa ({$a1[[0]], $b1[[0]]}, $c[[0]], $d[[0]], $mem[[S1<int>($a2[[1]], $b2[[2]], $ptr[[nullptr]])]]);
1904 ExpectedHint{".a=",
"a1"}, ExpectedHint{
".b=",
"b1"},
1905 ExpectedHint{
".c=",
"c"}, ExpectedHint{
".d=",
"d"},
1906 ExpectedHint{
".mem=",
"mem"}, ExpectedHint{
".a=",
"a2"},
1907 ExpectedHint{
".b=",
"b2"},
1908 ExpectedHint{
".ptr=",
"ptr"});
1911TEST(InlayHints, RestrictRange) {
1920 ElementsAre(labelIs(
": int"), labelIs(
": char")));
1923TEST(ParameterHints, PseudoObjectExpr) {
1926 __declspec(property(get=GetX, put=PutX)) int x[];
1927 int GetX(int y, int z) { return 42 + y; }
1930 // This is a PseudoObjectExpression whose syntactic form is a binary
1932 void Work(int y) { x = y; } // Not `x = y: y`.
1935 int printf(const char *Format, ...);
1939 __builtin_dump_struct(&s, printf); // Not `Format: __builtin_dump_struct()`
1940 printf($Param[["Hello, %d"]], 42); // Normal calls are not affected.
1941 // This builds a PseudoObjectExpr, but here it's useful for showing the
1942 // arguments from the semantic form.
1943 return s.x[ $one[[1]] ][ $two[[2]] ]; // `x[y: 1][z: 2]`
1947 TU.ExtraArgs.push_back(
"-fms-extensions");
1948 auto AST = TU.build();
1950 ElementsAre(HintMatcher(ExpectedHint{
"Format: ",
"Param"}, Code),
1951 HintMatcher(ExpectedHint{
"y: ",
"one"}, Code),
1952 HintMatcher(ExpectedHint{
"z: ",
"two"}, Code)));
1955TEST(ParameterHints, ArgPacksAndConstructors) {
1956 assertParameterHints(
1958 struct Foo{ Foo(); Foo(int x); };
1959 void foo(Foo a, int b);
1960 template <typename... Args>
1961 void bar(Args... args) {
1964 template <typename... Args>
1965 void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
1967 template <typename... Args>
1968 void bax(Args... args) { foo($param3[[{args...}]], args...); }
1971 bar($param4[[Foo{}]], $param5[[42]]);
1972 bar($param6[[42]], $param7[[42]]);
1977 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"},
1978 ExpectedHint{
"a: ",
"param3"}, ExpectedHint{
"a: ",
"param4"},
1979 ExpectedHint{
"b: ",
"param5"}, ExpectedHint{
"a: ",
"param6"},
1980 ExpectedHint{
"b: ",
"param7"}, ExpectedHint{
"x: ",
"param8"},
1981 ExpectedHint{
"b: ",
"param9"});
1984TEST(ParameterHints, DoesntExpandAllArgs) {
1985 assertParameterHints(
1987 void foo(int x, int y);
1988 int id(int a, int b, int c);
1989 template <typename... Args>
1990 void bar(Args... args) {
1991 foo(id($param1[[args]], $param2[[1]], $param3[[args]])...);
1994 bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1997 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"},
1998 ExpectedHint{
"c: ",
"param3"});
2001TEST(BlockEndHints, Functions) {
2002 assertBlockEndHints(R
"cpp(
2009 // No hint for lambda for now
2016 // No hint because this isn't a definition
2020 bool operator==(S, S) {
2024 ExpectedHint{" // foo",
"foo"},
2025 ExpectedHint{
" // bar",
"bar"},
2026 ExpectedHint{
" // operator==",
"opEqual"});
2029TEST(BlockEndHints, Methods) {
2030 assertBlockEndHints(R
"cpp(
2032 // No hint because there's no function body
2041 // No hint because this isn't a definition
2044 template <typename T>
2048 // No hint because this isn't a definition
2049 template <typename T>
2052 Test operator+(int) const {
2056 operator bool() const {
2060 // No hint because there's no function body
2061 operator int() const = delete;
2064 void Test::method2() {
2067 template <typename T>
2068 void Test::method4() {
2071 ExpectedHint{" // ~Test",
"dtor"},
2072 ExpectedHint{
" // method1",
"method1"},
2073 ExpectedHint{
" // method3",
"method3"},
2074 ExpectedHint{
" // operator+",
"opIdentity"},
2075 ExpectedHint{
" // operator bool",
"opBool"},
2076 ExpectedHint{
" // Test::method2",
"method2"},
2077 ExpectedHint{
" // Test::method4",
"method4"});
2080TEST(BlockEndHints, Namespaces) {
2081 assertBlockEndHints(
2091 ExpectedHint{" // namespace",
"anon"},
2092 ExpectedHint{
" // namespace ns",
"ns"});
2095TEST(BlockEndHints, Types) {
2096 assertBlockEndHints(
2113 ExpectedHint{" // struct S",
"S"}, ExpectedHint{
" // class C",
"C"},
2114 ExpectedHint{
" // union U",
"U"}, ExpectedHint{
" // enum E1",
"E1"},
2115 ExpectedHint{
" // enum class E2",
"E2"});
2118TEST(BlockEndHints, If) {
2119 assertBlockEndHints(
2121 void foo(bool cond) {
2143 if (auto X = cond) {
2146 if (int i = 0; i > 10) {
2149 if (ptr != nullptr) {
2153 ExpectedHint{" // if cond",
"simple"},
2154 ExpectedHint{
" // if cond",
"ifelse"}, ExpectedHint{
" // if",
"elseif"},
2155 ExpectedHint{
" // if !cond",
"inner"},
2156 ExpectedHint{
" // if cond",
"outer"}, ExpectedHint{
" // if X",
"init"},
2157 ExpectedHint{
" // if i > 10",
"init_cond"},
2158 ExpectedHint{
" // if ptr != nullptr",
"null_check"});
2161TEST(BlockEndHints, Loops) {
2162 assertBlockEndHints(
2177 for (int I = 0; I < 10; ++I) {
2185 ExpectedHint{" // while true",
"while"},
2186 ExpectedHint{
" // for true",
"forcond"},
2187 ExpectedHint{
" // for I",
"forvar"},
2188 ExpectedHint{
" // for V",
"foreach"});
2191TEST(BlockEndHints, Switch) {
2192 assertBlockEndHints(
2200 ExpectedHint{" // switch I",
"switch"});
2203TEST(BlockEndHints, PrintLiterals) {
2204 assertBlockEndHints(
2210 while ("foo but this time it is very long") {
2223 ExpectedHint{" // while \"foo\"",
"string"},
2224 ExpectedHint{
" // while \"foo but...\"",
"string_long"},
2225 ExpectedHint{
" // while true",
"boolean"},
2226 ExpectedHint{
" // while 1",
"integer"},
2227 ExpectedHint{
" // while 1.5",
"float"});
2230TEST(BlockEndHints, PrintRefs) {
2231 assertBlockEndHints(
2236 int func2(int, int);
2239 int method1() const;
2240 int method2(int, int) const;
2248 while (ns::func1()) {
2251 while (ns::func2(int_a, int_a)) {
2254 while (ns::S{}.Field) {
2257 while (ns::S{}.method1()) {
2260 while (ns::S{}.method2(int_a, int_a)) {
2264 ExpectedHint{" // while Var",
"var"},
2265 ExpectedHint{
" // while func1()",
"func1"},
2266 ExpectedHint{
" // while func2(...)",
"func2"},
2267 ExpectedHint{
" // while Field",
"field"},
2268 ExpectedHint{
" // while method1()",
"method1"},
2269 ExpectedHint{
" // while method2(...)",
"method2"});
2272TEST(BlockEndHints, PrintConversions) {
2273 assertBlockEndHints(
2278 explicit operator bool();
2282 $convert_primitive[[}]]
2288 $construct_class[[}]]
2291 ExpectedHint{" // while float",
"convert_primitive"},
2292 ExpectedHint{
" // while S",
"convert_class"},
2293 ExpectedHint{
" // while S",
"construct_class"});
2296TEST(BlockEndHints, PrintOperators) {
2297 std::string AnnotatedCode = R
"cpp(
2298 void foo(Integer I) {
2317 while((I + I) < (I + I)){
2318 $binary_complex[[}]]
2323 auto AssertExpectedHints = [&](llvm::StringRef Code) {
2324 assertBlockEndHints(Code, ExpectedHint{
" // while ++I",
"preinc"},
2325 ExpectedHint{
" // while I++",
"postinc"},
2326 ExpectedHint{
" // while",
"unary_complex"},
2327 ExpectedHint{
" // while I < 0",
"compare"},
2328 ExpectedHint{
" // while ... < I",
"lhs_complex"},
2329 ExpectedHint{
" // while I < ...",
"rhs_complex"},
2330 ExpectedHint{
" // while",
"binary_complex"});
2334 AssertExpectedHints(
"using Integer = int;" + AnnotatedCode);
2336 AssertExpectedHints(R
"cpp(
2338 explicit operator bool();
2339 Integer operator++();
2340 Integer operator++(int);
2341 Integer operator+(Integer);
2342 Integer operator+();
2343 bool operator<(Integer);
2344 bool operator<(int);
2346 )cpp" + AnnotatedCode);
2349TEST(BlockEndHints, TrailingSemicolon) {
2350 assertBlockEndHints(R"cpp(
2351 // The hint is placed after the trailing ';'
2355 // The hint is always placed in the same line with the closing '}'.
2356 // So in this case where ';' is missing, it is attached to '}'.
2362 // No hint because only one trailing ';' is allowed
2366 // No hint because trailing ';' is only allowed for class/struct/union/enum
2370 // Rare case, but yes we'll have a hint here.
2377 ExpectedHint{" // struct S1",
"S1"},
2378 ExpectedHint{
" // struct S2",
"S2"},
2379 ExpectedHint{
" // struct",
"anon"});
2382TEST(BlockEndHints, TrailingText) {
2383 assertBlockEndHints(R
"cpp(
2387 // No hint for S2 because of the trailing comment
2389 }; /* Put anything here */
2392 // No hint for S4 because of the trailing source code
2396 // No hint for ns because of the trailing comment
2400 ExpectedHint{" // struct S1",
"S1"},
2401 ExpectedHint{
" // struct S3",
"S3"});
2405 assertBlockEndHints(R
"cpp(
2406 #define DECL_STRUCT(NAME) struct NAME {
2412 // No hint because we require a '}'
2416 ExpectedHint{" // struct S1",
"S1"});
2419TEST(BlockEndHints, PointerToMemberFunction) {
2421 assertBlockEndHints(R
"cpp(
2423 using Predicate = bool(A::*)();
2424 void foo(A* a, Predicate p) {
2429 ExpectedHint{" // if ()",
"ptrmem"});
2432TEST(BlockEndHints, MinLineLimit) {
2437 assertBlockEndHintsWithOpts(
2442 int func2(int, int);
2445 int method1() const;
2446 int method2(int, int) const;
2454 while (ns::func1()) {
2457 while (ns::func2(int_a, int_a)) {
2460 while (ns::S{}.Field) {
2463 while (ns::S{}.method1()) {
2466 while (ns::S{}.method2(int_a, int_a)) {
2470 Opts, ExpectedHint{" // namespace ns",
"namespace"},
2471 ExpectedHint{
" // foo",
"foo"});
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
void addSource(llvm::StringRef Filename, llvm::StringRef Code)
WithContextValue extends Context::current() with a single value.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
MATCHER_P2(hasFlag, Flag, Path, "")
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
TEST(BackgroundQueueTest, Priority)
InlayHintKind
Inlay hint kinds.
@ BlockEnd
A hint after function, type or namespace definition, indicating the defined symbol name of the defini...
@ DefaultArgument
An inlay hint that is for a default argument.
@ Parameter
An inlay hint that is for a parameter.
@ Type
An inlay hint that for a type annotation.
@ Designator
A hint before an element of an aggregate braced initializer list, indicating what it is initializing.
std::vector< InlayHint > inlayHints(ParsedAST &AST, std::optional< Range > RestrictRange, InlayHintOptions HintOptions)
Compute and return inlay hints for a file.
===– 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.
struct clang::clangd::Config::@041344304366110202143331236314370324353035136032 InlayHints
std::string joinLabels() const
Join the label[].value together.
Range range
The range of source code to which the hint applies.
static TestTU withCode(llvm::StringRef Code)