16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/ScopedPrinter.h"
18#include "gmock/gmock.h"
19#include "gtest/gtest.h"
33using ::testing::ElementsAre;
34using ::testing::IsEmpty;
37 std::vector<InlayHint> Result;
39 if (Hint.kind ==
Kind)
40 Result.push_back(Hint);
52 friend llvm::raw_ostream &
operator<<(llvm::raw_ostream &Stream,
53 const ExpectedHint &Hint) {
54 return Stream << Hint.Label <<
"@$" << Hint.RangeName;
59 llvm::StringRef ExpectedView(
Expected.Label);
60 std::string ResultLabel = arg.joinLabels();
61 if (ResultLabel != ExpectedView.trim(
" ") ||
62 arg.paddingLeft != ExpectedView.starts_with(
" ") ||
63 arg.paddingRight != ExpectedView.ends_with(
" ")) {
64 *result_listener <<
"label is '" << ResultLabel <<
"'";
68 *result_listener <<
"range is " << llvm::to_string(arg.range) <<
" but $"
78Config noHintsConfig() {
80 C.InlayHints.Parameters =
false;
81 C.InlayHints.DeducedTypes =
false;
82 C.InlayHints.Designators =
false;
83 C.InlayHints.BlockEnd =
false;
87template <
typename... ExpectedHints>
89 llvm::StringRef HeaderContent,
91 Annotations Source(AnnotatedSource);
93 TU.ExtraArgs.push_back(
"-std=c++23");
94 TU.HeaderCode = HeaderContent;
95 auto AST = TU.build();
97 EXPECT_THAT(hintsOfKind(
AST,
Kind),
98 ElementsAre(HintMatcher(
Expected, Source)...));
101 WithContextValue WithCfg(
Config::Key, noHintsConfig());
105template <
typename... ExpectedHints>
108 return assertHintsWithHeader(
Kind, AnnotatedSource,
"",
113template <
typename...
T>
void ignore(T &&...) {}
115template <
typename... ExpectedHints>
116void assertParameterHints(llvm::StringRef AnnotatedSource,
122template <
typename... ExpectedHints>
123void assertTypeHints(llvm::StringRef AnnotatedSource,
129template <
typename... ExpectedHints>
130void assertDesignatorHints(llvm::StringRef AnnotatedSource,
134 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
138template <
typename... ExpectedHints>
139void assertBlockEndHints(llvm::StringRef AnnotatedSource,
143 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
147TEST(ParameterHints, Smoke) {
148 assertParameterHints(R
"cpp(
154 ExpectedHint{"param: ",
"param"});
157TEST(ParameterHints, NoName) {
159 assertParameterHints(R
"cpp(
167TEST(ParameterHints, NoNameConstReference) {
169 assertParameterHints(R
"cpp(
170 void foo(const int&);
177TEST(ParameterHints, NoNameReference) {
179 assertParameterHints(R
"cpp(
186 ExpectedHint{"&: ",
"param"});
189TEST(ParameterHints, NoNameRValueReference) {
191 assertParameterHints(R
"cpp(
199TEST(ParameterHints, NoNameVariadicDeclaration) {
201 assertParameterHints(R
"cpp(
202 template <typename... Args>
203 void foo(Args&& ...);
210TEST(ParameterHints, NoNameVariadicForwarded) {
213 assertParameterHints(R
"cpp(
214 namespace std { template <typename T> T&& forward(T&); }
216 template <typename... Args>
217 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
224TEST(ParameterHints, NoNameVariadicPlain) {
226 assertParameterHints(R
"cpp(
228 template <typename... Args>
229 void bar(Args&&... args) { return foo(args...); }
236TEST(ParameterHints, NameInDefinition) {
238 assertParameterHints(R
"cpp(
243 void foo(int param) {};
245 ExpectedHint{"param: ",
"param"});
248TEST(ParameterHints, NamePartiallyInDefinition) {
250 assertParameterHints(R
"cpp(
251 void foo(int, int b);
253 foo($param1[[42]], $param2[[42]]);
255 void foo(int a, int) {};
257 ExpectedHint{"a: ",
"param1"},
258 ExpectedHint{
"b: ",
"param2"});
261TEST(ParameterHints, NameInDefinitionVariadic) {
263 assertParameterHints(R
"cpp(
265 template <typename... Args>
266 void bar(Args... args) {
270 bar($param1[[42]], $param2[[42]]);
272 void foo(int a, int b) {};
274 ExpectedHint{"a: ",
"param1"},
275 ExpectedHint{
"b: ",
"param2"});
278TEST(ParameterHints, NameMismatch) {
280 assertParameterHints(R
"cpp(
285 void foo(int bad) {};
287 ExpectedHint{"good: ",
"good"});
290TEST(ParameterHints, NameConstReference) {
292 assertParameterHints(R
"cpp(
293 void foo(const int& param);
298 ExpectedHint{"param: ",
"param"});
301TEST(ParameterHints, NameTypeAliasConstReference) {
303 assertParameterHints(R
"cpp(
304 using alias = const int&;
305 void foo(alias param);
311 ExpectedHint{"param: ",
"param"});
314TEST(ParameterHints, NameReference) {
316 assertParameterHints(R
"cpp(
317 void foo(int& param);
323 ExpectedHint{"¶m: ",
"param"});
326TEST(ParameterHints, NameTypeAliasReference) {
328 assertParameterHints(R
"cpp(
330 void foo(alias param);
336 ExpectedHint{"¶m: ",
"param"});
339TEST(ParameterHints, NameRValueReference) {
341 assertParameterHints(R
"cpp(
342 void foo(int&& param);
347 ExpectedHint{"param: ",
"param"});
350TEST(ParameterHints, VariadicForwardedConstructor) {
353 assertParameterHints(R
"cpp(
354 namespace std { template <typename T> T&& forward(T&); }
355 struct S { S(int a); };
356 template <typename T, typename... Args>
357 T bar(Args&&... args) { return T{std::forward<Args>(args)...}; }
363 ExpectedHint{"a: ",
"param"});
366TEST(ParameterHints, VariadicPlainConstructor) {
368 assertParameterHints(R
"cpp(
369 struct S { S(int a); };
370 template <typename T, typename... Args>
371 T bar(Args&&... args) { return T{args...}; }
377 ExpectedHint{"a: ",
"param"});
380TEST(ParameterHints, VariadicForwardedNewConstructor) {
383 assertParameterHints(R
"cpp(
384 namespace std { template <typename T> T&& forward(T&); }
385 struct S { S(int a); };
386 template <typename T, typename... Args>
387 T* bar(Args&&... args) { return new T{std::forward<Args>(args)...}; }
393 ExpectedHint{"a: ",
"param"});
396TEST(ParameterHints, VariadicPlainNewConstructor) {
398 assertParameterHints(R
"cpp(
399 struct S { S(int a); };
400 template <typename T, typename... Args>
401 T* bar(Args&&... args) { return new T{args...}; }
407 ExpectedHint{"a: ",
"param"});
410TEST(ParameterHints, VariadicForwarded) {
413 assertParameterHints(R
"cpp(
414 namespace std { template <typename T> T&& forward(T&); }
416 template <typename... Args>
417 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
423 ExpectedHint{"a: ",
"param"});
426TEST(ParameterHints, VariadicPlain) {
428 assertParameterHints(R
"cpp(
430 template <typename... Args>
431 void bar(Args&&... args) { return foo(args...); }
436 ExpectedHint{"a: ",
"param"});
439TEST(ParameterHints, VariadicPlainWithPackFirst) {
442 assertParameterHints(R
"cpp(
444 template <typename... Args, typename Arg>
445 void bar(Arg, Args&&... args) { return foo(args...); }
447 bar(1, $param[[42]]);
450 ExpectedHint{"a: ",
"param"});
453TEST(ParameterHints, VariadicSplitTwolevel) {
457 assertParameterHints(R
"cpp(
458 namespace std { template <typename T> T&& forward(T&); }
459 void baz(int, int b, double);
460 template <typename... Args>
461 void foo(int a, Args&&... args) {
462 return baz(1, std::forward<Args>(args)..., 1.0);
464 template <typename... Args>
465 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
467 bar($param1[[32]], $param2[[42]]);
470 ExpectedHint{"a: ",
"param1"},
471 ExpectedHint{
"b: ",
"param2"});
474TEST(ParameterHints, VariadicNameFromSpecialization) {
477 assertParameterHints(R
"cpp(
479 template <typename... Args>
480 void bar(Args... args) {
484 void bar<int>(int b);
489 ExpectedHint{"b: ",
"param"});
492TEST(ParameterHints, VariadicNameFromSpecializationRecursive) {
495 assertParameterHints(R
"cpp(
497 template <typename... Args>
498 void foo(Args... args) {
501 template <typename... Args>
502 void bar(Args... args) {
506 void foo<int>(int b);
511 ExpectedHint{"b: ",
"param"});
514TEST(ParameterHints, VariadicOverloaded) {
518 assertParameterHints(
520 namespace std { template <typename T> T&& forward(T&); }
521 void baz(int b, int c);
522 void baz(int bb, int cc, int dd);
523 template <typename... Args>
524 void foo(int a, Args&&... args) {
525 return baz(std::forward<Args>(args)...);
527 template <typename... Args>
528 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
530 bar($param1[[32]], $param2[[42]], $param3[[52]]);
531 bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
534 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"},
535 ExpectedHint{
"c: ",
"param3"}, ExpectedHint{
"a: ",
"param4"},
536 ExpectedHint{
"bb: ",
"param5"}, ExpectedHint{
"cc: ",
"param6"},
537 ExpectedHint{
"dd: ",
"param7"});
540TEST(ParameterHints, VariadicRecursive) {
542 assertParameterHints(
546 template <typename Head, typename... Tail>
547 void foo(Head head, Tail... tail) {
551 template <typename... Args>
552 void bar(Args... args) {
562TEST(ParameterHints, VariadicVarargs) {
564 assertParameterHints(R
"cpp(
565 void foo(int fixed, ...);
566 template <typename... Args>
567 void bar(Args&&... args) {
572 bar($fixed[[41]], 42, 43);
577TEST(ParameterHints, VariadicTwolevelUnresolved) {
579 assertParameterHints(R
"cpp(
580 template <typename... Args>
581 void foo(int fixed, Args&& ... args);
582 template <typename... Args>
583 void bar(Args&&... args) {
588 bar($fixed[[41]], 42, 43);
591 ExpectedHint{"fixed: ",
"fixed"});
594TEST(ParameterHints, VariadicTwoCalls) {
596 assertParameterHints(
598 void f1(int a, int b);
599 void f2(int c, int d);
603 template <typename... Args>
604 void foo(Args... args) {
613 foo($param1[[1]], $param2[[2]]);
616 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"});
619TEST(ParameterHints, VariadicInfinite) {
621 assertParameterHints(
623 template <typename... Args>
626 template <typename... Args>
627 void bar(Args... args) {
631 template <typename... Args>
632 void foo(Args... args) {
642TEST(ParameterHints, VariadicDuplicatePack) {
644 assertParameterHints(
646 void foo(int a, int b, int c, int);
648 template <typename... Args>
649 void bar(int, Args... args, int d) {
653 template <typename... Args>
654 void baz(Args... args, Args... args2) {
655 bar<Args..., int>(1, args..., args2...);
659 baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
662 ExpectedHint{"a: ",
"p1"}, ExpectedHint{
"b: ",
"p2"},
663 ExpectedHint{
"c: ",
"p3"}, ExpectedHint{
"d: ",
"p4"});
666TEST(ParameterHints, VariadicEmplace) {
669 assertParameterHints(
671 namespace std { template <typename T> T&& forward(T&); }
672 using size_t = decltype(sizeof(0));
673 void *operator new(size_t, void *);
679 template <typename T>
681 template <typename T, typename... Args>
682 void construct(T* ptr, Args&&... args) {
683 ::new ((void*)ptr) T{std::forward<Args>(args)...};
686 template <typename T>
688 template <typename... Args>
689 void emplace(Args&&... args) {
691 auto ptr = a.template allocate<T>();
692 a.construct(ptr, std::forward<Args>(args)...);
697 c.emplace($param1[[1]]);
698 c.emplace($param2[[2]], $param3[[3]]);
701 ExpectedHint{"A: ",
"param1"}, ExpectedHint{
"B: ",
"param2"},
702 ExpectedHint{
"C: ",
"param3"});
705TEST(ParameterHints, VariadicReferenceHint) {
706 assertParameterHints(R
"cpp(
708 template <typename... Args>
709 void bar(Args... args) { return foo(args...); }
718TEST(ParameterHints, VariadicReferenceHintForwardingRef) {
719 assertParameterHints(R"cpp(
721 template <typename... Args>
722 void bar(Args&&... args) { return foo(args...); }
729 ExpectedHint{"&: ",
"param"});
732TEST(ParameterHints, VariadicReferenceHintForwardingRefStdForward) {
733 assertParameterHints(R
"cpp(
734 namespace std { template <typename T> T&& forward(T&); }
736 template <typename... Args>
737 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
743 ExpectedHint{"&: ",
"param"});
746TEST(ParameterHints, VariadicNoReferenceHintForwardingRefStdForward) {
747 assertParameterHints(R
"cpp(
748 namespace std { template <typename T> T&& forward(T&); }
750 template <typename... Args>
751 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
760TEST(ParameterHints, VariadicNoReferenceHintUnresolvedForward) {
761 assertParameterHints(R"cpp(
762 template <typename... Args>
763 void foo(Args&&... args);
771TEST(ParameterHints, MatchingNameVariadicForwarded) {
774 assertParameterHints(R
"cpp(
775 namespace std { template <typename T> T&& forward(T&); }
777 template <typename... Args>
778 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
786TEST(ParameterHints, MatchingNameVariadicPlain) {
788 assertParameterHints(R
"cpp(
790 template <typename... Args>
791 void bar(Args&&... args) { return foo(args...); }
801 assertParameterHints(R
"cpp(
803 void operator+(S lhs, S rhs);
811TEST(ParameterHints, FunctionCallOperator) {
812 assertParameterHints(R"cpp(
814 void operator()(int x);
818 static void operator()(int x, int y);
821 auto l1 = [](int x) {};
822 auto l2 = [](int x) static {};
826 s.operator()($2[[1]]);
827 s.operator()($3[[1]], $4[[2]]);
828 S::operator()($5[[1]], $6[[2]]);
831 l1.operator()($8[[1]]);
833 l2.operator()($10[[1]]);
835 void (*ptr)(int a, int b) = &S::operator();
836 ptr($11[[1]], $12[[2]]);
839 ExpectedHint{"x: ",
"1"}, ExpectedHint{
"x: ",
"2"},
840 ExpectedHint{
"x: ",
"3"}, ExpectedHint{
"y: ",
"4"},
841 ExpectedHint{
"x: ",
"5"}, ExpectedHint{
"y: ",
"6"},
842 ExpectedHint{
"x: ",
"7"}, ExpectedHint{
"x: ",
"8"},
843 ExpectedHint{
"x: ",
"9"}, ExpectedHint{
"x: ",
"10"},
844 ExpectedHint{
"a: ",
"11"}, ExpectedHint{
"b: ",
"12"});
847TEST(ParameterHints, DeducingThis) {
848 assertParameterHints(R
"cpp(
850 template <typename This>
851 auto operator()(this This &&Self, int Param) {
855 auto function(this auto &Self, int Param) {
862 s.function($2[[42]]);
864 auto lambda = [](this auto &Self, char C) -> void {
870 ExpectedHint{"Param: ",
"1"},
871 ExpectedHint{
"Param: ",
"2"},
872 ExpectedHint{
"Param: ",
"3"}, ExpectedHint{
"C: ",
"4"});
875TEST(ParameterHints, Macros) {
880 assertParameterHints(R
"cpp(
882 #define ExpandsToCall() foo(42)
890 assertParameterHints(R
"cpp(
892 void foo(double param);
897 ExpectedHint{"param: ",
"param"});
900 assertParameterHints(R
"cpp(
902 #define ASSERT(expr) if (!expr) abort()
905 ASSERT(foo($param[[42]]) == 0);
908 ExpectedHint{"param: ",
"param"});
911 assertParameterHints(R
"cpp(
912 void foo(double x, double y);
913 #define CONSTANTS 3.14, 2.72
920TEST(ParameterHints, ConstructorParens) {
921 assertParameterHints(R"cpp(
929 ExpectedHint{"param: ",
"param"});
932TEST(ParameterHints, ConstructorBraces) {
933 assertParameterHints(R
"cpp(
941 ExpectedHint{"param: ",
"param"});
944TEST(ParameterHints, ConstructorStdInitList) {
946 assertParameterHints(R
"cpp(
948 template <typename E> class initializer_list { const E *a, *b; };
951 S(std::initializer_list<int> param);
959TEST(ParameterHints, MemberInit) {
960 assertParameterHints(R"cpp(
966 T() : member($param[[42]]) {}
969 ExpectedHint{"param: ",
"param"});
972TEST(ParameterHints, ImplicitConstructor) {
973 assertParameterHints(R
"cpp(
979 // Do not show hint for implicit constructor call in argument.
981 // Do not show hint for implicit constructor call in return.
987TEST(ParameterHints, FunctionPointer) {
988 assertParameterHints(
990 void (*f1)(int param);
991 void (__stdcall *f2)(int param);
992 using f3_t = void(*)(int param);
994 using f4_t = void(__stdcall *)(int param);
1003 ExpectedHint{"param: ",
"f1"}, ExpectedHint{
"param: ",
"f2"},
1004 ExpectedHint{
"param: ",
"f3"}, ExpectedHint{
"param: ",
"f4"});
1007TEST(ParameterHints, ArgMatchesParam) {
1008 assertParameterHints(R
"cpp(
1009 void foo(int param);
1011 static const int param = 42;
1015 // Do not show redundant "param: param".
1017 // But show it if the argument is qualified.
1018 foo($param[[S::param]]);
1023 // Do not show "param: param" for member-expr.
1028 ExpectedHint{"param: ",
"param"});
1031TEST(ParameterHints, ArgMatchesParamReference) {
1032 assertParameterHints(R
"cpp(
1033 void foo(int& param);
1034 void foo2(const int& param);
1037 // show reference hint on mutable reference
1038 foo($param[[param]]);
1039 // but not on const reference
1043 ExpectedHint{"&: ",
"param"});
1046TEST(ParameterHints, LeadingUnderscore) {
1047 assertParameterHints(R
"cpp(
1048 void foo(int p1, int _p2, int __p3);
1050 foo($p1[[41]], $p2[[42]], $p3[[43]]);
1053 ExpectedHint{"p1: ",
"p1"}, ExpectedHint{
"p2: ",
"p2"},
1054 ExpectedHint{
"p3: ",
"p3"});
1057TEST(ParameterHints, DependentCalls) {
1058 assertParameterHints(R
"cpp(
1059 template <typename T>
1060 void nonmember(T par1);
1062 template <typename T>
1064 void member(T par2);
1065 static void static_member(T par3);
1068 void overload(int anInt);
1069 void overload(double aDouble);
1071 template <typename T>
1073 void bar(A<T> a, T t) {
1074 nonmember($par1[[t]]);
1075 a.member($par2[[t]]);
1076 A<T>::static_member($par3[[t]]);
1077 // We don't want to arbitrarily pick between
1078 // "anInt" or "aDouble", so just show no hint.
1083 ExpectedHint{"par1: ",
"par1"},
1084 ExpectedHint{
"par2: ",
"par2"},
1085 ExpectedHint{
"par3: ",
"par3"});
1088TEST(ParameterHints, VariadicFunction) {
1089 assertParameterHints(R
"cpp(
1090 template <typename... T>
1091 void foo(int fixed, T... variadic);
1094 foo($fixed[[41]], 42, 43);
1097 ExpectedHint{"fixed: ",
"fixed"});
1100TEST(ParameterHints, VarargsFunction) {
1101 assertParameterHints(R
"cpp(
1102 void foo(int fixed, ...);
1105 foo($fixed[[41]], 42, 43);
1108 ExpectedHint{"fixed: ",
"fixed"});
1111TEST(ParameterHints, CopyOrMoveConstructor) {
1113 assertParameterHints(R
"cpp(
1127TEST(ParameterHints, AggregateInit) {
1130 assertParameterHints(R
"cpp(
1141TEST(ParameterHints, UserDefinedLiteral) {
1143 assertParameterHints(R
"cpp(
1144 long double operator"" _w(long double param);
1151TEST(ParameterHints, ParamNameComment) {
1154 assertParameterHints(R
"cpp(
1155 void foo(int param);
1158 foo( /* param = */ 42);
1162 foo(/*param=*/Z(a));
1163 foo($macro[[Z(a)]]);
1164 foo(/* the answer */$param[[42]]);
1167 ExpectedHint{"param: ",
"macro"},
1168 ExpectedHint{
"param: ",
"param"});
1171TEST(ParameterHints, SetterFunctions) {
1172 assertParameterHints(R
"cpp(
1174 void setParent(S* parent);
1175 void set_parent(S* parent);
1176 void setTimeout(int timeoutMillis);
1177 void setTimeoutMillis(int timeout_millis);
1181 // Parameter name matches setter name - omit hint.
1182 s.setParent(nullptr);
1183 // Support snake_case
1184 s.set_parent(nullptr);
1185 // Parameter name may contain extra info - show hint.
1186 s.setTimeout($timeoutMillis[[120]]);
1187 // FIXME: Ideally we'd want to omit this.
1188 s.setTimeoutMillis($timeout_millis[[120]]);
1191 ExpectedHint{"timeoutMillis: ",
"timeoutMillis"},
1192 ExpectedHint{
"timeout_millis: ",
"timeout_millis"});
1195TEST(ParameterHints, BuiltinFunctions) {
1197 assertParameterHints(R
"cpp(
1198 namespace std { template <typename T> T&& forward(T&); }
1206TEST(ParameterHints, IncludeAtNonGlobalScope) {
1207 Annotations FooInc(R"cpp(
1208 void bar() { foo(42); }
1210 Annotations FooCC(R"cpp(
1212 void foo(int param);
1217 TestWorkspace Workspace;
1218 Workspace.addSource("foo.inc", FooInc.code());
1219 Workspace.addMainFile(
"foo.cc", FooCC.code());
1221 auto AST = Workspace.openFile(
"foo.cc");
1222 ASSERT_TRUE(
bool(
AST));
1228TEST(TypeHints, Smoke) {
1229 assertTypeHints(R
"cpp(
1230 auto $waldo[[waldo]] = 42;
1232 ExpectedHint{": int",
"waldo"});
1235TEST(TypeHints, Decorations) {
1236 assertTypeHints(R
"cpp(
1238 auto* $var1[[var1]] = &x;
1239 auto&& $var2[[var2]] = x;
1240 const auto& $var3[[var3]] = x;
1242 ExpectedHint{": int *",
"var1"},
1243 ExpectedHint{
": int &",
"var2"},
1244 ExpectedHint{
": const int &",
"var3"});
1247TEST(TypeHints, DecltypeAuto) {
1248 assertTypeHints(R
"cpp(
1251 decltype(auto) $z[[z]] = y;
1253 ExpectedHint{": int &",
"z"});
1256TEST(TypeHints, NoQualifiers) {
1257 assertTypeHints(R
"cpp(
1262 auto $x[[x]] = foo();
1265 template <typename T>
1268 S2::Inner<int> bar();
1269 auto $y[[y]] = bar();
1273 ExpectedHint{": S1",
"x"},
1280 ExpectedHint{
": S2::Inner<int>",
"y"});
1283TEST(TypeHints, Lambda) {
1286 assertTypeHints(R
"cpp(
1289 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1290 return a + cap + init;
1294 ExpectedHint{": (lambda)",
"L"},
1295 ExpectedHint{
": int",
"init"}, ExpectedHint{
"-> int",
"ret"});
1299 assertTypeHints(
"auto $L[[x]] = <:$ret[[:>]]{return 42;};",
1300 ExpectedHint{
": (lambda)",
"L"},
1301 ExpectedHint{
"-> int",
"ret"});
1307TEST(TypeHints, StructuredBindings_PublicStruct) {
1308 assertTypeHints(R
"cpp(
1309 // Struct with public fields.
1315 auto [$x[[x]], $y[[y]]] = foo();
1317 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
1320TEST(TypeHints, StructuredBindings_Array) {
1321 assertTypeHints(R
"cpp(
1323 auto [$x[[x]], $y[[y]]] = arr;
1325 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
1328TEST(TypeHints, StructuredBindings_TupleLike) {
1329 assertTypeHints(R
"cpp(
1336 template <typename T>
1337 struct tuple_size {};
1339 struct tuple_size<IntPair> {
1340 constexpr static unsigned value = 2;
1342 template <unsigned I, typename T>
1343 struct tuple_element {};
1344 template <unsigned I>
1345 struct tuple_element<I, IntPair> {
1349 template <unsigned I>
1350 int get(const IntPair& p) {
1351 if constexpr (I == 0) {
1353 } else if constexpr (I == 1) {
1358 auto [$x[[x]], $y[[y]]] = bar();
1360 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
1363TEST(TypeHints, StructuredBindings_NoInitializer) {
1364 assertTypeHints(R
"cpp(
1365 // No initializer (ill-formed).
1366 // Do not show useless "NULL TYPE" hint.
1367 auto [x, y]; /*error-ok*/
1371TEST(TypeHints, InvalidType) {
1372 assertTypeHints(R"cpp(
1373 auto x = (unknown_type)42; /*error-ok*/
1374 auto *y = (unknown_ptr)nullptr;
1378TEST(TypeHints, ReturnTypeDeduction) {
1381 auto f1(int x$ret1a[[)]]; // Hint forward declaration too
1382 auto f1(int x$ret1b[[)]] { return x + 1; }
1384 // Include pointer operators in hint
1386 auto& f2($ret2[[)]] { return s; }
1388 // Do not hint `auto` for trailing return type.
1391 // Do not hint when a trailing return type is specified.
1392 auto f4() -> auto* { return "foo"; }
1394 auto f5($noreturn[[)]] {}
1396 // `auto` conversion operator
1398 operator auto($retConv[[)]] { return 42; }
1401 // FIXME: Dependent types do not work yet.
1402 template <typename T>
1404 auto method() { return T(); }
1407 ExpectedHint{"-> int",
"ret1a"}, ExpectedHint{
"-> int",
"ret1b"},
1408 ExpectedHint{
"-> int &",
"ret2"}, ExpectedHint{
"-> void",
"noreturn"},
1409 ExpectedHint{
"-> int",
"retConv"});
1412TEST(TypeHints, DependentType) {
1413 assertTypeHints(R
"cpp(
1414 template <typename T>
1416 // The hint would just be "auto" and we can't do any better.
1417 auto var1 = arg.method();
1418 // FIXME: It would be nice to show "T" as the hint.
1419 auto $var2[[var2]] = arg;
1422 template <typename T>
1429TEST(TypeHints, LongTypeName) {
1430 assertTypeHints(R"cpp(
1431 template <typename, typename, typename>
1433 struct MultipleWords {};
1434 A<MultipleWords, MultipleWords, MultipleWords> foo();
1435 // Omit type hint past a certain length (currently 32)
1441 WithContextValue WithCfg(Config::Key, std::move(Cfg));
1445 template <typename, typename, typename>
1447 struct MultipleWords {};
1448 A<MultipleWords, MultipleWords, MultipleWords> foo();
1449 // Should have type hint with TypeNameLimit = 0
1450 auto $var[[var]] = foo();
1452 ExpectedHint{": A<MultipleWords, MultipleWords, MultipleWords>",
"var"});
1455TEST(TypeHints, DefaultTemplateArgs) {
1456 assertTypeHints(R
"cpp(
1457 template <typename, typename = int>
1460 auto $var[[var]] = foo();
1462 auto [$binding[[value]]] = bar;
1464 ExpectedHint{": A<float>",
"var"},
1465 ExpectedHint{
": A<float>",
"binding"});
1468TEST(TypeHints, Deduplication) {
1469 assertTypeHints(R
"cpp(
1470 template <typename T>
1472 auto $var[[var]] = 42;
1474 template void foo<int>();
1475 template void foo<float>();
1477 ExpectedHint{": int",
"var"});
1480TEST(TypeHints, SinglyInstantiatedTemplate) {
1481 assertTypeHints(R
"cpp(
1482 auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
1483 int m = x("foo", 3);
1485 ExpectedHint{": (lambda)",
"lambda"},
1486 ExpectedHint{
": const char *",
"param"});
1489 assertTypeHints(R
"cpp(
1490 int x(auto $a[[a]], auto... b, auto c) { return 42; }
1491 int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
1493 ExpectedHint{": void *",
"a"});
1496TEST(TypeHints, Aliased) {
1500 TU.ExtraArgs.push_back(
"-xc");
1501 auto AST = TU.build();
1506TEST(TypeHints, Decltype) {
1507 assertTypeHints(R
"cpp(
1508 $a[[decltype(0)]] a;
1509 $b[[decltype(a)]] b;
1510 const $c[[decltype(0)]] &c = b;
1512 // Don't show for dependent type
1514 constexpr decltype(T{}) d;
1516 $e[[decltype(0)]] e();
1517 auto f() -> $f[[decltype(0)]];
1519 template <class, class> struct Foo;
1520 using G = Foo<$g[[decltype(0)]], float>;
1522 auto $h[[h]] = $i[[decltype(0)]]{};
1528 ExpectedHint{": int",
"a"}, ExpectedHint{
": int",
"b"},
1529 ExpectedHint{
": int",
"c"}, ExpectedHint{
": int",
"e"},
1530 ExpectedHint{
": int",
"f"}, ExpectedHint{
": int",
"g"},
1531 ExpectedHint{
": int",
"h"}, ExpectedHint{
": int",
"i"});
1534TEST(TypeHints, SubstTemplateParameterAliases) {
1535 llvm::StringRef Header = R
"cpp(
1536 template <class T> struct allocator {};
1538 template <class T, class A>
1539 struct vector_base {
1543 template <class T, class A>
1544 struct internal_iterator_type_template_we_dont_expect {};
1546 struct my_iterator {};
1548 template <class T, class A = allocator<T>>
1549 struct vector : vector_base<T, A> {
1550 using base = vector_base<T, A>;
1551 typedef T value_type;
1552 typedef base::pointer pointer;
1553 using allocator_type = A;
1554 using size_type = int;
1555 using iterator = internal_iterator_type_template_we_dont_expect<T, A>;
1556 using non_template_iterator = my_iterator;
1558 value_type& operator[](int index) { return elements[index]; }
1559 const value_type& at(int index) const { return elements[index]; }
1560 pointer data() { return &elements[0]; }
1561 allocator_type get_allocator() { return A(); }
1562 size_type size() const { return 10; }
1563 iterator begin() { return iterator(); }
1564 non_template_iterator end() { return non_template_iterator(); }
1570 llvm::StringRef VectorIntPtr = R"cpp(
1571 vector<int *> array;
1572 auto $no_modifier[[x]] = array[3];
1573 auto* $ptr_modifier[[ptr]] = &array[3];
1574 auto& $ref_modifier[[ref]] = array[3];
1575 auto& $at[[immutable]] = array.at(3);
1577 auto $data[[data]] = array.data();
1578 auto $allocator[[alloc]] = array.get_allocator();
1579 auto $size[[size]] = array.size();
1580 auto $begin[[begin]] = array.begin();
1581 auto $end[[end]] = array.end();
1584 assertHintsWithHeader(
1586 ExpectedHint{": int *",
"no_modifier"},
1587 ExpectedHint{
": int **",
"ptr_modifier"},
1588 ExpectedHint{
": int *&",
"ref_modifier"},
1589 ExpectedHint{
": int *const &",
"at"}, ExpectedHint{
": int **",
"data"},
1590 ExpectedHint{
": allocator<int *>",
"allocator"},
1591 ExpectedHint{
": size_type",
"size"}, ExpectedHint{
": iterator",
"begin"},
1592 ExpectedHint{
": non_template_iterator",
"end"});
1594 llvm::StringRef VectorInt = R
"cpp(
1596 auto $no_modifier[[by_value]] = array[3];
1597 auto* $ptr_modifier[[ptr]] = &array[3];
1598 auto& $ref_modifier[[ref]] = array[3];
1599 auto& $at[[immutable]] = array.at(3);
1601 auto $data[[data]] = array.data();
1602 auto $allocator[[alloc]] = array.get_allocator();
1603 auto $size[[size]] = array.size();
1604 auto $begin[[begin]] = array.begin();
1605 auto $end[[end]] = array.end();
1608 assertHintsWithHeader(
1610 ExpectedHint{": int",
"no_modifier"},
1611 ExpectedHint{
": int *",
"ptr_modifier"},
1612 ExpectedHint{
": int &",
"ref_modifier"},
1613 ExpectedHint{
": const int &",
"at"}, ExpectedHint{
": int *",
"data"},
1614 ExpectedHint{
": allocator<int>",
"allocator"},
1615 ExpectedHint{
": size_type",
"size"}, ExpectedHint{
": iterator",
"begin"},
1616 ExpectedHint{
": non_template_iterator",
"end"});
1619 // If the type alias is not of substituted template parameter type,
1620 // do not show desugared type.
1621 using VeryLongLongTypeName = my_iterator;
1622 using Short = VeryLongLongTypeName;
1624 auto $short_name[[my_value]] = Short();
1626 // Same applies with templates.
1627 template <typename T, typename A>
1628 using basic_static_vector = vector<T, A>;
1629 template <typename T>
1630 using static_vector = basic_static_vector<T, allocator<T>>;
1632 auto $vector_name[[vec]] = static_vector<int>();
1636 ExpectedHint{": Short",
"short_name"},
1637 ExpectedHint{
": static_vector<int>",
"vector_name"});
1640TEST(DesignatorHints, Basic) {
1641 assertDesignatorHints(R
"cpp(
1642 struct S { int x, y, z; };
1643 S s {$x[[1]], $y[[2+2]]};
1645 int x[] = {$0[[0]], $1[[1]]};
1647 ExpectedHint{".x=",
"x"}, ExpectedHint{
".y=",
"y"},
1648 ExpectedHint{
"[0]=",
"0"}, ExpectedHint{
"[1]=",
"1"});
1651TEST(DesignatorHints, Nested) {
1652 assertDesignatorHints(R
"cpp(
1653 struct Inner { int x, y; };
1654 struct Outer { Inner a, b; };
1655 Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
1657 ExpectedHint{".a=",
"a"}, ExpectedHint{
".x=",
"x"},
1658 ExpectedHint{
".y=",
"y"}, ExpectedHint{
".b.x=",
"bx"});
1661TEST(DesignatorHints, AnonymousRecord) {
1662 assertDesignatorHints(R
"cpp(
1674 ExpectedHint{".x.y=",
"xy"});
1677TEST(DesignatorHints, Suppression) {
1678 assertDesignatorHints(R
"cpp(
1679 struct Point { int a, b, c, d, e, f, g, h; };
1680 Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
1682 ExpectedHint{".e=",
"e"});
1685TEST(DesignatorHints, StdArray) {
1688 assertDesignatorHints(R
"cpp(
1689 template <typename T, int N> struct Array { T __elements[N]; };
1690 Array<int, 2> x = {$0[[0]], $1[[1]]};
1692 ExpectedHint{"[0]=",
"0"}, ExpectedHint{
"[1]=",
"1"});
1695TEST(DesignatorHints, OnlyAggregateInit) {
1696 assertDesignatorHints(R
"cpp(
1697 struct Copyable { int x; } c;
1700 struct Constructible { Constructible(int x); };
1701 Constructible x{42};
1705TEST(DesignatorHints, NoCrash) {
1706 assertDesignatorHints(R
"cpp(
1709 struct Foo {int a; int b;};
1711 Foo f{A(), $b[[1]]};
1714 ExpectedHint{".b=",
"b"});
1717TEST(InlayHints, RestrictRange) {
1718 Annotations
Code(R
"cpp(
1726 ElementsAre(labelIs(
": int"), labelIs(
": char")));
1729TEST(ParameterHints, PseudoObjectExpr) {
1730 Annotations
Code(R
"cpp(
1732 __declspec(property(get=GetX, put=PutX)) int x[];
1733 int GetX(int y, int z) { return 42 + y; }
1736 // This is a PseudoObjectExpression whose syntactic form is a binary
1738 void Work(int y) { x = y; } // Not `x = y: y`.
1741 int printf(const char *Format, ...);
1745 __builtin_dump_struct(&s, printf); // Not `Format: __builtin_dump_struct()`
1746 printf($Param[["Hello, %d"]], 42); // Normal calls are not affected.
1747 // This builds a PseudoObjectExpr, but here it's useful for showing the
1748 // arguments from the semantic form.
1749 return s.x[ $one[[1]] ][ $two[[2]] ]; // `x[y: 1][z: 2]`
1753 TU.ExtraArgs.push_back(
"-fms-extensions");
1754 auto AST = TU.build();
1756 ElementsAre(HintMatcher(ExpectedHint{
"Format: ",
"Param"},
Code),
1757 HintMatcher(ExpectedHint{
"y: ",
"one"},
Code),
1758 HintMatcher(ExpectedHint{
"z: ",
"two"},
Code)));
1761TEST(ParameterHints, ArgPacksAndConstructors) {
1762 assertParameterHints(
1764 struct Foo{ Foo(); Foo(int x); };
1765 void foo(Foo a, int b);
1766 template <typename... Args>
1767 void bar(Args... args) {
1770 template <typename... Args>
1771 void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
1773 template <typename... Args>
1774 void bax(Args... args) { foo($param3[[{args...}]], args...); }
1777 bar($param4[[Foo{}]], $param5[[42]]);
1778 bar($param6[[42]], $param7[[42]]);
1783 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"},
1784 ExpectedHint{
"a: ",
"param3"}, ExpectedHint{
"a: ",
"param4"},
1785 ExpectedHint{
"b: ",
"param5"}, ExpectedHint{
"a: ",
"param6"},
1786 ExpectedHint{
"b: ",
"param7"}, ExpectedHint{
"x: ",
"param8"},
1787 ExpectedHint{
"b: ",
"param9"});
1790TEST(ParameterHints, DoesntExpandAllArgs) {
1791 assertParameterHints(
1793 void foo(int x, int y);
1794 int id(int a, int b, int c);
1795 template <typename... Args>
1796 void bar(Args... args) {
1797 foo(id($param1[[args]], $param2[[1]], $param3[[args]])...);
1800 bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1803 ExpectedHint{"a: ",
"param1"}, ExpectedHint{
"b: ",
"param2"},
1804 ExpectedHint{
"c: ",
"param3"});
1807TEST(BlockEndHints, Functions) {
1808 assertBlockEndHints(R
"cpp(
1815 // No hint for lambda for now
1822 // No hint because this isn't a definition
1826 bool operator==(S, S) {
1830 ExpectedHint{" // foo",
"foo"},
1831 ExpectedHint{
" // bar",
"bar"},
1832 ExpectedHint{
" // operator==",
"opEqual"});
1835TEST(BlockEndHints, Methods) {
1836 assertBlockEndHints(R
"cpp(
1838 // No hint because there's no function body
1847 // No hint because this isn't a definition
1850 template <typename T>
1854 // No hint because this isn't a definition
1855 template <typename T>
1858 Test operator+(int) const {
1862 operator bool() const {
1866 // No hint because there's no function body
1867 operator int() const = delete;
1870 void Test::method2() {
1873 template <typename T>
1874 void Test::method4() {
1877 ExpectedHint{" // ~Test",
"dtor"},
1878 ExpectedHint{
" // method1",
"method1"},
1879 ExpectedHint{
" // method3",
"method3"},
1880 ExpectedHint{
" // operator+",
"opIdentity"},
1881 ExpectedHint{
" // operator bool",
"opBool"},
1882 ExpectedHint{
" // Test::method2",
"method2"},
1883 ExpectedHint{
" // Test::method4",
"method4"});
1886TEST(BlockEndHints, Namespaces) {
1887 assertBlockEndHints(
1897 ExpectedHint{" // namespace",
"anon"},
1898 ExpectedHint{
" // namespace ns",
"ns"});
1901TEST(BlockEndHints, Types) {
1902 assertBlockEndHints(
1919 ExpectedHint{" // struct S",
"S"}, ExpectedHint{
" // class C",
"C"},
1920 ExpectedHint{
" // union U",
"U"}, ExpectedHint{
" // enum E1",
"E1"},
1921 ExpectedHint{
" // enum class E2",
"E2"});
1924TEST(BlockEndHints, If) {
1925 assertBlockEndHints(
1927 void foo(bool cond) {
1948 if (auto X = cond) {
1951 if (int i = 0; i > 10) {
1955 ExpectedHint{" // if cond",
"simple"},
1956 ExpectedHint{
" // if cond",
"ifelse"}, ExpectedHint{
" // if",
"elseif"},
1957 ExpectedHint{
" // if !cond",
"inner"},
1958 ExpectedHint{
" // if cond",
"outer"}, ExpectedHint{
" // if X",
"init"},
1959 ExpectedHint{
" // if i > 10",
"init_cond"});
1962TEST(BlockEndHints, Loops) {
1963 assertBlockEndHints(
1978 for (int I = 0; I < 10; ++I) {
1986 ExpectedHint{" // while true",
"while"},
1987 ExpectedHint{
" // for true",
"forcond"},
1988 ExpectedHint{
" // for I",
"forvar"},
1989 ExpectedHint{
" // for V",
"foreach"});
1992TEST(BlockEndHints, Switch) {
1993 assertBlockEndHints(
2001 ExpectedHint{" // switch I",
"switch"});
2004TEST(BlockEndHints, PrintLiterals) {
2005 assertBlockEndHints(
2011 while ("foo but this time it is very long") {
2024 ExpectedHint{" // while \"foo\"",
"string"},
2025 ExpectedHint{
" // while \"foo but...\"",
"string_long"},
2026 ExpectedHint{
" // while true",
"boolean"},
2027 ExpectedHint{
" // while 1",
"integer"},
2028 ExpectedHint{
" // while 1.5",
"float"});
2031TEST(BlockEndHints, PrintRefs) {
2032 assertBlockEndHints(
2046 while (ns::func()) {
2049 while (ns::S{}.Field) {
2052 while (ns::S{}.method()) {
2056 ExpectedHint{" // while Var",
"var"},
2057 ExpectedHint{
" // while func",
"func"},
2058 ExpectedHint{
" // while Field",
"field"},
2059 ExpectedHint{
" // while method",
"method"});
2062TEST(BlockEndHints, PrintConversions) {
2063 assertBlockEndHints(
2068 explicit operator bool();
2072 $convert_primitive[[}]]
2078 $construct_class[[}]]
2081 ExpectedHint{" // while float",
"convert_primitive"},
2082 ExpectedHint{
" // while S",
"convert_class"},
2083 ExpectedHint{
" // while S",
"construct_class"});
2086TEST(BlockEndHints, PrintOperators) {
2088 void foo(Integer I) {
2107 while((I + I) < (I + I)){
2108 $binary_complex[[}]]
2113 auto AssertExpectedHints = [&](llvm::StringRef
Code) {
2114 assertBlockEndHints(
Code, ExpectedHint{
" // while ++I",
"preinc"},
2115 ExpectedHint{
" // while I++",
"postinc"},
2116 ExpectedHint{
" // while",
"unary_complex"},
2117 ExpectedHint{
" // while I < 0",
"compare"},
2118 ExpectedHint{
" // while ... < I",
"lhs_complex"},
2119 ExpectedHint{
" // while I < ...",
"rhs_complex"},
2120 ExpectedHint{
" // while",
"binary_complex"});
2124 AssertExpectedHints(
"using Integer = int;" +
AnnotatedCode);
2126 AssertExpectedHints(R
"cpp(
2128 explicit operator bool();
2129 Integer operator++();
2130 Integer operator++(int);
2131 Integer operator+(Integer);
2132 Integer operator+();
2133 bool operator<(Integer);
2134 bool operator<(int);
2139TEST(BlockEndHints, TrailingSemicolon) {
2140 assertBlockEndHints(R"cpp(
2141 // The hint is placed after the trailing ';'
2145 // The hint is always placed in the same line with the closing '}'.
2146 // So in this case where ';' is missing, it is attached to '}'.
2152 // No hint because only one trailing ';' is allowed
2156 // No hint because trailing ';' is only allowed for class/struct/union/enum
2160 // Rare case, but yes we'll have a hint here.
2167 ExpectedHint{" // struct S1",
"S1"},
2168 ExpectedHint{
" // struct S2",
"S2"},
2169 ExpectedHint{
" // struct",
"anon"});
2172TEST(BlockEndHints, TrailingText) {
2173 assertBlockEndHints(R
"cpp(
2177 // No hint for S2 because of the trailing comment
2179 }; /* Put anything here */
2182 // No hint for S4 because of the trailing source code
2186 // No hint for ns because of the trailing comment
2190 ExpectedHint{" // struct S1",
"S1"},
2191 ExpectedHint{
" // struct S3",
"S3"});
2195 assertBlockEndHints(R
"cpp(
2196 #define DECL_STRUCT(NAME) struct NAME {
2202 // No hint because we require a '}'
2206 ExpectedHint{" // struct S1",
"S1"});
2209TEST(BlockEndHints, PointerToMemberFunction) {
2211 assertBlockEndHints(R
"cpp(
2213 using Predicate = bool(A::*)();
2214 void foo(A* a, Predicate p) {
2219 ExpectedHint{" // if",
"ptrmem"});
std::string AnnotatedCode
std::vector< const char * > Expected
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...
@ 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)
Compute and return inlay hints for a file.
@ TypeAlias
The path from one type to the other involves desugaring type aliases.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
struct clang::clangd::Config::@8 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)