xref: /llvm-project/clang-tools-extra/clangd/unittests/InlayHintTests.cpp (revision 5518bb215b51cc339c3ecac064032f6791ae6476)
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 "llvm/Support/raw_ostream.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <optional>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 namespace clang {
27 namespace clangd {
28 
29 llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
30                               const InlayHint &Hint) {
31   return Stream << Hint.joinLabels() << "@" << Hint.range;
32 }
33 
34 namespace {
35 
36 using ::testing::ElementsAre;
37 using ::testing::IsEmpty;
38 
39 std::vector<InlayHint> hintsOfKind(ParsedAST &AST, InlayHintKind Kind) {
40   std::vector<InlayHint> Result;
41   for (auto &Hint : inlayHints(AST, /*RestrictRange=*/std::nullopt)) {
42     if (Hint.kind == Kind)
43       Result.push_back(Hint);
44   }
45   return Result;
46 }
47 
48 enum HintSide { Left, Right };
49 
50 struct ExpectedHint {
51   std::string Label;
52   std::string RangeName;
53   HintSide Side = Left;
54 
55   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
56                                        const ExpectedHint &Hint) {
57     return Stream << Hint.Label << "@$" << Hint.RangeName;
58   }
59 };
60 
61 MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) {
62   llvm::StringRef ExpectedView(Expected.Label);
63   std::string ResultLabel = arg.joinLabels();
64   if (ResultLabel != ExpectedView.trim(" ") ||
65       arg.paddingLeft != ExpectedView.starts_with(" ") ||
66       arg.paddingRight != ExpectedView.ends_with(" ")) {
67     *result_listener << "label is '" << ResultLabel << "'";
68     return false;
69   }
70   if (arg.range != Code.range(Expected.RangeName)) {
71     *result_listener << "range is " << llvm::to_string(arg.range) << " but $"
72                      << Expected.RangeName << " is "
73                      << llvm::to_string(Code.range(Expected.RangeName));
74     return false;
75   }
76   return true;
77 }
78 
79 MATCHER_P(labelIs, Label, "") { return arg.joinLabels() == Label; }
80 
81 Config noHintsConfig() {
82   Config C;
83   C.InlayHints.Parameters = false;
84   C.InlayHints.DeducedTypes = false;
85   C.InlayHints.Designators = false;
86   C.InlayHints.BlockEnd = false;
87   C.InlayHints.DefaultArguments = false;
88   return C;
89 }
90 
91 template <typename... ExpectedHints>
92 void assertHintsWithHeader(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
93                            llvm::StringRef HeaderContent,
94                            ExpectedHints... Expected) {
95   Annotations Source(AnnotatedSource);
96   TestTU TU = TestTU::withCode(Source.code());
97   TU.ExtraArgs.push_back("-std=c++23");
98   TU.HeaderCode = HeaderContent;
99   auto AST = TU.build();
100 
101   EXPECT_THAT(hintsOfKind(AST, Kind),
102               ElementsAre(HintMatcher(Expected, Source)...));
103   // Sneak in a cross-cutting check that hints are disabled by config.
104   // We'll hit an assertion failure if addInlayHint still gets called.
105   WithContextValue WithCfg(Config::Key, noHintsConfig());
106   EXPECT_THAT(inlayHints(AST, std::nullopt), IsEmpty());
107 }
108 
109 template <typename... ExpectedHints>
110 void assertHints(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
111                  ExpectedHints... Expected) {
112   return assertHintsWithHeader(Kind, AnnotatedSource, "",
113                                std::move(Expected)...);
114 }
115 
116 // Hack to allow expression-statements operating on parameter packs in C++14.
117 template <typename... T> void ignore(T &&...) {}
118 
119 template <typename... ExpectedHints>
120 void assertParameterHints(llvm::StringRef AnnotatedSource,
121                           ExpectedHints... Expected) {
122   ignore(Expected.Side = Left...);
123   assertHints(InlayHintKind::Parameter, AnnotatedSource, Expected...);
124 }
125 
126 template <typename... ExpectedHints>
127 void assertTypeHints(llvm::StringRef AnnotatedSource,
128                      ExpectedHints... Expected) {
129   ignore(Expected.Side = Right...);
130   assertHints(InlayHintKind::Type, AnnotatedSource, Expected...);
131 }
132 
133 template <typename... ExpectedHints>
134 void assertDesignatorHints(llvm::StringRef AnnotatedSource,
135                            ExpectedHints... Expected) {
136   Config Cfg;
137   Cfg.InlayHints.Designators = true;
138   WithContextValue WithCfg(Config::Key, std::move(Cfg));
139   assertHints(InlayHintKind::Designator, AnnotatedSource, Expected...);
140 }
141 
142 template <typename... ExpectedHints>
143 void assertBlockEndHints(llvm::StringRef AnnotatedSource,
144                          ExpectedHints... Expected) {
145   Config Cfg;
146   Cfg.InlayHints.BlockEnd = true;
147   WithContextValue WithCfg(Config::Key, std::move(Cfg));
148   assertHints(InlayHintKind::BlockEnd, AnnotatedSource, Expected...);
149 }
150 
151 TEST(ParameterHints, Smoke) {
152   assertParameterHints(R"cpp(
153     void foo(int param);
154     void bar() {
155       foo($param[[42]]);
156     }
157   )cpp",
158                        ExpectedHint{"param: ", "param"});
159 }
160 
161 TEST(ParameterHints, NoName) {
162   // No hint for anonymous parameter.
163   assertParameterHints(R"cpp(
164     void foo(int);
165     void bar() {
166       foo(42);
167     }
168   )cpp");
169 }
170 
171 TEST(ParameterHints, NoNameConstReference) {
172   // No hint for anonymous const l-value ref parameter.
173   assertParameterHints(R"cpp(
174     void foo(const int&);
175     void bar() {
176       foo(42);
177     }
178   )cpp");
179 }
180 
181 TEST(ParameterHints, NoNameReference) {
182   // Reference hint for anonymous l-value ref parameter.
183   assertParameterHints(R"cpp(
184     void foo(int&);
185     void bar() {
186       int i;
187       foo($param[[i]]);
188     }
189   )cpp",
190                        ExpectedHint{"&: ", "param"});
191 }
192 
193 TEST(ParameterHints, NoNameRValueReference) {
194   // No reference hint for anonymous r-value ref parameter.
195   assertParameterHints(R"cpp(
196     void foo(int&&);
197     void bar() {
198       foo(42);
199     }
200   )cpp");
201 }
202 
203 TEST(ParameterHints, NoNameVariadicDeclaration) {
204   // No hint for anonymous variadic parameter
205   assertParameterHints(R"cpp(
206     template <typename... Args>
207     void foo(Args&& ...);
208     void bar() {
209       foo(42);
210     }
211   )cpp");
212 }
213 
214 TEST(ParameterHints, NoNameVariadicForwarded) {
215   // No hint for anonymous variadic parameter
216   // This prototype of std::forward is sufficient for clang to recognize it
217   assertParameterHints(R"cpp(
218     namespace std { template <typename T> T&& forward(T&); }
219     void foo(int);
220     template <typename... Args>
221     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
222     void baz() {
223       bar(42);
224     }
225   )cpp");
226 }
227 
228 TEST(ParameterHints, NoNameVariadicPlain) {
229   // No hint for anonymous variadic parameter
230   assertParameterHints(R"cpp(
231     void foo(int);
232     template <typename... Args>
233     void bar(Args&&... args) { return foo(args...); }
234     void baz() {
235       bar(42);
236     }
237   )cpp");
238 }
239 
240 TEST(ParameterHints, NameInDefinition) {
241   // Parameter name picked up from definition if necessary.
242   assertParameterHints(R"cpp(
243     void foo(int);
244     void bar() {
245       foo($param[[42]]);
246     }
247     void foo(int param) {};
248   )cpp",
249                        ExpectedHint{"param: ", "param"});
250 }
251 
252 TEST(ParameterHints, NamePartiallyInDefinition) {
253   // Parameter name picked up from definition if necessary.
254   assertParameterHints(R"cpp(
255     void foo(int, int b);
256     void bar() {
257       foo($param1[[42]], $param2[[42]]);
258     }
259     void foo(int a, int) {};
260   )cpp",
261                        ExpectedHint{"a: ", "param1"},
262                        ExpectedHint{"b: ", "param2"});
263 }
264 
265 TEST(ParameterHints, NameInDefinitionVariadic) {
266   // Parameter name picked up from definition in a resolved forwarded parameter.
267   assertParameterHints(R"cpp(
268     void foo(int, int);
269     template <typename... Args>
270     void bar(Args... args) {
271       foo(args...);
272     }
273     void baz() {
274       bar($param1[[42]], $param2[[42]]);
275     }
276     void foo(int a, int b) {};
277   )cpp",
278                        ExpectedHint{"a: ", "param1"},
279                        ExpectedHint{"b: ", "param2"});
280 }
281 
282 TEST(ParameterHints, NameMismatch) {
283   // Prefer name from declaration.
284   assertParameterHints(R"cpp(
285     void foo(int good);
286     void bar() {
287       foo($good[[42]]);
288     }
289     void foo(int bad) {};
290   )cpp",
291                        ExpectedHint{"good: ", "good"});
292 }
293 
294 TEST(ParameterHints, NameConstReference) {
295   // Only name hint for const l-value ref parameter.
296   assertParameterHints(R"cpp(
297     void foo(const int& param);
298     void bar() {
299       foo($param[[42]]);
300     }
301   )cpp",
302                        ExpectedHint{"param: ", "param"});
303 }
304 
305 TEST(ParameterHints, NameTypeAliasConstReference) {
306   // Only name hint for const l-value ref parameter via type alias.
307   assertParameterHints(R"cpp(
308     using alias = const int&;
309     void foo(alias param);
310     void bar() {
311       int i;
312       foo($param[[i]]);
313     }
314   )cpp",
315                        ExpectedHint{"param: ", "param"});
316 }
317 
318 TEST(ParameterHints, NameReference) {
319   // Reference and name hint for l-value ref parameter.
320   assertParameterHints(R"cpp(
321     void foo(int& param);
322     void bar() {
323       int i;
324       foo($param[[i]]);
325     }
326   )cpp",
327                        ExpectedHint{"&param: ", "param"});
328 }
329 
330 TEST(ParameterHints, NameTypeAliasReference) {
331   // Reference and name hint for l-value ref parameter via type alias.
332   assertParameterHints(R"cpp(
333     using alias = int&;
334     void foo(alias param);
335     void bar() {
336       int i;
337       foo($param[[i]]);
338     }
339   )cpp",
340                        ExpectedHint{"&param: ", "param"});
341 }
342 
343 TEST(ParameterHints, NameRValueReference) {
344   // Only name hint for r-value ref parameter.
345   assertParameterHints(R"cpp(
346     void foo(int&& param);
347     void bar() {
348       foo($param[[42]]);
349     }
350   )cpp",
351                        ExpectedHint{"param: ", "param"});
352 }
353 
354 TEST(ParameterHints, VariadicForwardedConstructor) {
355   // Name hint for variadic parameter using std::forward in a constructor call
356   // This prototype of std::forward is sufficient for clang to recognize it
357   assertParameterHints(R"cpp(
358     namespace std { template <typename T> T&& forward(T&); }
359     struct S { S(int a); };
360     template <typename T, typename... Args>
361     T bar(Args&&... args) { return T{std::forward<Args>(args)...}; }
362     void baz() {
363       int b;
364       bar<S>($param[[b]]);
365     }
366   )cpp",
367                        ExpectedHint{"a: ", "param"});
368 }
369 
370 TEST(ParameterHints, VariadicPlainConstructor) {
371   // Name hint for variadic parameter in a constructor call
372   assertParameterHints(R"cpp(
373     struct S { S(int a); };
374     template <typename T, typename... Args>
375     T bar(Args&&... args) { return T{args...}; }
376     void baz() {
377       int b;
378       bar<S>($param[[b]]);
379     }
380   )cpp",
381                        ExpectedHint{"a: ", "param"});
382 }
383 
384 TEST(ParameterHints, VariadicForwardedNewConstructor) {
385   // Name hint for variadic parameter using std::forward in a new expression
386   // This prototype of std::forward is sufficient for clang to recognize it
387   assertParameterHints(R"cpp(
388     namespace std { template <typename T> T&& forward(T&); }
389     struct S { S(int a); };
390     template <typename T, typename... Args>
391     T* bar(Args&&... args) { return new T{std::forward<Args>(args)...}; }
392     void baz() {
393       int b;
394       bar<S>($param[[b]]);
395     }
396   )cpp",
397                        ExpectedHint{"a: ", "param"});
398 }
399 
400 TEST(ParameterHints, VariadicPlainNewConstructor) {
401   // Name hint for variadic parameter in a new expression
402   assertParameterHints(R"cpp(
403     struct S { S(int a); };
404     template <typename T, typename... Args>
405     T* bar(Args&&... args) { return new T{args...}; }
406     void baz() {
407       int b;
408       bar<S>($param[[b]]);
409     }
410   )cpp",
411                        ExpectedHint{"a: ", "param"});
412 }
413 
414 TEST(ParameterHints, VariadicForwarded) {
415   // Name for variadic parameter using std::forward
416   // This prototype of std::forward is sufficient for clang to recognize it
417   assertParameterHints(R"cpp(
418     namespace std { template <typename T> T&& forward(T&); }
419     void foo(int a);
420     template <typename... Args>
421     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
422     void baz() {
423       int b;
424       bar($param[[b]]);
425     }
426   )cpp",
427                        ExpectedHint{"a: ", "param"});
428 }
429 
430 TEST(ParameterHints, VariadicPlain) {
431   // Name hint for variadic parameter
432   assertParameterHints(R"cpp(
433     void foo(int a);
434     template <typename... Args>
435     void bar(Args&&... args) { return foo(args...); }
436     void baz() {
437       bar($param[[42]]);
438     }
439   )cpp",
440                        ExpectedHint{"a: ", "param"});
441 }
442 
443 TEST(ParameterHints, VariadicPlainWithPackFirst) {
444   // Name hint for variadic parameter when the parameter pack is not the last
445   // template parameter
446   assertParameterHints(R"cpp(
447     void foo(int a);
448     template <typename... Args, typename Arg>
449     void bar(Arg, Args&&... args) { return foo(args...); }
450     void baz() {
451       bar(1, $param[[42]]);
452     }
453   )cpp",
454                        ExpectedHint{"a: ", "param"});
455 }
456 
457 TEST(ParameterHints, VariadicSplitTwolevel) {
458   // Name for variadic parameter that involves both head and tail parameters to
459   // deal with.
460   // This prototype of std::forward is sufficient for clang to recognize it
461   assertParameterHints(R"cpp(
462     namespace std { template <typename T> T&& forward(T&); }
463     void baz(int, int b, double);
464     template <typename... Args>
465     void foo(int a, Args&&... args) {
466       return baz(1, std::forward<Args>(args)..., 1.0);
467     }
468     template <typename... Args>
469     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
470     void bazz() {
471       bar($param1[[32]], $param2[[42]]);
472     }
473   )cpp",
474                        ExpectedHint{"a: ", "param1"},
475                        ExpectedHint{"b: ", "param2"});
476 }
477 
478 TEST(ParameterHints, VariadicNameFromSpecialization) {
479   // We don't try to resolve forwarding parameters if the function call uses a
480   // specialization.
481   assertParameterHints(R"cpp(
482     void foo(int a);
483     template <typename... Args>
484     void bar(Args... args) {
485       foo(args...);
486     }
487     template <>
488     void bar<int>(int b);
489     void baz() {
490       bar($param[[42]]);
491     }
492   )cpp",
493                        ExpectedHint{"b: ", "param"});
494 }
495 
496 TEST(ParameterHints, VariadicNameFromSpecializationRecursive) {
497   // We don't try to resolve forwarding parameters inside a forwarding function
498   // call if that function call uses a specialization.
499   assertParameterHints(R"cpp(
500     void foo2(int a);
501     template <typename... Args>
502     void foo(Args... args) {
503       foo2(args...);
504     }
505     template <typename... Args>
506     void bar(Args... args) {
507       foo(args...);
508     }
509     template <>
510     void foo<int>(int b);
511     void baz() {
512       bar($param[[42]]);
513     }
514   )cpp",
515                        ExpectedHint{"b: ", "param"});
516 }
517 
518 TEST(ParameterHints, VariadicOverloaded) {
519   // Name for variadic parameter for an overloaded function with unique number
520   // of parameters.
521   // This prototype of std::forward is sufficient for clang to recognize it
522   assertParameterHints(
523       R"cpp(
524     namespace std { template <typename T> T&& forward(T&); }
525     void baz(int b, int c);
526     void baz(int bb, int cc, int dd);
527     template <typename... Args>
528     void foo(int a, Args&&... args) {
529       return baz(std::forward<Args>(args)...);
530     }
531     template <typename... Args>
532     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
533     void bazz() {
534       bar($param1[[32]], $param2[[42]], $param3[[52]]);
535       bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
536     }
537   )cpp",
538       ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
539       ExpectedHint{"c: ", "param3"}, ExpectedHint{"a: ", "param4"},
540       ExpectedHint{"bb: ", "param5"}, ExpectedHint{"cc: ", "param6"},
541       ExpectedHint{"dd: ", "param7"});
542 }
543 
544 TEST(ParameterHints, VariadicRecursive) {
545   // make_tuple-like recursive variadic call
546   assertParameterHints(
547       R"cpp(
548     void foo();
549 
550     template <typename Head, typename... Tail>
551     void foo(Head head, Tail... tail) {
552       foo(tail...);
553     }
554 
555     template <typename... Args>
556     void bar(Args... args) {
557       foo(args...);
558     }
559 
560     int main() {
561       bar(1, 2, 3);
562     }
563   )cpp");
564 }
565 
566 TEST(ParameterHints, VariadicVarargs) {
567   // variadic call involving varargs (to make sure we don't crash)
568   assertParameterHints(R"cpp(
569     void foo(int fixed, ...);
570     template <typename... Args>
571     void bar(Args&&... args) {
572       foo(args...);
573     }
574 
575     void baz() {
576       bar($fixed[[41]], 42, 43);
577     }
578   )cpp");
579 }
580 
581 TEST(ParameterHints, VariadicTwolevelUnresolved) {
582   // the same setting as VariadicVarargs, only with parameter pack
583   assertParameterHints(R"cpp(
584     template <typename... Args>
585     void foo(int fixed, Args&& ... args);
586     template <typename... Args>
587     void bar(Args&&... args) {
588       foo(args...);
589     }
590 
591     void baz() {
592       bar($fixed[[41]], 42, 43);
593     }
594   )cpp",
595                        ExpectedHint{"fixed: ", "fixed"});
596 }
597 
598 TEST(ParameterHints, VariadicTwoCalls) {
599   // only the first call using the parameter pack should be picked up
600   assertParameterHints(
601       R"cpp(
602     void f1(int a, int b);
603     void f2(int c, int d);
604 
605     bool cond;
606 
607     template <typename... Args>
608     void foo(Args... args) {
609       if (cond) {
610         f1(args...);
611       } else {
612         f2(args...);
613       }
614     }
615 
616     int main() {
617       foo($param1[[1]], $param2[[2]]);
618     }
619   )cpp",
620       ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"});
621 }
622 
623 TEST(ParameterHints, VariadicInfinite) {
624   // infinite recursion should not break clangd
625   assertParameterHints(
626       R"cpp(
627     template <typename... Args>
628     void foo(Args...);
629 
630     template <typename... Args>
631     void bar(Args... args) {
632       foo(args...);
633     }
634 
635     template <typename... Args>
636     void foo(Args... args) {
637       bar(args...);
638     }
639 
640     int main() {
641       foo(1, 2);
642     }
643   )cpp");
644 }
645 
646 TEST(ParameterHints, VariadicDuplicatePack) {
647   // edge cases with multiple adjacent packs should work
648   assertParameterHints(
649       R"cpp(
650     void foo(int a, int b, int c, int);
651 
652     template <typename... Args>
653     void bar(int, Args... args, int d) {
654       foo(args..., d);
655     }
656 
657     template <typename... Args>
658     void baz(Args... args, Args... args2) {
659       bar<Args..., int>(1, args..., args2...);
660     }
661 
662     int main() {
663       baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
664     }
665   )cpp",
666       ExpectedHint{"a: ", "p1"}, ExpectedHint{"b: ", "p2"},
667       ExpectedHint{"c: ", "p3"}, ExpectedHint{"d: ", "p4"});
668 }
669 
670 TEST(ParameterHints, VariadicEmplace) {
671   // emplace-like calls should forward constructor parameters
672   // This prototype of std::forward is sufficient for clang to recognize it
673   assertParameterHints(
674       R"cpp(
675     namespace std { template <typename T> T&& forward(T&); }
676     using size_t = decltype(sizeof(0));
677     void *operator new(size_t, void *);
678     struct S {
679       S(int A);
680       S(int B, int C);
681     };
682     struct alloc {
683       template <typename T>
684       T* allocate();
685       template <typename T, typename... Args>
686       void construct(T* ptr, Args&&... args) {
687         ::new ((void*)ptr) T{std::forward<Args>(args)...};
688       }
689     };
690     template <typename T>
691     struct container {
692       template <typename... Args>
693       void emplace(Args&&... args) {
694         alloc a;
695         auto ptr = a.template allocate<T>();
696         a.construct(ptr, std::forward<Args>(args)...);
697       }
698     };
699     void foo() {
700       container<S> c;
701       c.emplace($param1[[1]]);
702       c.emplace($param2[[2]], $param3[[3]]);
703     }
704   )cpp",
705       ExpectedHint{"A: ", "param1"}, ExpectedHint{"B: ", "param2"},
706       ExpectedHint{"C: ", "param3"});
707 }
708 
709 TEST(ParameterHints, VariadicReferenceHint) {
710   assertParameterHints(R"cpp(
711     void foo(int&);
712     template <typename... Args>
713     void bar(Args... args) { return foo(args...); }
714     void baz() {
715       int a;
716       bar(a);
717       bar(1);
718     }
719   )cpp");
720 }
721 
722 TEST(ParameterHints, VariadicReferenceHintForwardingRef) {
723   assertParameterHints(R"cpp(
724     void foo(int&);
725     template <typename... Args>
726     void bar(Args&&... args) { return foo(args...); }
727     void baz() {
728       int a;
729       bar($param[[a]]);
730       bar(1);
731     }
732   )cpp",
733                        ExpectedHint{"&: ", "param"});
734 }
735 
736 TEST(ParameterHints, VariadicReferenceHintForwardingRefStdForward) {
737   assertParameterHints(R"cpp(
738     namespace std { template <typename T> T&& forward(T&); }
739     void foo(int&);
740     template <typename... Args>
741     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
742     void baz() {
743       int a;
744       bar($param[[a]]);
745     }
746   )cpp",
747                        ExpectedHint{"&: ", "param"});
748 }
749 
750 TEST(ParameterHints, VariadicNoReferenceHintForwardingRefStdForward) {
751   assertParameterHints(R"cpp(
752     namespace std { template <typename T> T&& forward(T&); }
753     void foo(int);
754     template <typename... Args>
755     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
756     void baz() {
757       int a;
758       bar(a);
759       bar(1);
760     }
761   )cpp");
762 }
763 
764 TEST(ParameterHints, VariadicNoReferenceHintUnresolvedForward) {
765   assertParameterHints(R"cpp(
766     template <typename... Args>
767     void foo(Args&&... args);
768     void bar() {
769       int a;
770       foo(a);
771     }
772   )cpp");
773 }
774 
775 TEST(ParameterHints, MatchingNameVariadicForwarded) {
776   // No name hint for variadic parameter with matching name
777   // This prototype of std::forward is sufficient for clang to recognize it
778   assertParameterHints(R"cpp(
779     namespace std { template <typename T> T&& forward(T&); }
780     void foo(int a);
781     template <typename... Args>
782     void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
783     void baz() {
784       int a;
785       bar(a);
786     }
787   )cpp");
788 }
789 
790 TEST(ParameterHints, MatchingNameVariadicPlain) {
791   // No name hint for variadic parameter with matching name
792   assertParameterHints(R"cpp(
793     void foo(int a);
794     template <typename... Args>
795     void bar(Args&&... args) { return foo(args...); }
796     void baz() {
797       int a;
798       bar(a);
799     }
800   )cpp");
801 }
802 
803 TEST(ParameterHints, Operator) {
804   // No hint for operator call with operator syntax.
805   assertParameterHints(R"cpp(
806     struct S {};
807     void operator+(S lhs, S rhs);
808     void bar() {
809       S a, b;
810       a + b;
811     }
812   )cpp");
813 }
814 
815 TEST(ParameterHints, FunctionCallOperator) {
816   assertParameterHints(R"cpp(
817     struct W {
818       void operator()(int x);
819     };
820     struct S : W {
821       using W::operator();
822       static void operator()(int x, int y);
823     };
824     void bar() {
825       auto l1 = [](int x) {};
826       auto l2 = [](int x) static {};
827 
828       S s;
829       s($1[[1]]);
830       s.operator()($2[[1]]);
831       s.operator()($3[[1]], $4[[2]]);
832       S::operator()($5[[1]], $6[[2]]);
833 
834       l1($7[[1]]);
835       l1.operator()($8[[1]]);
836       l2($9[[1]]);
837       l2.operator()($10[[1]]);
838 
839       void (*ptr)(int a, int b) = &S::operator();
840       ptr($11[[1]], $12[[2]]);
841     }
842   )cpp",
843                        ExpectedHint{"x: ", "1"}, ExpectedHint{"x: ", "2"},
844                        ExpectedHint{"x: ", "3"}, ExpectedHint{"y: ", "4"},
845                        ExpectedHint{"x: ", "5"}, ExpectedHint{"y: ", "6"},
846                        ExpectedHint{"x: ", "7"}, ExpectedHint{"x: ", "8"},
847                        ExpectedHint{"x: ", "9"}, ExpectedHint{"x: ", "10"},
848                        ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"});
849 }
850 
851 TEST(ParameterHints, DeducingThis) {
852   assertParameterHints(R"cpp(
853     struct S {
854       template <typename This>
855       auto operator()(this This &&Self, int Param) {
856         return 42;
857       }
858 
859       auto function(this auto &Self, int Param) {
860         return Param;
861       }
862     };
863     void work() {
864       S s;
865       s($1[[42]]);
866       s.function($2[[42]]);
867       S()($3[[42]]);
868       auto lambda = [](this auto &Self, char C) -> void {
869         return Self(C);
870       };
871       lambda($4[['A']]);
872     }
873   )cpp",
874                        ExpectedHint{"Param: ", "1"},
875                        ExpectedHint{"Param: ", "2"},
876                        ExpectedHint{"Param: ", "3"}, ExpectedHint{"C: ", "4"});
877 }
878 
879 TEST(ParameterHints, Macros) {
880   // Handling of macros depends on where the call's argument list comes from.
881 
882   // If it comes from a macro definition, there's nothing to hint
883   // at the invocation site.
884   assertParameterHints(R"cpp(
885     void foo(int param);
886     #define ExpandsToCall() foo(42)
887     void bar() {
888       ExpandsToCall();
889     }
890   )cpp");
891 
892   // The argument expression being a macro invocation shouldn't interfere
893   // with hinting.
894   assertParameterHints(R"cpp(
895     #define PI 3.14
896     void foo(double param);
897     void bar() {
898       foo($param[[PI]]);
899     }
900   )cpp",
901                        ExpectedHint{"param: ", "param"});
902 
903   // If the whole argument list comes from a macro parameter, hint it.
904   assertParameterHints(R"cpp(
905     void abort();
906     #define ASSERT(expr) if (!expr) abort()
907     int foo(int param);
908     void bar() {
909       ASSERT(foo($param[[42]]) == 0);
910     }
911   )cpp",
912                        ExpectedHint{"param: ", "param"});
913 
914   // If the macro expands to multiple arguments, don't hint it.
915   assertParameterHints(R"cpp(
916     void foo(double x, double y);
917     #define CONSTANTS 3.14, 2.72
918     void bar() {
919       foo(CONSTANTS);
920     }
921   )cpp");
922 }
923 
924 TEST(ParameterHints, ConstructorParens) {
925   assertParameterHints(R"cpp(
926     struct S {
927       S(int param);
928     };
929     void bar() {
930       S obj($param[[42]]);
931     }
932   )cpp",
933                        ExpectedHint{"param: ", "param"});
934 }
935 
936 TEST(ParameterHints, ConstructorBraces) {
937   assertParameterHints(R"cpp(
938     struct S {
939       S(int param);
940     };
941     void bar() {
942       S obj{$param[[42]]};
943     }
944   )cpp",
945                        ExpectedHint{"param: ", "param"});
946 }
947 
948 TEST(ParameterHints, ConstructorStdInitList) {
949   // Do not show hints for std::initializer_list constructors.
950   assertParameterHints(R"cpp(
951     namespace std {
952       template <typename E> class initializer_list { const E *a, *b; };
953     }
954     struct S {
955       S(std::initializer_list<int> param);
956     };
957     void bar() {
958       S obj{42, 43};
959     }
960   )cpp");
961 }
962 
963 TEST(ParameterHints, MemberInit) {
964   assertParameterHints(R"cpp(
965     struct S {
966       S(int param);
967     };
968     struct T {
969       S member;
970       T() : member($param[[42]]) {}
971     };
972   )cpp",
973                        ExpectedHint{"param: ", "param"});
974 }
975 
976 TEST(ParameterHints, ImplicitConstructor) {
977   assertParameterHints(R"cpp(
978     struct S {
979       S(int param);
980     };
981     void bar(S);
982     S foo() {
983       // Do not show hint for implicit constructor call in argument.
984       bar(42);
985       // Do not show hint for implicit constructor call in return.
986       return 42;
987     }
988   )cpp");
989 }
990 
991 TEST(ParameterHints, FunctionPointer) {
992   assertParameterHints(
993       R"cpp(
994     void (*f1)(int param);
995     void (__stdcall *f2)(int param);
996     using f3_t = void(*)(int param);
997     f3_t f3;
998     using f4_t = void(__stdcall *)(int param);
999     f4_t f4;
1000     void bar() {
1001       f1($f1[[42]]);
1002       f2($f2[[42]]);
1003       f3($f3[[42]]);
1004       f4($f4[[42]]);
1005     }
1006   )cpp",
1007       ExpectedHint{"param: ", "f1"}, ExpectedHint{"param: ", "f2"},
1008       ExpectedHint{"param: ", "f3"}, ExpectedHint{"param: ", "f4"});
1009 }
1010 
1011 TEST(ParameterHints, ArgMatchesParam) {
1012   assertParameterHints(R"cpp(
1013     void foo(int param);
1014     struct S {
1015       static const int param = 42;
1016     };
1017     void bar() {
1018       int param = 42;
1019       // Do not show redundant "param: param".
1020       foo(param);
1021       // But show it if the argument is qualified.
1022       foo($param[[S::param]]);
1023     }
1024     struct A {
1025       int param;
1026       void bar() {
1027         // Do not show "param: param" for member-expr.
1028         foo(param);
1029       }
1030     };
1031   )cpp",
1032                        ExpectedHint{"param: ", "param"});
1033 }
1034 
1035 TEST(ParameterHints, ArgMatchesParamReference) {
1036   assertParameterHints(R"cpp(
1037     void foo(int& param);
1038     void foo2(const int& param);
1039     void bar() {
1040       int param;
1041       // show reference hint on mutable reference
1042       foo($param[[param]]);
1043       // but not on const reference
1044       foo2(param);
1045     }
1046   )cpp",
1047                        ExpectedHint{"&: ", "param"});
1048 }
1049 
1050 TEST(ParameterHints, LeadingUnderscore) {
1051   assertParameterHints(R"cpp(
1052     void foo(int p1, int _p2, int __p3);
1053     void bar() {
1054       foo($p1[[41]], $p2[[42]], $p3[[43]]);
1055     }
1056   )cpp",
1057                        ExpectedHint{"p1: ", "p1"}, ExpectedHint{"p2: ", "p2"},
1058                        ExpectedHint{"p3: ", "p3"});
1059 }
1060 
1061 TEST(ParameterHints, DependentCalls) {
1062   assertParameterHints(R"cpp(
1063     template <typename T>
1064     void nonmember(T par1);
1065 
1066     template <typename T>
1067     struct A {
1068       void member(T par2);
1069       static void static_member(T par3);
1070     };
1071 
1072     void overload(int anInt);
1073     void overload(double aDouble);
1074 
1075     template <typename T>
1076     struct S {
1077       void bar(A<T> a, T t) {
1078         nonmember($par1[[t]]);
1079         a.member($par2[[t]]);
1080         A<T>::static_member($par3[[t]]);
1081         // We don't want to arbitrarily pick between
1082         // "anInt" or "aDouble", so just show no hint.
1083         overload(T{});
1084       }
1085     };
1086   )cpp",
1087                        ExpectedHint{"par1: ", "par1"},
1088                        ExpectedHint{"par2: ", "par2"},
1089                        ExpectedHint{"par3: ", "par3"});
1090 }
1091 
1092 TEST(ParameterHints, VariadicFunction) {
1093   assertParameterHints(R"cpp(
1094     template <typename... T>
1095     void foo(int fixed, T... variadic);
1096 
1097     void bar() {
1098       foo($fixed[[41]], 42, 43);
1099     }
1100   )cpp",
1101                        ExpectedHint{"fixed: ", "fixed"});
1102 }
1103 
1104 TEST(ParameterHints, VarargsFunction) {
1105   assertParameterHints(R"cpp(
1106     void foo(int fixed, ...);
1107 
1108     void bar() {
1109       foo($fixed[[41]], 42, 43);
1110     }
1111   )cpp",
1112                        ExpectedHint{"fixed: ", "fixed"});
1113 }
1114 
1115 TEST(ParameterHints, CopyOrMoveConstructor) {
1116   // Do not show hint for parameter of copy or move constructor.
1117   assertParameterHints(R"cpp(
1118     struct S {
1119       S();
1120       S(const S& other);
1121       S(S&& other);
1122     };
1123     void bar() {
1124       S a;
1125       S b(a);    // copy
1126       S c(S());  // move
1127     }
1128   )cpp");
1129 }
1130 
1131 TEST(ParameterHints, AggregateInit) {
1132   // FIXME: This is not implemented yet, but it would be a natural
1133   // extension to show member names as hints here.
1134   assertParameterHints(R"cpp(
1135     struct Point {
1136       int x;
1137       int y;
1138     };
1139     void bar() {
1140       Point p{41, 42};
1141     }
1142   )cpp");
1143 }
1144 
1145 TEST(ParameterHints, UserDefinedLiteral) {
1146   // Do not hint call to user-defined literal operator.
1147   assertParameterHints(R"cpp(
1148     long double operator"" _w(long double param);
1149     void bar() {
1150       1.2_w;
1151     }
1152   )cpp");
1153 }
1154 
1155 TEST(ParameterHints, ParamNameComment) {
1156   // Do not hint an argument which already has a comment
1157   // with the parameter name preceding it.
1158   assertParameterHints(R"cpp(
1159     void foo(int param);
1160     void bar() {
1161       foo(/*param*/42);
1162       foo( /* param = */ 42);
1163 #define X 42
1164 #define Y X
1165 #define Z(...) Y
1166       foo(/*param=*/Z(a));
1167       foo($macro[[Z(a)]]);
1168       foo(/* the answer */$param[[42]]);
1169     }
1170   )cpp",
1171                        ExpectedHint{"param: ", "macro"},
1172                        ExpectedHint{"param: ", "param"});
1173 }
1174 
1175 TEST(ParameterHints, SetterFunctions) {
1176   assertParameterHints(R"cpp(
1177     struct S {
1178       void setParent(S* parent);
1179       void set_parent(S* parent);
1180       void setTimeout(int timeoutMillis);
1181       void setTimeoutMillis(int timeout_millis);
1182     };
1183     void bar() {
1184       S s;
1185       // Parameter name matches setter name - omit hint.
1186       s.setParent(nullptr);
1187       // Support snake_case
1188       s.set_parent(nullptr);
1189       // Parameter name may contain extra info - show hint.
1190       s.setTimeout($timeoutMillis[[120]]);
1191       // FIXME: Ideally we'd want to omit this.
1192       s.setTimeoutMillis($timeout_millis[[120]]);
1193     }
1194   )cpp",
1195                        ExpectedHint{"timeoutMillis: ", "timeoutMillis"},
1196                        ExpectedHint{"timeout_millis: ", "timeout_millis"});
1197 }
1198 
1199 TEST(ParameterHints, BuiltinFunctions) {
1200   // This prototype of std::forward is sufficient for clang to recognize it
1201   assertParameterHints(R"cpp(
1202     namespace std { template <typename T> T&& forward(T&); }
1203     void foo() {
1204       int i;
1205       std::forward(i);
1206     }
1207   )cpp");
1208 }
1209 
1210 TEST(ParameterHints, IncludeAtNonGlobalScope) {
1211   Annotations FooInc(R"cpp(
1212     void bar() { foo(42); }
1213   )cpp");
1214   Annotations FooCC(R"cpp(
1215     struct S {
1216       void foo(int param);
1217       #include "foo.inc"
1218     };
1219   )cpp");
1220 
1221   TestWorkspace Workspace;
1222   Workspace.addSource("foo.inc", FooInc.code());
1223   Workspace.addMainFile("foo.cc", FooCC.code());
1224 
1225   auto AST = Workspace.openFile("foo.cc");
1226   ASSERT_TRUE(bool(AST));
1227 
1228   // Ensure the hint for the call in foo.inc is NOT materialized in foo.cc.
1229   EXPECT_EQ(hintsOfKind(*AST, InlayHintKind::Parameter).size(), 0u);
1230 }
1231 
1232 TEST(TypeHints, Smoke) {
1233   assertTypeHints(R"cpp(
1234     auto $waldo[[waldo]] = 42;
1235   )cpp",
1236                   ExpectedHint{": int", "waldo"});
1237 }
1238 
1239 TEST(TypeHints, Decorations) {
1240   assertTypeHints(R"cpp(
1241     int x = 42;
1242     auto* $var1[[var1]] = &x;
1243     auto&& $var2[[var2]] = x;
1244     const auto& $var3[[var3]] = x;
1245   )cpp",
1246                   ExpectedHint{": int *", "var1"},
1247                   ExpectedHint{": int &", "var2"},
1248                   ExpectedHint{": const int &", "var3"});
1249 }
1250 
1251 TEST(TypeHints, DecltypeAuto) {
1252   assertTypeHints(R"cpp(
1253     int x = 42;
1254     int& y = x;
1255     decltype(auto) $z[[z]] = y;
1256   )cpp",
1257                   ExpectedHint{": int &", "z"});
1258 }
1259 
1260 TEST(TypeHints, NoQualifiers) {
1261   assertTypeHints(R"cpp(
1262     namespace A {
1263       namespace B {
1264         struct S1 {};
1265         S1 foo();
1266         auto $x[[x]] = foo();
1267 
1268         struct S2 {
1269           template <typename T>
1270           struct Inner {};
1271         };
1272         S2::Inner<int> bar();
1273         auto $y[[y]] = bar();
1274       }
1275     }
1276   )cpp",
1277                   ExpectedHint{": S1", "x"},
1278                   // FIXME: We want to suppress scope specifiers
1279                   //        here because we are into the whole
1280                   //        brevity thing, but the ElaboratedType
1281                   //        printer does not honor the SuppressScope
1282                   //        flag by design, so we need to extend the
1283                   //        PrintingPolicy to support this use case.
1284                   ExpectedHint{": S2::Inner<int>", "y"});
1285 }
1286 
1287 TEST(TypeHints, Lambda) {
1288   // Do not print something overly verbose like the lambda's location.
1289   // Show hints for init-captures (but not regular captures).
1290   assertTypeHints(R"cpp(
1291     void f() {
1292       int cap = 42;
1293       auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1294         return a + cap + init;
1295       };
1296     }
1297   )cpp",
1298                   ExpectedHint{": (lambda)", "L"},
1299                   ExpectedHint{": int", "init"}, ExpectedHint{"-> int", "ret"});
1300 
1301   // Lambda return hint shown even if no param list.
1302   // (The digraph :> is just a ] that doesn't conflict with the annotations).
1303   assertTypeHints("auto $L[[x]] = <:$ret[[:>]]{return 42;};",
1304                   ExpectedHint{": (lambda)", "L"},
1305                   ExpectedHint{"-> int", "ret"});
1306 }
1307 
1308 // Structured bindings tests.
1309 // Note, we hint the individual bindings, not the aggregate.
1310 
1311 TEST(TypeHints, StructuredBindings_PublicStruct) {
1312   assertTypeHints(R"cpp(
1313     // Struct with public fields.
1314     struct Point {
1315       int x;
1316       int y;
1317     };
1318     Point foo();
1319     auto [$x[[x]], $y[[y]]] = foo();
1320   )cpp",
1321                   ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1322 }
1323 
1324 TEST(TypeHints, StructuredBindings_Array) {
1325   assertTypeHints(R"cpp(
1326     int arr[2];
1327     auto [$x[[x]], $y[[y]]] = arr;
1328   )cpp",
1329                   ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1330 }
1331 
1332 TEST(TypeHints, StructuredBindings_TupleLike) {
1333   assertTypeHints(R"cpp(
1334     // Tuple-like type.
1335     struct IntPair {
1336       int a;
1337       int b;
1338     };
1339     namespace std {
1340       template <typename T>
1341       struct tuple_size {};
1342       template <>
1343       struct tuple_size<IntPair> {
1344         constexpr static unsigned value = 2;
1345       };
1346       template <unsigned I, typename T>
1347       struct tuple_element {};
1348       template <unsigned I>
1349       struct tuple_element<I, IntPair> {
1350         using type = int;
1351       };
1352     }
1353     template <unsigned I>
1354     int get(const IntPair& p) {
1355       if constexpr (I == 0) {
1356         return p.a;
1357       } else if constexpr (I == 1) {
1358         return p.b;
1359       }
1360     }
1361     IntPair bar();
1362     auto [$x[[x]], $y[[y]]] = bar();
1363   )cpp",
1364                   ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1365 }
1366 
1367 TEST(TypeHints, StructuredBindings_NoInitializer) {
1368   assertTypeHints(R"cpp(
1369     // No initializer (ill-formed).
1370     // Do not show useless "NULL TYPE" hint.
1371     auto [x, y];  /*error-ok*/
1372   )cpp");
1373 }
1374 
1375 TEST(TypeHints, InvalidType) {
1376   assertTypeHints(R"cpp(
1377     auto x = (unknown_type)42; /*error-ok*/
1378     auto *y = (unknown_ptr)nullptr;
1379   )cpp");
1380 }
1381 
1382 TEST(TypeHints, ReturnTypeDeduction) {
1383   assertTypeHints(
1384       R"cpp(
1385     auto f1(int x$ret1a[[)]];  // Hint forward declaration too
1386     auto f1(int x$ret1b[[)]] { return x + 1; }
1387 
1388     // Include pointer operators in hint
1389     int s;
1390     auto& f2($ret2[[)]] { return s; }
1391 
1392     // Do not hint `auto` for trailing return type.
1393     auto f3() -> int;
1394 
1395     // Do not hint when a trailing return type is specified.
1396     auto f4() -> auto* { return "foo"; }
1397 
1398     auto f5($noreturn[[)]] {}
1399 
1400     // `auto` conversion operator
1401     struct A {
1402       operator auto($retConv[[)]] { return 42; }
1403     };
1404 
1405     // FIXME: Dependent types do not work yet.
1406     template <typename T>
1407     struct S {
1408       auto method() { return T(); }
1409     };
1410   )cpp",
1411       ExpectedHint{"-> int", "ret1a"}, ExpectedHint{"-> int", "ret1b"},
1412       ExpectedHint{"-> int &", "ret2"}, ExpectedHint{"-> void", "noreturn"},
1413       ExpectedHint{"-> int", "retConv"});
1414 }
1415 
1416 TEST(TypeHints, DependentType) {
1417   assertTypeHints(R"cpp(
1418     template <typename T>
1419     void foo(T arg) {
1420       // The hint would just be "auto" and we can't do any better.
1421       auto var1 = arg.method();
1422       // FIXME: It would be nice to show "T" as the hint.
1423       auto $var2[[var2]] = arg;
1424     }
1425 
1426     template <typename T>
1427     void bar(T arg) {
1428       auto [a, b] = arg;
1429     }
1430   )cpp");
1431 }
1432 
1433 TEST(TypeHints, LongTypeName) {
1434   assertTypeHints(R"cpp(
1435     template <typename, typename, typename>
1436     struct A {};
1437     struct MultipleWords {};
1438     A<MultipleWords, MultipleWords, MultipleWords> foo();
1439     // Omit type hint past a certain length (currently 32)
1440     auto var = foo();
1441   )cpp");
1442 
1443   Config Cfg;
1444   Cfg.InlayHints.TypeNameLimit = 0;
1445   WithContextValue WithCfg(Config::Key, std::move(Cfg));
1446 
1447   assertTypeHints(
1448       R"cpp(
1449     template <typename, typename, typename>
1450     struct A {};
1451     struct MultipleWords {};
1452     A<MultipleWords, MultipleWords, MultipleWords> foo();
1453     // Should have type hint with TypeNameLimit = 0
1454     auto $var[[var]] = foo();
1455   )cpp",
1456       ExpectedHint{": A<MultipleWords, MultipleWords, MultipleWords>", "var"});
1457 }
1458 
1459 TEST(TypeHints, DefaultTemplateArgs) {
1460   assertTypeHints(R"cpp(
1461     template <typename, typename = int>
1462     struct A {};
1463     A<float> foo();
1464     auto $var[[var]] = foo();
1465     A<float> bar[1];
1466     auto [$binding[[value]]] = bar;
1467   )cpp",
1468                   ExpectedHint{": A<float>", "var"},
1469                   ExpectedHint{": A<float>", "binding"});
1470 }
1471 
1472 TEST(DefaultArguments, Smoke) {
1473   Config Cfg;
1474   Cfg.InlayHints.Parameters =
1475       true; // To test interplay of parameters and default parameters
1476   Cfg.InlayHints.DeducedTypes = false;
1477   Cfg.InlayHints.Designators = false;
1478   Cfg.InlayHints.BlockEnd = false;
1479 
1480   Cfg.InlayHints.DefaultArguments = true;
1481   WithContextValue WithCfg(Config::Key, std::move(Cfg));
1482 
1483   const auto *Code = R"cpp(
1484     int foo(int A = 4) { return A; }
1485     int bar(int A, int B = 1, bool C = foo($default1[[)]]) { return A; }
1486     int A = bar($explicit[[2]]$default2[[)]];
1487 
1488     void baz(int = 5) { if (false) baz($unnamed[[)]]; };
1489   )cpp";
1490 
1491   assertHints(InlayHintKind::DefaultArgument, Code,
1492               ExpectedHint{"A: 4", "default1", Left},
1493               ExpectedHint{", B: 1, C: foo()", "default2", Left},
1494               ExpectedHint{"5", "unnamed", Left});
1495 
1496   assertHints(InlayHintKind::Parameter, Code,
1497               ExpectedHint{"A: ", "explicit", Left});
1498 }
1499 
1500 TEST(DefaultArguments, WithoutParameterNames) {
1501   Config Cfg;
1502   Cfg.InlayHints.Parameters = false; // To test just default args this time
1503   Cfg.InlayHints.DeducedTypes = false;
1504   Cfg.InlayHints.Designators = false;
1505   Cfg.InlayHints.BlockEnd = false;
1506 
1507   Cfg.InlayHints.DefaultArguments = true;
1508   WithContextValue WithCfg(Config::Key, std::move(Cfg));
1509 
1510   const auto *Code = R"cpp(
1511     struct Baz {
1512       Baz(float a = 3 //
1513                     + 2);
1514     };
1515     struct Foo {
1516       Foo(int, Baz baz = //
1517               Baz{$abbreviated[[}]]
1518 
1519           //
1520       ) {}
1521     };
1522 
1523     int main() {
1524       Foo foo1(1$paren[[)]];
1525       Foo foo2{2$brace1[[}]];
1526       Foo foo3 = {3$brace2[[}]];
1527       auto foo4 = Foo{4$brace3[[}]];
1528     }
1529   )cpp";
1530 
1531   assertHints(InlayHintKind::DefaultArgument, Code,
1532               ExpectedHint{"...", "abbreviated", Left},
1533               ExpectedHint{", Baz{}", "paren", Left},
1534               ExpectedHint{", Baz{}", "brace1", Left},
1535               ExpectedHint{", Baz{}", "brace2", Left},
1536               ExpectedHint{", Baz{}", "brace3", Left});
1537 
1538   assertHints(InlayHintKind::Parameter, Code);
1539 }
1540 
1541 TEST(TypeHints, Deduplication) {
1542   assertTypeHints(R"cpp(
1543     template <typename T>
1544     void foo() {
1545       auto $var[[var]] = 42;
1546     }
1547     template void foo<int>();
1548     template void foo<float>();
1549   )cpp",
1550                   ExpectedHint{": int", "var"});
1551 }
1552 
1553 TEST(TypeHints, SinglyInstantiatedTemplate) {
1554   assertTypeHints(R"cpp(
1555     auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
1556     int m = x("foo", 3);
1557   )cpp",
1558                   ExpectedHint{": (lambda)", "lambda"},
1559                   ExpectedHint{": const char *", "param"});
1560 
1561   // No hint for packs, or auto params following packs
1562   assertTypeHints(R"cpp(
1563     int x(auto $a[[a]], auto... b, auto c) { return 42; }
1564     int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
1565   )cpp",
1566                   ExpectedHint{": void *", "a"});
1567 }
1568 
1569 TEST(TypeHints, Aliased) {
1570   // Check that we don't crash for functions without a FunctionTypeLoc.
1571   // https://github.com/clangd/clangd/issues/1140
1572   TestTU TU = TestTU::withCode("void foo(void){} extern typeof(foo) foo;");
1573   TU.ExtraArgs.push_back("-xc");
1574   auto AST = TU.build();
1575 
1576   EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
1577 }
1578 
1579 TEST(TypeHints, CallingConvention) {
1580   // Check that we don't crash for lambdas without a FunctionTypeLoc
1581   // https://github.com/clangd/clangd/issues/2223
1582   std::string Code = R"cpp(
1583     void test() {
1584       []() __cdecl {};
1585     }
1586   )cpp";
1587   TestTU TU = TestTU::withCode(Code);
1588   TU.ExtraArgs.push_back("--target=x86_64-w64-mingw32");
1589   TU.PredefineMacros = true; // for the __cdecl
1590   auto AST = TU.build();
1591 
1592   EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
1593 }
1594 
1595 TEST(TypeHints, Decltype) {
1596   assertTypeHints(R"cpp(
1597     $a[[decltype(0)]] a;
1598     $b[[decltype(a)]] b;
1599     const $c[[decltype(0)]] &c = b;
1600 
1601     // Don't show for dependent type
1602     template <class T>
1603     constexpr decltype(T{}) d;
1604 
1605     $e[[decltype(0)]] e();
1606     auto f() -> $f[[decltype(0)]];
1607 
1608     template <class, class> struct Foo;
1609     using G = Foo<$g[[decltype(0)]], float>;
1610 
1611     auto $h[[h]] = $i[[decltype(0)]]{};
1612 
1613     // No crash
1614     /* error-ok */
1615     auto $j[[s]];
1616   )cpp",
1617                   ExpectedHint{": int", "a"}, ExpectedHint{": int", "b"},
1618                   ExpectedHint{": int", "c"}, ExpectedHint{": int", "e"},
1619                   ExpectedHint{": int", "f"}, ExpectedHint{": int", "g"},
1620                   ExpectedHint{": int", "h"}, ExpectedHint{": int", "i"});
1621 }
1622 
1623 TEST(TypeHints, SubstTemplateParameterAliases) {
1624   llvm::StringRef Header = R"cpp(
1625   template <class T> struct allocator {};
1626 
1627   template <class T, class A>
1628   struct vector_base {
1629     using pointer = T*;
1630   };
1631 
1632   template <class T, class A>
1633   struct internal_iterator_type_template_we_dont_expect {};
1634 
1635   struct my_iterator {};
1636 
1637   template <class T, class A = allocator<T>>
1638   struct vector : vector_base<T, A> {
1639     using base = vector_base<T, A>;
1640     typedef T value_type;
1641     typedef base::pointer pointer;
1642     using allocator_type = A;
1643     using size_type = int;
1644     using iterator = internal_iterator_type_template_we_dont_expect<T, A>;
1645     using non_template_iterator = my_iterator;
1646 
1647     value_type& operator[](int index) { return elements[index]; }
1648     const value_type& at(int index) const { return elements[index]; }
1649     pointer data() { return &elements[0]; }
1650     allocator_type get_allocator() { return A(); }
1651     size_type size() const { return 10; }
1652     iterator begin() { return iterator(); }
1653     non_template_iterator end() { return non_template_iterator(); }
1654 
1655     T elements[10];
1656   };
1657   )cpp";
1658 
1659   llvm::StringRef VectorIntPtr = R"cpp(
1660     vector<int *> array;
1661     auto $no_modifier[[x]] = array[3];
1662     auto* $ptr_modifier[[ptr]] = &array[3];
1663     auto& $ref_modifier[[ref]] = array[3];
1664     auto& $at[[immutable]] = array.at(3);
1665 
1666     auto $data[[data]] = array.data();
1667     auto $allocator[[alloc]] = array.get_allocator();
1668     auto $size[[size]] = array.size();
1669     auto $begin[[begin]] = array.begin();
1670     auto $end[[end]] = array.end();
1671   )cpp";
1672 
1673   assertHintsWithHeader(
1674       InlayHintKind::Type, VectorIntPtr, Header,
1675       ExpectedHint{": int *", "no_modifier"},
1676       ExpectedHint{": int **", "ptr_modifier"},
1677       ExpectedHint{": int *&", "ref_modifier"},
1678       ExpectedHint{": int *const &", "at"}, ExpectedHint{": int **", "data"},
1679       ExpectedHint{": allocator<int *>", "allocator"},
1680       ExpectedHint{": size_type", "size"}, ExpectedHint{": iterator", "begin"},
1681       ExpectedHint{": non_template_iterator", "end"});
1682 
1683   llvm::StringRef VectorInt = R"cpp(
1684   vector<int> array;
1685   auto $no_modifier[[by_value]] = array[3];
1686   auto* $ptr_modifier[[ptr]] = &array[3];
1687   auto& $ref_modifier[[ref]] = array[3];
1688   auto& $at[[immutable]] = array.at(3);
1689 
1690   auto $data[[data]] = array.data();
1691   auto $allocator[[alloc]] = array.get_allocator();
1692   auto $size[[size]] = array.size();
1693   auto $begin[[begin]] = array.begin();
1694   auto $end[[end]] = array.end();
1695   )cpp";
1696 
1697   assertHintsWithHeader(
1698       InlayHintKind::Type, VectorInt, Header,
1699       ExpectedHint{": int", "no_modifier"},
1700       ExpectedHint{": int *", "ptr_modifier"},
1701       ExpectedHint{": int &", "ref_modifier"},
1702       ExpectedHint{": const int &", "at"}, ExpectedHint{": int *", "data"},
1703       ExpectedHint{": allocator<int>", "allocator"},
1704       ExpectedHint{": size_type", "size"}, ExpectedHint{": iterator", "begin"},
1705       ExpectedHint{": non_template_iterator", "end"});
1706 
1707   llvm::StringRef TypeAlias = R"cpp(
1708   // If the type alias is not of substituted template parameter type,
1709   // do not show desugared type.
1710   using VeryLongLongTypeName = my_iterator;
1711   using Short = VeryLongLongTypeName;
1712 
1713   auto $short_name[[my_value]] = Short();
1714 
1715   // Same applies with templates.
1716   template <typename T, typename A>
1717   using basic_static_vector = vector<T, A>;
1718   template <typename T>
1719   using static_vector = basic_static_vector<T, allocator<T>>;
1720 
1721   auto $vector_name[[vec]] = static_vector<int>();
1722   )cpp";
1723 
1724   assertHintsWithHeader(InlayHintKind::Type, TypeAlias, Header,
1725                         ExpectedHint{": Short", "short_name"},
1726                         ExpectedHint{": static_vector<int>", "vector_name"});
1727 }
1728 
1729 TEST(DesignatorHints, Basic) {
1730   assertDesignatorHints(R"cpp(
1731     struct S { int x, y, z; };
1732     S s {$x[[1]], $y[[2+2]]};
1733 
1734     int x[] = {$0[[0]], $1[[1]]};
1735   )cpp",
1736                         ExpectedHint{".x=", "x"}, ExpectedHint{".y=", "y"},
1737                         ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"});
1738 }
1739 
1740 TEST(DesignatorHints, Nested) {
1741   assertDesignatorHints(R"cpp(
1742     struct Inner { int x, y; };
1743     struct Outer { Inner a, b; };
1744     Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
1745   )cpp",
1746                         ExpectedHint{".a=", "a"}, ExpectedHint{".x=", "x"},
1747                         ExpectedHint{".y=", "y"}, ExpectedHint{".b.x=", "bx"});
1748 }
1749 
1750 TEST(DesignatorHints, AnonymousRecord) {
1751   assertDesignatorHints(R"cpp(
1752     struct S {
1753       union {
1754         struct {
1755           struct {
1756             int y;
1757           };
1758         } x;
1759       };
1760     };
1761     S s{$xy[[42]]};
1762   )cpp",
1763                         ExpectedHint{".x.y=", "xy"});
1764 }
1765 
1766 TEST(DesignatorHints, Suppression) {
1767   assertDesignatorHints(R"cpp(
1768     struct Point { int a, b, c, d, e, f, g, h; };
1769     Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
1770   )cpp",
1771                         ExpectedHint{".e=", "e"});
1772 }
1773 
1774 TEST(DesignatorHints, StdArray) {
1775   // Designators for std::array should be [0] rather than .__elements[0].
1776   // While technically correct, the designator is useless and horrible to read.
1777   assertDesignatorHints(R"cpp(
1778     template <typename T, int N> struct Array { T __elements[N]; };
1779     Array<int, 2> x = {$0[[0]], $1[[1]]};
1780   )cpp",
1781                         ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"});
1782 }
1783 
1784 TEST(DesignatorHints, OnlyAggregateInit) {
1785   assertDesignatorHints(R"cpp(
1786     struct Copyable { int x; } c;
1787     Copyable d{c};
1788 
1789     struct Constructible { Constructible(int x); };
1790     Constructible x{42};
1791   )cpp" /*no designator hints expected (but param hints!)*/);
1792 }
1793 
1794 TEST(DesignatorHints, NoCrash) {
1795   assertDesignatorHints(R"cpp(
1796     /*error-ok*/
1797     struct A {};
1798     struct Foo {int a; int b;};
1799     void test() {
1800       Foo f{A(), $b[[1]]};
1801     }
1802   )cpp",
1803                         ExpectedHint{".b=", "b"});
1804 }
1805 
1806 TEST(InlayHints, RestrictRange) {
1807   Annotations Code(R"cpp(
1808     auto a = false;
1809     [[auto b = 1;
1810     auto c = '2';]]
1811     auto d = 3.f;
1812   )cpp");
1813   auto AST = TestTU::withCode(Code.code()).build();
1814   EXPECT_THAT(inlayHints(AST, Code.range()),
1815               ElementsAre(labelIs(": int"), labelIs(": char")));
1816 }
1817 
1818 TEST(ParameterHints, PseudoObjectExpr) {
1819   Annotations Code(R"cpp(
1820     struct S {
1821       __declspec(property(get=GetX, put=PutX)) int x[];
1822       int GetX(int y, int z) { return 42 + y; }
1823       void PutX(int) { }
1824 
1825       // This is a PseudoObjectExpression whose syntactic form is a binary
1826       // operator.
1827       void Work(int y) { x = y; } // Not `x = y: y`.
1828     };
1829 
1830     int printf(const char *Format, ...);
1831 
1832     int main() {
1833       S s;
1834       __builtin_dump_struct(&s, printf); // Not `Format: __builtin_dump_struct()`
1835       printf($Param[["Hello, %d"]], 42); // Normal calls are not affected.
1836       // This builds a PseudoObjectExpr, but here it's useful for showing the
1837       // arguments from the semantic form.
1838       return s.x[ $one[[1]] ][ $two[[2]] ]; // `x[y: 1][z: 2]`
1839     }
1840   )cpp");
1841   auto TU = TestTU::withCode(Code.code());
1842   TU.ExtraArgs.push_back("-fms-extensions");
1843   auto AST = TU.build();
1844   EXPECT_THAT(inlayHints(AST, std::nullopt),
1845               ElementsAre(HintMatcher(ExpectedHint{"Format: ", "Param"}, Code),
1846                           HintMatcher(ExpectedHint{"y: ", "one"}, Code),
1847                           HintMatcher(ExpectedHint{"z: ", "two"}, Code)));
1848 }
1849 
1850 TEST(ParameterHints, ArgPacksAndConstructors) {
1851   assertParameterHints(
1852       R"cpp(
1853     struct Foo{ Foo(); Foo(int x); };
1854     void foo(Foo a, int b);
1855     template <typename... Args>
1856     void bar(Args... args) {
1857       foo(args...);
1858     }
1859     template <typename... Args>
1860     void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
1861 
1862     template <typename... Args>
1863     void bax(Args... args) { foo($param3[[{args...}]], args...); }
1864 
1865     void foo() {
1866       bar($param4[[Foo{}]], $param5[[42]]);
1867       bar($param6[[42]], $param7[[42]]);
1868       baz($param8[[42]]);
1869       bax($param9[[42]]);
1870     }
1871   )cpp",
1872       ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
1873       ExpectedHint{"a: ", "param3"}, ExpectedHint{"a: ", "param4"},
1874       ExpectedHint{"b: ", "param5"}, ExpectedHint{"a: ", "param6"},
1875       ExpectedHint{"b: ", "param7"}, ExpectedHint{"x: ", "param8"},
1876       ExpectedHint{"b: ", "param9"});
1877 }
1878 
1879 TEST(ParameterHints, DoesntExpandAllArgs) {
1880   assertParameterHints(
1881       R"cpp(
1882     void foo(int x, int y);
1883     int id(int a, int b, int c);
1884     template <typename... Args>
1885     void bar(Args... args) {
1886       foo(id($param1[[args]], $param2[[1]], $param3[[args]])...);
1887     }
1888     void foo() {
1889       bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1890     }
1891   )cpp",
1892       ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
1893       ExpectedHint{"c: ", "param3"});
1894 }
1895 
1896 TEST(BlockEndHints, Functions) {
1897   assertBlockEndHints(R"cpp(
1898     int foo() {
1899       return 41;
1900     $foo[[}]]
1901 
1902     template<int X>
1903     int bar() {
1904       // No hint for lambda for now
1905       auto f = []() {
1906         return X;
1907       };
1908       return f();
1909     $bar[[}]]
1910 
1911     // No hint because this isn't a definition
1912     int buz();
1913 
1914     struct S{};
1915     bool operator==(S, S) {
1916       return true;
1917     $opEqual[[}]]
1918   )cpp",
1919                       ExpectedHint{" // foo", "foo"},
1920                       ExpectedHint{" // bar", "bar"},
1921                       ExpectedHint{" // operator==", "opEqual"});
1922 }
1923 
1924 TEST(BlockEndHints, Methods) {
1925   assertBlockEndHints(R"cpp(
1926     struct Test {
1927       // No hint because there's no function body
1928       Test() = default;
1929 
1930       ~Test() {
1931       $dtor[[}]]
1932 
1933       void method1() {
1934       $method1[[}]]
1935 
1936       // No hint because this isn't a definition
1937       void method2();
1938 
1939       template <typename T>
1940       void method3() {
1941       $method3[[}]]
1942 
1943       // No hint because this isn't a definition
1944       template <typename T>
1945       void method4();
1946 
1947       Test operator+(int) const {
1948         return *this;
1949       $opIdentity[[}]]
1950 
1951       operator bool() const {
1952         return true;
1953       $opBool[[}]]
1954 
1955       // No hint because there's no function body
1956       operator int() const = delete;
1957     } x;
1958 
1959     void Test::method2() {
1960     $method2[[}]]
1961 
1962     template <typename T>
1963     void Test::method4() {
1964     $method4[[}]]
1965   )cpp",
1966                       ExpectedHint{" // ~Test", "dtor"},
1967                       ExpectedHint{" // method1", "method1"},
1968                       ExpectedHint{" // method3", "method3"},
1969                       ExpectedHint{" // operator+", "opIdentity"},
1970                       ExpectedHint{" // operator bool", "opBool"},
1971                       ExpectedHint{" // Test::method2", "method2"},
1972                       ExpectedHint{" // Test::method4", "method4"});
1973 }
1974 
1975 TEST(BlockEndHints, Namespaces) {
1976   assertBlockEndHints(
1977       R"cpp(
1978     namespace {
1979       void foo();
1980     $anon[[}]]
1981 
1982     namespace ns {
1983       void bar();
1984     $ns[[}]]
1985   )cpp",
1986       ExpectedHint{" // namespace", "anon"},
1987       ExpectedHint{" // namespace ns", "ns"});
1988 }
1989 
1990 TEST(BlockEndHints, Types) {
1991   assertBlockEndHints(
1992       R"cpp(
1993     struct S {
1994     $S[[};]]
1995 
1996     class C {
1997     $C[[};]]
1998 
1999     union U {
2000     $U[[};]]
2001 
2002     enum E1 {
2003     $E1[[};]]
2004 
2005     enum class E2 {
2006     $E2[[};]]
2007   )cpp",
2008       ExpectedHint{" // struct S", "S"}, ExpectedHint{" // class C", "C"},
2009       ExpectedHint{" // union U", "U"}, ExpectedHint{" // enum E1", "E1"},
2010       ExpectedHint{" // enum class E2", "E2"});
2011 }
2012 
2013 TEST(BlockEndHints, If) {
2014   assertBlockEndHints(
2015       R"cpp(
2016     void foo(bool cond) {
2017        if (cond)
2018           ;
2019 
2020        if (cond) {
2021        $simple[[}]]
2022 
2023        if (cond) {
2024        } else {
2025        $ifelse[[}]]
2026 
2027        if (cond) {
2028        } else if (!cond) {
2029        $elseif[[}]]
2030 
2031        if (cond) {
2032        } else {
2033          if (!cond) {
2034          $inner[[}]]
2035        $outer[[}]]
2036 
2037        if (auto X = cond) {
2038        $init[[}]]
2039 
2040        if (int i = 0; i > 10) {
2041        $init_cond[[}]]
2042     } // suppress
2043   )cpp",
2044       ExpectedHint{" // if cond", "simple"},
2045       ExpectedHint{" // if cond", "ifelse"}, ExpectedHint{" // if", "elseif"},
2046       ExpectedHint{" // if !cond", "inner"},
2047       ExpectedHint{" // if cond", "outer"}, ExpectedHint{" // if X", "init"},
2048       ExpectedHint{" // if i > 10", "init_cond"});
2049 }
2050 
2051 TEST(BlockEndHints, Loops) {
2052   assertBlockEndHints(
2053       R"cpp(
2054     void foo() {
2055        while (true)
2056           ;
2057 
2058        while (true) {
2059        $while[[}]]
2060 
2061        do {
2062        } while (true);
2063 
2064        for (;true;) {
2065        $forcond[[}]]
2066 
2067        for (int I = 0; I < 10; ++I) {
2068        $forvar[[}]]
2069 
2070        int Vs[] = {1,2,3};
2071        for (auto V : Vs) {
2072        $foreach[[}]]
2073     } // suppress
2074   )cpp",
2075       ExpectedHint{" // while true", "while"},
2076       ExpectedHint{" // for true", "forcond"},
2077       ExpectedHint{" // for I", "forvar"},
2078       ExpectedHint{" // for V", "foreach"});
2079 }
2080 
2081 TEST(BlockEndHints, Switch) {
2082   assertBlockEndHints(
2083       R"cpp(
2084     void foo(int I) {
2085       switch (I) {
2086         case 0: break;
2087       $switch[[}]]
2088     } // suppress
2089   )cpp",
2090       ExpectedHint{" // switch I", "switch"});
2091 }
2092 
2093 TEST(BlockEndHints, PrintLiterals) {
2094   assertBlockEndHints(
2095       R"cpp(
2096     void foo() {
2097       while ("foo") {
2098       $string[[}]]
2099 
2100       while ("foo but this time it is very long") {
2101       $string_long[[}]]
2102 
2103       while (true) {
2104       $boolean[[}]]
2105 
2106       while (1) {
2107       $integer[[}]]
2108 
2109       while (1.5) {
2110       $float[[}]]
2111     } // suppress
2112   )cpp",
2113       ExpectedHint{" // while \"foo\"", "string"},
2114       ExpectedHint{" // while \"foo but...\"", "string_long"},
2115       ExpectedHint{" // while true", "boolean"},
2116       ExpectedHint{" // while 1", "integer"},
2117       ExpectedHint{" // while 1.5", "float"});
2118 }
2119 
2120 TEST(BlockEndHints, PrintRefs) {
2121   assertBlockEndHints(
2122       R"cpp(
2123     namespace ns {
2124       int Var;
2125       int func();
2126       struct S {
2127         int Field;
2128         int method() const;
2129       }; // suppress
2130     } // suppress
2131     void foo() {
2132       while (ns::Var) {
2133       $var[[}]]
2134 
2135       while (ns::func()) {
2136       $func[[}]]
2137 
2138       while (ns::S{}.Field) {
2139       $field[[}]]
2140 
2141       while (ns::S{}.method()) {
2142       $method[[}]]
2143     } // suppress
2144   )cpp",
2145       ExpectedHint{" // while Var", "var"},
2146       ExpectedHint{" // while func", "func"},
2147       ExpectedHint{" // while Field", "field"},
2148       ExpectedHint{" // while method", "method"});
2149 }
2150 
2151 TEST(BlockEndHints, PrintConversions) {
2152   assertBlockEndHints(
2153       R"cpp(
2154     struct S {
2155       S(int);
2156       S(int, int);
2157       explicit operator bool();
2158     }; // suppress
2159     void foo(int I) {
2160       while (float(I)) {
2161       $convert_primitive[[}]]
2162 
2163       while (S(I)) {
2164       $convert_class[[}]]
2165 
2166       while (S(I, I)) {
2167       $construct_class[[}]]
2168     } // suppress
2169   )cpp",
2170       ExpectedHint{" // while float", "convert_primitive"},
2171       ExpectedHint{" // while S", "convert_class"},
2172       ExpectedHint{" // while S", "construct_class"});
2173 }
2174 
2175 TEST(BlockEndHints, PrintOperators) {
2176   std::string AnnotatedCode = R"cpp(
2177     void foo(Integer I) {
2178       while(++I){
2179       $preinc[[}]]
2180 
2181       while(I++){
2182       $postinc[[}]]
2183 
2184       while(+(I + I)){
2185       $unary_complex[[}]]
2186 
2187       while(I < 0){
2188       $compare[[}]]
2189 
2190       while((I + I) < I){
2191       $lhs_complex[[}]]
2192 
2193       while(I < (I + I)){
2194       $rhs_complex[[}]]
2195 
2196       while((I + I) < (I + I)){
2197       $binary_complex[[}]]
2198     } // suppress
2199   )cpp";
2200 
2201   // We can't store shared expectations in a vector, assertHints uses varargs.
2202   auto AssertExpectedHints = [&](llvm::StringRef Code) {
2203     assertBlockEndHints(Code, ExpectedHint{" // while ++I", "preinc"},
2204                         ExpectedHint{" // while I++", "postinc"},
2205                         ExpectedHint{" // while", "unary_complex"},
2206                         ExpectedHint{" // while I < 0", "compare"},
2207                         ExpectedHint{" // while ... < I", "lhs_complex"},
2208                         ExpectedHint{" // while I < ...", "rhs_complex"},
2209                         ExpectedHint{" // while", "binary_complex"});
2210   };
2211 
2212   // First with built-in operators.
2213   AssertExpectedHints("using Integer = int;" + AnnotatedCode);
2214   // And now with overloading!
2215   AssertExpectedHints(R"cpp(
2216     struct Integer {
2217       explicit operator bool();
2218       Integer operator++();
2219       Integer operator++(int);
2220       Integer operator+(Integer);
2221       Integer operator+();
2222       bool operator<(Integer);
2223       bool operator<(int);
2224     }; // suppress
2225   )cpp" + AnnotatedCode);
2226 }
2227 
2228 TEST(BlockEndHints, TrailingSemicolon) {
2229   assertBlockEndHints(R"cpp(
2230     // The hint is placed after the trailing ';'
2231     struct S1 {
2232     $S1[[}  ;]]
2233 
2234     // The hint is always placed in the same line with the closing '}'.
2235     // So in this case where ';' is missing, it is attached to '}'.
2236     struct S2 {
2237     $S2[[}]]
2238 
2239     ;
2240 
2241     // No hint because only one trailing ';' is allowed
2242     struct S3 {
2243     };;
2244 
2245     // No hint because trailing ';' is only allowed for class/struct/union/enum
2246     void foo() {
2247     };
2248 
2249     // Rare case, but yes we'll have a hint here.
2250     struct {
2251       int x;
2252     $anon[[}]]
2253 
2254     s2;
2255   )cpp",
2256                       ExpectedHint{" // struct S1", "S1"},
2257                       ExpectedHint{" // struct S2", "S2"},
2258                       ExpectedHint{" // struct", "anon"});
2259 }
2260 
2261 TEST(BlockEndHints, TrailingText) {
2262   assertBlockEndHints(R"cpp(
2263     struct S1 {
2264     $S1[[}      ;]]
2265 
2266     // No hint for S2 because of the trailing comment
2267     struct S2 {
2268     }; /* Put anything here */
2269 
2270     struct S3 {
2271       // No hint for S4 because of the trailing source code
2272       struct S4 {
2273       };$S3[[};]]
2274 
2275     // No hint for ns because of the trailing comment
2276     namespace ns {
2277     } // namespace ns
2278   )cpp",
2279                       ExpectedHint{" // struct S1", "S1"},
2280                       ExpectedHint{" // struct S3", "S3"});
2281 }
2282 
2283 TEST(BlockEndHints, Macro) {
2284   assertBlockEndHints(R"cpp(
2285     #define DECL_STRUCT(NAME) struct NAME {
2286     #define RBRACE }
2287 
2288     DECL_STRUCT(S1)
2289     $S1[[};]]
2290 
2291     // No hint because we require a '}'
2292     DECL_STRUCT(S2)
2293     RBRACE;
2294   )cpp",
2295                       ExpectedHint{" // struct S1", "S1"});
2296 }
2297 
2298 TEST(BlockEndHints, PointerToMemberFunction) {
2299   // Do not crash trying to summarize `a->*p`.
2300   assertBlockEndHints(R"cpp(
2301     class A {};
2302     using Predicate = bool(A::*)();
2303     void foo(A* a, Predicate p) {
2304       if ((a->*p)()) {
2305       $ptrmem[[}]]
2306     } // suppress
2307   )cpp",
2308                       ExpectedHint{" // if", "ptrmem"});
2309 }
2310 
2311 // FIXME: Low-hanging fruit where we could omit a type hint:
2312 //  - auto x = TypeName(...);
2313 //  - auto x = (TypeName) (...);
2314 //  - auto x = static_cast<TypeName>(...);  // and other built-in casts
2315 
2316 // Annoyances for which a heuristic is not obvious:
2317 //  - auto x = llvm::dyn_cast<LongTypeName>(y);  // and similar
2318 //  - stdlib algos return unwieldy __normal_iterator<X*, ...> type
2319 //    (For this one, perhaps we should omit type hints that start
2320 //     with a double underscore.)
2321 
2322 } // namespace
2323 } // namespace clangd
2324 } // namespace clang
2325