[clangd] don't add inlay hint for dependent type in structured binding
[llvm-project.git] / clang-tools-extra / clangd / unittests / InlayHintTests.cpp
blob1d12db3661c9ebbc89bd9fee9ea5739263bf6fc2
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"
20 #include <string>
21 #include <vector>
23 namespace clang {
24 namespace clangd {
26 llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
27 const InlayHint &Hint) {
28 return Stream << Hint.label << "@" << Hint.range;
31 namespace {
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);
42 return Result;
45 enum HintSide { Left, Right };
47 struct ExpectedHint {
48 std::string Label;
49 std::string RangeName;
50 HintSide Side = Left;
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 << "'";
64 return false;
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));
70 return false;
72 return true;
75 MATCHER_P(labelIs, Label, "") { return arg.label == Label; }
77 Config noHintsConfig() {
78 Config C;
79 C.InlayHints.Parameters = false;
80 C.InlayHints.DeducedTypes = false;
81 C.InlayHints.Designators = false;
82 C.InlayHints.BlockEnd = false;
83 return C;
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) {
131 Config Cfg;
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) {
140 Config Cfg;
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(
148 void foo(int param);
149 void bar() {
150 foo($param[[42]]);
152 )cpp",
153 ExpectedHint{"param: ", "param"});
156 TEST(ParameterHints, NoName) {
157 // No hint for anonymous parameter.
158 assertParameterHints(R"cpp(
159 void foo(int);
160 void bar() {
161 foo(42);
163 )cpp");
166 TEST(ParameterHints, NoNameConstReference) {
167 // No hint for anonymous const l-value ref parameter.
168 assertParameterHints(R"cpp(
169 void foo(const int&);
170 void bar() {
171 foo(42);
173 )cpp");
176 TEST(ParameterHints, NoNameReference) {
177 // Reference hint for anonymous l-value ref parameter.
178 assertParameterHints(R"cpp(
179 void foo(int&);
180 void bar() {
181 int i;
182 foo($param[[i]]);
184 )cpp",
185 ExpectedHint{"&: ", "param"});
188 TEST(ParameterHints, NoNameRValueReference) {
189 // No reference hint for anonymous r-value ref parameter.
190 assertParameterHints(R"cpp(
191 void foo(int&&);
192 void bar() {
193 foo(42);
195 )cpp");
198 TEST(ParameterHints, NoNameVariadicDeclaration) {
199 // No hint for anonymous variadic parameter
200 assertParameterHints(R"cpp(
201 template <typename... Args>
202 void foo(Args&& ...);
203 void bar() {
204 foo(42);
206 )cpp");
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&); }
214 void foo(int);
215 template <typename... Args>
216 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
217 void baz() {
218 bar(42);
220 )cpp");
223 TEST(ParameterHints, NoNameVariadicPlain) {
224 // No hint for anonymous variadic parameter
225 assertParameterHints(R"cpp(
226 void foo(int);
227 template <typename... Args>
228 void bar(Args&&... args) { return foo(args...); }
229 void baz() {
230 bar(42);
232 )cpp");
235 TEST(ParameterHints, NameInDefinition) {
236 // Parameter name picked up from definition if necessary.
237 assertParameterHints(R"cpp(
238 void foo(int);
239 void bar() {
240 foo($param[[42]]);
242 void foo(int param) {};
243 )cpp",
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);
251 void bar() {
252 foo($param1[[42]], $param2[[42]]);
254 void foo(int a, int) {};
255 )cpp",
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(
263 void foo(int, int);
264 template <typename... Args>
265 void bar(Args... args) {
266 foo(args...);
268 void baz() {
269 bar($param1[[42]], $param2[[42]]);
271 void foo(int a, int b) {};
272 )cpp",
273 ExpectedHint{"a: ", "param1"},
274 ExpectedHint{"b: ", "param2"});
277 TEST(ParameterHints, NameMismatch) {
278 // Prefer name from declaration.
279 assertParameterHints(R"cpp(
280 void foo(int good);
281 void bar() {
282 foo($good[[42]]);
284 void foo(int bad) {};
285 )cpp",
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);
293 void bar() {
294 foo($param[[42]]);
296 )cpp",
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);
305 void bar() {
306 int i;
307 foo($param[[i]]);
309 )cpp",
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);
317 void bar() {
318 int i;
319 foo($param[[i]]);
321 )cpp",
322 ExpectedHint{"&param: ", "param"});
325 TEST(ParameterHints, NameTypeAliasReference) {
326 // Reference and name hint for l-value ref parameter via type alias.
327 assertParameterHints(R"cpp(
328 using alias = int&;
329 void foo(alias param);
330 void bar() {
331 int i;
332 foo($param[[i]]);
334 )cpp",
335 ExpectedHint{"&param: ", "param"});
338 TEST(ParameterHints, NameRValueReference) {
339 // Only name hint for r-value ref parameter.
340 assertParameterHints(R"cpp(
341 void foo(int&& param);
342 void bar() {
343 foo($param[[42]]);
345 )cpp",
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)...}; }
357 void baz() {
358 int b;
359 bar<S>($param[[b]]);
361 )cpp",
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...}; }
371 void baz() {
372 int b;
373 bar<S>($param[[b]]);
375 )cpp",
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)...}; }
387 void baz() {
388 int b;
389 bar<S>($param[[b]]);
391 )cpp",
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...}; }
401 void baz() {
402 int b;
403 bar<S>($param[[b]]);
405 )cpp",
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&); }
414 void foo(int a);
415 template <typename... Args>
416 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
417 void baz() {
418 int b;
419 bar($param[[b]]);
421 )cpp",
422 ExpectedHint{"a: ", "param"});
425 TEST(ParameterHints, VariadicPlain) {
426 // Name hint for variadic parameter
427 assertParameterHints(R"cpp(
428 void foo(int a);
429 template <typename... Args>
430 void bar(Args&&... args) { return foo(args...); }
431 void baz() {
432 bar($param[[42]]);
434 )cpp",
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(
442 void foo(int a);
443 template <typename... Args, typename Arg>
444 void bar(Arg, Args&&... args) { return foo(args...); }
445 void baz() {
446 bar(1, $param[[42]]);
448 )cpp",
449 ExpectedHint{"a: ", "param"});
452 TEST(ParameterHints, VariadicSplitTwolevel) {
453 // Name for variadic parameter that involves both head and tail parameters to
454 // deal with.
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)...); }
465 void bazz() {
466 bar($param1[[32]], $param2[[42]]);
468 )cpp",
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
475 // specialization.
476 assertParameterHints(R"cpp(
477 void foo(int a);
478 template <typename... Args>
479 void bar(Args... args) {
480 foo(args...);
482 template <>
483 void bar<int>(int b);
484 void baz() {
485 bar($param[[42]]);
487 )cpp",
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(
495 void foo2(int a);
496 template <typename... Args>
497 void foo(Args... args) {
498 foo2(args...);
500 template <typename... Args>
501 void bar(Args... args) {
502 foo(args...);
504 template <>
505 void foo<int>(int b);
506 void baz() {
507 bar($param[[42]]);
509 )cpp",
510 ExpectedHint{"b: ", "param"});
513 TEST(ParameterHints, VariadicOverloaded) {
514 // Name for variadic parameter for an overloaded function with unique number
515 // of parameters.
516 // This prototype of std::forward is sufficient for clang to recognize it
517 assertParameterHints(
518 R"cpp(
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)...); }
528 void bazz() {
529 bar($param1[[32]], $param2[[42]], $param3[[52]]);
530 bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
532 )cpp",
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(
542 R"cpp(
543 void foo();
545 template <typename Head, typename... Tail>
546 void foo(Head head, Tail... tail) {
547 foo(tail...);
550 template <typename... Args>
551 void bar(Args... args) {
552 foo(args...);
555 int main() {
556 bar(1, 2, 3);
558 )cpp");
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) {
567 foo(args...);
570 void baz() {
571 bar($fixed[[41]], 42, 43);
573 )cpp");
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) {
583 foo(args...);
586 void baz() {
587 bar($fixed[[41]], 42, 43);
589 )cpp",
590 ExpectedHint{"fixed: ", "fixed"});
593 TEST(ParameterHints, VariadicTwoCalls) {
594 // only the first call using the parameter pack should be picked up
595 assertParameterHints(
596 R"cpp(
597 void f1(int a, int b);
598 void f2(int c, int d);
600 bool cond;
602 template <typename... Args>
603 void foo(Args... args) {
604 if (cond) {
605 f1(args...);
606 } else {
607 f2(args...);
611 int main() {
612 foo($param1[[1]], $param2[[2]]);
614 )cpp",
615 ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"});
618 TEST(ParameterHints, VariadicInfinite) {
619 // infinite recursion should not break clangd
620 assertParameterHints(
621 R"cpp(
622 template <typename... Args>
623 void foo(Args...);
625 template <typename... Args>
626 void bar(Args... args) {
627 foo(args...);
630 template <typename... Args>
631 void foo(Args... args) {
632 bar(args...);
635 int main() {
636 foo(1, 2);
638 )cpp");
641 TEST(ParameterHints, VariadicDuplicatePack) {
642 // edge cases with multiple adjacent packs should work
643 assertParameterHints(
644 R"cpp(
645 void foo(int a, int b, int c, int);
647 template <typename... Args>
648 void bar(int, Args... args, int d) {
649 foo(args..., d);
652 template <typename... Args>
653 void baz(Args... args, Args... args2) {
654 bar<Args..., int>(1, args..., args2...);
657 int main() {
658 baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
660 )cpp",
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(
669 R"cpp(
670 namespace std { template <typename T> T&& forward(T&); }
671 using size_t = decltype(sizeof(0));
672 void *operator new(size_t, void *);
673 struct S {
674 S(int A);
675 S(int B, int C);
677 struct alloc {
678 template <typename T>
679 T* allocate();
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>
686 struct container {
687 template <typename... Args>
688 void emplace(Args&&... args) {
689 alloc a;
690 auto ptr = a.template allocate<T>();
691 a.construct(ptr, std::forward<Args>(args)...);
694 void foo() {
695 container<S> c;
696 c.emplace($param1[[1]]);
697 c.emplace($param2[[2]], $param3[[3]]);
699 )cpp",
700 ExpectedHint{"A: ", "param1"}, ExpectedHint{"B: ", "param2"},
701 ExpectedHint{"C: ", "param3"});
704 TEST(ParameterHints, VariadicReferenceHint) {
705 assertParameterHints(R"cpp(
706 void foo(int&);
707 template <typename... Args>
708 void bar(Args... args) { return foo(args...); }
709 void baz() {
710 int a;
711 bar(a);
712 bar(1);
714 )cpp");
717 TEST(ParameterHints, VariadicReferenceHintForwardingRef) {
718 assertParameterHints(R"cpp(
719 void foo(int&);
720 template <typename... Args>
721 void bar(Args&&... args) { return foo(args...); }
722 void baz() {
723 int a;
724 bar($param[[a]]);
725 bar(1);
727 )cpp",
728 ExpectedHint{"&: ", "param"});
731 TEST(ParameterHints, VariadicReferenceHintForwardingRefStdForward) {
732 assertParameterHints(R"cpp(
733 namespace std { template <typename T> T&& forward(T&); }
734 void foo(int&);
735 template <typename... Args>
736 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
737 void baz() {
738 int a;
739 bar($param[[a]]);
741 )cpp",
742 ExpectedHint{"&: ", "param"});
745 TEST(ParameterHints, VariadicNoReferenceHintForwardingRefStdForward) {
746 assertParameterHints(R"cpp(
747 namespace std { template <typename T> T&& forward(T&); }
748 void foo(int);
749 template <typename... Args>
750 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
751 void baz() {
752 int a;
753 bar(a);
754 bar(1);
756 )cpp");
759 TEST(ParameterHints, VariadicNoReferenceHintUnresolvedForward) {
760 assertParameterHints(R"cpp(
761 template <typename... Args>
762 void foo(Args&&... args);
763 void bar() {
764 int a;
765 foo(a);
767 )cpp");
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&); }
775 void foo(int a);
776 template <typename... Args>
777 void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
778 void baz() {
779 int a;
780 bar(a);
782 )cpp");
785 TEST(ParameterHints, MatchingNameVariadicPlain) {
786 // No name hint for variadic parameter with matching name
787 assertParameterHints(R"cpp(
788 void foo(int a);
789 template <typename... Args>
790 void bar(Args&&... args) { return foo(args...); }
791 void baz() {
792 int a;
793 bar(a);
795 )cpp");
798 TEST(ParameterHints, Operator) {
799 // No hint for operator call with operator syntax.
800 assertParameterHints(R"cpp(
801 struct S {};
802 void operator+(S lhs, S rhs);
803 void bar() {
804 S a, b;
805 a + b;
807 )cpp");
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(
816 void foo(int param);
817 #define ExpandsToCall() foo(42)
818 void bar() {
819 ExpandsToCall();
821 )cpp");
823 // The argument expression being a macro invocation shouldn't interfere
824 // with hinting.
825 assertParameterHints(R"cpp(
826 #define PI 3.14
827 void foo(double param);
828 void bar() {
829 foo($param[[PI]]);
831 )cpp",
832 ExpectedHint{"param: ", "param"});
834 // If the whole argument list comes from a macro parameter, hint it.
835 assertParameterHints(R"cpp(
836 void abort();
837 #define ASSERT(expr) if (!expr) abort()
838 int foo(int param);
839 void bar() {
840 ASSERT(foo($param[[42]]) == 0);
842 )cpp",
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
849 void bar() {
850 foo(CONSTANTS);
852 )cpp");
855 TEST(ParameterHints, ConstructorParens) {
856 assertParameterHints(R"cpp(
857 struct S {
858 S(int param);
860 void bar() {
861 S obj($param[[42]]);
863 )cpp",
864 ExpectedHint{"param: ", "param"});
867 TEST(ParameterHints, ConstructorBraces) {
868 assertParameterHints(R"cpp(
869 struct S {
870 S(int param);
872 void bar() {
873 S obj{$param[[42]]};
875 )cpp",
876 ExpectedHint{"param: ", "param"});
879 TEST(ParameterHints, ConstructorStdInitList) {
880 // Do not show hints for std::initializer_list constructors.
881 assertParameterHints(R"cpp(
882 namespace std {
883 template <typename> class initializer_list {};
885 struct S {
886 S(std::initializer_list<int> param);
888 void bar() {
889 S obj{42, 43};
891 )cpp");
894 TEST(ParameterHints, MemberInit) {
895 assertParameterHints(R"cpp(
896 struct S {
897 S(int param);
899 struct T {
900 S member;
901 T() : member($param[[42]]) {}
903 )cpp",
904 ExpectedHint{"param: ", "param"});
907 TEST(ParameterHints, ImplicitConstructor) {
908 assertParameterHints(R"cpp(
909 struct S {
910 S(int param);
912 void bar(S);
913 S foo() {
914 // Do not show hint for implicit constructor call in argument.
915 bar(42);
916 // Do not show hint for implicit constructor call in return.
917 return 42;
919 )cpp");
922 TEST(ParameterHints, FunctionPointer) {
923 assertParameterHints(
924 R"cpp(
925 void (*f1)(int param);
926 void (__stdcall *f2)(int param);
927 using f3_t = void(*)(int param);
928 f3_t f3;
929 using f4_t = void(__stdcall *)(int param);
930 f4_t f4;
931 void bar() {
932 f1($f1[[42]]);
933 f2($f2[[42]]);
934 f3($f3[[42]]);
935 f4($f4[[42]]);
937 )cpp",
938 ExpectedHint{"param: ", "f1"}, ExpectedHint{"param: ", "f2"},
939 ExpectedHint{"param: ", "f3"}, ExpectedHint{"param: ", "f4"});
942 TEST(ParameterHints, ArgMatchesParam) {
943 assertParameterHints(R"cpp(
944 void foo(int param);
945 struct S {
946 static const int param = 42;
948 void bar() {
949 int param = 42;
950 // Do not show redundant "param: param".
951 foo(param);
952 // But show it if the argument is qualified.
953 foo($param[[S::param]]);
955 struct A {
956 int param;
957 void bar() {
958 // Do not show "param: param" for member-expr.
959 foo(param);
962 )cpp",
963 ExpectedHint{"param: ", "param"});
966 TEST(ParameterHints, ArgMatchesParamReference) {
967 assertParameterHints(R"cpp(
968 void foo(int& param);
969 void foo2(const int& param);
970 void bar() {
971 int param;
972 // show reference hint on mutable reference
973 foo($param[[param]]);
974 // but not on const reference
975 foo2(param);
977 )cpp",
978 ExpectedHint{"&: ", "param"});
981 TEST(ParameterHints, LeadingUnderscore) {
982 assertParameterHints(R"cpp(
983 void foo(int p1, int _p2, int __p3);
984 void bar() {
985 foo($p1[[41]], $p2[[42]], $p3[[43]]);
987 )cpp",
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>
998 struct A {
999 void member(T par2);
1000 static void static_member(T par3);
1003 void overload(int anInt);
1004 void overload(double aDouble);
1006 template <typename T>
1007 struct S {
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.
1014 overload(T{});
1017 )cpp",
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);
1028 void bar() {
1029 foo($fixed[[41]], 42, 43);
1031 )cpp",
1032 ExpectedHint{"fixed: ", "fixed"});
1035 TEST(ParameterHints, VarargsFunction) {
1036 assertParameterHints(R"cpp(
1037 void foo(int fixed, ...);
1039 void bar() {
1040 foo($fixed[[41]], 42, 43);
1042 )cpp",
1043 ExpectedHint{"fixed: ", "fixed"});
1046 TEST(ParameterHints, CopyOrMoveConstructor) {
1047 // Do not show hint for parameter of copy or move constructor.
1048 assertParameterHints(R"cpp(
1049 struct S {
1050 S();
1051 S(const S& other);
1052 S(S&& other);
1054 void bar() {
1055 S a;
1056 S b(a); // copy
1057 S c(S()); // move
1059 )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(
1066 struct Point {
1067 int x;
1068 int y;
1070 void bar() {
1071 Point p{41, 42};
1073 )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);
1080 void bar() {
1081 1.2_w;
1083 )cpp");
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);
1091 void bar() {
1092 foo(/*param*/42);
1093 foo( /* param = */ 42);
1094 #define X 42
1095 #define Y X
1096 #define Z(...) Y
1097 foo(/*param=*/Z(a));
1098 foo($macro[[Z(a)]]);
1099 foo(/* the answer */$param[[42]]);
1101 )cpp",
1102 ExpectedHint{"param: ", "macro"},
1103 ExpectedHint{"param: ", "param"});
1106 TEST(ParameterHints, SetterFunctions) {
1107 assertParameterHints(R"cpp(
1108 struct S {
1109 void setParent(S* parent);
1110 void set_parent(S* parent);
1111 void setTimeout(int timeoutMillis);
1112 void setTimeoutMillis(int timeout_millis);
1114 void bar() {
1115 S s;
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]]);
1125 )cpp",
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&); }
1134 void foo() {
1135 int i;
1136 std::forward(i);
1138 )cpp");
1141 TEST(ParameterHints, IncludeAtNonGlobalScope) {
1142 Annotations FooInc(R"cpp(
1143 void bar() { foo(42); }
1144 )cpp");
1145 Annotations FooCC(R"cpp(
1146 struct S {
1147 void foo(int param);
1148 #include "foo.inc"
1150 )cpp");
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;
1166 )cpp",
1167 ExpectedHint{": int", "waldo"});
1170 TEST(TypeHints, Decorations) {
1171 assertTypeHints(R"cpp(
1172 int x = 42;
1173 auto* $var1[[var1]] = &x;
1174 auto&& $var2[[var2]] = x;
1175 const auto& $var3[[var3]] = x;
1176 )cpp",
1177 ExpectedHint{": int *", "var1"},
1178 ExpectedHint{": int &", "var2"},
1179 ExpectedHint{": const int &", "var3"});
1182 TEST(TypeHints, DecltypeAuto) {
1183 assertTypeHints(R"cpp(
1184 int x = 42;
1185 int& y = x;
1186 decltype(auto) $z[[z]] = y;
1187 )cpp",
1188 ExpectedHint{": int &", "z"});
1191 TEST(TypeHints, NoQualifiers) {
1192 assertTypeHints(R"cpp(
1193 namespace A {
1194 namespace B {
1195 struct S1 {};
1196 S1 foo();
1197 auto $x[[x]] = foo();
1199 struct S2 {
1200 template <typename T>
1201 struct Inner {};
1203 S2::Inner<int> bar();
1204 auto $y[[y]] = bar();
1207 )cpp",
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(
1222 void f() {
1223 int cap = 42;
1224 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1225 return a + cap + init;
1228 )cpp",
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.
1245 struct Point {
1246 int x;
1247 int y;
1249 Point foo();
1250 auto [$x[[x]], $y[[y]]] = foo();
1251 )cpp",
1252 ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1255 TEST(TypeHints, StructuredBindings_Array) {
1256 assertTypeHints(R"cpp(
1257 int arr[2];
1258 auto [$x[[x]], $y[[y]]] = arr;
1259 )cpp",
1260 ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1263 TEST(TypeHints, StructuredBindings_TupleLike) {
1264 assertTypeHints(R"cpp(
1265 // Tuple-like type.
1266 struct IntPair {
1267 int a;
1268 int b;
1270 namespace std {
1271 template <typename T>
1272 struct tuple_size {};
1273 template <>
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> {
1281 using type = int;
1284 template <unsigned I>
1285 int get(const IntPair& p) {
1286 if constexpr (I == 0) {
1287 return p.a;
1288 } else if constexpr (I == 1) {
1289 return p.b;
1292 IntPair bar();
1293 auto [$x[[x]], $y[[y]]] = bar();
1294 )cpp",
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*/
1303 )cpp");
1306 TEST(TypeHints, InvalidType) {
1307 assertTypeHints(R"cpp(
1308 auto x = (unknown_type)42; /*error-ok*/
1309 auto *y = (unknown_ptr)nullptr;
1310 )cpp");
1313 TEST(TypeHints, ReturnTypeDeduction) {
1314 assertTypeHints(
1315 R"cpp(
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
1320 int s;
1321 auto& f2($ret2[[)]] { return s; }
1323 // Do not hint `auto` for trailing return type.
1324 auto f3() -> int;
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
1332 struct A {
1333 operator auto($retConv[[)]] { return 42; }
1336 // FIXME: Dependent types do not work yet.
1337 template <typename T>
1338 struct S {
1339 auto method() { return T(); }
1341 )cpp",
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>
1350 void foo(T arg) {
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>
1358 void bar(T arg) {
1359 auto [a, b] = arg;
1361 )cpp");
1364 TEST(TypeHints, LongTypeName) {
1365 assertTypeHints(R"cpp(
1366 template <typename, typename, typename>
1367 struct A {};
1368 struct MultipleWords {};
1369 A<MultipleWords, MultipleWords, MultipleWords> foo();
1370 // Omit type hint past a certain length (currently 32)
1371 auto var = foo();
1372 )cpp");
1374 Config Cfg;
1375 Cfg.InlayHints.TypeNameLimit = 0;
1376 WithContextValue WithCfg(Config::Key, std::move(Cfg));
1378 assertTypeHints(
1379 R"cpp(
1380 template <typename, typename, typename>
1381 struct A {};
1382 struct MultipleWords {};
1383 A<MultipleWords, MultipleWords, MultipleWords> foo();
1384 // Should have type hint with TypeNameLimit = 0
1385 auto $var[[var]] = foo();
1386 )cpp",
1387 ExpectedHint{": A<MultipleWords, MultipleWords, MultipleWords>", "var"});
1390 TEST(TypeHints, DefaultTemplateArgs) {
1391 assertTypeHints(R"cpp(
1392 template <typename, typename = int>
1393 struct A {};
1394 A<float> foo();
1395 auto $var[[var]] = foo();
1396 A<float> bar[1];
1397 auto [$binding[[value]]] = bar;
1398 )cpp",
1399 ExpectedHint{": A<float>", "var"},
1400 ExpectedHint{": A<float>", "binding"});
1403 TEST(TypeHints, Deduplication) {
1404 assertTypeHints(R"cpp(
1405 template <typename T>
1406 void foo() {
1407 auto $var[[var]] = 42;
1409 template void foo<int>();
1410 template void foo<float>();
1411 )cpp",
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);
1419 )cpp",
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);
1427 )cpp",
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
1448 template <class T>
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)]]{};
1459 // No crash
1460 /* error-ok */
1461 auto $j[[s]];
1462 )cpp",
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 {
1475 using pointer = T*;
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(); }
1501 T elements[10];
1503 )cpp";
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();
1517 )cpp";
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(
1530 vector<int> array;
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();
1541 )cpp";
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>();
1568 )cpp";
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]]};
1581 )cpp",
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]] };
1591 )cpp",
1592 ExpectedHint{".a=", "a"}, ExpectedHint{".x=", "x"},
1593 ExpectedHint{".y=", "y"}, ExpectedHint{".b.x=", "bx"});
1596 TEST(DesignatorHints, AnonymousRecord) {
1597 assertDesignatorHints(R"cpp(
1598 struct S {
1599 union {
1600 struct {
1601 struct {
1602 int y;
1604 } x;
1607 S s{$xy[[42]]};
1608 )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]]};
1616 )cpp",
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]]};
1626 )cpp",
1627 ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"});
1630 TEST(DesignatorHints, OnlyAggregateInit) {
1631 assertDesignatorHints(R"cpp(
1632 struct Copyable { int x; } c;
1633 Copyable d{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(
1642 /*error-ok*/
1643 struct A {};
1644 struct Foo {int a; int b;};
1645 void test() {
1646 Foo f{A(), $b[[1]]};
1648 )cpp", ExpectedHint{".b=", "b"});
1651 TEST(InlayHints, RestrictRange) {
1652 Annotations Code(R"cpp(
1653 auto a = false;
1654 [[auto b = 1;
1655 auto c = '2';]]
1656 auto d = 3.f;
1657 )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(
1665 R"cpp(
1666 struct Foo{ Foo(); Foo(int x); };
1667 void foo(Foo a, int b);
1668 template <typename... Args>
1669 void bar(Args... args) {
1670 foo(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...); }
1678 void foo() {
1679 bar($param4[[Foo{}]], $param5[[42]]);
1680 bar($param6[[42]], $param7[[42]]);
1681 baz($param8[[42]]);
1682 bax($param9[[42]]);
1684 )cpp",
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(
1694 R"cpp(
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]])...);
1701 void foo() {
1702 bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1704 )cpp",
1705 ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
1706 ExpectedHint{"c: ", "param3"});
1709 TEST(BlockEndHints, Functions) {
1710 assertBlockEndHints(R"cpp(
1711 int foo() {
1712 return 41;
1713 $foo[[}]]
1715 template<int X>
1716 int bar() {
1717 // No hint for lambda for now
1718 auto f = []() {
1719 return X;
1721 return f();
1722 $bar[[}]]
1724 // No hint because this isn't a definition
1725 int buz();
1727 struct S{};
1728 bool operator==(S, S) {
1729 return true;
1730 $opEqual[[}]]
1731 )cpp",
1732 ExpectedHint{" // foo", "foo"},
1733 ExpectedHint{" // bar", "bar"},
1734 ExpectedHint{" // operator==", "opEqual"});
1737 TEST(BlockEndHints, Methods) {
1738 assertBlockEndHints(R"cpp(
1739 struct Test {
1740 // No hint because there's no function body
1741 Test() = default;
1743 ~Test() {
1744 $dtor[[}]]
1746 void method1() {
1747 $method1[[}]]
1749 // No hint because this isn't a definition
1750 void method2();
1752 template <typename T>
1753 void method3() {
1754 $method3[[}]]
1756 // No hint because this isn't a definition
1757 template <typename T>
1758 void method4();
1760 Test operator+(int) const {
1761 return *this;
1762 $opIdentity[[}]]
1764 operator bool() const {
1765 return true;
1766 $opBool[[}]]
1768 // No hint because there's no function body
1769 operator int() const = delete;
1770 } x;
1772 void Test::method2() {
1773 $method2[[}]]
1775 template <typename T>
1776 void Test::method4() {
1777 $method4[[}]]
1778 )cpp",
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(
1790 R"cpp(
1791 namespace {
1792 void foo();
1793 $anon[[}]]
1795 namespace ns {
1796 void bar();
1797 $ns[[}]]
1798 )cpp",
1799 ExpectedHint{" // namespace", "anon"},
1800 ExpectedHint{" // namespace ns", "ns"});
1803 TEST(BlockEndHints, Types) {
1804 assertBlockEndHints(
1805 R"cpp(
1806 struct S {
1807 $S[[};]]
1809 class C {
1810 $C[[};]]
1812 union U {
1813 $U[[};]]
1815 enum E1 {
1816 $E1[[};]]
1818 enum class E2 {
1819 $E2[[};]]
1820 )cpp",
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(
1828 R"cpp(
1829 void foo(bool cond) {
1830 if (cond)
1833 if (cond) {
1834 $simple[[}]]
1836 if (cond) {
1837 } else {
1838 $ifelse[[}]]
1840 if (cond) {
1841 } else if (!cond) {
1842 $elseif[[}]]
1844 if (cond) {
1845 } else {
1846 if (!cond) {
1847 $inner[[}]]
1848 $outer[[}]]
1850 if (auto X = cond) {
1851 $init[[}]]
1853 if (int i = 0; i > 10) {
1854 $init_cond[[}]]
1855 } // suppress
1856 )cpp",
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(
1866 R"cpp(
1867 void foo() {
1868 while (true)
1871 while (true) {
1872 $while[[}]]
1874 do {
1875 } while (true);
1877 for (;true;) {
1878 $forcond[[}]]
1880 for (int I = 0; I < 10; ++I) {
1881 $forvar[[}]]
1883 int Vs[] = {1,2,3};
1884 for (auto V : Vs) {
1885 $foreach[[}]]
1886 } // suppress
1887 )cpp",
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(
1896 R"cpp(
1897 void foo(int I) {
1898 switch (I) {
1899 case 0: break;
1900 $switch[[}]]
1901 } // suppress
1902 )cpp",
1903 ExpectedHint{" // switch I", "switch"});
1906 TEST(BlockEndHints, PrintLiterals) {
1907 assertBlockEndHints(
1908 R"cpp(
1909 void foo() {
1910 while ("foo") {
1911 $string[[}]]
1913 while ("foo but this time it is very long") {
1914 $string_long[[}]]
1916 while (true) {
1917 $boolean[[}]]
1919 while (1) {
1920 $integer[[}]]
1922 while (1.5) {
1923 $float[[}]]
1924 } // suppress
1925 )cpp",
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(
1935 R"cpp(
1936 namespace ns {
1937 int Var;
1938 int func();
1939 struct S {
1940 int Field;
1941 int method() const;
1942 }; // suppress
1943 } // suppress
1944 void foo() {
1945 while (ns::Var) {
1946 $var[[}]]
1948 while (ns::func()) {
1949 $func[[}]]
1951 while (ns::S{}.Field) {
1952 $field[[}]]
1954 while (ns::S{}.method()) {
1955 $method[[}]]
1956 } // suppress
1957 )cpp",
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(
1966 R"cpp(
1967 struct S {
1968 S(int);
1969 S(int, int);
1970 explicit operator bool();
1971 }; // suppress
1972 void foo(int I) {
1973 while (float(I)) {
1974 $convert_primitive[[}]]
1976 while (S(I)) {
1977 $convert_class[[}]]
1979 while (S(I, I)) {
1980 $construct_class[[}]]
1981 } // suppress
1982 )cpp",
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) {
1991 while(++I){
1992 $preinc[[}]]
1994 while(I++){
1995 $postinc[[}]]
1997 while(+(I + I)){
1998 $unary_complex[[}]]
2000 while(I < 0){
2001 $compare[[}]]
2003 while((I + I) < I){
2004 $lhs_complex[[}]]
2006 while(I < (I + I)){
2007 $rhs_complex[[}]]
2009 while((I + I) < (I + I)){
2010 $binary_complex[[}]]
2011 } // suppress
2012 )cpp";
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(
2029 struct Integer {
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);
2037 }; // suppress
2038 )cpp" + AnnotatedCode);
2041 TEST(BlockEndHints, TrailingSemicolon) {
2042 assertBlockEndHints(R"cpp(
2043 // The hint is placed after the trailing ';'
2044 struct S1 {
2045 $S1[[} ;]]
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 '}'.
2049 struct S2 {
2050 $S2[[}]]
2054 // No hint because only one trailing ';' is allowed
2055 struct S3 {
2058 // No hint because trailing ';' is only allowed for class/struct/union/enum
2059 void foo() {
2062 // Rare case, but yes we'll have a hint here.
2063 struct {
2064 int x;
2065 $anon[[}]]
2068 )cpp",
2069 ExpectedHint{" // struct S1", "S1"},
2070 ExpectedHint{" // struct S2", "S2"},
2071 ExpectedHint{" // struct", "anon"});
2074 TEST(BlockEndHints, TrailingText) {
2075 assertBlockEndHints(R"cpp(
2076 struct S1 {
2077 $S1[[} ;]]
2079 // No hint for S2 because of the trailing comment
2080 struct S2 {
2081 }; /* Put anything here */
2083 struct S3 {
2084 // No hint for S4 because of the trailing source code
2085 struct S4 {
2086 };$S3[[};]]
2088 // No hint for ns because of the trailing comment
2089 namespace ns {
2090 } // namespace ns
2091 )cpp",
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 {
2099 #define RBRACE }
2101 DECL_STRUCT(S1)
2102 $S1[[};]]
2104 // No hint because we require a '}'
2105 DECL_STRUCT(S2)
2106 RBRACE;
2107 )cpp",
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.)
2122 } // namespace
2123 } // namespace clangd
2124 } // namespace clang