[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clangd / unittests / InlayHintTests.cpp
blob59ec9aa4776daec258def6fa430e2e6a5d91d8f5
1 //===-- InlayHintTests.cpp -------------------------------*- C++ -*-------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 #include "Annotations.h"
9 #include "Config.h"
10 #include "InlayHints.h"
11 #include "Protocol.h"
12 #include "TestTU.h"
13 #include "TestWorkspace.h"
14 #include "XRefs.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"
21 namespace clang {
22 namespace clangd {
24 llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
25 const InlayHint &Hint) {
26 return Stream << Hint.label << "@" << Hint.range;
29 namespace {
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);
40 return Result;
43 enum HintSide { Left, Right };
45 struct ExpectedHint {
46 std::string Label;
47 std::string RangeName;
48 HintSide Side = Left;
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 << "'";
62 return false;
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));
68 return false;
70 return true;
73 MATCHER_P(labelIs, Label, "") { return arg.label == Label; }
75 Config noHintsConfig() {
76 Config C;
77 C.InlayHints.Parameters = false;
78 C.InlayHints.DeducedTypes = false;
79 C.InlayHints.Designators = false;
80 return C;
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) {
119 Config Cfg;
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(
127 void foo(int param);
128 void bar() {
129 foo($param[[42]]);
131 )cpp",
132 ExpectedHint{"param: ", "param"});
135 TEST(ParameterHints, NoName) {
136 // No hint for anonymous parameter.
137 assertParameterHints(R"cpp(
138 void foo(int);
139 void bar() {
140 foo(42);
142 )cpp");
145 TEST(ParameterHints, NoNameConstReference) {
146 // No hint for anonymous const l-value ref parameter.
147 assertParameterHints(R"cpp(
148 void foo(const int&);
149 void bar() {
150 foo(42);
152 )cpp");
155 TEST(ParameterHints, NoNameReference) {
156 // Reference hint for anonymous l-value ref parameter.
157 assertParameterHints(R"cpp(
158 void foo(int&);
159 void bar() {
160 int i;
161 foo($param[[i]]);
163 )cpp",
164 ExpectedHint{"&: ", "param"});
167 TEST(ParameterHints, NoNameRValueReference) {
168 // No reference hint for anonymous r-value ref parameter.
169 assertParameterHints(R"cpp(
170 void foo(int&&);
171 void bar() {
172 foo(42);
174 )cpp");
177 TEST(ParameterHints, NoNameVariadicDeclaration) {
178 // No hint for anonymous variadic parameter
179 assertParameterHints(R"cpp(
180 template <typename... Args>
181 void foo(Args&& ...);
182 void bar() {
183 foo(42);
185 )cpp");
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&); }
193 void foo(int);
194 template <typename... Args>
195 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
196 void baz() {
197 bar(42);
199 )cpp");
202 TEST(ParameterHints, NoNameVariadicPlain) {
203 // No hint for anonymous variadic parameter
204 assertParameterHints(R"cpp(
205 void foo(int);
206 template <typename... Args>
207 void bar(Args&&... args) { return foo(args...); }
208 void baz() {
209 bar(42);
211 )cpp");
214 TEST(ParameterHints, NameInDefinition) {
215 // Parameter name picked up from definition if necessary.
216 assertParameterHints(R"cpp(
217 void foo(int);
218 void bar() {
219 foo($param[[42]]);
221 void foo(int param) {};
222 )cpp",
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);
230 void bar() {
231 foo($param1[[42]], $param2[[42]]);
233 void foo(int a, int) {};
234 )cpp",
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(
242 void foo(int, int);
243 template <typename... Args>
244 void bar(Args... args) {
245 foo(args...);
247 void baz() {
248 bar($param1[[42]], $param2[[42]]);
250 void foo(int a, int b) {};
251 )cpp",
252 ExpectedHint{"a: ", "param1"},
253 ExpectedHint{"b: ", "param2"});
256 TEST(ParameterHints, NameMismatch) {
257 // Prefer name from declaration.
258 assertParameterHints(R"cpp(
259 void foo(int good);
260 void bar() {
261 foo($good[[42]]);
263 void foo(int bad) {};
264 )cpp",
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);
272 void bar() {
273 foo($param[[42]]);
275 )cpp",
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);
284 void bar() {
285 int i;
286 foo($param[[i]]);
288 )cpp",
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);
296 void bar() {
297 int i;
298 foo($param[[i]]);
300 )cpp",
301 ExpectedHint{"&param: ", "param"});
304 TEST(ParameterHints, NameTypeAliasReference) {
305 // Reference and name hint for l-value ref parameter via type alias.
306 assertParameterHints(R"cpp(
307 using alias = int&;
308 void foo(alias param);
309 void bar() {
310 int i;
311 foo($param[[i]]);
313 )cpp",
314 ExpectedHint{"&param: ", "param"});
317 TEST(ParameterHints, NameRValueReference) {
318 // Only name hint for r-value ref parameter.
319 assertParameterHints(R"cpp(
320 void foo(int&& param);
321 void bar() {
322 foo($param[[42]]);
324 )cpp",
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)...}; }
336 void baz() {
337 int b;
338 bar<S>($param[[b]]);
340 )cpp",
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...}; }
350 void baz() {
351 int b;
352 bar<S>($param[[b]]);
354 )cpp",
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)...}; }
366 void baz() {
367 int b;
368 bar<S>($param[[b]]);
370 )cpp",
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...}; }
380 void baz() {
381 int b;
382 bar<S>($param[[b]]);
384 )cpp",
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&); }
393 void foo(int a);
394 template <typename... Args>
395 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
396 void baz() {
397 int b;
398 bar($param[[b]]);
400 )cpp",
401 ExpectedHint{"a: ", "param"});
404 TEST(ParameterHints, VariadicPlain) {
405 // Name hint for variadic parameter
406 assertParameterHints(R"cpp(
407 void foo(int a);
408 template <typename... Args>
409 void bar(Args&&... args) { return foo(args...); }
410 void baz() {
411 bar($param[[42]]);
413 )cpp",
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(
421 void foo(int a);
422 template <typename... Args, typename Arg>
423 void bar(Arg, Args&&... args) { return foo(args...); }
424 void baz() {
425 bar(1, $param[[42]]);
427 )cpp",
428 ExpectedHint{"a: ", "param"});
431 TEST(ParameterHints, VariadicSplitTwolevel) {
432 // Name for variadic parameter that involves both head and tail parameters to
433 // deal with.
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)...); }
444 void bazz() {
445 bar($param1[[32]], $param2[[42]]);
447 )cpp",
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
454 // specialization.
455 assertParameterHints(R"cpp(
456 void foo(int a);
457 template <typename... Args>
458 void bar(Args... args) {
459 foo(args...);
461 template <>
462 void bar<int>(int b);
463 void baz() {
464 bar($param[[42]]);
466 )cpp",
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(
474 void foo2(int a);
475 template <typename... Args>
476 void foo(Args... args) {
477 foo2(args...);
479 template <typename... Args>
480 void bar(Args... args) {
481 foo(args...);
483 template <>
484 void foo<int>(int b);
485 void baz() {
486 bar($param[[42]]);
488 )cpp",
489 ExpectedHint{"b: ", "param"});
492 TEST(ParameterHints, VariadicOverloaded) {
493 // Name for variadic parameter for an overloaded function with unique number
494 // of parameters.
495 // This prototype of std::forward is sufficient for clang to recognize it
496 assertParameterHints(
497 R"cpp(
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)...); }
507 void bazz() {
508 bar($param1[[32]], $param2[[42]], $param3[[52]]);
509 bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
511 )cpp",
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(
521 R"cpp(
522 void foo();
524 template <typename Head, typename... Tail>
525 void foo(Head head, Tail... tail) {
526 foo(tail...);
529 template <typename... Args>
530 void bar(Args... args) {
531 foo(args...);
534 int main() {
535 bar(1, 2, 3);
537 )cpp");
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) {
546 foo(args...);
549 void baz() {
550 bar($fixed[[41]], 42, 43);
552 )cpp");
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) {
562 foo(args...);
565 void baz() {
566 bar($fixed[[41]], 42, 43);
568 )cpp",
569 ExpectedHint{"fixed: ", "fixed"});
572 TEST(ParameterHints, VariadicTwoCalls) {
573 // only the first call using the parameter pack should be picked up
574 assertParameterHints(
575 R"cpp(
576 void f1(int a, int b);
577 void f2(int c, int d);
579 bool cond;
581 template <typename... Args>
582 void foo(Args... args) {
583 if (cond) {
584 f1(args...);
585 } else {
586 f2(args...);
590 int main() {
591 foo($param1[[1]], $param2[[2]]);
593 )cpp",
594 ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"});
597 TEST(ParameterHints, VariadicInfinite) {
598 // infinite recursion should not break clangd
599 assertParameterHints(
600 R"cpp(
601 template <typename... Args>
602 void foo(Args...);
604 template <typename... Args>
605 void bar(Args... args) {
606 foo(args...);
609 template <typename... Args>
610 void foo(Args... args) {
611 bar(args...);
614 int main() {
615 foo(1, 2);
617 )cpp");
620 TEST(ParameterHints, VariadicDuplicatePack) {
621 // edge cases with multiple adjacent packs should work
622 assertParameterHints(
623 R"cpp(
624 void foo(int a, int b, int c, int);
626 template <typename... Args>
627 void bar(int, Args... args, int d) {
628 foo(args..., d);
631 template <typename... Args>
632 void baz(Args... args, Args... args2) {
633 bar<Args..., int>(1, args..., args2...);
636 int main() {
637 baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
639 )cpp",
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(
648 R"cpp(
649 namespace std { template <typename T> T&& forward(T&); }
650 using size_t = decltype(sizeof(0));
651 void *operator new(size_t, void *);
652 struct S {
653 S(int A);
654 S(int B, int C);
656 struct alloc {
657 template <typename T>
658 T* allocate();
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>
665 struct container {
666 template <typename... Args>
667 void emplace(Args&&... args) {
668 alloc a;
669 auto ptr = a.template allocate<T>();
670 a.construct(ptr, std::forward<Args>(args)...);
673 void foo() {
674 container<S> c;
675 c.emplace($param1[[1]]);
676 c.emplace($param2[[2]], $param3[[3]]);
678 )cpp",
679 ExpectedHint{"A: ", "param1"}, ExpectedHint{"B: ", "param2"},
680 ExpectedHint{"C: ", "param3"});
683 TEST(ParameterHints, VariadicReferenceHint) {
684 assertParameterHints(R"cpp(
685 void foo(int&);
686 template <typename... Args>
687 void bar(Args... args) { return foo(args...); }
688 void baz() {
689 int a;
690 bar(a);
691 bar(1);
693 )cpp");
696 TEST(ParameterHints, VariadicReferenceHintForwardingRef) {
697 assertParameterHints(R"cpp(
698 void foo(int&);
699 template <typename... Args>
700 void bar(Args&&... args) { return foo(args...); }
701 void baz() {
702 int a;
703 bar($param[[a]]);
704 bar(1);
706 )cpp",
707 ExpectedHint{"&: ", "param"});
710 TEST(ParameterHints, VariadicReferenceHintForwardingRefStdForward) {
711 assertParameterHints(R"cpp(
712 namespace std { template <typename T> T&& forward(T&); }
713 void foo(int&);
714 template <typename... Args>
715 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
716 void baz() {
717 int a;
718 bar($param[[a]]);
720 )cpp",
721 ExpectedHint{"&: ", "param"});
724 TEST(ParameterHints, VariadicNoReferenceHintForwardingRefStdForward) {
725 assertParameterHints(R"cpp(
726 namespace std { template <typename T> T&& forward(T&); }
727 void foo(int);
728 template <typename... Args>
729 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
730 void baz() {
731 int a;
732 bar(a);
733 bar(1);
735 )cpp");
738 TEST(ParameterHints, VariadicNoReferenceHintUnresolvedForward) {
739 assertParameterHints(R"cpp(
740 template <typename... Args>
741 void foo(Args&&... args);
742 void bar() {
743 int a;
744 foo(a);
746 )cpp");
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&); }
754 void foo(int a);
755 template <typename... Args>
756 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
757 void baz() {
758 int a;
759 bar(a);
761 )cpp");
764 TEST(ParameterHints, MatchingNameVariadicPlain) {
765 // No name hint for variadic parameter with matching name
766 assertParameterHints(R"cpp(
767 void foo(int a);
768 template <typename... Args>
769 void bar(Args&&... args) { return foo(args...); }
770 void baz() {
771 int a;
772 bar(a);
774 )cpp");
777 TEST(ParameterHints, Operator) {
778 // No hint for operator call with operator syntax.
779 assertParameterHints(R"cpp(
780 struct S {};
781 void operator+(S lhs, S rhs);
782 void bar() {
783 S a, b;
784 a + b;
786 )cpp");
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(
795 void foo(int param);
796 #define ExpandsToCall() foo(42)
797 void bar() {
798 ExpandsToCall();
800 )cpp");
802 // The argument expression being a macro invocation shouldn't interfere
803 // with hinting.
804 assertParameterHints(R"cpp(
805 #define PI 3.14
806 void foo(double param);
807 void bar() {
808 foo($param[[PI]]);
810 )cpp",
811 ExpectedHint{"param: ", "param"});
813 // If the whole argument list comes from a macro parameter, hint it.
814 assertParameterHints(R"cpp(
815 void abort();
816 #define ASSERT(expr) if (!expr) abort()
817 int foo(int param);
818 void bar() {
819 ASSERT(foo($param[[42]]) == 0);
821 )cpp",
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
828 void bar() {
829 foo(CONSTANTS);
831 )cpp");
834 TEST(ParameterHints, ConstructorParens) {
835 assertParameterHints(R"cpp(
836 struct S {
837 S(int param);
839 void bar() {
840 S obj($param[[42]]);
842 )cpp",
843 ExpectedHint{"param: ", "param"});
846 TEST(ParameterHints, ConstructorBraces) {
847 assertParameterHints(R"cpp(
848 struct S {
849 S(int param);
851 void bar() {
852 S obj{$param[[42]]};
854 )cpp",
855 ExpectedHint{"param: ", "param"});
858 TEST(ParameterHints, ConstructorStdInitList) {
859 // Do not show hints for std::initializer_list constructors.
860 assertParameterHints(R"cpp(
861 namespace std {
862 template <typename> class initializer_list {};
864 struct S {
865 S(std::initializer_list<int> param);
867 void bar() {
868 S obj{42, 43};
870 )cpp");
873 TEST(ParameterHints, MemberInit) {
874 assertParameterHints(R"cpp(
875 struct S {
876 S(int param);
878 struct T {
879 S member;
880 T() : member($param[[42]]) {}
882 )cpp",
883 ExpectedHint{"param: ", "param"});
886 TEST(ParameterHints, ImplicitConstructor) {
887 assertParameterHints(R"cpp(
888 struct S {
889 S(int param);
891 void bar(S);
892 S foo() {
893 // Do not show hint for implicit constructor call in argument.
894 bar(42);
895 // Do not show hint for implicit constructor call in return.
896 return 42;
898 )cpp");
901 TEST(ParameterHints, ArgMatchesParam) {
902 assertParameterHints(R"cpp(
903 void foo(int param);
904 struct S {
905 static const int param = 42;
907 void bar() {
908 int param = 42;
909 // Do not show redundant "param: param".
910 foo(param);
911 // But show it if the argument is qualified.
912 foo($param[[S::param]]);
914 struct A {
915 int param;
916 void bar() {
917 // Do not show "param: param" for member-expr.
918 foo(param);
921 )cpp",
922 ExpectedHint{"param: ", "param"});
925 TEST(ParameterHints, ArgMatchesParamReference) {
926 assertParameterHints(R"cpp(
927 void foo(int& param);
928 void foo2(const int& param);
929 void bar() {
930 int param;
931 // show reference hint on mutable reference
932 foo($param[[param]]);
933 // but not on const reference
934 foo2(param);
936 )cpp",
937 ExpectedHint{"&: ", "param"});
940 TEST(ParameterHints, LeadingUnderscore) {
941 assertParameterHints(R"cpp(
942 void foo(int p1, int _p2, int __p3);
943 void bar() {
944 foo($p1[[41]], $p2[[42]], $p3[[43]]);
946 )cpp",
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>
957 struct A {
958 void member(T par2);
959 static void static_member(T par3);
962 void overload(int anInt);
963 void overload(double aDouble);
965 template <typename T>
966 struct S {
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.
973 overload(T{});
976 )cpp",
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);
987 void bar() {
988 foo($fixed[[41]], 42, 43);
990 )cpp",
991 ExpectedHint{"fixed: ", "fixed"});
994 TEST(ParameterHints, VarargsFunction) {
995 assertParameterHints(R"cpp(
996 void foo(int fixed, ...);
998 void bar() {
999 foo($fixed[[41]], 42, 43);
1001 )cpp",
1002 ExpectedHint{"fixed: ", "fixed"});
1005 TEST(ParameterHints, CopyOrMoveConstructor) {
1006 // Do not show hint for parameter of copy or move constructor.
1007 assertParameterHints(R"cpp(
1008 struct S {
1009 S();
1010 S(const S& other);
1011 S(S&& other);
1013 void bar() {
1014 S a;
1015 S b(a); // copy
1016 S c(S()); // move
1018 )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(
1025 struct Point {
1026 int x;
1027 int y;
1029 void bar() {
1030 Point p{41, 42};
1032 )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);
1039 void bar() {
1040 1.2_w;
1042 )cpp");
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);
1050 void bar() {
1051 foo(/*param*/42);
1052 foo( /* param = */ 42);
1053 #define X 42
1054 #define Y X
1055 #define Z(...) Y
1056 foo(/*param=*/Z(a));
1057 foo($macro[[Z(a)]]);
1058 foo(/* the answer */$param[[42]]);
1060 )cpp",
1061 ExpectedHint{"param: ", "macro"},
1062 ExpectedHint{"param: ", "param"});
1065 TEST(ParameterHints, SetterFunctions) {
1066 assertParameterHints(R"cpp(
1067 struct S {
1068 void setParent(S* parent);
1069 void set_parent(S* parent);
1070 void setTimeout(int timeoutMillis);
1071 void setTimeoutMillis(int timeout_millis);
1073 void bar() {
1074 S s;
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]]);
1084 )cpp",
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&); }
1093 void foo() {
1094 int i;
1095 std::forward(i);
1097 )cpp");
1100 TEST(ParameterHints, IncludeAtNonGlobalScope) {
1101 Annotations FooInc(R"cpp(
1102 void bar() { foo(42); }
1103 )cpp");
1104 Annotations FooCC(R"cpp(
1105 struct S {
1106 void foo(int param);
1107 #include "foo.inc"
1109 )cpp");
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;
1125 )cpp",
1126 ExpectedHint{": int", "waldo"});
1129 TEST(TypeHints, Decorations) {
1130 assertTypeHints(R"cpp(
1131 int x = 42;
1132 auto* $var1[[var1]] = &x;
1133 auto&& $var2[[var2]] = x;
1134 const auto& $var3[[var3]] = x;
1135 )cpp",
1136 ExpectedHint{": int *", "var1"},
1137 ExpectedHint{": int &", "var2"},
1138 ExpectedHint{": const int &", "var3"});
1141 TEST(TypeHints, DecltypeAuto) {
1142 assertTypeHints(R"cpp(
1143 int x = 42;
1144 int& y = x;
1145 decltype(auto) $z[[z]] = y;
1146 )cpp",
1147 ExpectedHint{": int &", "z"});
1150 TEST(TypeHints, NoQualifiers) {
1151 assertTypeHints(R"cpp(
1152 namespace A {
1153 namespace B {
1154 struct S1 {};
1155 S1 foo();
1156 auto $x[[x]] = foo();
1158 struct S2 {
1159 template <typename T>
1160 struct Inner {};
1162 S2::Inner<int> bar();
1163 auto $y[[y]] = bar();
1166 )cpp",
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(
1181 void f() {
1182 int cap = 42;
1183 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1184 return a + cap + init;
1187 )cpp",
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.
1204 struct Point {
1205 int x;
1206 int y;
1208 Point foo();
1209 auto [$x[[x]], $y[[y]]] = foo();
1210 )cpp",
1211 ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1214 TEST(TypeHints, StructuredBindings_Array) {
1215 assertTypeHints(R"cpp(
1216 int arr[2];
1217 auto [$x[[x]], $y[[y]]] = arr;
1218 )cpp",
1219 ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1222 TEST(TypeHints, StructuredBindings_TupleLike) {
1223 assertTypeHints(R"cpp(
1224 // Tuple-like type.
1225 struct IntPair {
1226 int a;
1227 int b;
1229 namespace std {
1230 template <typename T>
1231 struct tuple_size {};
1232 template <>
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> {
1240 using type = int;
1243 template <unsigned I>
1244 int get(const IntPair& p) {
1245 if constexpr (I == 0) {
1246 return p.a;
1247 } else if constexpr (I == 1) {
1248 return p.b;
1251 IntPair bar();
1252 auto [$x[[x]], $y[[y]]] = bar();
1253 )cpp",
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*/
1262 )cpp");
1265 TEST(TypeHints, InvalidType) {
1266 assertTypeHints(R"cpp(
1267 auto x = (unknown_type)42; /*error-ok*/
1268 auto *y = (unknown_ptr)nullptr;
1269 )cpp");
1272 TEST(TypeHints, ReturnTypeDeduction) {
1273 assertTypeHints(
1274 R"cpp(
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
1279 int s;
1280 auto& f2($ret2[[)]] { return s; }
1282 // Do not hint `auto` for trailing return type.
1283 auto f3() -> int;
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
1291 struct A {
1292 operator auto($retConv[[)]] { return 42; }
1295 // FIXME: Dependent types do not work yet.
1296 template <typename T>
1297 struct S {
1298 auto method() { return T(); }
1300 )cpp",
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>
1309 void foo(T arg) {
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;
1315 )cpp");
1318 TEST(TypeHints, LongTypeName) {
1319 assertTypeHints(R"cpp(
1320 template <typename, typename, typename>
1321 struct A {};
1322 struct MultipleWords {};
1323 A<MultipleWords, MultipleWords, MultipleWords> foo();
1324 // Omit type hint past a certain length (currently 32)
1325 auto var = foo();
1326 )cpp");
1328 Config Cfg;
1329 Cfg.InlayHints.TypeNameLimit = 0;
1330 WithContextValue WithCfg(Config::Key, std::move(Cfg));
1332 assertTypeHints(
1333 R"cpp(
1334 template <typename, typename, typename>
1335 struct A {};
1336 struct MultipleWords {};
1337 A<MultipleWords, MultipleWords, MultipleWords> foo();
1338 // Should have type hint with TypeNameLimit = 0
1339 auto $var[[var]] = foo();
1340 )cpp",
1341 ExpectedHint{": A<MultipleWords, MultipleWords, MultipleWords>", "var"});
1344 TEST(TypeHints, DefaultTemplateArgs) {
1345 assertTypeHints(R"cpp(
1346 template <typename, typename = int>
1347 struct A {};
1348 A<float> foo();
1349 auto $var[[var]] = foo();
1350 A<float> bar[1];
1351 auto [$binding[[value]]] = bar;
1352 )cpp",
1353 ExpectedHint{": A<float>", "var"},
1354 ExpectedHint{": A<float>", "binding"});
1357 TEST(TypeHints, Deduplication) {
1358 assertTypeHints(R"cpp(
1359 template <typename T>
1360 void foo() {
1361 auto $var[[var]] = 42;
1363 template void foo<int>();
1364 template void foo<float>();
1365 )cpp",
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);
1373 )cpp",
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);
1381 )cpp",
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
1402 template <class T>
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)]]{};
1413 // No crash
1414 /* error-ok */
1415 auto $j[[s]];
1416 )cpp",
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) {
1424 assertTypeHints(
1425 R"cpp(
1426 template <class T> struct allocator {};
1428 template <class T, class A>
1429 struct vector_base {
1430 using pointer = T*;
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(); }
1456 T elements[10];
1459 vector<int> array;
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>();
1487 )cpp",
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]]};
1505 )cpp",
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]] };
1515 )cpp",
1516 ExpectedHint{".a=", "a"}, ExpectedHint{".x=", "x"},
1517 ExpectedHint{".y=", "y"}, ExpectedHint{".b.x=", "bx"});
1520 TEST(DesignatorHints, AnonymousRecord) {
1521 assertDesignatorHints(R"cpp(
1522 struct S {
1523 union {
1524 struct {
1525 struct {
1526 int y;
1528 } x;
1531 S s{$xy[[42]]};
1532 )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]]};
1540 )cpp",
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]]};
1550 )cpp",
1551 ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"});
1554 TEST(DesignatorHints, OnlyAggregateInit) {
1555 assertDesignatorHints(R"cpp(
1556 struct Copyable { int x; } c;
1557 Copyable d{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(
1566 /*error-ok*/
1567 struct A {};
1568 struct Foo {int a; int b;};
1569 void test() {
1570 Foo f{A(), $b[[1]]};
1572 )cpp", ExpectedHint{".b=", "b"});
1575 TEST(InlayHints, RestrictRange) {
1576 Annotations Code(R"cpp(
1577 auto a = false;
1578 [[auto b = 1;
1579 auto c = '2';]]
1580 auto d = 3.f;
1581 )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(
1589 R"cpp(
1590 struct Foo{ Foo(); Foo(int x); };
1591 void foo(Foo a, int b);
1592 template <typename... Args>
1593 void bar(Args... args) {
1594 foo(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...); }
1602 void foo() {
1603 bar($param4[[Foo{}]], $param5[[42]]);
1604 bar($param6[[42]], $param7[[42]]);
1605 baz($param8[[42]]);
1606 bax($param9[[42]]);
1608 )cpp",
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(
1618 R"cpp(
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]])...);
1625 void foo() {
1626 bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1628 )cpp",
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.)
1643 } // namespace
1644 } // namespace clangd
1645 } // namespace clang