1 //===-- InlayHintTests.cpp -------------------------------*- C++ -*-------===//
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 //===----------------------------------------------------------------------===//
8 #include "Annotations.h"
10 #include "InlayHints.h"
13 #include "TestWorkspace.h"
15 #include "support/Context.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/ScopedPrinter.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
24 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&Stream
,
25 const InlayHint
&Hint
) {
26 return Stream
<< Hint
.label
<< "@" << Hint
.range
;
31 using ::testing::ElementsAre
;
32 using ::testing::IsEmpty
;
34 std::vector
<InlayHint
> hintsOfKind(ParsedAST
&AST
, InlayHintKind Kind
) {
35 std::vector
<InlayHint
> Result
;
36 for (auto &Hint
: inlayHints(AST
, /*RestrictRange=*/std::nullopt
)) {
37 if (Hint
.kind
== Kind
)
38 Result
.push_back(Hint
);
43 enum HintSide
{ Left
, Right
};
47 std::string RangeName
;
50 friend llvm::raw_ostream
&operator<<(llvm::raw_ostream
&Stream
,
51 const ExpectedHint
&Hint
) {
52 return Stream
<< Hint
.Label
<< "@$" << Hint
.RangeName
;
56 MATCHER_P2(HintMatcher
, Expected
, Code
, llvm::to_string(Expected
)) {
57 llvm::StringRef
ExpectedView(Expected
.Label
);
58 if (arg
.label
!= ExpectedView
.trim(" ") ||
59 arg
.paddingLeft
!= ExpectedView
.startswith(" ") ||
60 arg
.paddingRight
!= ExpectedView
.endswith(" ")) {
61 *result_listener
<< "label is '" << arg
.label
<< "'";
64 if (arg
.range
!= Code
.range(Expected
.RangeName
)) {
65 *result_listener
<< "range is " << llvm::to_string(arg
.range
) << " but $"
66 << Expected
.RangeName
<< " is "
67 << llvm::to_string(Code
.range(Expected
.RangeName
));
73 MATCHER_P(labelIs
, Label
, "") { return arg
.label
== Label
; }
75 Config
noHintsConfig() {
77 C
.InlayHints
.Parameters
= false;
78 C
.InlayHints
.DeducedTypes
= false;
79 C
.InlayHints
.Designators
= false;
83 template <typename
... ExpectedHints
>
84 void assertHints(InlayHintKind Kind
, llvm::StringRef AnnotatedSource
,
85 ExpectedHints
... Expected
) {
86 Annotations
Source(AnnotatedSource
);
87 TestTU TU
= TestTU::withCode(Source
.code());
88 TU
.ExtraArgs
.push_back("-std=c++20");
89 auto AST
= TU
.build();
91 EXPECT_THAT(hintsOfKind(AST
, Kind
),
92 ElementsAre(HintMatcher(Expected
, Source
)...));
93 // Sneak in a cross-cutting check that hints are disabled by config.
94 // We'll hit an assertion failure if addInlayHint still gets called.
95 WithContextValue
WithCfg(Config::Key
, noHintsConfig());
96 EXPECT_THAT(inlayHints(AST
, std::nullopt
), IsEmpty());
99 // Hack to allow expression-statements operating on parameter packs in C++14.
100 template <typename
... T
> void ignore(T
&&...) {}
102 template <typename
... ExpectedHints
>
103 void assertParameterHints(llvm::StringRef AnnotatedSource
,
104 ExpectedHints
... Expected
) {
105 ignore(Expected
.Side
= Left
...);
106 assertHints(InlayHintKind::Parameter
, AnnotatedSource
, Expected
...);
109 template <typename
... ExpectedHints
>
110 void assertTypeHints(llvm::StringRef AnnotatedSource
,
111 ExpectedHints
... Expected
) {
112 ignore(Expected
.Side
= Right
...);
113 assertHints(InlayHintKind::Type
, AnnotatedSource
, Expected
...);
116 template <typename
... ExpectedHints
>
117 void assertDesignatorHints(llvm::StringRef AnnotatedSource
,
118 ExpectedHints
... Expected
) {
120 Cfg
.InlayHints
.Designators
= true;
121 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
122 assertHints(InlayHintKind::Designator
, AnnotatedSource
, Expected
...);
125 TEST(ParameterHints
, Smoke
) {
126 assertParameterHints(R
"cpp(
132 ExpectedHint
{"param: ", "param"});
135 TEST(ParameterHints
, NoName
) {
136 // No hint for anonymous parameter.
137 assertParameterHints(R
"cpp(
145 TEST(ParameterHints
, NoNameConstReference
) {
146 // No hint for anonymous const l-value ref parameter.
147 assertParameterHints(R
"cpp(
148 void foo(const int&);
155 TEST(ParameterHints
, NoNameReference
) {
156 // Reference hint for anonymous l-value ref parameter.
157 assertParameterHints(R
"cpp(
164 ExpectedHint
{"&: ", "param"});
167 TEST(ParameterHints
, NoNameRValueReference
) {
168 // No reference hint for anonymous r-value ref parameter.
169 assertParameterHints(R
"cpp(
177 TEST(ParameterHints
, NoNameVariadicDeclaration
) {
178 // No hint for anonymous variadic parameter
179 assertParameterHints(R
"cpp(
180 template <typename... Args>
181 void foo(Args&& ...);
188 TEST(ParameterHints
, NoNameVariadicForwarded
) {
189 // No hint for anonymous variadic parameter
190 // This prototype of std::forward is sufficient for clang to recognize it
191 assertParameterHints(R
"cpp(
192 namespace std { template <typename T> T&& forward(T&); }
194 template <typename... Args>
195 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
202 TEST(ParameterHints
, NoNameVariadicPlain
) {
203 // No hint for anonymous variadic parameter
204 assertParameterHints(R
"cpp(
206 template <typename... Args>
207 void bar(Args&&... args) { return foo(args...); }
214 TEST(ParameterHints
, NameInDefinition
) {
215 // Parameter name picked up from definition if necessary.
216 assertParameterHints(R
"cpp(
221 void foo(int param) {};
223 ExpectedHint
{"param: ", "param"});
226 TEST(ParameterHints
, NamePartiallyInDefinition
) {
227 // Parameter name picked up from definition if necessary.
228 assertParameterHints(R
"cpp(
229 void foo(int, int b);
231 foo($param1[[42]], $param2[[42]]);
233 void foo(int a, int) {};
235 ExpectedHint
{"a: ", "param1"},
236 ExpectedHint
{"b: ", "param2"});
239 TEST(ParameterHints
, NameInDefinitionVariadic
) {
240 // Parameter name picked up from definition in a resolved forwarded parameter.
241 assertParameterHints(R
"cpp(
243 template <typename... Args>
244 void bar(Args... args) {
248 bar($param1[[42]], $param2[[42]]);
250 void foo(int a, int b) {};
252 ExpectedHint
{"a: ", "param1"},
253 ExpectedHint
{"b: ", "param2"});
256 TEST(ParameterHints
, NameMismatch
) {
257 // Prefer name from declaration.
258 assertParameterHints(R
"cpp(
263 void foo(int bad) {};
265 ExpectedHint
{"good: ", "good"});
268 TEST(ParameterHints
, NameConstReference
) {
269 // Only name hint for const l-value ref parameter.
270 assertParameterHints(R
"cpp(
271 void foo(const int& param);
276 ExpectedHint
{"param: ", "param"});
279 TEST(ParameterHints
, NameTypeAliasConstReference
) {
280 // Only name hint for const l-value ref parameter via type alias.
281 assertParameterHints(R
"cpp(
282 using alias = const int&;
283 void foo(alias param);
289 ExpectedHint
{"param: ", "param"});
292 TEST(ParameterHints
, NameReference
) {
293 // Reference and name hint for l-value ref parameter.
294 assertParameterHints(R
"cpp(
295 void foo(int& param);
301 ExpectedHint
{"¶m: ", "param"});
304 TEST(ParameterHints
, NameTypeAliasReference
) {
305 // Reference and name hint for l-value ref parameter via type alias.
306 assertParameterHints(R
"cpp(
308 void foo(alias param);
314 ExpectedHint
{"¶m: ", "param"});
317 TEST(ParameterHints
, NameRValueReference
) {
318 // Only name hint for r-value ref parameter.
319 assertParameterHints(R
"cpp(
320 void foo(int&& param);
325 ExpectedHint
{"param: ", "param"});
328 TEST(ParameterHints
, VariadicForwardedConstructor
) {
329 // Name hint for variadic parameter using std::forward in a constructor call
330 // This prototype of std::forward is sufficient for clang to recognize it
331 assertParameterHints(R
"cpp(
332 namespace std { template <typename T> T&& forward(T&); }
333 struct S { S(int a); };
334 template <typename T, typename... Args>
335 T bar(Args&&... args) { return T{std::forward<Args>(args)...}; }
341 ExpectedHint
{"a: ", "param"});
344 TEST(ParameterHints
, VariadicPlainConstructor
) {
345 // Name hint for variadic parameter in a constructor call
346 assertParameterHints(R
"cpp(
347 struct S { S(int a); };
348 template <typename T, typename... Args>
349 T bar(Args&&... args) { return T{args...}; }
355 ExpectedHint
{"a: ", "param"});
358 TEST(ParameterHints
, VariadicForwardedNewConstructor
) {
359 // Name hint for variadic parameter using std::forward in a new expression
360 // This prototype of std::forward is sufficient for clang to recognize it
361 assertParameterHints(R
"cpp(
362 namespace std { template <typename T> T&& forward(T&); }
363 struct S { S(int a); };
364 template <typename T, typename... Args>
365 T* bar(Args&&... args) { return new T{std::forward<Args>(args)...}; }
371 ExpectedHint
{"a: ", "param"});
374 TEST(ParameterHints
, VariadicPlainNewConstructor
) {
375 // Name hint for variadic parameter in a new expression
376 assertParameterHints(R
"cpp(
377 struct S { S(int a); };
378 template <typename T, typename... Args>
379 T* bar(Args&&... args) { return new T{args...}; }
385 ExpectedHint
{"a: ", "param"});
388 TEST(ParameterHints
, VariadicForwarded
) {
389 // Name for variadic parameter using std::forward
390 // This prototype of std::forward is sufficient for clang to recognize it
391 assertParameterHints(R
"cpp(
392 namespace std { template <typename T> T&& forward(T&); }
394 template <typename... Args>
395 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
401 ExpectedHint
{"a: ", "param"});
404 TEST(ParameterHints
, VariadicPlain
) {
405 // Name hint for variadic parameter
406 assertParameterHints(R
"cpp(
408 template <typename... Args>
409 void bar(Args&&... args) { return foo(args...); }
414 ExpectedHint
{"a: ", "param"});
417 TEST(ParameterHints
, VariadicPlainWithPackFirst
) {
418 // Name hint for variadic parameter when the parameter pack is not the last
419 // template parameter
420 assertParameterHints(R
"cpp(
422 template <typename... Args, typename Arg>
423 void bar(Arg, Args&&... args) { return foo(args...); }
425 bar(1, $param[[42]]);
428 ExpectedHint
{"a: ", "param"});
431 TEST(ParameterHints
, VariadicSplitTwolevel
) {
432 // Name for variadic parameter that involves both head and tail parameters to
434 // This prototype of std::forward is sufficient for clang to recognize it
435 assertParameterHints(R
"cpp(
436 namespace std { template <typename T> T&& forward(T&); }
437 void baz(int, int b, double);
438 template <typename... Args>
439 void foo(int a, Args&&... args) {
440 return baz(1, std::forward<Args>(args)..., 1.0);
442 template <typename... Args>
443 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
445 bar($param1[[32]], $param2[[42]]);
448 ExpectedHint
{"a: ", "param1"},
449 ExpectedHint
{"b: ", "param2"});
452 TEST(ParameterHints
, VariadicNameFromSpecialization
) {
453 // We don't try to resolve forwarding parameters if the function call uses a
455 assertParameterHints(R
"cpp(
457 template <typename... Args>
458 void bar(Args... args) {
462 void bar<int>(int b);
467 ExpectedHint
{"b: ", "param"});
470 TEST(ParameterHints
, VariadicNameFromSpecializationRecursive
) {
471 // We don't try to resolve forwarding parameters inside a forwarding function
472 // call if that function call uses a specialization.
473 assertParameterHints(R
"cpp(
475 template <typename... Args>
476 void foo(Args... args) {
479 template <typename... Args>
480 void bar(Args... args) {
484 void foo<int>(int b);
489 ExpectedHint
{"b: ", "param"});
492 TEST(ParameterHints
, VariadicOverloaded
) {
493 // Name for variadic parameter for an overloaded function with unique number
495 // This prototype of std::forward is sufficient for clang to recognize it
496 assertParameterHints(
498 namespace std { template <typename T> T&& forward(T&); }
499 void baz(int b, int c);
500 void baz(int bb, int cc, int dd);
501 template <typename... Args>
502 void foo(int a, Args&&... args) {
503 return baz(std::forward<Args>(args)...);
505 template <typename... Args>
506 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
508 bar($param1[[32]], $param2[[42]], $param3[[52]]);
509 bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
512 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"},
513 ExpectedHint
{"c: ", "param3"}, ExpectedHint
{"a: ", "param4"},
514 ExpectedHint
{"bb: ", "param5"}, ExpectedHint
{"cc: ", "param6"},
515 ExpectedHint
{"dd: ", "param7"});
518 TEST(ParameterHints
, VariadicRecursive
) {
519 // make_tuple-like recursive variadic call
520 assertParameterHints(
524 template <typename Head, typename... Tail>
525 void foo(Head head, Tail... tail) {
529 template <typename... Args>
530 void bar(Args... args) {
540 TEST(ParameterHints
, VariadicVarargs
) {
541 // variadic call involving varargs (to make sure we don't crash)
542 assertParameterHints(R
"cpp(
543 void foo(int fixed, ...);
544 template <typename... Args>
545 void bar(Args&&... args) {
550 bar($fixed[[41]], 42, 43);
555 TEST(ParameterHints
, VariadicTwolevelUnresolved
) {
556 // the same setting as VariadicVarargs, only with parameter pack
557 assertParameterHints(R
"cpp(
558 template <typename... Args>
559 void foo(int fixed, Args&& ... args);
560 template <typename... Args>
561 void bar(Args&&... args) {
566 bar($fixed[[41]], 42, 43);
569 ExpectedHint
{"fixed: ", "fixed"});
572 TEST(ParameterHints
, VariadicTwoCalls
) {
573 // only the first call using the parameter pack should be picked up
574 assertParameterHints(
576 void f1(int a, int b);
577 void f2(int c, int d);
581 template <typename... Args>
582 void foo(Args... args) {
591 foo($param1[[1]], $param2[[2]]);
594 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"});
597 TEST(ParameterHints
, VariadicInfinite
) {
598 // infinite recursion should not break clangd
599 assertParameterHints(
601 template <typename... Args>
604 template <typename... Args>
605 void bar(Args... args) {
609 template <typename... Args>
610 void foo(Args... args) {
620 TEST(ParameterHints
, VariadicDuplicatePack
) {
621 // edge cases with multiple adjacent packs should work
622 assertParameterHints(
624 void foo(int a, int b, int c, int);
626 template <typename... Args>
627 void bar(int, Args... args, int d) {
631 template <typename... Args>
632 void baz(Args... args, Args... args2) {
633 bar<Args..., int>(1, args..., args2...);
637 baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
640 ExpectedHint
{"a: ", "p1"}, ExpectedHint
{"b: ", "p2"},
641 ExpectedHint
{"c: ", "p3"}, ExpectedHint
{"d: ", "p4"});
644 TEST(ParameterHints
, VariadicEmplace
) {
645 // emplace-like calls should forward constructor parameters
646 // This prototype of std::forward is sufficient for clang to recognize it
647 assertParameterHints(
649 namespace std { template <typename T> T&& forward(T&); }
650 using size_t = decltype(sizeof(0));
651 void *operator new(size_t, void *);
657 template <typename T>
659 template <typename T, typename... Args>
660 void construct(T* ptr, Args&&... args) {
661 ::new ((void*)ptr) T{std::forward<Args>(args)...};
664 template <typename T>
666 template <typename... Args>
667 void emplace(Args&&... args) {
669 auto ptr = a.template allocate<T>();
670 a.construct(ptr, std::forward<Args>(args)...);
675 c.emplace($param1[[1]]);
676 c.emplace($param2[[2]], $param3[[3]]);
679 ExpectedHint
{"A: ", "param1"}, ExpectedHint
{"B: ", "param2"},
680 ExpectedHint
{"C: ", "param3"});
683 TEST(ParameterHints
, VariadicReferenceHint
) {
684 assertParameterHints(R
"cpp(
686 template <typename... Args>
687 void bar(Args... args) { return foo(args...); }
696 TEST(ParameterHints
, VariadicReferenceHintForwardingRef
) {
697 assertParameterHints(R
"cpp(
699 template <typename... Args>
700 void bar(Args&&... args) { return foo(args...); }
707 ExpectedHint
{"&: ", "param"});
710 TEST(ParameterHints
, VariadicReferenceHintForwardingRefStdForward
) {
711 assertParameterHints(R
"cpp(
712 namespace std { template <typename T> T&& forward(T&); }
714 template <typename... Args>
715 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
721 ExpectedHint
{"&: ", "param"});
724 TEST(ParameterHints
, VariadicNoReferenceHintForwardingRefStdForward
) {
725 assertParameterHints(R
"cpp(
726 namespace std { template <typename T> T&& forward(T&); }
728 template <typename... Args>
729 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
738 TEST(ParameterHints
, VariadicNoReferenceHintUnresolvedForward
) {
739 assertParameterHints(R
"cpp(
740 template <typename... Args>
741 void foo(Args&&... args);
749 TEST(ParameterHints
, MatchingNameVariadicForwarded
) {
750 // No name hint for variadic parameter with matching name
751 // This prototype of std::forward is sufficient for clang to recognize it
752 assertParameterHints(R
"cpp(
753 namespace std { template <typename T> T&& forward(T&); }
755 template <typename... Args>
756 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
764 TEST(ParameterHints
, MatchingNameVariadicPlain
) {
765 // No name hint for variadic parameter with matching name
766 assertParameterHints(R
"cpp(
768 template <typename... Args>
769 void bar(Args&&... args) { return foo(args...); }
777 TEST(ParameterHints
, Operator
) {
778 // No hint for operator call with operator syntax.
779 assertParameterHints(R
"cpp(
781 void operator+(S lhs, S rhs);
789 TEST(ParameterHints
, Macros
) {
790 // Handling of macros depends on where the call's argument list comes from.
792 // If it comes from a macro definition, there's nothing to hint
793 // at the invocation site.
794 assertParameterHints(R
"cpp(
796 #define ExpandsToCall() foo(42)
802 // The argument expression being a macro invocation shouldn't interfere
804 assertParameterHints(R
"cpp(
806 void foo(double param);
811 ExpectedHint
{"param: ", "param"});
813 // If the whole argument list comes from a macro parameter, hint it.
814 assertParameterHints(R
"cpp(
816 #define ASSERT(expr) if (!expr) abort()
819 ASSERT(foo($param[[42]]) == 0);
822 ExpectedHint
{"param: ", "param"});
824 // If the macro expands to multiple arguments, don't hint it.
825 assertParameterHints(R
"cpp(
826 void foo(double x, double y);
827 #define CONSTANTS 3.14, 2.72
834 TEST(ParameterHints
, ConstructorParens
) {
835 assertParameterHints(R
"cpp(
843 ExpectedHint
{"param: ", "param"});
846 TEST(ParameterHints
, ConstructorBraces
) {
847 assertParameterHints(R
"cpp(
855 ExpectedHint
{"param: ", "param"});
858 TEST(ParameterHints
, ConstructorStdInitList
) {
859 // Do not show hints for std::initializer_list constructors.
860 assertParameterHints(R
"cpp(
862 template <typename> class initializer_list {};
865 S(std::initializer_list<int> param);
873 TEST(ParameterHints
, MemberInit
) {
874 assertParameterHints(R
"cpp(
880 T() : member($param[[42]]) {}
883 ExpectedHint
{"param: ", "param"});
886 TEST(ParameterHints
, ImplicitConstructor
) {
887 assertParameterHints(R
"cpp(
893 // Do not show hint for implicit constructor call in argument.
895 // Do not show hint for implicit constructor call in return.
901 TEST(ParameterHints
, ArgMatchesParam
) {
902 assertParameterHints(R
"cpp(
905 static const int param = 42;
909 // Do not show redundant "param
: param
".
911 // But show it if the argument is qualified.
912 foo($param[[S::param]]);
917 // Do not show "param
: param
" for member-expr.
922 ExpectedHint
{"param: ", "param"});
925 TEST(ParameterHints
, ArgMatchesParamReference
) {
926 assertParameterHints(R
"cpp(
927 void foo(int& param);
928 void foo2(const int& param);
931 // show reference hint on mutable reference
932 foo($param[[param]]);
933 // but not on const reference
937 ExpectedHint
{"&: ", "param"});
940 TEST(ParameterHints
, LeadingUnderscore
) {
941 assertParameterHints(R
"cpp(
942 void foo(int p1, int _p2, int __p3);
944 foo($p1[[41]], $p2[[42]], $p3[[43]]);
947 ExpectedHint
{"p1: ", "p1"}, ExpectedHint
{"p2: ", "p2"},
948 ExpectedHint
{"p3: ", "p3"});
951 TEST(ParameterHints
, DependentCalls
) {
952 assertParameterHints(R
"cpp(
953 template <typename T>
954 void nonmember(T par1);
956 template <typename T>
959 static void static_member(T par3);
962 void overload(int anInt);
963 void overload(double aDouble);
965 template <typename T>
967 void bar(A<T> a, T t) {
968 nonmember($par1[[t]]);
969 a.member($par2[[t]]);
970 A<T>::static_member($par3[[t]]);
971 // We don't want to arbitrarily pick between
972 // "anInt
" or "aDouble
", so just show no hint.
977 ExpectedHint
{"par1: ", "par1"},
978 ExpectedHint
{"par2: ", "par2"},
979 ExpectedHint
{"par3: ", "par3"});
982 TEST(ParameterHints
, VariadicFunction
) {
983 assertParameterHints(R
"cpp(
984 template <typename... T>
985 void foo(int fixed, T... variadic);
988 foo($fixed[[41]], 42, 43);
991 ExpectedHint
{"fixed: ", "fixed"});
994 TEST(ParameterHints
, VarargsFunction
) {
995 assertParameterHints(R
"cpp(
996 void foo(int fixed, ...);
999 foo($fixed[[41]], 42, 43);
1002 ExpectedHint
{"fixed: ", "fixed"});
1005 TEST(ParameterHints
, CopyOrMoveConstructor
) {
1006 // Do not show hint for parameter of copy or move constructor.
1007 assertParameterHints(R
"cpp(
1021 TEST(ParameterHints
, AggregateInit
) {
1022 // FIXME: This is not implemented yet, but it would be a natural
1023 // extension to show member names as hints here.
1024 assertParameterHints(R
"cpp(
1035 TEST(ParameterHints
, UserDefinedLiteral
) {
1036 // Do not hint call to user-defined literal operator.
1037 assertParameterHints(R
"cpp(
1038 long double operator"" _w(long double param);
1045 TEST(ParameterHints
, ParamNameComment
) {
1046 // Do not hint an argument which already has a comment
1047 // with the parameter name preceding it.
1048 assertParameterHints(R
"cpp(
1049 void foo(int param);
1052 foo( /* param = */ 42);
1056 foo(/*param=*/Z(a));
1057 foo($macro[[Z(a)]]);
1058 foo(/* the answer */$param[[42]]);
1061 ExpectedHint
{"param: ", "macro"},
1062 ExpectedHint
{"param: ", "param"});
1065 TEST(ParameterHints
, SetterFunctions
) {
1066 assertParameterHints(R
"cpp(
1068 void setParent(S* parent);
1069 void set_parent(S* parent);
1070 void setTimeout(int timeoutMillis);
1071 void setTimeoutMillis(int timeout_millis);
1075 // Parameter name matches setter name - omit hint.
1076 s.setParent(nullptr);
1077 // Support snake_case
1078 s.set_parent(nullptr);
1079 // Parameter name may contain extra info - show hint.
1080 s.setTimeout($timeoutMillis[[120]]);
1081 // FIXME: Ideally we'd want to omit this.
1082 s.setTimeoutMillis($timeout_millis[[120]]);
1085 ExpectedHint
{"timeoutMillis: ", "timeoutMillis"},
1086 ExpectedHint
{"timeout_millis: ", "timeout_millis"});
1089 TEST(ParameterHints
, BuiltinFunctions
) {
1090 // This prototype of std::forward is sufficient for clang to recognize it
1091 assertParameterHints(R
"cpp(
1092 namespace std { template <typename T> T&& forward(T&); }
1100 TEST(ParameterHints
, IncludeAtNonGlobalScope
) {
1101 Annotations
FooInc(R
"cpp(
1102 void bar() { foo(42); }
1104 Annotations
FooCC(R
"cpp(
1106 void foo(int param);
1111 TestWorkspace Workspace
;
1112 Workspace
.addSource("foo.inc", FooInc
.code());
1113 Workspace
.addMainFile("foo.cc", FooCC
.code());
1115 auto AST
= Workspace
.openFile("foo.cc");
1116 ASSERT_TRUE(bool(AST
));
1118 // Ensure the hint for the call in foo.inc is NOT materialized in foo.cc.
1119 EXPECT_EQ(hintsOfKind(*AST
, InlayHintKind::Parameter
).size(), 0u);
1122 TEST(TypeHints
, Smoke
) {
1123 assertTypeHints(R
"cpp(
1124 auto $waldo[[waldo]] = 42;
1126 ExpectedHint
{": int", "waldo"});
1129 TEST(TypeHints
, Decorations
) {
1130 assertTypeHints(R
"cpp(
1132 auto* $var1[[var1]] = &x;
1133 auto&& $var2[[var2]] = x;
1134 const auto& $var3[[var3]] = x;
1136 ExpectedHint
{": int *", "var1"},
1137 ExpectedHint
{": int &", "var2"},
1138 ExpectedHint
{": const int &", "var3"});
1141 TEST(TypeHints
, DecltypeAuto
) {
1142 assertTypeHints(R
"cpp(
1145 decltype(auto) $z[[z]] = y;
1147 ExpectedHint
{": int &", "z"});
1150 TEST(TypeHints
, NoQualifiers
) {
1151 assertTypeHints(R
"cpp(
1156 auto $x[[x]] = foo();
1159 template <typename T>
1162 S2::Inner<int> bar();
1163 auto $y[[y]] = bar();
1167 ExpectedHint
{": S1", "x"},
1168 // FIXME: We want to suppress scope specifiers
1169 // here because we are into the whole
1170 // brevity thing, but the ElaboratedType
1171 // printer does not honor the SuppressScope
1172 // flag by design, so we need to extend the
1173 // PrintingPolicy to support this use case.
1174 ExpectedHint
{": S2::Inner<int>", "y"});
1177 TEST(TypeHints
, Lambda
) {
1178 // Do not print something overly verbose like the lambda's location.
1179 // Show hints for init-captures (but not regular captures).
1180 assertTypeHints(R
"cpp(
1183 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1184 return a + cap + init;
1188 ExpectedHint
{": (lambda)", "L"},
1189 ExpectedHint
{": int", "init"}, ExpectedHint
{"-> int", "ret"});
1191 // Lambda return hint shown even if no param list.
1192 // (The digraph :> is just a ] that doesn't conflict with the annotations).
1193 assertTypeHints("auto $L[[x]] = <:$ret[[:>]]{return 42;};",
1194 ExpectedHint
{": (lambda)", "L"},
1195 ExpectedHint
{"-> int", "ret"});
1198 // Structured bindings tests.
1199 // Note, we hint the individual bindings, not the aggregate.
1201 TEST(TypeHints
, StructuredBindings_PublicStruct
) {
1202 assertTypeHints(R
"cpp(
1203 // Struct with public fields.
1209 auto [$x[[x]], $y[[y]]] = foo();
1211 ExpectedHint
{": int", "x"}, ExpectedHint
{": int", "y"});
1214 TEST(TypeHints
, StructuredBindings_Array
) {
1215 assertTypeHints(R
"cpp(
1217 auto [$x[[x]], $y[[y]]] = arr;
1219 ExpectedHint
{": int", "x"}, ExpectedHint
{": int", "y"});
1222 TEST(TypeHints
, StructuredBindings_TupleLike
) {
1223 assertTypeHints(R
"cpp(
1230 template <typename T>
1231 struct tuple_size {};
1233 struct tuple_size<IntPair> {
1234 constexpr static unsigned value = 2;
1236 template <unsigned I, typename T>
1237 struct tuple_element {};
1238 template <unsigned I>
1239 struct tuple_element<I, IntPair> {
1243 template <unsigned I>
1244 int get(const IntPair& p) {
1245 if constexpr (I == 0) {
1247 } else if constexpr (I == 1) {
1252 auto [$x[[x]], $y[[y]]] = bar();
1254 ExpectedHint
{": int", "x"}, ExpectedHint
{": int", "y"});
1257 TEST(TypeHints
, StructuredBindings_NoInitializer
) {
1258 assertTypeHints(R
"cpp(
1259 // No initializer (ill-formed).
1260 // Do not show useless "NULL TYPE
" hint.
1261 auto [x, y]; /*error-ok*/
1265 TEST(TypeHints
, InvalidType
) {
1266 assertTypeHints(R
"cpp(
1267 auto x = (unknown_type)42; /*error-ok*/
1268 auto *y = (unknown_ptr)nullptr;
1272 TEST(TypeHints
, ReturnTypeDeduction
) {
1275 auto f1(int x$ret1a[[)]]; // Hint forward declaration too
1276 auto f1(int x$ret1b[[)]] { return x + 1; }
1278 // Include pointer operators in hint
1280 auto& f2($ret2[[)]] { return s; }
1282 // Do not hint `auto` for trailing return type.
1285 // Do not hint when a trailing return type is specified.
1286 auto f4() -> auto* { return "foo
"; }
1288 auto f5($noreturn[[)]] {}
1290 // `auto` conversion operator
1292 operator auto($retConv[[)]] { return 42; }
1295 // FIXME: Dependent types do not work yet.
1296 template <typename T>
1298 auto method() { return T(); }
1301 ExpectedHint
{"-> int", "ret1a"}, ExpectedHint
{"-> int", "ret1b"},
1302 ExpectedHint
{"-> int &", "ret2"}, ExpectedHint
{"-> void", "noreturn"},
1303 ExpectedHint
{"-> int", "retConv"});
1306 TEST(TypeHints
, DependentType
) {
1307 assertTypeHints(R
"cpp(
1308 template <typename T>
1310 // The hint would just be "auto" and we can't do any better.
1311 auto var1 = arg.method();
1312 // FIXME: It would be nice to show "T
" as the hint.
1313 auto $var2[[var2]] = arg;
1318 TEST(TypeHints
, LongTypeName
) {
1319 assertTypeHints(R
"cpp(
1320 template <typename, typename, typename>
1322 struct MultipleWords {};
1323 A<MultipleWords, MultipleWords, MultipleWords> foo();
1324 // Omit type hint past a certain length (currently 32)
1329 Cfg
.InlayHints
.TypeNameLimit
= 0;
1330 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
1334 template <typename, typename, typename>
1336 struct MultipleWords {};
1337 A<MultipleWords, MultipleWords, MultipleWords> foo();
1338 // Should have type hint with TypeNameLimit = 0
1339 auto $var[[var]] = foo();
1341 ExpectedHint
{": A<MultipleWords, MultipleWords, MultipleWords>", "var"});
1344 TEST(TypeHints
, DefaultTemplateArgs
) {
1345 assertTypeHints(R
"cpp(
1346 template <typename, typename = int>
1349 auto $var[[var]] = foo();
1351 auto [$binding[[value]]] = bar;
1353 ExpectedHint
{": A<float>", "var"},
1354 ExpectedHint
{": A<float>", "binding"});
1357 TEST(TypeHints
, Deduplication
) {
1358 assertTypeHints(R
"cpp(
1359 template <typename T>
1361 auto $var[[var]] = 42;
1363 template void foo<int>();
1364 template void foo<float>();
1366 ExpectedHint
{": int", "var"});
1369 TEST(TypeHints
, SinglyInstantiatedTemplate
) {
1370 assertTypeHints(R
"cpp(
1371 auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
1372 int m = x("foo
", 3);
1374 ExpectedHint
{": (lambda)", "lambda"},
1375 ExpectedHint
{": const char *", "param"});
1377 // No hint for packs, or auto params following packs
1378 assertTypeHints(R
"cpp(
1379 int x(auto $a[[a]], auto... b, auto c) { return 42; }
1380 int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
1382 ExpectedHint
{": void *", "a"});
1385 TEST(TypeHints
, Aliased
) {
1386 // Check that we don't crash for functions without a FunctionTypeLoc.
1387 // https://github.com/clangd/clangd/issues/1140
1388 TestTU TU
= TestTU::withCode("void foo(void){} extern typeof(foo) foo;");
1389 TU
.ExtraArgs
.push_back("-xc");
1390 auto AST
= TU
.build();
1392 EXPECT_THAT(hintsOfKind(AST
, InlayHintKind::Type
), IsEmpty());
1395 TEST(TypeHints
, Decltype
) {
1396 assertTypeHints(R
"cpp(
1397 $a[[decltype(0)]] a;
1398 $b[[decltype(a)]] b;
1399 const $c[[decltype(0)]] &c = b;
1401 // Don't show for dependent type
1403 constexpr decltype(T{}) d;
1405 $e[[decltype(0)]] e();
1406 auto f() -> $f[[decltype(0)]];
1408 template <class, class> struct Foo;
1409 using G = Foo<$g[[decltype(0)]], float>;
1411 auto $h[[h]] = $i[[decltype(0)]]{};
1417 ExpectedHint
{": int", "a"}, ExpectedHint
{": int", "b"},
1418 ExpectedHint
{": int", "c"}, ExpectedHint
{": int", "e"},
1419 ExpectedHint
{": int", "f"}, ExpectedHint
{": int", "g"},
1420 ExpectedHint
{": int", "h"}, ExpectedHint
{": int", "i"});
1423 TEST(TypeHints
, SubstTemplateParameterAliases
) {
1426 template <class T> struct allocator {};
1428 template <class T, class A>
1429 struct vector_base {
1433 template <class T, class A>
1434 struct internal_iterator_type_template_we_dont_expect {};
1436 struct my_iterator {};
1438 template <class T, class A = allocator<T>>
1439 struct vector : vector_base<T, A> {
1440 using base = vector_base<T, A>;
1441 typedef T value_type;
1442 typedef base::pointer pointer;
1443 using allocator_type = A;
1444 using size_type = int;
1445 using iterator = internal_iterator_type_template_we_dont_expect<T, A>;
1446 using non_template_iterator = my_iterator;
1448 value_type& operator[](int index) { return elements[index]; }
1449 const value_type& at(int index) const { return elements[index]; }
1450 pointer data() { return &elements[0]; }
1451 allocator_type get_allocator() { return A(); }
1452 size_type size() const { return 10; }
1453 iterator begin() { return iterator(); }
1454 non_template_iterator end() { return non_template_iterator(); }
1461 auto $no_modifier[[by_value]] = array[3];
1462 auto* $ptr_modifier[[ptr]] = &array[3];
1463 auto& $ref_modifier[[ref]] = array[3];
1464 auto& $at[[immutable]] = array.at(3);
1466 auto $data[[data]] = array.data();
1467 auto $allocator[[alloc]] = array.get_allocator();
1468 auto $size[[size]] = array.size();
1469 auto $begin[[begin]] = array.begin();
1470 auto $end[[end]] = array.end();
1473 // If the type alias is not of substituted template parameter type,
1474 // do not show desugared type.
1475 using VeryLongLongTypeName = my_iterator;
1476 using Short = VeryLongLongTypeName;
1478 auto $short_name[[my_value]] = Short();
1480 // Same applies with templates.
1481 template <typename T, typename A>
1482 using basic_static_vector = vector<T, A>;
1483 template <typename T>
1484 using static_vector = basic_static_vector<T, allocator<T>>;
1486 auto $vector_name[[vec]] = static_vector<int>();
1488 ExpectedHint
{": int", "no_modifier"},
1489 ExpectedHint
{": int *", "ptr_modifier"},
1490 ExpectedHint
{": int &", "ref_modifier"},
1491 ExpectedHint
{": const int &", "at"}, ExpectedHint
{": int *", "data"},
1492 ExpectedHint
{": allocator<int>", "allocator"},
1493 ExpectedHint
{": size_type", "size"}, ExpectedHint
{": iterator", "begin"},
1494 ExpectedHint
{": non_template_iterator", "end"},
1495 ExpectedHint
{": Short", "short_name"},
1496 ExpectedHint
{": static_vector<int>", "vector_name"});
1499 TEST(DesignatorHints
, Basic
) {
1500 assertDesignatorHints(R
"cpp(
1501 struct S { int x, y, z; };
1502 S s {$x[[1]], $y[[2+2]]};
1504 int x[] = {$0[[0]], $1[[1]]};
1506 ExpectedHint
{".x=", "x"}, ExpectedHint
{".y=", "y"},
1507 ExpectedHint
{"[0]=", "0"}, ExpectedHint
{"[1]=", "1"});
1510 TEST(DesignatorHints
, Nested
) {
1511 assertDesignatorHints(R
"cpp(
1512 struct Inner { int x, y; };
1513 struct Outer { Inner a, b; };
1514 Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
1516 ExpectedHint
{".a=", "a"}, ExpectedHint
{".x=", "x"},
1517 ExpectedHint
{".y=", "y"}, ExpectedHint
{".b.x=", "bx"});
1520 TEST(DesignatorHints
, AnonymousRecord
) {
1521 assertDesignatorHints(R
"cpp(
1533 ExpectedHint
{".x.y=", "xy"});
1536 TEST(DesignatorHints
, Suppression
) {
1537 assertDesignatorHints(R
"cpp(
1538 struct Point { int a, b, c, d, e, f, g, h; };
1539 Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
1541 ExpectedHint
{".e=", "e"});
1544 TEST(DesignatorHints
, StdArray
) {
1545 // Designators for std::array should be [0] rather than .__elements[0].
1546 // While technically correct, the designator is useless and horrible to read.
1547 assertDesignatorHints(R
"cpp(
1548 template <typename T, int N> struct Array { T __elements[N]; };
1549 Array<int, 2> x = {$0[[0]], $1[[1]]};
1551 ExpectedHint
{"[0]=", "0"}, ExpectedHint
{"[1]=", "1"});
1554 TEST(DesignatorHints
, OnlyAggregateInit
) {
1555 assertDesignatorHints(R
"cpp(
1556 struct Copyable { int x; } c;
1559 struct Constructible { Constructible(int x); };
1560 Constructible x{42};
1561 )cpp" /*no designator hints expected (but param hints!)*/);
1564 TEST(DesignatorHints
, NoCrash
) {
1565 assertDesignatorHints(R
"cpp(
1568 struct Foo {int a; int b;};
1570 Foo f{A(), $b[[1]]};
1572 )cpp", ExpectedHint
{".b=", "b"});
1575 TEST(InlayHints
, RestrictRange
) {
1576 Annotations
Code(R
"cpp(
1582 auto AST
= TestTU::withCode(Code
.code()).build();
1583 EXPECT_THAT(inlayHints(AST
, Code
.range()),
1584 ElementsAre(labelIs(": int"), labelIs(": char")));
1587 TEST(ParameterHints
, ArgPacksAndConstructors
) {
1588 assertParameterHints(
1590 struct Foo{ Foo(); Foo(int x); };
1591 void foo(Foo a, int b);
1592 template <typename... Args>
1593 void bar(Args... args) {
1596 template <typename... Args>
1597 void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
1599 template <typename... Args>
1600 void bax(Args... args) { foo($param3[[{args...}]], args...); }
1603 bar($param4[[Foo{}]], $param5[[42]]);
1604 bar($param6[[42]], $param7[[42]]);
1609 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"},
1610 ExpectedHint
{"a: ", "param3"}, ExpectedHint
{"a: ", "param4"},
1611 ExpectedHint
{"b: ", "param5"}, ExpectedHint
{"a: ", "param6"},
1612 ExpectedHint
{"b: ", "param7"}, ExpectedHint
{"x: ", "param8"},
1613 ExpectedHint
{"b: ", "param9"});
1616 TEST(ParameterHints
, DoesntExpandAllArgs
) {
1617 assertParameterHints(
1619 void foo(int x, int y);
1620 int id(int a, int b, int c);
1621 template <typename... Args>
1622 void bar(Args... args) {
1623 foo(id($param1[[args]], $param2[[1]], $param3[[args]])...);
1626 bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1629 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"},
1630 ExpectedHint
{"c: ", "param3"});
1632 // FIXME: Low-hanging fruit where we could omit a type hint:
1633 // - auto x = TypeName(...);
1634 // - auto x = (TypeName) (...);
1635 // - auto x = static_cast<TypeName>(...); // and other built-in casts
1637 // Annoyances for which a heuristic is not obvious:
1638 // - auto x = llvm::dyn_cast<LongTypeName>(y); // and similar
1639 // - stdlib algos return unwieldy __normal_iterator<X*, ...> type
1640 // (For this one, perhaps we should omit type hints that start
1641 // with a double underscore.)
1644 } // namespace clangd
1645 } // namespace clang