clang-tools  16.0.0git
InlayHintTests.cpp
Go to the documentation of this file.
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 
21 namespace clang {
22 namespace clangd {
23 
24 llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
25  const InlayHint &Hint) {
26  return Stream << Hint.label << "@" << Hint.range;
27 }
28 
29 namespace {
30 
31 using ::testing::ElementsAre;
32 using ::testing::IsEmpty;
33 
34 std::vector<InlayHint> hintsOfKind(ParsedAST &AST, InlayHintKind Kind) {
35  std::vector<InlayHint> Result;
36  for (auto &Hint : inlayHints(AST, /*RestrictRange=*/llvm::None)) {
37  if (Hint.kind == Kind)
38  Result.push_back(Hint);
39  }
40  return Result;
41 }
42 
43 enum HintSide { Left, Right };
44 
45 struct ExpectedHint {
46  std::string Label;
47  std::string RangeName;
48  HintSide Side = Left;
49 
50  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
51  const ExpectedHint &Hint) {
52  return Stream << Hint.Label << "@$" << Hint.RangeName;
53  }
54 };
55 
56 MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) {
57  llvm::StringRef ExpectedView(Expected.Label);
58  if (arg.label != ExpectedView.trim(" ") ||
59  arg.paddingLeft != ExpectedView.startswith(" ") ||
60  arg.paddingRight != ExpectedView.endswith(" ")) {
61  *result_listener << "label is '" << arg.label << "'";
62  return false;
63  }
64  if (arg.range != Code.range(Expected.RangeName)) {
65  *result_listener << "range is " << llvm::to_string(arg.range) << " but $"
66  << Expected.RangeName << " is "
67  << llvm::to_string(Code.range(Expected.RangeName));
68  return false;
69  }
70  return true;
71 }
72 
73 MATCHER_P(labelIs, Label, "") { return arg.label == Label; }
74 
75 Config noHintsConfig() {
76  Config C;
77  C.InlayHints.Parameters = false;
78  C.InlayHints.DeducedTypes = false;
79  C.InlayHints.Designators = false;
80  return C;
81 }
82 
83 template <typename... ExpectedHints>
84 void assertHints(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
85  ExpectedHints... Expected) {
86  Annotations Source(AnnotatedSource);
87  TestTU TU = TestTU::withCode(Source.code());
88  TU.ExtraArgs.push_back("-std=c++20");
89  auto AST = TU.build();
90 
91  EXPECT_THAT(hintsOfKind(AST, Kind),
92  ElementsAre(HintMatcher(Expected, Source)...));
93  // Sneak in a cross-cutting check that hints are disabled by config.
94  // We'll hit an assertion failure if addInlayHint still gets called.
95  WithContextValue WithCfg(Config::Key, noHintsConfig());
96  EXPECT_THAT(inlayHints(AST, llvm::None), IsEmpty());
97 }
98 
99 // Hack to allow expression-statements operating on parameter packs in C++14.
100 template <typename... T> void ignore(T &&...) {}
101 
102 template <typename... ExpectedHints>
103 void assertParameterHints(llvm::StringRef AnnotatedSource,
104  ExpectedHints... Expected) {
105  ignore(Expected.Side = Left...);
106  assertHints(InlayHintKind::Parameter, AnnotatedSource, Expected...);
107 }
108 
109 template <typename... ExpectedHints>
110 void assertTypeHints(llvm::StringRef AnnotatedSource,
111  ExpectedHints... Expected) {
112  ignore(Expected.Side = Right...);
113  assertHints(InlayHintKind::Type, AnnotatedSource, Expected...);
114 }
115 
116 template <typename... ExpectedHints>
117 void assertDesignatorHints(llvm::StringRef AnnotatedSource,
118  ExpectedHints... Expected) {
119  Config Cfg;
120  Cfg.InlayHints.Designators = true;
121  WithContextValue WithCfg(Config::Key, std::move(Cfg));
122  assertHints(InlayHintKind::Designator, AnnotatedSource, Expected...);
123 }
124 
125 TEST(ParameterHints, Smoke) {
126  assertParameterHints(R"cpp(
127  void foo(int param);
128  void bar() {
129  foo($param[[42]]);
130  }
131  )cpp",
132  ExpectedHint{"param: ", "param"});
133 }
134 
135 TEST(ParameterHints, NoName) {
136  // No hint for anonymous parameter.
137  assertParameterHints(R"cpp(
138  void foo(int);
139  void bar() {
140  foo(42);
141  }
142  )cpp");
143 }
144 
145 TEST(ParameterHints, NoNameConstReference) {
146  // No hint for anonymous const l-value ref parameter.
147  assertParameterHints(R"cpp(
148  void foo(const int&);
149  void bar() {
150  foo(42);
151  }
152  )cpp");
153 }
154 
155 TEST(ParameterHints, NoNameReference) {
156  // Reference hint for anonymous l-value ref parameter.
157  assertParameterHints(R"cpp(
158  void foo(int&);
159  void bar() {
160  int i;
161  foo($param[[i]]);
162  }
163  )cpp",
164  ExpectedHint{"&: ", "param"});
165 }
166 
167 TEST(ParameterHints, NoNameRValueReference) {
168  // No reference hint for anonymous r-value ref parameter.
169  assertParameterHints(R"cpp(
170  void foo(int&&);
171  void bar() {
172  foo(42);
173  }
174  )cpp");
175 }
176 
177 TEST(ParameterHints, NoNameVariadicDeclaration) {
178  // No hint for anonymous variadic parameter
179  assertParameterHints(R"cpp(
180  template <typename... Args>
181  void foo(Args&& ...);
182  void bar() {
183  foo(42);
184  }
185  )cpp");
186 }
187 
188 TEST(ParameterHints, NoNameVariadicForwarded) {
189  // No hint for anonymous variadic parameter
190  // This prototype of std::forward is sufficient for clang to recognize it
191  assertParameterHints(R"cpp(
192  namespace std { template <typename T> T&& forward(T&); }
193  void foo(int);
194  template <typename... Args>
195  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
196  void baz() {
197  bar(42);
198  }
199  )cpp");
200 }
201 
202 TEST(ParameterHints, NoNameVariadicPlain) {
203  // No hint for anonymous variadic parameter
204  assertParameterHints(R"cpp(
205  void foo(int);
206  template <typename... Args>
207  void bar(Args&&... args) { return foo(args...); }
208  void baz() {
209  bar(42);
210  }
211  )cpp");
212 }
213 
214 TEST(ParameterHints, NameInDefinition) {
215  // Parameter name picked up from definition if necessary.
216  assertParameterHints(R"cpp(
217  void foo(int);
218  void bar() {
219  foo($param[[42]]);
220  }
221  void foo(int param) {};
222  )cpp",
223  ExpectedHint{"param: ", "param"});
224 }
225 
226 TEST(ParameterHints, NamePartiallyInDefinition) {
227  // Parameter name picked up from definition if necessary.
228  assertParameterHints(R"cpp(
229  void foo(int, int b);
230  void bar() {
231  foo($param1[[42]], $param2[[42]]);
232  }
233  void foo(int a, int) {};
234  )cpp",
235  ExpectedHint{"a: ", "param1"},
236  ExpectedHint{"b: ", "param2"});
237 }
238 
239 TEST(ParameterHints, NameInDefinitionVariadic) {
240  // Parameter name picked up from definition in a resolved forwarded parameter.
241  assertParameterHints(R"cpp(
242  void foo(int, int);
243  template <typename... Args>
244  void bar(Args... args) {
245  foo(args...);
246  }
247  void baz() {
248  bar($param1[[42]], $param2[[42]]);
249  }
250  void foo(int a, int b) {};
251  )cpp",
252  ExpectedHint{"a: ", "param1"},
253  ExpectedHint{"b: ", "param2"});
254 }
255 
256 TEST(ParameterHints, NameMismatch) {
257  // Prefer name from declaration.
258  assertParameterHints(R"cpp(
259  void foo(int good);
260  void bar() {
261  foo($good[[42]]);
262  }
263  void foo(int bad) {};
264  )cpp",
265  ExpectedHint{"good: ", "good"});
266 }
267 
268 TEST(ParameterHints, NameConstReference) {
269  // Only name hint for const l-value ref parameter.
270  assertParameterHints(R"cpp(
271  void foo(const int& param);
272  void bar() {
273  foo($param[[42]]);
274  }
275  )cpp",
276  ExpectedHint{"param: ", "param"});
277 }
278 
279 TEST(ParameterHints, NameTypeAliasConstReference) {
280  // Only name hint for const l-value ref parameter via type alias.
281  assertParameterHints(R"cpp(
282  using alias = const int&;
283  void foo(alias param);
284  void bar() {
285  int i;
286  foo($param[[i]]);
287  }
288  )cpp",
289  ExpectedHint{"param: ", "param"});
290 }
291 
292 TEST(ParameterHints, NameReference) {
293  // Reference and name hint for l-value ref parameter.
294  assertParameterHints(R"cpp(
295  void foo(int& param);
296  void bar() {
297  int i;
298  foo($param[[i]]);
299  }
300  )cpp",
301  ExpectedHint{"&param: ", "param"});
302 }
303 
304 TEST(ParameterHints, NameTypeAliasReference) {
305  // Reference and name hint for l-value ref parameter via type alias.
306  assertParameterHints(R"cpp(
307  using alias = int&;
308  void foo(alias param);
309  void bar() {
310  int i;
311  foo($param[[i]]);
312  }
313  )cpp",
314  ExpectedHint{"&param: ", "param"});
315 }
316 
317 TEST(ParameterHints, NameRValueReference) {
318  // Only name hint for r-value ref parameter.
319  assertParameterHints(R"cpp(
320  void foo(int&& param);
321  void bar() {
322  foo($param[[42]]);
323  }
324  )cpp",
325  ExpectedHint{"param: ", "param"});
326 }
327 
328 TEST(ParameterHints, VariadicForwardedConstructor) {
329  // Name hint for variadic parameter using std::forward in a constructor call
330  // This prototype of std::forward is sufficient for clang to recognize it
331  assertParameterHints(R"cpp(
332  namespace std { template <typename T> T&& forward(T&); }
333  struct S { S(int a); };
334  template <typename T, typename... Args>
335  T bar(Args&&... args) { return T{std::forward<Args>(args)...}; }
336  void baz() {
337  int b;
338  bar<S>($param[[b]]);
339  }
340  )cpp",
341  ExpectedHint{"a: ", "param"});
342 }
343 
344 TEST(ParameterHints, VariadicPlainConstructor) {
345  // Name hint for variadic parameter in a constructor call
346  assertParameterHints(R"cpp(
347  struct S { S(int a); };
348  template <typename T, typename... Args>
349  T bar(Args&&... args) { return T{args...}; }
350  void baz() {
351  int b;
352  bar<S>($param[[b]]);
353  }
354  )cpp",
355  ExpectedHint{"a: ", "param"});
356 }
357 
358 TEST(ParameterHints, VariadicForwardedNewConstructor) {
359  // Name hint for variadic parameter using std::forward in a new expression
360  // This prototype of std::forward is sufficient for clang to recognize it
361  assertParameterHints(R"cpp(
362  namespace std { template <typename T> T&& forward(T&); }
363  struct S { S(int a); };
364  template <typename T, typename... Args>
365  T* bar(Args&&... args) { return new T{std::forward<Args>(args)...}; }
366  void baz() {
367  int b;
368  bar<S>($param[[b]]);
369  }
370  )cpp",
371  ExpectedHint{"a: ", "param"});
372 }
373 
374 TEST(ParameterHints, VariadicPlainNewConstructor) {
375  // Name hint for variadic parameter in a new expression
376  assertParameterHints(R"cpp(
377  struct S { S(int a); };
378  template <typename T, typename... Args>
379  T* bar(Args&&... args) { return new T{args...}; }
380  void baz() {
381  int b;
382  bar<S>($param[[b]]);
383  }
384  )cpp",
385  ExpectedHint{"a: ", "param"});
386 }
387 
388 TEST(ParameterHints, VariadicForwarded) {
389  // Name for variadic parameter using std::forward
390  // This prototype of std::forward is sufficient for clang to recognize it
391  assertParameterHints(R"cpp(
392  namespace std { template <typename T> T&& forward(T&); }
393  void foo(int a);
394  template <typename... Args>
395  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
396  void baz() {
397  int b;
398  bar($param[[b]]);
399  }
400  )cpp",
401  ExpectedHint{"a: ", "param"});
402 }
403 
404 TEST(ParameterHints, VariadicPlain) {
405  // Name hint for variadic parameter
406  assertParameterHints(R"cpp(
407  void foo(int a);
408  template <typename... Args>
409  void bar(Args&&... args) { return foo(args...); }
410  void baz() {
411  bar($param[[42]]);
412  }
413  )cpp",
414  ExpectedHint{"a: ", "param"});
415 }
416 
417 TEST(ParameterHints, VariadicPlainWithPackFirst) {
418  // Name hint for variadic parameter when the parameter pack is not the last
419  // template parameter
420  assertParameterHints(R"cpp(
421  void foo(int a);
422  template <typename... Args, typename Arg>
423  void bar(Arg, Args&&... args) { return foo(args...); }
424  void baz() {
425  bar(1, $param[[42]]);
426  }
427  )cpp",
428  ExpectedHint{"a: ", "param"});
429 }
430 
431 TEST(ParameterHints, VariadicSplitTwolevel) {
432  // Name for variadic parameter that involves both head and tail parameters to
433  // deal with.
434  // This prototype of std::forward is sufficient for clang to recognize it
435  assertParameterHints(R"cpp(
436  namespace std { template <typename T> T&& forward(T&); }
437  void baz(int, int b, double);
438  template <typename... Args>
439  void foo(int a, Args&&... args) {
440  return baz(1, std::forward<Args>(args)..., 1.0);
441  }
442  template <typename... Args>
443  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
444  void bazz() {
445  bar($param1[[32]], $param2[[42]]);
446  }
447  )cpp",
448  ExpectedHint{"a: ", "param1"},
449  ExpectedHint{"b: ", "param2"});
450 }
451 
452 TEST(ParameterHints, VariadicNameFromSpecialization) {
453  // We don't try to resolve forwarding parameters if the function call uses a
454  // specialization.
455  assertParameterHints(R"cpp(
456  void foo(int a);
457  template <typename... Args>
458  void bar(Args... args) {
459  foo(args...);
460  }
461  template <>
462  void bar<int>(int b);
463  void baz() {
464  bar($param[[42]]);
465  }
466  )cpp",
467  ExpectedHint{"b: ", "param"});
468 }
469 
470 TEST(ParameterHints, VariadicNameFromSpecializationRecursive) {
471  // We don't try to resolve forwarding parameters inside a forwarding function
472  // call if that function call uses a specialization.
473  assertParameterHints(R"cpp(
474  void foo2(int a);
475  template <typename... Args>
476  void foo(Args... args) {
477  foo2(args...);
478  }
479  template <typename... Args>
480  void bar(Args... args) {
481  foo(args...);
482  }
483  template <>
484  void foo<int>(int b);
485  void baz() {
486  bar($param[[42]]);
487  }
488  )cpp",
489  ExpectedHint{"b: ", "param"});
490 }
491 
492 TEST(ParameterHints, VariadicOverloaded) {
493  // Name for variadic parameter for an overloaded function with unique number
494  // of parameters.
495  // This prototype of std::forward is sufficient for clang to recognize it
496  assertParameterHints(
497  R"cpp(
498  namespace std { template <typename T> T&& forward(T&); }
499  void baz(int b, int c);
500  void baz(int bb, int cc, int dd);
501  template <typename... Args>
502  void foo(int a, Args&&... args) {
503  return baz(std::forward<Args>(args)...);
504  }
505  template <typename... Args>
506  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
507  void bazz() {
508  bar($param1[[32]], $param2[[42]], $param3[[52]]);
509  bar($param4[[1]], $param5[[2]], $param6[[3]], $param7[[4]]);
510  }
511  )cpp",
512  ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
513  ExpectedHint{"c: ", "param3"}, ExpectedHint{"a: ", "param4"},
514  ExpectedHint{"bb: ", "param5"}, ExpectedHint{"cc: ", "param6"},
515  ExpectedHint{"dd: ", "param7"});
516 }
517 
518 TEST(ParameterHints, VariadicRecursive) {
519  // make_tuple-like recursive variadic call
520  assertParameterHints(
521  R"cpp(
522  void foo();
523 
524  template <typename Head, typename... Tail>
525  void foo(Head head, Tail... tail) {
526  foo(tail...);
527  }
528 
529  template <typename... Args>
530  void bar(Args... args) {
531  foo(args...);
532  }
533 
534  int main() {
535  bar(1, 2, 3);
536  }
537  )cpp");
538 }
539 
540 TEST(ParameterHints, VariadicVarargs) {
541  // variadic call involving varargs (to make sure we don't crash)
542  assertParameterHints(R"cpp(
543  void foo(int fixed, ...);
544  template <typename... Args>
545  void bar(Args&&... args) {
546  foo(args...);
547  }
548 
549  void baz() {
550  bar($fixed[[41]], 42, 43);
551  }
552  )cpp");
553 }
554 
555 TEST(ParameterHints, VariadicTwolevelUnresolved) {
556  // the same setting as VariadicVarargs, only with parameter pack
557  assertParameterHints(R"cpp(
558  template <typename... Args>
559  void foo(int fixed, Args&& ... args);
560  template <typename... Args>
561  void bar(Args&&... args) {
562  foo(args...);
563  }
564 
565  void baz() {
566  bar($fixed[[41]], 42, 43);
567  }
568  )cpp",
569  ExpectedHint{"fixed: ", "fixed"});
570 }
571 
572 TEST(ParameterHints, VariadicTwoCalls) {
573  // only the first call using the parameter pack should be picked up
574  assertParameterHints(
575  R"cpp(
576  void f1(int a, int b);
577  void f2(int c, int d);
578 
579  bool cond;
580 
581  template <typename... Args>
582  void foo(Args... args) {
583  if (cond) {
584  f1(args...);
585  } else {
586  f2(args...);
587  }
588  }
589 
590  int main() {
591  foo($param1[[1]], $param2[[2]]);
592  }
593  )cpp",
594  ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"});
595 }
596 
597 TEST(ParameterHints, VariadicInfinite) {
598  // infinite recursion should not break clangd
599  assertParameterHints(
600  R"cpp(
601  template <typename... Args>
602  void foo(Args...);
603 
604  template <typename... Args>
605  void bar(Args... args) {
606  foo(args...);
607  }
608 
609  template <typename... Args>
610  void foo(Args... args) {
611  bar(args...);
612  }
613 
614  int main() {
615  foo(1, 2);
616  }
617  )cpp");
618 }
619 
620 TEST(ParameterHints, VariadicDuplicatePack) {
621  // edge cases with multiple adjacent packs should work
622  assertParameterHints(
623  R"cpp(
624  void foo(int a, int b, int c, int);
625 
626  template <typename... Args>
627  void bar(int, Args... args, int d) {
628  foo(args..., d);
629  }
630 
631  template <typename... Args>
632  void baz(Args... args, Args... args2) {
633  bar<Args..., int>(1, args..., args2...);
634  }
635 
636  int main() {
637  baz<int, int>($p1[[1]], $p2[[2]], $p3[[3]], $p4[[4]]);
638  }
639  )cpp",
640  ExpectedHint{"a: ", "p1"}, ExpectedHint{"b: ", "p2"},
641  ExpectedHint{"c: ", "p3"}, ExpectedHint{"d: ", "p4"});
642 }
643 
644 TEST(ParameterHints, VariadicEmplace) {
645  // emplace-like calls should forward constructor parameters
646  // This prototype of std::forward is sufficient for clang to recognize it
647  assertParameterHints(
648  R"cpp(
649  namespace std { template <typename T> T&& forward(T&); }
650  using size_t = decltype(sizeof(0));
651  void *operator new(size_t, void *);
652  struct S {
653  S(int A);
654  S(int B, int C);
655  };
656  struct alloc {
657  template <typename T>
658  T* allocate();
659  template <typename T, typename... Args>
660  void construct(T* ptr, Args&&... args) {
661  ::new ((void*)ptr) T{std::forward<Args>(args)...};
662  }
663  };
664  template <typename T>
665  struct container {
666  template <typename... Args>
667  void emplace(Args&&... args) {
668  alloc a;
669  auto ptr = a.template allocate<T>();
670  a.construct(ptr, std::forward<Args>(args)...);
671  }
672  };
673  void foo() {
674  container<S> c;
675  c.emplace($param1[[1]]);
676  c.emplace($param2[[2]], $param3[[3]]);
677  }
678  )cpp",
679  ExpectedHint{"A: ", "param1"}, ExpectedHint{"B: ", "param2"},
680  ExpectedHint{"C: ", "param3"});
681 }
682 
683 TEST(ParameterHints, VariadicReferenceHint) {
684  assertParameterHints(R"cpp(
685  void foo(int&);
686  template <typename... Args>
687  void bar(Args... args) { return foo(args...); }
688  void baz() {
689  int a;
690  bar(a);
691  bar(1);
692  }
693  )cpp");
694 }
695 
696 TEST(ParameterHints, VariadicReferenceHintForwardingRef) {
697  assertParameterHints(R"cpp(
698  void foo(int&);
699  template <typename... Args>
700  void bar(Args&&... args) { return foo(args...); }
701  void baz() {
702  int a;
703  bar($param[[a]]);
704  bar(1);
705  }
706  )cpp",
707  ExpectedHint{"&: ", "param"});
708 }
709 
710 TEST(ParameterHints, VariadicReferenceHintForwardingRefStdForward) {
711  assertParameterHints(R"cpp(
712  namespace std { template <typename T> T&& forward(T&); }
713  void foo(int&);
714  template <typename... Args>
715  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
716  void baz() {
717  int a;
718  bar($param[[a]]);
719  }
720  )cpp",
721  ExpectedHint{"&: ", "param"});
722 }
723 
724 TEST(ParameterHints, VariadicNoReferenceHintForwardingRefStdForward) {
725  assertParameterHints(R"cpp(
726  namespace std { template <typename T> T&& forward(T&); }
727  void foo(int);
728  template <typename... Args>
729  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
730  void baz() {
731  int a;
732  bar(a);
733  bar(1);
734  }
735  )cpp");
736 }
737 
738 TEST(ParameterHints, VariadicNoReferenceHintUnresolvedForward) {
739  assertParameterHints(R"cpp(
740  template <typename... Args>
741  void foo(Args&&... args);
742  void bar() {
743  int a;
744  foo(a);
745  }
746  )cpp");
747 }
748 
749 TEST(ParameterHints, MatchingNameVariadicForwarded) {
750  // No name hint for variadic parameter with matching name
751  // This prototype of std::forward is sufficient for clang to recognize it
752  assertParameterHints(R"cpp(
753  namespace std { template <typename T> T&& forward(T&); }
754  void foo(int a);
755  template <typename... Args>
756  void bar(Args&&... args) { return foo(std::forward<Args>(args)...); }
757  void baz() {
758  int a;
759  bar(a);
760  }
761  )cpp");
762 }
763 
764 TEST(ParameterHints, MatchingNameVariadicPlain) {
765  // No name hint for variadic parameter with matching name
766  assertParameterHints(R"cpp(
767  void foo(int a);
768  template <typename... Args>
769  void bar(Args&&... args) { return foo(args...); }
770  void baz() {
771  int a;
772  bar(a);
773  }
774  )cpp");
775 }
776 
777 TEST(ParameterHints, Operator) {
778  // No hint for operator call with operator syntax.
779  assertParameterHints(R"cpp(
780  struct S {};
781  void operator+(S lhs, S rhs);
782  void bar() {
783  S a, b;
784  a + b;
785  }
786  )cpp");
787 }
788 
789 TEST(ParameterHints, Macros) {
790  // Handling of macros depends on where the call's argument list comes from.
791 
792  // If it comes from a macro definition, there's nothing to hint
793  // at the invocation site.
794  assertParameterHints(R"cpp(
795  void foo(int param);
796  #define ExpandsToCall() foo(42)
797  void bar() {
798  ExpandsToCall();
799  }
800  )cpp");
801 
802  // The argument expression being a macro invocation shouldn't interfere
803  // with hinting.
804  assertParameterHints(R"cpp(
805  #define PI 3.14
806  void foo(double param);
807  void bar() {
808  foo($param[[PI]]);
809  }
810  )cpp",
811  ExpectedHint{"param: ", "param"});
812 
813  // If the whole argument list comes from a macro parameter, hint it.
814  assertParameterHints(R"cpp(
815  void abort();
816  #define ASSERT(expr) if (!expr) abort()
817  int foo(int param);
818  void bar() {
819  ASSERT(foo($param[[42]]) == 0);
820  }
821  )cpp",
822  ExpectedHint{"param: ", "param"});
823 
824  // If the macro expands to multiple arguments, don't hint it.
825  assertParameterHints(R"cpp(
826  void foo(double x, double y);
827  #define CONSTANTS 3.14, 2.72
828  void bar() {
829  foo(CONSTANTS);
830  }
831  )cpp");
832 }
833 
834 TEST(ParameterHints, ConstructorParens) {
835  assertParameterHints(R"cpp(
836  struct S {
837  S(int param);
838  };
839  void bar() {
840  S obj($param[[42]]);
841  }
842  )cpp",
843  ExpectedHint{"param: ", "param"});
844 }
845 
846 TEST(ParameterHints, ConstructorBraces) {
847  assertParameterHints(R"cpp(
848  struct S {
849  S(int param);
850  };
851  void bar() {
852  S obj{$param[[42]]};
853  }
854  )cpp",
855  ExpectedHint{"param: ", "param"});
856 }
857 
858 TEST(ParameterHints, ConstructorStdInitList) {
859  // Do not show hints for std::initializer_list constructors.
860  assertParameterHints(R"cpp(
861  namespace std {
862  template <typename> class initializer_list {};
863  }
864  struct S {
865  S(std::initializer_list<int> param);
866  };
867  void bar() {
868  S obj{42, 43};
869  }
870  )cpp");
871 }
872 
873 TEST(ParameterHints, MemberInit) {
874  assertParameterHints(R"cpp(
875  struct S {
876  S(int param);
877  };
878  struct T {
879  S member;
880  T() : member($param[[42]]) {}
881  };
882  )cpp",
883  ExpectedHint{"param: ", "param"});
884 }
885 
886 TEST(ParameterHints, ImplicitConstructor) {
887  assertParameterHints(R"cpp(
888  struct S {
889  S(int param);
890  };
891  void bar(S);
892  S foo() {
893  // Do not show hint for implicit constructor call in argument.
894  bar(42);
895  // Do not show hint for implicit constructor call in return.
896  return 42;
897  }
898  )cpp");
899 }
900 
901 TEST(ParameterHints, ArgMatchesParam) {
902  assertParameterHints(R"cpp(
903  void foo(int param);
904  struct S {
905  static const int param = 42;
906  };
907  void bar() {
908  int param = 42;
909  // Do not show redundant "param: param".
910  foo(param);
911  // But show it if the argument is qualified.
912  foo($param[[S::param]]);
913  }
914  struct A {
915  int param;
916  void bar() {
917  // Do not show "param: param" for member-expr.
918  foo(param);
919  }
920  };
921  )cpp",
922  ExpectedHint{"param: ", "param"});
923 }
924 
925 TEST(ParameterHints, ArgMatchesParamReference) {
926  assertParameterHints(R"cpp(
927  void foo(int& param);
928  void foo2(const int& param);
929  void bar() {
930  int param;
931  // show reference hint on mutable reference
932  foo($param[[param]]);
933  // but not on const reference
934  foo2(param);
935  }
936  )cpp",
937  ExpectedHint{"&: ", "param"});
938 }
939 
940 TEST(ParameterHints, LeadingUnderscore) {
941  assertParameterHints(R"cpp(
942  void foo(int p1, int _p2, int __p3);
943  void bar() {
944  foo($p1[[41]], $p2[[42]], $p3[[43]]);
945  }
946  )cpp",
947  ExpectedHint{"p1: ", "p1"}, ExpectedHint{"p2: ", "p2"},
948  ExpectedHint{"p3: ", "p3"});
949 }
950 
951 TEST(ParameterHints, DependentCalls) {
952  assertParameterHints(R"cpp(
953  template <typename T>
954  void nonmember(T par1);
955 
956  template <typename T>
957  struct A {
958  void member(T par2);
959  static void static_member(T par3);
960  };
961 
962  void overload(int anInt);
963  void overload(double aDouble);
964 
965  template <typename T>
966  struct S {
967  void bar(A<T> a, T t) {
968  nonmember($par1[[t]]);
969  a.member($par2[[t]]);
970  A<T>::static_member($par3[[t]]);
971  // We don't want to arbitrarily pick between
972  // "anInt" or "aDouble", so just show no hint.
973  overload(T{});
974  }
975  };
976  )cpp",
977  ExpectedHint{"par1: ", "par1"},
978  ExpectedHint{"par2: ", "par2"},
979  ExpectedHint{"par3: ", "par3"});
980 }
981 
982 TEST(ParameterHints, VariadicFunction) {
983  assertParameterHints(R"cpp(
984  template <typename... T>
985  void foo(int fixed, T... variadic);
986 
987  void bar() {
988  foo($fixed[[41]], 42, 43);
989  }
990  )cpp",
991  ExpectedHint{"fixed: ", "fixed"});
992 }
993 
994 TEST(ParameterHints, VarargsFunction) {
995  assertParameterHints(R"cpp(
996  void foo(int fixed, ...);
997 
998  void bar() {
999  foo($fixed[[41]], 42, 43);
1000  }
1001  )cpp",
1002  ExpectedHint{"fixed: ", "fixed"});
1003 }
1004 
1005 TEST(ParameterHints, CopyOrMoveConstructor) {
1006  // Do not show hint for parameter of copy or move constructor.
1007  assertParameterHints(R"cpp(
1008  struct S {
1009  S();
1010  S(const S& other);
1011  S(S&& other);
1012  };
1013  void bar() {
1014  S a;
1015  S b(a); // copy
1016  S c(S()); // move
1017  }
1018  )cpp");
1019 }
1020 
1021 TEST(ParameterHints, AggregateInit) {
1022  // FIXME: This is not implemented yet, but it would be a natural
1023  // extension to show member names as hints here.
1024  assertParameterHints(R"cpp(
1025  struct Point {
1026  int x;
1027  int y;
1028  };
1029  void bar() {
1030  Point p{41, 42};
1031  }
1032  )cpp");
1033 }
1034 
1035 TEST(ParameterHints, UserDefinedLiteral) {
1036  // Do not hint call to user-defined literal operator.
1037  assertParameterHints(R"cpp(
1038  long double operator"" _w(long double param);
1039  void bar() {
1040  1.2_w;
1041  }
1042  )cpp");
1043 }
1044 
1045 TEST(ParameterHints, ParamNameComment) {
1046  // Do not hint an argument which already has a comment
1047  // with the parameter name preceding it.
1048  assertParameterHints(R"cpp(
1049  void foo(int param);
1050  void bar() {
1051  foo(/*param*/42);
1052  foo( /* param = */ 42);
1053  foo(/* the answer */$param[[42]]);
1054  }
1055  )cpp",
1056  ExpectedHint{"param: ", "param"});
1057 }
1058 
1059 TEST(ParameterHints, SetterFunctions) {
1060  assertParameterHints(R"cpp(
1061  struct S {
1062  void setParent(S* parent);
1063  void set_parent(S* parent);
1064  void setTimeout(int timeoutMillis);
1065  void setTimeoutMillis(int timeout_millis);
1066  };
1067  void bar() {
1068  S s;
1069  // Parameter name matches setter name - omit hint.
1070  s.setParent(nullptr);
1071  // Support snake_case
1072  s.set_parent(nullptr);
1073  // Parameter name may contain extra info - show hint.
1074  s.setTimeout($timeoutMillis[[120]]);
1075  // FIXME: Ideally we'd want to omit this.
1076  s.setTimeoutMillis($timeout_millis[[120]]);
1077  }
1078  )cpp",
1079  ExpectedHint{"timeoutMillis: ", "timeoutMillis"},
1080  ExpectedHint{"timeout_millis: ", "timeout_millis"});
1081 }
1082 
1083 TEST(ParameterHints, BuiltinFunctions) {
1084  // This prototype of std::forward is sufficient for clang to recognize it
1085  assertParameterHints(R"cpp(
1086  namespace std { template <typename T> T&& forward(T&); }
1087  void foo() {
1088  int i;
1089  std::forward(i);
1090  }
1091  )cpp");
1092 }
1093 
1094 TEST(ParameterHints, IncludeAtNonGlobalScope) {
1095  Annotations FooInc(R"cpp(
1096  void bar() { foo(42); }
1097  )cpp");
1098  Annotations FooCC(R"cpp(
1099  struct S {
1100  void foo(int param);
1101  #include "foo.inc"
1102  };
1103  )cpp");
1104 
1105  TestWorkspace Workspace;
1106  Workspace.addSource("foo.inc", FooInc.code());
1107  Workspace.addMainFile("foo.cc", FooCC.code());
1108 
1109  auto AST = Workspace.openFile("foo.cc");
1110  ASSERT_TRUE(bool(AST));
1111 
1112  // Ensure the hint for the call in foo.inc is NOT materialized in foo.cc.
1113  EXPECT_EQ(hintsOfKind(*AST, InlayHintKind::Parameter).size(), 0u);
1114 }
1115 
1116 TEST(TypeHints, Smoke) {
1117  assertTypeHints(R"cpp(
1118  auto $waldo[[waldo]] = 42;
1119  )cpp",
1120  ExpectedHint{": int", "waldo"});
1121 }
1122 
1123 TEST(TypeHints, Decorations) {
1124  assertTypeHints(R"cpp(
1125  int x = 42;
1126  auto* $var1[[var1]] = &x;
1127  auto&& $var2[[var2]] = x;
1128  const auto& $var3[[var3]] = x;
1129  )cpp",
1130  ExpectedHint{": int *", "var1"},
1131  ExpectedHint{": int &", "var2"},
1132  ExpectedHint{": const int &", "var3"});
1133 }
1134 
1135 TEST(TypeHints, DecltypeAuto) {
1136  assertTypeHints(R"cpp(
1137  int x = 42;
1138  int& y = x;
1139  decltype(auto) $z[[z]] = y;
1140  )cpp",
1141  ExpectedHint{": int &", "z"});
1142 }
1143 
1144 TEST(TypeHints, NoQualifiers) {
1145  assertTypeHints(R"cpp(
1146  namespace A {
1147  namespace B {
1148  struct S1 {};
1149  S1 foo();
1150  auto $x[[x]] = foo();
1151 
1152  struct S2 {
1153  template <typename T>
1154  struct Inner {};
1155  };
1156  S2::Inner<int> bar();
1157  auto $y[[y]] = bar();
1158  }
1159  }
1160  )cpp",
1161  ExpectedHint{": S1", "x"},
1162  // FIXME: We want to suppress scope specifiers
1163  // here because we are into the whole
1164  // brevity thing, but the ElaboratedType
1165  // printer does not honor the SuppressScope
1166  // flag by design, so we need to extend the
1167  // PrintingPolicy to support this use case.
1168  ExpectedHint{": S2::Inner<int>", "y"});
1169 }
1170 
1171 TEST(TypeHints, Lambda) {
1172  // Do not print something overly verbose like the lambda's location.
1173  // Show hints for init-captures (but not regular captures).
1174  assertTypeHints(R"cpp(
1175  void f() {
1176  int cap = 42;
1177  auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
1178  return a + cap + init;
1179  };
1180  }
1181  )cpp",
1182  ExpectedHint{": (lambda)", "L"},
1183  ExpectedHint{": int", "init"}, ExpectedHint{"-> int", "ret"});
1184 
1185  // Lambda return hint shown even if no param list.
1186  // (The digraph :> is just a ] that doesn't conflict with the annotations).
1187  assertTypeHints("auto $L[[x]] = <:$ret[[:>]]{return 42;};",
1188  ExpectedHint{": (lambda)", "L"},
1189  ExpectedHint{"-> int", "ret"});
1190 }
1191 
1192 // Structured bindings tests.
1193 // Note, we hint the individual bindings, not the aggregate.
1194 
1195 TEST(TypeHints, StructuredBindings_PublicStruct) {
1196  assertTypeHints(R"cpp(
1197  // Struct with public fields.
1198  struct Point {
1199  int x;
1200  int y;
1201  };
1202  Point foo();
1203  auto [$x[[x]], $y[[y]]] = foo();
1204  )cpp",
1205  ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1206 }
1207 
1208 TEST(TypeHints, StructuredBindings_Array) {
1209  assertTypeHints(R"cpp(
1210  int arr[2];
1211  auto [$x[[x]], $y[[y]]] = arr;
1212  )cpp",
1213  ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1214 }
1215 
1216 TEST(TypeHints, StructuredBindings_TupleLike) {
1217  assertTypeHints(R"cpp(
1218  // Tuple-like type.
1219  struct IntPair {
1220  int a;
1221  int b;
1222  };
1223  namespace std {
1224  template <typename T>
1225  struct tuple_size {};
1226  template <>
1227  struct tuple_size<IntPair> {
1228  constexpr static unsigned value = 2;
1229  };
1230  template <unsigned I, typename T>
1231  struct tuple_element {};
1232  template <unsigned I>
1233  struct tuple_element<I, IntPair> {
1234  using type = int;
1235  };
1236  }
1237  template <unsigned I>
1238  int get(const IntPair& p) {
1239  if constexpr (I == 0) {
1240  return p.a;
1241  } else if constexpr (I == 1) {
1242  return p.b;
1243  }
1244  }
1245  IntPair bar();
1246  auto [$x[[x]], $y[[y]]] = bar();
1247  )cpp",
1248  ExpectedHint{": int", "x"}, ExpectedHint{": int", "y"});
1249 }
1250 
1251 TEST(TypeHints, StructuredBindings_NoInitializer) {
1252  assertTypeHints(R"cpp(
1253  // No initializer (ill-formed).
1254  // Do not show useless "NULL TYPE" hint.
1255  auto [x, y]; /*error-ok*/
1256  )cpp");
1257 }
1258 
1259 TEST(TypeHints, ReturnTypeDeduction) {
1260  assertTypeHints(
1261  R"cpp(
1262  auto f1(int x$ret1a[[)]]; // Hint forward declaration too
1263  auto f1(int x$ret1b[[)]] { return x + 1; }
1264 
1265  // Include pointer operators in hint
1266  int s;
1267  auto& f2($ret2[[)]] { return s; }
1268 
1269  // Do not hint `auto` for trailing return type.
1270  auto f3() -> int;
1271 
1272  // Do not hint when a trailing return type is specified.
1273  auto f4() -> auto* { return "foo"; }
1274 
1275  auto f5($noreturn[[)]] {}
1276 
1277  // `auto` conversion operator
1278  struct A {
1279  operator auto($retConv[[)]] { return 42; }
1280  };
1281 
1282  // FIXME: Dependent types do not work yet.
1283  template <typename T>
1284  struct S {
1285  auto method() { return T(); }
1286  };
1287  )cpp",
1288  ExpectedHint{"-> int", "ret1a"}, ExpectedHint{"-> int", "ret1b"},
1289  ExpectedHint{"-> int &", "ret2"}, ExpectedHint{"-> void", "noreturn"},
1290  ExpectedHint{"-> int", "retConv"});
1291 }
1292 
1293 TEST(TypeHints, DependentType) {
1294  assertTypeHints(R"cpp(
1295  template <typename T>
1296  void foo(T arg) {
1297  // The hint would just be "auto" and we can't do any better.
1298  auto var1 = arg.method();
1299  // FIXME: It would be nice to show "T" as the hint.
1300  auto $var2[[var2]] = arg;
1301  }
1302  )cpp");
1303 }
1304 
1305 TEST(TypeHints, LongTypeName) {
1306  assertTypeHints(R"cpp(
1307  template <typename, typename, typename>
1308  struct A {};
1309  struct MultipleWords {};
1310  A<MultipleWords, MultipleWords, MultipleWords> foo();
1311  // Omit type hint past a certain length (currently 32)
1312  auto var = foo();
1313  )cpp");
1314 }
1315 
1316 TEST(TypeHints, DefaultTemplateArgs) {
1317  assertTypeHints(R"cpp(
1318  template <typename, typename = int>
1319  struct A {};
1320  A<float> foo();
1321  auto $var[[var]] = foo();
1322  )cpp",
1323  ExpectedHint{": A<float>", "var"});
1324 }
1325 
1326 TEST(TypeHints, Deduplication) {
1327  assertTypeHints(R"cpp(
1328  template <typename T>
1329  void foo() {
1330  auto $var[[var]] = 42;
1331  }
1332  template void foo<int>();
1333  template void foo<float>();
1334  )cpp",
1335  ExpectedHint{": int", "var"});
1336 }
1337 
1338 TEST(TypeHints, SinglyInstantiatedTemplate) {
1339  assertTypeHints(R"cpp(
1340  auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
1341  int m = x("foo", 3);
1342  )cpp",
1343  ExpectedHint{": (lambda)", "lambda"},
1344  ExpectedHint{": const char *", "param"});
1345 
1346  // No hint for packs, or auto params following packs
1347  assertTypeHints(R"cpp(
1348  int x(auto $a[[a]], auto... b, auto c) { return 42; }
1349  int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
1350  )cpp",
1351  ExpectedHint{": void *", "a"});
1352 }
1353 
1354 TEST(TypeHints, Aliased) {
1355  // Check that we don't crash for functions without a FunctionTypeLoc.
1356  // https://github.com/clangd/clangd/issues/1140
1357  TestTU TU = TestTU::withCode("void foo(void){} extern typeof(foo) foo;");
1358  TU.ExtraArgs.push_back("-xc");
1359  auto AST = TU.build();
1360 
1361  EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
1362 }
1363 
1364 TEST(DesignatorHints, Basic) {
1365  assertDesignatorHints(R"cpp(
1366  struct S { int x, y, z; };
1367  S s {$x[[1]], $y[[2+2]]};
1368 
1369  int x[] = {$0[[0]], $1[[1]]};
1370  )cpp",
1371  ExpectedHint{".x=", "x"}, ExpectedHint{".y=", "y"},
1372  ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"});
1373 }
1374 
1375 TEST(DesignatorHints, Nested) {
1376  assertDesignatorHints(R"cpp(
1377  struct Inner { int x, y; };
1378  struct Outer { Inner a, b; };
1379  Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
1380  )cpp",
1381  ExpectedHint{".a=", "a"}, ExpectedHint{".x=", "x"},
1382  ExpectedHint{".y=", "y"}, ExpectedHint{".b.x=", "bx"});
1383 }
1384 
1385 TEST(DesignatorHints, AnonymousRecord) {
1386  assertDesignatorHints(R"cpp(
1387  struct S {
1388  union {
1389  struct {
1390  struct {
1391  int y;
1392  };
1393  } x;
1394  };
1395  };
1396  S s{$xy[[42]]};
1397  )cpp",
1398  ExpectedHint{".x.y=", "xy"});
1399 }
1400 
1401 TEST(DesignatorHints, Suppression) {
1402  assertDesignatorHints(R"cpp(
1403  struct Point { int a, b, c, d, e, f, g, h; };
1404  Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
1405  )cpp",
1406  ExpectedHint{".e=", "e"});
1407 }
1408 
1409 TEST(DesignatorHints, StdArray) {
1410  // Designators for std::array should be [0] rather than .__elements[0].
1411  // While technically correct, the designator is useless and horrible to read.
1412  assertDesignatorHints(R"cpp(
1413  template <typename T, int N> struct Array { T __elements[N]; };
1414  Array<int, 2> x = {$0[[0]], $1[[1]]};
1415  )cpp",
1416  ExpectedHint{"[0]=", "0"}, ExpectedHint{"[1]=", "1"});
1417 }
1418 
1419 TEST(DesignatorHints, OnlyAggregateInit) {
1420  assertDesignatorHints(R"cpp(
1421  struct Copyable { int x; } c;
1422  Copyable d{c};
1423 
1424  struct Constructible { Constructible(int x); };
1425  Constructible x{42};
1426  )cpp" /*no designator hints expected (but param hints!)*/);
1427 }
1428 
1429 TEST(DesignatorHints, NoCrash) {
1430  assertDesignatorHints(R"cpp(
1431  /*error-ok*/
1432  struct A {};
1433  struct Foo {int a; int b;};
1434  void test() {
1435  Foo f{A(), $b[[1]]};
1436  }
1437  )cpp", ExpectedHint{".b=", "b"});
1438 }
1439 
1440 TEST(InlayHints, RestrictRange) {
1441  Annotations Code(R"cpp(
1442  auto a = false;
1443  [[auto b = 1;
1444  auto c = '2';]]
1445  auto d = 3.f;
1446  )cpp");
1447  auto AST = TestTU::withCode(Code.code()).build();
1448  EXPECT_THAT(inlayHints(AST, Code.range()),
1449  ElementsAre(labelIs(": int"), labelIs(": char")));
1450 }
1451 
1452 TEST(ParameterHints, ArgPacksAndConstructors) {
1453  assertParameterHints(
1454  R"cpp(
1455  struct Foo{ Foo(); Foo(int x); };
1456  void foo(Foo a, int b);
1457  template <typename... Args>
1458  void bar(Args... args) {
1459  foo(args...);
1460  }
1461  template <typename... Args>
1462  void baz(Args... args) { foo($param1[[Foo{args...}]], $param2[[1]]); }
1463 
1464  template <typename... Args>
1465  void bax(Args... args) { foo($param3[[{args...}]], args...); }
1466 
1467  void foo() {
1468  bar($param4[[Foo{}]], $param5[[42]]);
1469  bar($param6[[42]], $param7[[42]]);
1470  baz($param8[[42]]);
1471  bax($param9[[42]]);
1472  }
1473  )cpp",
1474  ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
1475  ExpectedHint{"a: ", "param3"}, ExpectedHint{"a: ", "param4"},
1476  ExpectedHint{"b: ", "param5"}, ExpectedHint{"a: ", "param6"},
1477  ExpectedHint{"b: ", "param7"}, ExpectedHint{"x: ", "param8"},
1478  ExpectedHint{"b: ", "param9"});
1479 }
1480 
1481 TEST(ParameterHints, DoesntExpandAllArgs) {
1482  assertParameterHints(
1483  R"cpp(
1484  void foo(int x, int y);
1485  int id(int a, int b, int c);
1486  template <typename... Args>
1487  void bar(Args... args) {
1488  foo(id($param1[[args]], $param2[[1]], $param3[[args]])...);
1489  }
1490  void foo() {
1491  bar(1, 2); // FIXME: We could have `bar(a: 1, a: 2)` here.
1492  }
1493  )cpp",
1494  ExpectedHint{"a: ", "param1"}, ExpectedHint{"b: ", "param2"},
1495  ExpectedHint{"c: ", "param3"});
1496 }
1497 // FIXME: Low-hanging fruit where we could omit a type hint:
1498 // - auto x = TypeName(...);
1499 // - auto x = (TypeName) (...);
1500 // - auto x = static_cast<TypeName>(...); // and other built-in casts
1501 
1502 // Annoyances for which a heuristic is not obvious:
1503 // - auto x = llvm::dyn_cast<LongTypeName>(y); // and similar
1504 // - stdlib algos return unwieldy __normal_iterator<X*, ...> type
1505 // (For this one, perhaps we should omit type hints that start
1506 // with a double underscore.)
1507 
1508 } // namespace
1509 } // namespace clangd
1510 } // namespace clang
XRefs.h
clang::clangd::InlayHintKind::Designator
@ Designator
A hint before an element of an aggregate braced initializer list, indicating what it is initializing.
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:750
clang::clangd::InlayHint::label
std::string label
The label of this hint.
Definition: Protocol.h:1599
clang::clangd::MATCHER_P2
MATCHER_P2(hasFlag, Flag, Path, "")
Definition: GlobalCompilationDatabaseTests.cpp:444
Label
std::string Label
Definition: InlayHintTests.cpp:46
clang::tidy::utils::fixit::QualifierPolicy::Right
@ Right
Macros
llvm::DenseSet< FileID > Macros
Definition: IncludeCleaner.cpp:195
clang::clangd::MATCHER_P
MATCHER_P(named, N, "")
Definition: BackgroundIndexTests.cpp:30
clang::clangd::TestTU::build
ParsedAST build() const
Definition: TestTU.cpp:114
Expected
std::vector< const char * > Expected
Definition: PrintASTTests.cpp:26
TestTU.h
Kind
BindArgumentKind Kind
Definition: AvoidBindCheck.cpp:59
TestWorkspace.h
RangeName
std::string RangeName
Definition: InlayHintTests.cpp:47
InlayHints.h
Protocol.h
clang::clangd::ParsedAST::build
static llvm::Optional< ParsedAST > build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble)
Attempts to run Clang and store the parsed AST.
Definition: ParsedAST.cpp:342
clang::clangd::InlayHint
Inlay hint information.
Definition: Protocol.h:1591
clang::tidy::utils::fixit::QualifierPolicy::Left
@ Left
Code
std::string Code
Definition: FindTargetTests.cpp:67
clang::clangd::Config::Designators
bool Designators
Definition: Config.h:141
Config
static cl::opt< std::string > Config("config", cl::desc(R"( Specifies a configuration in YAML/JSON format: -config="{Checks:' *', CheckOptions:{x:y}}" When the value is empty, clang-tidy will attempt to find a file named .clang-tidy for each source file in its parent directories. )"), cl::init(""), cl::cat(ClangTidyCategory))
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:36
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:2217
Annotations.h
Config.h
clang::clangd::InlayHintKind::Type
@ Type
An inlay hint that for a type annotation.
clang::clangd::Config::InlayHints
struct clang::clangd::Config::@8 InlayHints
C
const Criteria C
Definition: FunctionCognitiveComplexityCheck.cpp:93
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::Config::Key
static clangd::Key< Config > Key
Context key which can be used to set the current Config.
Definition: Config.h:48
clang::clangd::inlayHints
std::vector< InlayHint > inlayHints(ParsedAST &AST, llvm::Optional< Range > RestrictRange)
Compute and return inlay hints for a file.
Definition: InlayHints.cpp:700
Side
HintSide Side
Definition: InlayHintTests.cpp:48
clang::clangd::InlayHintKind
InlayHintKind
Inlay hint kinds.
Definition: Protocol.h:1560
clang::clangd::InlayHint::range
Range range
The range of source code to which the hint applies.
Definition: Protocol.h:1624
Context.h
clang::clangd::InlayHintKind::Parameter
@ Parameter
An inlay hint that is for a parameter.