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"
26 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&Stream
,
27 const InlayHint
&Hint
) {
28 return Stream
<< Hint
.label
<< "@" << Hint
.range
;
33 using ::testing::ElementsAre
;
34 using ::testing::IsEmpty
;
36 std::vector
<InlayHint
> hintsOfKind(ParsedAST
&AST
, InlayHintKind Kind
) {
37 std::vector
<InlayHint
> Result
;
38 for (auto &Hint
: inlayHints(AST
, /*RestrictRange=*/std::nullopt
)) {
39 if (Hint
.kind
== Kind
)
40 Result
.push_back(Hint
);
45 enum HintSide
{ Left
, Right
};
49 std::string RangeName
;
52 friend llvm::raw_ostream
&operator<<(llvm::raw_ostream
&Stream
,
53 const ExpectedHint
&Hint
) {
54 return Stream
<< Hint
.Label
<< "@$" << Hint
.RangeName
;
58 MATCHER_P2(HintMatcher
, Expected
, Code
, llvm::to_string(Expected
)) {
59 llvm::StringRef
ExpectedView(Expected
.Label
);
60 if (arg
.label
!= ExpectedView
.trim(" ") ||
61 arg
.paddingLeft
!= ExpectedView
.startswith(" ") ||
62 arg
.paddingRight
!= ExpectedView
.endswith(" ")) {
63 *result_listener
<< "label is '" << arg
.label
<< "'";
66 if (arg
.range
!= Code
.range(Expected
.RangeName
)) {
67 *result_listener
<< "range is " << llvm::to_string(arg
.range
) << " but $"
68 << Expected
.RangeName
<< " is "
69 << llvm::to_string(Code
.range(Expected
.RangeName
));
75 MATCHER_P(labelIs
, Label
, "") { return arg
.label
== Label
; }
77 Config
noHintsConfig() {
79 C
.InlayHints
.Parameters
= false;
80 C
.InlayHints
.DeducedTypes
= false;
81 C
.InlayHints
.Designators
= false;
82 C
.InlayHints
.BlockEnd
= false;
86 template <typename
... ExpectedHints
>
87 void assertHintsWithHeader(InlayHintKind Kind
, llvm::StringRef AnnotatedSource
,
88 llvm::StringRef HeaderContent
,
89 ExpectedHints
... Expected
) {
90 Annotations
Source(AnnotatedSource
);
91 TestTU TU
= TestTU::withCode(Source
.code());
92 TU
.ExtraArgs
.push_back("-std=c++20");
93 TU
.HeaderCode
= HeaderContent
;
94 auto AST
= TU
.build();
96 EXPECT_THAT(hintsOfKind(AST
, Kind
),
97 ElementsAre(HintMatcher(Expected
, Source
)...));
98 // Sneak in a cross-cutting check that hints are disabled by config.
99 // We'll hit an assertion failure if addInlayHint still gets called.
100 WithContextValue
WithCfg(Config::Key
, noHintsConfig());
101 EXPECT_THAT(inlayHints(AST
, std::nullopt
), IsEmpty());
104 template <typename
... ExpectedHints
>
105 void assertHints(InlayHintKind Kind
, llvm::StringRef AnnotatedSource
,
106 ExpectedHints
... Expected
) {
107 return assertHintsWithHeader(Kind
, AnnotatedSource
, "",
108 std::move(Expected
)...);
111 // Hack to allow expression-statements operating on parameter packs in C++14.
112 template <typename
... T
> void ignore(T
&&...) {}
114 template <typename
... ExpectedHints
>
115 void assertParameterHints(llvm::StringRef AnnotatedSource
,
116 ExpectedHints
... Expected
) {
117 ignore(Expected
.Side
= Left
...);
118 assertHints(InlayHintKind::Parameter
, AnnotatedSource
, Expected
...);
121 template <typename
... ExpectedHints
>
122 void assertTypeHints(llvm::StringRef AnnotatedSource
,
123 ExpectedHints
... Expected
) {
124 ignore(Expected
.Side
= Right
...);
125 assertHints(InlayHintKind::Type
, AnnotatedSource
, Expected
...);
128 template <typename
... ExpectedHints
>
129 void assertDesignatorHints(llvm::StringRef AnnotatedSource
,
130 ExpectedHints
... Expected
) {
132 Cfg
.InlayHints
.Designators
= true;
133 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
134 assertHints(InlayHintKind::Designator
, AnnotatedSource
, Expected
...);
137 template <typename
... ExpectedHints
>
138 void assertBlockEndHints(llvm::StringRef AnnotatedSource
,
139 ExpectedHints
... Expected
) {
141 Cfg
.InlayHints
.BlockEnd
= true;
142 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
143 assertHints(InlayHintKind::BlockEnd
, AnnotatedSource
, Expected
...);
146 TEST(ParameterHints
, Smoke
) {
147 assertParameterHints(R
"cpp(
153 ExpectedHint
{"param: ", "param"});
156 TEST(ParameterHints
, NoName
) {
157 // No hint for anonymous parameter.
158 assertParameterHints(R
"cpp(
166 TEST(ParameterHints
, NoNameConstReference
) {
167 // No hint for anonymous const l-value ref parameter.
168 assertParameterHints(R
"cpp(
169 void foo(const int&);
176 TEST(ParameterHints
, NoNameReference
) {
177 // Reference hint for anonymous l-value ref parameter.
178 assertParameterHints(R
"cpp(
185 ExpectedHint
{"&: ", "param"});
188 TEST(ParameterHints
, NoNameRValueReference
) {
189 // No reference hint for anonymous r-value ref parameter.
190 assertParameterHints(R
"cpp(
198 TEST(ParameterHints
, NoNameVariadicDeclaration
) {
199 // No hint for anonymous variadic parameter
200 assertParameterHints(R
"cpp(
201 template <typename... Args>
202 void foo(Args&& ...);
209 TEST(ParameterHints
, NoNameVariadicForwarded
) {
210 // No hint for anonymous variadic parameter
211 // This prototype of std::forward is sufficient for clang to recognize it
212 assertParameterHints(R
"cpp(
213 namespace std { template <typename T> T&& forward(T&); }
215 template <typename... Args>
216 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
223 TEST(ParameterHints
, NoNameVariadicPlain
) {
224 // No hint for anonymous variadic parameter
225 assertParameterHints(R
"cpp(
227 template <typename... Args>
228 void bar(Args&&... args) { return foo(args...); }
235 TEST(ParameterHints
, NameInDefinition
) {
236 // Parameter name picked up from definition if necessary.
237 assertParameterHints(R
"cpp(
242 void foo(int param) {};
244 ExpectedHint
{"param: ", "param"});
247 TEST(ParameterHints
, NamePartiallyInDefinition
) {
248 // Parameter name picked up from definition if necessary.
249 assertParameterHints(R
"cpp(
250 void foo(int, int b);
252 foo($param1[[42]], $param2[[42]]);
254 void foo(int a, int) {};
256 ExpectedHint
{"a: ", "param1"},
257 ExpectedHint
{"b: ", "param2"});
260 TEST(ParameterHints
, NameInDefinitionVariadic
) {
261 // Parameter name picked up from definition in a resolved forwarded parameter.
262 assertParameterHints(R
"cpp(
264 template <typename... Args>
265 void bar(Args... args) {
269 bar($param1[[42]], $param2[[42]]);
271 void foo(int a, int b) {};
273 ExpectedHint
{"a: ", "param1"},
274 ExpectedHint
{"b: ", "param2"});
277 TEST(ParameterHints
, NameMismatch
) {
278 // Prefer name from declaration.
279 assertParameterHints(R
"cpp(
284 void foo(int bad) {};
286 ExpectedHint
{"good: ", "good"});
289 TEST(ParameterHints
, NameConstReference
) {
290 // Only name hint for const l-value ref parameter.
291 assertParameterHints(R
"cpp(
292 void foo(const int& param);
297 ExpectedHint
{"param: ", "param"});
300 TEST(ParameterHints
, NameTypeAliasConstReference
) {
301 // Only name hint for const l-value ref parameter via type alias.
302 assertParameterHints(R
"cpp(
303 using alias = const int&;
304 void foo(alias param);
310 ExpectedHint
{"param: ", "param"});
313 TEST(ParameterHints
, NameReference
) {
314 // Reference and name hint for l-value ref parameter.
315 assertParameterHints(R
"cpp(
316 void foo(int& param);
322 ExpectedHint
{"¶m: ", "param"});
325 TEST(ParameterHints
, NameTypeAliasReference
) {
326 // Reference and name hint for l-value ref parameter via type alias.
327 assertParameterHints(R
"cpp(
329 void foo(alias param);
335 ExpectedHint
{"¶m: ", "param"});
338 TEST(ParameterHints
, NameRValueReference
) {
339 // Only name hint for r-value ref parameter.
340 assertParameterHints(R
"cpp(
341 void foo(int&& param);
346 ExpectedHint
{"param: ", "param"});
349 TEST(ParameterHints
, VariadicForwardedConstructor
) {
350 // Name hint for variadic parameter using std::forward in a constructor call
351 // This prototype of std::forward is sufficient for clang to recognize it
352 assertParameterHints(R
"cpp(
353 namespace std { template <typename T> T&& forward(T&); }
354 struct S { S(int a); };
355 template <typename T, typename... Args>
356 T bar(Args&&... args) { return T{std::forward<Args>(args)...}; }
362 ExpectedHint
{"a: ", "param"});
365 TEST(ParameterHints
, VariadicPlainConstructor
) {
366 // Name hint for variadic parameter in a constructor call
367 assertParameterHints(R
"cpp(
368 struct S { S(int a); };
369 template <typename T, typename... Args>
370 T bar(Args&&... args) { return T{args...}; }
376 ExpectedHint
{"a: ", "param"});
379 TEST(ParameterHints
, VariadicForwardedNewConstructor
) {
380 // Name hint for variadic parameter using std::forward in a new expression
381 // This prototype of std::forward is sufficient for clang to recognize it
382 assertParameterHints(R
"cpp(
383 namespace std { template <typename T> T&& forward(T&); }
384 struct S { S(int a); };
385 template <typename T, typename... Args>
386 T* bar(Args&&... args) { return new T{std::forward<Args>(args)...}; }
392 ExpectedHint
{"a: ", "param"});
395 TEST(ParameterHints
, VariadicPlainNewConstructor
) {
396 // Name hint for variadic parameter in a new expression
397 assertParameterHints(R
"cpp(
398 struct S { S(int a); };
399 template <typename T, typename... Args>
400 T* bar(Args&&... args) { return new T{args...}; }
406 ExpectedHint
{"a: ", "param"});
409 TEST(ParameterHints
, VariadicForwarded
) {
410 // Name for variadic parameter using std::forward
411 // This prototype of std::forward is sufficient for clang to recognize it
412 assertParameterHints(R
"cpp(
413 namespace std { template <typename T> T&& forward(T&); }
415 template <typename... Args>
416 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
422 ExpectedHint
{"a: ", "param"});
425 TEST(ParameterHints
, VariadicPlain
) {
426 // Name hint for variadic parameter
427 assertParameterHints(R
"cpp(
429 template <typename... Args>
430 void bar(Args&&... args) { return foo(args...); }
435 ExpectedHint
{"a: ", "param"});
438 TEST(ParameterHints
, VariadicPlainWithPackFirst
) {
439 // Name hint for variadic parameter when the parameter pack is not the last
440 // template parameter
441 assertParameterHints(R
"cpp(
443 template <typename... Args, typename Arg>
444 void bar(Arg, Args&&... args) { return foo(args...); }
446 bar(1, $param[[42]]);
449 ExpectedHint
{"a: ", "param"});
452 TEST(ParameterHints
, VariadicSplitTwolevel
) {
453 // Name for variadic parameter that involves both head and tail parameters to
455 // This prototype of std::forward is sufficient for clang to recognize it
456 assertParameterHints(R
"cpp(
457 namespace std { template <typename T> T&& forward(T&); }
458 void baz(int, int b, double);
459 template <typename... Args>
460 void foo(int a, Args&&... args) {
461 return baz(1, std::forward<Args>(args)..., 1.0);
463 template <typename... Args>
464 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
466 bar($param1[[32]], $param2[[42]]);
469 ExpectedHint
{"a: ", "param1"},
470 ExpectedHint
{"b: ", "param2"});
473 TEST(ParameterHints
, VariadicNameFromSpecialization
) {
474 // We don't try to resolve forwarding parameters if the function call uses a
476 assertParameterHints(R
"cpp(
478 template <typename... Args>
479 void bar(Args... args) {
483 void bar<int>(int b);
488 ExpectedHint
{"b: ", "param"});
491 TEST(ParameterHints
, VariadicNameFromSpecializationRecursive
) {
492 // We don't try to resolve forwarding parameters inside a forwarding function
493 // call if that function call uses a specialization.
494 assertParameterHints(R
"cpp(
496 template <typename... Args>
497 void foo(Args... args) {
500 template <typename... Args>
501 void bar(Args... args) {
505 void foo<int>(int b);
510 ExpectedHint
{"b: ", "param"});
513 TEST(ParameterHints
, VariadicOverloaded
) {
514 // Name for variadic parameter for an overloaded function with unique number
516 // This prototype of std::forward is sufficient for clang to recognize it
517 assertParameterHints(
519 namespace std { template <typename T> T&& forward(T&); }
520 void baz(int b, int c);
521 void baz(int bb, int cc, int dd);
522 template <typename... Args>
523 void foo(int a, Args&&... args) {
524 return baz(std::forward<Args>(args)...);
526 template <typename... Args>
527 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
529 bar($param1[[32]], $param2[[42]], $param3[[52]]);
530 bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
533 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"},
534 ExpectedHint
{"c: ", "param3"}, ExpectedHint
{"a: ", "param4"},
535 ExpectedHint
{"bb: ", "param5"}, ExpectedHint
{"cc: ", "param6"},
536 ExpectedHint
{"dd: ", "param7"});
539 TEST(ParameterHints
, VariadicRecursive
) {
540 // make_tuple-like recursive variadic call
541 assertParameterHints(
545 template <typename Head, typename... Tail>
546 void foo(Head head, Tail... tail) {
550 template <typename... Args>
551 void bar(Args... args) {
561 TEST(ParameterHints
, VariadicVarargs
) {
562 // variadic call involving varargs (to make sure we don't crash)
563 assertParameterHints(R
"cpp(
564 void foo(int fixed, ...);
565 template <typename... Args>
566 void bar(Args&&... args) {
571 bar($fixed[[41]], 42, 43);
576 TEST(ParameterHints
, VariadicTwolevelUnresolved
) {
577 // the same setting as VariadicVarargs, only with parameter pack
578 assertParameterHints(R
"cpp(
579 template <typename... Args>
580 void foo(int fixed, Args&& ... args);
581 template <typename... Args>
582 void bar(Args&&... args) {
587 bar($fixed[[41]], 42, 43);
590 ExpectedHint
{"fixed: ", "fixed"});
593 TEST(ParameterHints
, VariadicTwoCalls
) {
594 // only the first call using the parameter pack should be picked up
595 assertParameterHints(
597 void f1(int a, int b);
598 void f2(int c, int d);
602 template <typename... Args>
603 void foo(Args... args) {
612 foo($param1[[1]], $param2[[2]]);
615 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"});
618 TEST(ParameterHints
, VariadicInfinite
) {
619 // infinite recursion should not break clangd
620 assertParameterHints(
622 template <typename... Args>
625 template <typename... Args>
626 void bar(Args... args) {
630 template <typename... Args>
631 void foo(Args... args) {
641 TEST(ParameterHints
, VariadicDuplicatePack
) {
642 // edge cases with multiple adjacent packs should work
643 assertParameterHints(
645 void foo(int a, int b, int c, int);
647 template <typename... Args>
648 void bar(int, Args... args, int d) {
652 template <typename... Args>
653 void baz(Args... args, Args... args2) {
654 bar<Args..., int>(1, args..., args2...);
658 baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
661 ExpectedHint
{"a: ", "p1"}, ExpectedHint
{"b: ", "p2"},
662 ExpectedHint
{"c: ", "p3"}, ExpectedHint
{"d: ", "p4"});
665 TEST(ParameterHints
, VariadicEmplace
) {
666 // emplace-like calls should forward constructor parameters
667 // This prototype of std::forward is sufficient for clang to recognize it
668 assertParameterHints(
670 namespace std { template <typename T> T&& forward(T&); }
671 using size_t = decltype(sizeof(0));
672 void *operator new(size_t, void *);
678 template <typename T>
680 template <typename T, typename... Args>
681 void construct(T* ptr, Args&&... args) {
682 ::new ((void*)ptr) T{std::forward<Args>(args)...};
685 template <typename T>
687 template <typename... Args>
688 void emplace(Args&&... args) {
690 auto ptr = a.template allocate<T>();
691 a.construct(ptr, std::forward<Args>(args)...);
696 c.emplace($param1[[1]]);
697 c.emplace($param2[[2]], $param3[[3]]);
700 ExpectedHint
{"A: ", "param1"}, ExpectedHint
{"B: ", "param2"},
701 ExpectedHint
{"C: ", "param3"});
704 TEST(ParameterHints
, VariadicReferenceHint
) {
705 assertParameterHints(R
"cpp(
707 template <typename... Args>
708 void bar(Args... args) { return foo(args...); }
717 TEST(ParameterHints
, VariadicReferenceHintForwardingRef
) {
718 assertParameterHints(R
"cpp(
720 template <typename... Args>
721 void bar(Args&&... args) { return foo(args...); }
728 ExpectedHint
{"&: ", "param"});
731 TEST(ParameterHints
, VariadicReferenceHintForwardingRefStdForward
) {
732 assertParameterHints(R
"cpp(
733 namespace std { template <typename T> T&& forward(T&); }
735 template <typename... Args>
736 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
742 ExpectedHint
{"&: ", "param"});
745 TEST(ParameterHints
, VariadicNoReferenceHintForwardingRefStdForward
) {
746 assertParameterHints(R
"cpp(
747 namespace std { template <typename T> T&& forward(T&); }
749 template <typename... Args>
750 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
759 TEST(ParameterHints
, VariadicNoReferenceHintUnresolvedForward
) {
760 assertParameterHints(R
"cpp(
761 template <typename... Args>
762 void foo(Args&&... args);
770 TEST(ParameterHints
, MatchingNameVariadicForwarded
) {
771 // No name hint for variadic parameter with matching name
772 // This prototype of std::forward is sufficient for clang to recognize it
773 assertParameterHints(R
"cpp(
774 namespace std { template <typename T> T&& forward(T&); }
776 template <typename... Args>
777 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
785 TEST(ParameterHints
, MatchingNameVariadicPlain
) {
786 // No name hint for variadic parameter with matching name
787 assertParameterHints(R
"cpp(
789 template <typename... Args>
790 void bar(Args&&... args) { return foo(args...); }
798 TEST(ParameterHints
, Operator
) {
799 // No hint for operator call with operator syntax.
800 assertParameterHints(R
"cpp(
802 void operator+(S lhs, S rhs);
810 TEST(ParameterHints
, Macros
) {
811 // Handling of macros depends on where the call's argument list comes from.
813 // If it comes from a macro definition, there's nothing to hint
814 // at the invocation site.
815 assertParameterHints(R
"cpp(
817 #define ExpandsToCall() foo(42)
823 // The argument expression being a macro invocation shouldn't interfere
825 assertParameterHints(R
"cpp(
827 void foo(double param);
832 ExpectedHint
{"param: ", "param"});
834 // If the whole argument list comes from a macro parameter, hint it.
835 assertParameterHints(R
"cpp(
837 #define ASSERT(expr) if (!expr) abort()
840 ASSERT(foo($param[[42]]) == 0);
843 ExpectedHint
{"param: ", "param"});
845 // If the macro expands to multiple arguments, don't hint it.
846 assertParameterHints(R
"cpp(
847 void foo(double x, double y);
848 #define CONSTANTS 3.14, 2.72
855 TEST(ParameterHints
, ConstructorParens
) {
856 assertParameterHints(R
"cpp(
864 ExpectedHint
{"param: ", "param"});
867 TEST(ParameterHints
, ConstructorBraces
) {
868 assertParameterHints(R
"cpp(
876 ExpectedHint
{"param: ", "param"});
879 TEST(ParameterHints
, ConstructorStdInitList
) {
880 // Do not show hints for std::initializer_list constructors.
881 assertParameterHints(R
"cpp(
883 template <typename> class initializer_list {};
886 S(std::initializer_list<int> param);
894 TEST(ParameterHints
, MemberInit
) {
895 assertParameterHints(R
"cpp(
901 T() : member($param[[42]]) {}
904 ExpectedHint
{"param: ", "param"});
907 TEST(ParameterHints
, ImplicitConstructor
) {
908 assertParameterHints(R
"cpp(
914 // Do not show hint for implicit constructor call in argument.
916 // Do not show hint for implicit constructor call in return.
922 TEST(ParameterHints
, FunctionPointer
) {
923 assertParameterHints(
925 void (*f1)(int param);
926 void (__stdcall *f2)(int param);
927 using f3_t = void(*)(int param);
929 using f4_t = void(__stdcall *)(int param);
938 ExpectedHint
{"param: ", "f1"}, ExpectedHint
{"param: ", "f2"},
939 ExpectedHint
{"param: ", "f3"}, ExpectedHint
{"param: ", "f4"});
942 TEST(ParameterHints
, ArgMatchesParam
) {
943 assertParameterHints(R
"cpp(
946 static const int param = 42;
950 // Do not show redundant "param
: param
".
952 // But show it if the argument is qualified.
953 foo($param[[S::param]]);
958 // Do not show "param
: param
" for member-expr.
963 ExpectedHint
{"param: ", "param"});
966 TEST(ParameterHints
, ArgMatchesParamReference
) {
967 assertParameterHints(R
"cpp(
968 void foo(int& param);
969 void foo2(const int& param);
972 // show reference hint on mutable reference
973 foo($param[[param]]);
974 // but not on const reference
978 ExpectedHint
{"&: ", "param"});
981 TEST(ParameterHints
, LeadingUnderscore
) {
982 assertParameterHints(R
"cpp(
983 void foo(int p1, int _p2, int __p3);
985 foo($p1[[41]], $p2[[42]], $p3[[43]]);
988 ExpectedHint
{"p1: ", "p1"}, ExpectedHint
{"p2: ", "p2"},
989 ExpectedHint
{"p3: ", "p3"});
992 TEST(ParameterHints
, DependentCalls
) {
993 assertParameterHints(R
"cpp(
994 template <typename T>
995 void nonmember(T par1);
997 template <typename T>
1000 static void static_member(T par3);
1003 void overload(int anInt);
1004 void overload(double aDouble);
1006 template <typename T>
1008 void bar(A<T> a, T t) {
1009 nonmember($par1[[t]]);
1010 a.member($par2[[t]]);
1011 A<T>::static_member($par3[[t]]);
1012 // We don't want to arbitrarily pick between
1013 // "anInt
" or "aDouble
", so just show no hint.
1018 ExpectedHint
{"par1: ", "par1"},
1019 ExpectedHint
{"par2: ", "par2"},
1020 ExpectedHint
{"par3: ", "par3"});
1023 TEST(ParameterHints
, VariadicFunction
) {
1024 assertParameterHints(R
"cpp(
1025 template <typename... T>
1026 void foo(int fixed, T... variadic);
1029 foo($fixed[[41]], 42, 43);
1032 ExpectedHint
{"fixed: ", "fixed"});
1035 TEST(ParameterHints
, VarargsFunction
) {
1036 assertParameterHints(R
"cpp(
1037 void foo(int fixed, ...);
1040 foo($fixed[[41]], 42, 43);
1043 ExpectedHint
{"fixed: ", "fixed"});
1046 TEST(ParameterHints
, CopyOrMoveConstructor
) {
1047 // Do not show hint for parameter of copy or move constructor.
1048 assertParameterHints(R
"cpp(
1062 TEST(ParameterHints
, AggregateInit
) {
1063 // FIXME: This is not implemented yet, but it would be a natural
1064 // extension to show member names as hints here.
1065 assertParameterHints(R
"cpp(
1076 TEST(ParameterHints
, UserDefinedLiteral
) {
1077 // Do not hint call to user-defined literal operator.
1078 assertParameterHints(R
"cpp(
1079 long double operator"" _w(long double param);
1086 TEST(ParameterHints
, ParamNameComment
) {
1087 // Do not hint an argument which already has a comment
1088 // with the parameter name preceding it.
1089 assertParameterHints(R
"cpp(
1090 void foo(int param);
1093 foo( /* param = */ 42);
1097 foo(/*param=*/Z(a));
1098 foo($macro[[Z(a)]]);
1099 foo(/* the answer */$param[[42]]);
1102 ExpectedHint
{"param: ", "macro"},
1103 ExpectedHint
{"param: ", "param"});
1106 TEST(ParameterHints
, SetterFunctions
) {
1107 assertParameterHints(R
"cpp(
1109 void setParent(S* parent);
1110 void set_parent(S* parent);
1111 void setTimeout(int timeoutMillis);
1112 void setTimeoutMillis(int timeout_millis);
1116 // Parameter name matches setter name - omit hint.
1117 s.setParent(nullptr);
1118 // Support snake_case
1119 s.set_parent(nullptr);
1120 // Parameter name may contain extra info - show hint.
1121 s.setTimeout($timeoutMillis[[120]]);
1122 // FIXME: Ideally we'd want to omit this.
1123 s.setTimeoutMillis($timeout_millis[[120]]);
1126 ExpectedHint
{"timeoutMillis: ", "timeoutMillis"},
1127 ExpectedHint
{"timeout_millis: ", "timeout_millis"});
1130 TEST(ParameterHints
, BuiltinFunctions
) {
1131 // This prototype of std::forward is sufficient for clang to recognize it
1132 assertParameterHints(R
"cpp(
1133 namespace std { template <typename T> T&& forward(T&); }
1141 TEST(ParameterHints
, IncludeAtNonGlobalScope
) {
1142 Annotations
FooInc(R
"cpp(
1143 void bar() { foo(42); }
1145 Annotations
FooCC(R
"cpp(
1147 void foo(int param);
1152 TestWorkspace Workspace
;
1153 Workspace
.addSource("foo.inc", FooInc
.code());
1154 Workspace
.addMainFile("foo.cc", FooCC
.code());
1156 auto AST
= Workspace
.openFile("foo.cc");
1157 ASSERT_TRUE(bool(AST
));
1159 // Ensure the hint for the call in foo.inc is NOT materialized in foo.cc.
1160 EXPECT_EQ(hintsOfKind(*AST
, InlayHintKind::Parameter
).size(), 0u);
1163 TEST(TypeHints
, Smoke
) {
1164 assertTypeHints(R
"cpp(
1165 auto $waldo[[waldo]] = 42;
1167 ExpectedHint
{": int", "waldo"});
1170 TEST(TypeHints
, Decorations
) {
1171 assertTypeHints(R
"cpp(
1173 auto* $var1[[var1]] = &x;
1174 auto&& $var2[[var2]] = x;
1175 const auto& $var3[[var3]] = x;
1177 ExpectedHint
{": int *", "var1"},
1178 ExpectedHint
{": int &", "var2"},
1179 ExpectedHint
{": const int &", "var3"});
1182 TEST(TypeHints
, DecltypeAuto
) {
1183 assertTypeHints(R
"cpp(
1186 decltype(auto) $z[[z]] = y;
1188 ExpectedHint
{": int &", "z"});
1191 TEST(TypeHints
, NoQualifiers
) {
1192 assertTypeHints(R
"cpp(
1197 auto $x[[x]] = foo();
1200 template <typename T>
1203 S2::Inner<int> bar();
1204 auto $y[[y]] = bar();
1208 ExpectedHint
{": S1", "x"},
1209 // FIXME: We want to suppress scope specifiers
1210 // here because we are into the whole
1211 // brevity thing, but the ElaboratedType
1212 // printer does not honor the SuppressScope
1213 // flag by design, so we need to extend the
1214 // PrintingPolicy to support this use case.
1215 ExpectedHint
{": S2::Inner<int>", "y"});
1218 TEST(TypeHints
, Lambda
) {
1219 // Do not print something overly verbose like the lambda's location.
1220 // Show hints for init-captures (but not regular captures).
1221 assertTypeHints(R
"cpp(
1224 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1225 return a + cap + init;
1229 ExpectedHint
{": (lambda)", "L"},
1230 ExpectedHint
{": int", "init"}, ExpectedHint
{"-> int", "ret"});
1232 // Lambda return hint shown even if no param list.
1233 // (The digraph :> is just a ] that doesn't conflict with the annotations).
1234 assertTypeHints("auto $L[[x]] = <:$ret[[:>]]{return 42;};",
1235 ExpectedHint
{": (lambda)", "L"},
1236 ExpectedHint
{"-> int", "ret"});
1239 // Structured bindings tests.
1240 // Note, we hint the individual bindings, not the aggregate.
1242 TEST(TypeHints
, StructuredBindings_PublicStruct
) {
1243 assertTypeHints(R
"cpp(
1244 // Struct with public fields.
1250 auto [$x[[x]], $y[[y]]] = foo();
1252 ExpectedHint
{": int", "x"}, ExpectedHint
{": int", "y"});
1255 TEST(TypeHints
, StructuredBindings_Array
) {
1256 assertTypeHints(R
"cpp(
1258 auto [$x[[x]], $y[[y]]] = arr;
1260 ExpectedHint
{": int", "x"}, ExpectedHint
{": int", "y"});
1263 TEST(TypeHints
, StructuredBindings_TupleLike
) {
1264 assertTypeHints(R
"cpp(
1271 template <typename T>
1272 struct tuple_size {};
1274 struct tuple_size<IntPair> {
1275 constexpr static unsigned value = 2;
1277 template <unsigned I, typename T>
1278 struct tuple_element {};
1279 template <unsigned I>
1280 struct tuple_element<I, IntPair> {
1284 template <unsigned I>
1285 int get(const IntPair& p) {
1286 if constexpr (I == 0) {
1288 } else if constexpr (I == 1) {
1293 auto [$x[[x]], $y[[y]]] = bar();
1295 ExpectedHint
{": int", "x"}, ExpectedHint
{": int", "y"});
1298 TEST(TypeHints
, StructuredBindings_NoInitializer
) {
1299 assertTypeHints(R
"cpp(
1300 // No initializer (ill-formed).
1301 // Do not show useless "NULL TYPE
" hint.
1302 auto [x, y]; /*error-ok*/
1306 TEST(TypeHints
, InvalidType
) {
1307 assertTypeHints(R
"cpp(
1308 auto x = (unknown_type)42; /*error-ok*/
1309 auto *y = (unknown_ptr)nullptr;
1313 TEST(TypeHints
, ReturnTypeDeduction
) {
1316 auto f1(int x$ret1a[[)]]; // Hint forward declaration too
1317 auto f1(int x$ret1b[[)]] { return x + 1; }
1319 // Include pointer operators in hint
1321 auto& f2($ret2[[)]] { return s; }
1323 // Do not hint `auto` for trailing return type.
1326 // Do not hint when a trailing return type is specified.
1327 auto f4() -> auto* { return "foo
"; }
1329 auto f5($noreturn[[)]] {}
1331 // `auto` conversion operator
1333 operator auto($retConv[[)]] { return 42; }
1336 // FIXME: Dependent types do not work yet.
1337 template <typename T>
1339 auto method() { return T(); }
1342 ExpectedHint
{"-> int", "ret1a"}, ExpectedHint
{"-> int", "ret1b"},
1343 ExpectedHint
{"-> int &", "ret2"}, ExpectedHint
{"-> void", "noreturn"},
1344 ExpectedHint
{"-> int", "retConv"});
1347 TEST(TypeHints
, DependentType
) {
1348 assertTypeHints(R
"cpp(
1349 template <typename T>
1351 // The hint would just be "auto" and we can't do any better.
1352 auto var1 = arg.method();
1353 // FIXME: It would be nice to show "T
" as the hint.
1354 auto $var2[[var2]] = arg;
1357 template <typename T>
1364 TEST(TypeHints
, LongTypeName
) {
1365 assertTypeHints(R
"cpp(
1366 template <typename, typename, typename>
1368 struct MultipleWords {};
1369 A<MultipleWords, MultipleWords, MultipleWords> foo();
1370 // Omit type hint past a certain length (currently 32)
1375 Cfg
.InlayHints
.TypeNameLimit
= 0;
1376 WithContextValue
WithCfg(Config::Key
, std::move(Cfg
));
1380 template <typename, typename, typename>
1382 struct MultipleWords {};
1383 A<MultipleWords, MultipleWords, MultipleWords> foo();
1384 // Should have type hint with TypeNameLimit = 0
1385 auto $var[[var]] = foo();
1387 ExpectedHint
{": A<MultipleWords, MultipleWords, MultipleWords>", "var"});
1390 TEST(TypeHints
, DefaultTemplateArgs
) {
1391 assertTypeHints(R
"cpp(
1392 template <typename, typename = int>
1395 auto $var[[var]] = foo();
1397 auto [$binding[[value]]] = bar;
1399 ExpectedHint
{": A<float>", "var"},
1400 ExpectedHint
{": A<float>", "binding"});
1403 TEST(TypeHints
, Deduplication
) {
1404 assertTypeHints(R
"cpp(
1405 template <typename T>
1407 auto $var[[var]] = 42;
1409 template void foo<int>();
1410 template void foo<float>();
1412 ExpectedHint
{": int", "var"});
1415 TEST(TypeHints
, SinglyInstantiatedTemplate
) {
1416 assertTypeHints(R
"cpp(
1417 auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
1418 int m = x("foo
", 3);
1420 ExpectedHint
{": (lambda)", "lambda"},
1421 ExpectedHint
{": const char *", "param"});
1423 // No hint for packs, or auto params following packs
1424 assertTypeHints(R
"cpp(
1425 int x(auto $a[[a]], auto... b, auto c) { return 42; }
1426 int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
1428 ExpectedHint
{": void *", "a"});
1431 TEST(TypeHints
, Aliased
) {
1432 // Check that we don't crash for functions without a FunctionTypeLoc.
1433 // https://github.com/clangd/clangd/issues/1140
1434 TestTU TU
= TestTU::withCode("void foo(void){} extern typeof(foo) foo;");
1435 TU
.ExtraArgs
.push_back("-xc");
1436 auto AST
= TU
.build();
1438 EXPECT_THAT(hintsOfKind(AST
, InlayHintKind::Type
), IsEmpty());
1441 TEST(TypeHints
, Decltype
) {
1442 assertTypeHints(R
"cpp(
1443 $a[[decltype(0)]] a;
1444 $b[[decltype(a)]] b;
1445 const $c[[decltype(0)]] &c = b;
1447 // Don't show for dependent type
1449 constexpr decltype(T{}) d;
1451 $e[[decltype(0)]] e();
1452 auto f() -> $f[[decltype(0)]];
1454 template <class, class> struct Foo;
1455 using G = Foo<$g[[decltype(0)]], float>;
1457 auto $h[[h]] = $i[[decltype(0)]]{};
1463 ExpectedHint
{": int", "a"}, ExpectedHint
{": int", "b"},
1464 ExpectedHint
{": int", "c"}, ExpectedHint
{": int", "e"},
1465 ExpectedHint
{": int", "f"}, ExpectedHint
{": int", "g"},
1466 ExpectedHint
{": int", "h"}, ExpectedHint
{": int", "i"});
1469 TEST(TypeHints
, SubstTemplateParameterAliases
) {
1470 llvm::StringRef Header
= R
"cpp(
1471 template <class T> struct allocator {};
1473 template <class T, class A>
1474 struct vector_base {
1478 template <class T, class A>
1479 struct internal_iterator_type_template_we_dont_expect {};
1481 struct my_iterator {};
1483 template <class T, class A = allocator<T>>
1484 struct vector : vector_base<T, A> {
1485 using base = vector_base<T, A>;
1486 typedef T value_type;
1487 typedef base::pointer pointer;
1488 using allocator_type = A;
1489 using size_type = int;
1490 using iterator = internal_iterator_type_template_we_dont_expect<T, A>;
1491 using non_template_iterator = my_iterator;
1493 value_type& operator[](int index) { return elements[index]; }
1494 const value_type& at(int index) const { return elements[index]; }
1495 pointer data() { return &elements[0]; }
1496 allocator_type get_allocator() { return A(); }
1497 size_type size() const { return 10; }
1498 iterator begin() { return iterator(); }
1499 non_template_iterator end() { return non_template_iterator(); }
1505 llvm::StringRef VectorIntPtr
= R
"cpp(
1506 vector<int *> array;
1507 auto $no_modifier[[x]] = array[3];
1508 auto* $ptr_modifier[[ptr]] = &array[3];
1509 auto& $ref_modifier[[ref]] = array[3];
1510 auto& $at[[immutable]] = array.at(3);
1512 auto $data[[data]] = array.data();
1513 auto $allocator[[alloc]] = array.get_allocator();
1514 auto $size[[size]] = array.size();
1515 auto $begin[[begin]] = array.begin();
1516 auto $end[[end]] = array.end();
1519 assertHintsWithHeader(
1520 InlayHintKind::Type
, VectorIntPtr
, Header
,
1521 ExpectedHint
{": int *", "no_modifier"},
1522 ExpectedHint
{": int **", "ptr_modifier"},
1523 ExpectedHint
{": int *&", "ref_modifier"},
1524 ExpectedHint
{": int *const &", "at"}, ExpectedHint
{": int **", "data"},
1525 ExpectedHint
{": allocator<int *>", "allocator"},
1526 ExpectedHint
{": size_type", "size"}, ExpectedHint
{": iterator", "begin"},
1527 ExpectedHint
{": non_template_iterator", "end"});
1529 llvm::StringRef VectorInt
= R
"cpp(
1531 auto $no_modifier[[by_value]] = array[3];
1532 auto* $ptr_modifier[[ptr]] = &array[3];
1533 auto& $ref_modifier[[ref]] = array[3];
1534 auto& $at[[immutable]] = array.at(3);
1536 auto $data[[data]] = array.data();
1537 auto $allocator[[alloc]] = array.get_allocator();
1538 auto $size[[size]] = array.size();
1539 auto $begin[[begin]] = array.begin();
1540 auto $end[[end]] = array.end();
1543 assertHintsWithHeader(
1544 InlayHintKind::Type
, VectorInt
, Header
,
1545 ExpectedHint
{": int", "no_modifier"},
1546 ExpectedHint
{": int *", "ptr_modifier"},
1547 ExpectedHint
{": int &", "ref_modifier"},
1548 ExpectedHint
{": const int &", "at"}, ExpectedHint
{": int *", "data"},
1549 ExpectedHint
{": allocator<int>", "allocator"},
1550 ExpectedHint
{": size_type", "size"}, ExpectedHint
{": iterator", "begin"},
1551 ExpectedHint
{": non_template_iterator", "end"});
1553 llvm::StringRef TypeAlias
= R
"cpp(
1554 // If the type alias is not of substituted template parameter type,
1555 // do not show desugared type.
1556 using VeryLongLongTypeName = my_iterator;
1557 using Short = VeryLongLongTypeName;
1559 auto $short_name[[my_value]] = Short();
1561 // Same applies with templates.
1562 template <typename T, typename A>
1563 using basic_static_vector = vector<T, A>;
1564 template <typename T>
1565 using static_vector = basic_static_vector<T, allocator<T>>;
1567 auto $vector_name[[vec]] = static_vector<int>();
1570 assertHintsWithHeader(InlayHintKind::Type
, TypeAlias
, Header
,
1571 ExpectedHint
{": Short", "short_name"},
1572 ExpectedHint
{": static_vector<int>", "vector_name"});
1575 TEST(DesignatorHints
, Basic
) {
1576 assertDesignatorHints(R
"cpp(
1577 struct S { int x, y, z; };
1578 S s {$x[[1]], $y[[2+2]]};
1580 int x[] = {$0[[0]], $1[[1]]};
1582 ExpectedHint
{".x=", "x"}, ExpectedHint
{".y=", "y"},
1583 ExpectedHint
{"[0]=", "0"}, ExpectedHint
{"[1]=", "1"});
1586 TEST(DesignatorHints
, Nested
) {
1587 assertDesignatorHints(R
"cpp(
1588 struct Inner { int x, y; };
1589 struct Outer { Inner a, b; };
1590 Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
1592 ExpectedHint
{".a=", "a"}, ExpectedHint
{".x=", "x"},
1593 ExpectedHint
{".y=", "y"}, ExpectedHint
{".b.x=", "bx"});
1596 TEST(DesignatorHints
, AnonymousRecord
) {
1597 assertDesignatorHints(R
"cpp(
1609 ExpectedHint
{".x.y=", "xy"});
1612 TEST(DesignatorHints
, Suppression
) {
1613 assertDesignatorHints(R
"cpp(
1614 struct Point { int a, b, c, d, e, f, g, h; };
1615 Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
1617 ExpectedHint
{".e=", "e"});
1620 TEST(DesignatorHints
, StdArray
) {
1621 // Designators for std::array should be [0] rather than .__elements[0].
1622 // While technically correct, the designator is useless and horrible to read.
1623 assertDesignatorHints(R
"cpp(
1624 template <typename T, int N> struct Array { T __elements[N]; };
1625 Array<int, 2> x = {$0[[0]], $1[[1]]};
1627 ExpectedHint
{"[0]=", "0"}, ExpectedHint
{"[1]=", "1"});
1630 TEST(DesignatorHints
, OnlyAggregateInit
) {
1631 assertDesignatorHints(R
"cpp(
1632 struct Copyable { int x; } c;
1635 struct Constructible { Constructible(int x); };
1636 Constructible x{42};
1637 )cpp" /*no designator hints expected (but param hints!)*/);
1640 TEST(DesignatorHints
, NoCrash
) {
1641 assertDesignatorHints(R
"cpp(
1644 struct Foo {int a; int b;};
1646 Foo f{A(), $b[[1]]};
1648 )cpp", ExpectedHint
{".b=", "b"});
1651 TEST(InlayHints
, RestrictRange
) {
1652 Annotations
Code(R
"cpp(
1658 auto AST
= TestTU::withCode(Code
.code()).build();
1659 EXPECT_THAT(inlayHints(AST
, Code
.range()),
1660 ElementsAre(labelIs(": int"), labelIs(": char")));
1663 TEST(ParameterHints
, ArgPacksAndConstructors
) {
1664 assertParameterHints(
1666 struct Foo{ Foo(); Foo(int x); };
1667 void foo(Foo a, int b);
1668 template <typename... Args>
1669 void bar(Args... args) {
1672 template <typename... Args>
1673 void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
1675 template <typename... Args>
1676 void bax(Args... args) { foo($param3[[{args...}]], args...); }
1679 bar($param4[[Foo{}]], $param5[[42]]);
1680 bar($param6[[42]], $param7[[42]]);
1685 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"},
1686 ExpectedHint
{"a: ", "param3"}, ExpectedHint
{"a: ", "param4"},
1687 ExpectedHint
{"b: ", "param5"}, ExpectedHint
{"a: ", "param6"},
1688 ExpectedHint
{"b: ", "param7"}, ExpectedHint
{"x: ", "param8"},
1689 ExpectedHint
{"b: ", "param9"});
1692 TEST(ParameterHints
, DoesntExpandAllArgs
) {
1693 assertParameterHints(
1695 void foo(int x, int y);
1696 int id(int a, int b, int c);
1697 template <typename... Args>
1698 void bar(Args... args) {
1699 foo(id($param1[[args]], $param2[[1]], $param3[[args]])...);
1702 bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1705 ExpectedHint
{"a: ", "param1"}, ExpectedHint
{"b: ", "param2"},
1706 ExpectedHint
{"c: ", "param3"});
1709 TEST(BlockEndHints
, Functions
) {
1710 assertBlockEndHints(R
"cpp(
1717 // No hint for lambda for now
1724 // No hint because this isn't a definition
1728 bool operator==(S, S) {
1732 ExpectedHint
{" // foo", "foo"},
1733 ExpectedHint
{" // bar", "bar"},
1734 ExpectedHint
{" // operator==", "opEqual"});
1737 TEST(BlockEndHints
, Methods
) {
1738 assertBlockEndHints(R
"cpp(
1740 // No hint because there's no function body
1749 // No hint because this isn't a definition
1752 template <typename T>
1756 // No hint because this isn't a definition
1757 template <typename T>
1760 Test operator+(int) const {
1764 operator bool() const {
1768 // No hint because there's no function body
1769 operator int() const = delete;
1772 void Test::method2() {
1775 template <typename T>
1776 void Test::method4() {
1779 ExpectedHint
{" // ~Test", "dtor"},
1780 ExpectedHint
{" // method1", "method1"},
1781 ExpectedHint
{" // method3", "method3"},
1782 ExpectedHint
{" // operator+", "opIdentity"},
1783 ExpectedHint
{" // operator bool", "opBool"},
1784 ExpectedHint
{" // Test::method2", "method2"},
1785 ExpectedHint
{" // Test::method4", "method4"});
1788 TEST(BlockEndHints
, Namespaces
) {
1789 assertBlockEndHints(
1799 ExpectedHint
{" // namespace", "anon"},
1800 ExpectedHint
{" // namespace ns", "ns"});
1803 TEST(BlockEndHints
, Types
) {
1804 assertBlockEndHints(
1821 ExpectedHint
{" // struct S", "S"}, ExpectedHint
{" // class C", "C"},
1822 ExpectedHint
{" // union U", "U"}, ExpectedHint
{" // enum E1", "E1"},
1823 ExpectedHint
{" // enum class E2", "E2"});
1826 TEST(BlockEndHints
, If
) {
1827 assertBlockEndHints(
1829 void foo(bool cond) {
1850 if (auto X = cond) {
1853 if (int i = 0; i > 10) {
1857 ExpectedHint
{" // if cond", "simple"},
1858 ExpectedHint
{" // if cond", "ifelse"}, ExpectedHint
{" // if", "elseif"},
1859 ExpectedHint
{" // if !cond", "inner"},
1860 ExpectedHint
{" // if cond", "outer"}, ExpectedHint
{" // if X", "init"},
1861 ExpectedHint
{" // if i > 10", "init_cond"});
1864 TEST(BlockEndHints
, Loops
) {
1865 assertBlockEndHints(
1880 for (int I = 0; I < 10; ++I) {
1888 ExpectedHint
{" // while true", "while"},
1889 ExpectedHint
{" // for true", "forcond"},
1890 ExpectedHint
{" // for I", "forvar"},
1891 ExpectedHint
{" // for V", "foreach"});
1894 TEST(BlockEndHints
, Switch
) {
1895 assertBlockEndHints(
1903 ExpectedHint
{" // switch I", "switch"});
1906 TEST(BlockEndHints
, PrintLiterals
) {
1907 assertBlockEndHints(
1913 while ("foo but
this time it is very
long") {
1926 ExpectedHint
{" // while \"foo\"", "string"},
1927 ExpectedHint
{" // while \"foo but...\"", "string_long"},
1928 ExpectedHint
{" // while true", "boolean"},
1929 ExpectedHint
{" // while 1", "integer"},
1930 ExpectedHint
{" // while 1.5", "float"});
1933 TEST(BlockEndHints
, PrintRefs
) {
1934 assertBlockEndHints(
1948 while (ns::func()) {
1951 while (ns::S{}.Field) {
1954 while (ns::S{}.method()) {
1958 ExpectedHint
{" // while Var", "var"},
1959 ExpectedHint
{" // while func", "func"},
1960 ExpectedHint
{" // while Field", "field"},
1961 ExpectedHint
{" // while method", "method"});
1964 TEST(BlockEndHints
, PrintConversions
) {
1965 assertBlockEndHints(
1970 explicit operator bool();
1974 $convert_primitive[[}]]
1980 $construct_class[[}]]
1983 ExpectedHint
{" // while float", "convert_primitive"},
1984 ExpectedHint
{" // while S", "convert_class"},
1985 ExpectedHint
{" // while S", "construct_class"});
1988 TEST(BlockEndHints
, PrintOperators
) {
1989 std::string AnnotatedCode
= R
"cpp(
1990 void foo(Integer I) {
2009 while((I + I) < (I + I)){
2010 $binary_complex[[}]]
2014 // We can't store shared expectations in a vector, assertHints uses varargs.
2015 auto AssertExpectedHints
= [&](llvm::StringRef Code
) {
2016 assertBlockEndHints(Code
, ExpectedHint
{" // while ++I", "preinc"},
2017 ExpectedHint
{" // while I++", "postinc"},
2018 ExpectedHint
{" // while", "unary_complex"},
2019 ExpectedHint
{" // while I < 0", "compare"},
2020 ExpectedHint
{" // while ... < I", "lhs_complex"},
2021 ExpectedHint
{" // while I < ...", "rhs_complex"},
2022 ExpectedHint
{" // while", "binary_complex"});
2025 // First with built-in operators.
2026 AssertExpectedHints("using Integer = int;" + AnnotatedCode
);
2027 // And now with overloading!
2028 AssertExpectedHints(R
"cpp(
2030 explicit operator bool();
2031 Integer operator++();
2032 Integer operator++(int);
2033 Integer operator+(Integer);
2034 Integer operator+();
2035 bool operator<(Integer);
2036 bool operator<(int);
2038 )cpp" + AnnotatedCode
);
2041 TEST(BlockEndHints
, TrailingSemicolon
) {
2042 assertBlockEndHints(R
"cpp(
2043 // The hint is placed after the trailing ';'
2047 // The hint is always placed in the same line with the closing '}'.
2048 // So in this case where ';' is missing, it is attached to '}'.
2054 // No hint because only one trailing ';' is allowed
2058 // No hint because trailing ';' is only allowed for class/struct/union/enum
2062 // Rare case, but yes we'll have a hint here.
2069 ExpectedHint
{" // struct S1", "S1"},
2070 ExpectedHint
{" // struct S2", "S2"},
2071 ExpectedHint
{" // struct", "anon"});
2074 TEST(BlockEndHints
, TrailingText
) {
2075 assertBlockEndHints(R
"cpp(
2079 // No hint for S2 because of the trailing comment
2081 }; /* Put anything here */
2084 // No hint for S4 because of the trailing source code
2088 // No hint for ns because of the trailing comment
2092 ExpectedHint
{" // struct S1", "S1"},
2093 ExpectedHint
{" // struct S3", "S3"});
2096 TEST(BlockEndHints
, Macro
) {
2097 assertBlockEndHints(R
"cpp(
2098 #define DECL_STRUCT(NAME) struct NAME {
2104 // No hint because we require a '}'
2108 ExpectedHint
{" // struct S1", "S1"});
2111 // FIXME: Low-hanging fruit where we could omit a type hint:
2112 // - auto x = TypeName(...);
2113 // - auto x = (TypeName) (...);
2114 // - auto x = static_cast<TypeName>(...); // and other built-in casts
2116 // Annoyances for which a heuristic is not obvious:
2117 // - auto x = llvm::dyn_cast<LongTypeName>(y); // and similar
2118 // - stdlib algos return unwieldy __normal_iterator<X*, ...> type
2119 // (For this one, perhaps we should omit type hints that start
2120 // with a double underscore.)
2123 } // namespace clangd
2124 } // namespace clang