1 //===--- InlayHints.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 "InlayHints.h"
9 #include "Config.h"
10 #include "HeuristicResolver.h"
11 #include "ParsedAST.h"
12 #include "clang/AST/DeclarationName.h"
13 #include "clang/AST/ExprCXX.h"
14 #include "clang/AST/RecursiveASTVisitor.h"
15 #include "clang/Basic/SourceManager.h"
16 #include "llvm/ADT/ScopeExit.h"
17 
18 namespace clang {
19 namespace clangd {
20 namespace {
21 
22 // For now, inlay hints are always anchored at the left or right of their range.
23 enum class HintSide { Left, Right };
24 
25 // Helper class to iterate over the designator names of an aggregate type.
26 //
27 // For an array type, yields [0], [1], [2]...
28 // For aggregate classes, yields null for each base, then .field1, .field2, ...
29 class AggregateDesignatorNames {
30 public:
31   AggregateDesignatorNames(QualType T) {
32     if (!T.isNull()) {
33       T = T.getCanonicalType();
34       if (T->isArrayType()) {
35         IsArray = true;
36         Valid = true;
37         return;
38       }
39       if (const RecordDecl *RD = T->getAsRecordDecl()) {
40         Valid = true;
41         FieldsIt = RD->field_begin();
42         FieldsEnd = RD->field_end();
43         if (const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(RD)) {
44           BasesIt = CRD->bases_begin();
45           BasesEnd = CRD->bases_end();
46           Valid = CRD->isAggregate();
47         }
48         OneField = Valid && BasesIt == BasesEnd && FieldsIt != FieldsEnd &&
49                    std::next(FieldsIt) == FieldsEnd;
50       }
51     }
52   }
53   // Returns false if the type was not an aggregate.
54   operator bool() { return Valid; }
55   // Advance to the next element in the aggregate.
56   void next() {
57     if (IsArray)
58       ++Index;
59     else if (BasesIt != BasesEnd)
60       ++BasesIt;
61     else if (FieldsIt != FieldsEnd)
62       ++FieldsIt;
63   }
64   // Print the designator to Out.
65   // Returns false if we could not produce a designator for this element.
66   bool append(std::string &Out, bool ForSubobject) {
67     if (IsArray) {
68       Out.push_back('[');
69       Out.append(std::to_string(Index));
70       Out.push_back(']');
71       return true;
72     }
73     if (BasesIt != BasesEnd)
74       return false; // Bases can't be designated. Should we make one up?
75     if (FieldsIt != FieldsEnd) {
76       llvm::StringRef FieldName;
77       if (const IdentifierInfo *II = FieldsIt->getIdentifier())
78         FieldName = II->getName();
79 
80       // For certain objects, their subobjects may be named directly.
81       if (ForSubobject &&
82           (FieldsIt->isAnonymousStructOrUnion() ||
83            // std::array<int,3> x = {1,2,3}. Designators not strictly valid!
84            (OneField && isReservedName(FieldName))))
85         return true;
86 
87       if (!FieldName.empty() && !isReservedName(FieldName)) {
88         Out.push_back('.');
89         Out.append(FieldName.begin(), FieldName.end());
90         return true;
91       }
92       return false;
93     }
94     return false;
95   }
96 
97 private:
98   bool Valid = false;
99   bool IsArray = false;
100   bool OneField = false; // e.g. std::array { T __elements[N]; }
101   unsigned Index = 0;
102   CXXRecordDecl::base_class_const_iterator BasesIt;
103   CXXRecordDecl::base_class_const_iterator BasesEnd;
104   RecordDecl::field_iterator FieldsIt;
105   RecordDecl::field_iterator FieldsEnd;
106 };
107 
108 // Collect designator labels describing the elements of an init list.
109 //
110 // This function contributes the designators of some (sub)object, which is
111 // represented by the semantic InitListExpr Sem.
112 // This includes any nested subobjects, but *only* if they are part of the same
113 // original syntactic init list (due to brace elision).
114 // In other words, it may descend into subobjects but not written init-lists.
115 //
116 // For example: struct Outer { Inner a,b; }; struct Inner { int x, y; }
117 //              Outer o{{1, 2}, 3};
118 // This function will be called with Sem = { {1, 2}, {3, ImplicitValue} }
119 // It should generate designators '.a:' and '.b.x:'.
120 // '.a:' is produced directly without recursing into the written sublist.
121 // (The written sublist will have a separate collectDesignators() call later).
122 // Recursion with Prefix='.b' and Sem = {3, ImplicitValue} produces '.b.x:'.
123 void collectDesignators(const InitListExpr *Sem,
124                         llvm::DenseMap<SourceLocation, std::string> &Out,
125                         const llvm::DenseSet<SourceLocation> &NestedBraces,
126                         std::string &Prefix) {
127   if (!Sem || Sem->isTransparent())
128     return;
129   assert(Sem->isSemanticForm());
130 
131   // The elements of the semantic form all correspond to direct subobjects of
132   // the aggregate type. `Fields` iterates over these subobject names.
133   AggregateDesignatorNames Fields(Sem->getType());
134   if (!Fields)
135     return;
136   for (const Expr *Init : Sem->inits()) {
137     auto Next = llvm::make_scope_exit([&, Size(Prefix.size())] {
138       Fields.next();       // Always advance to the next subobject name.
139       Prefix.resize(Size); // Erase any designator we appended.
140     });
141     if (llvm::isa<ImplicitValueInitExpr>(Init))
142       continue; // a "hole" for a subobject that was not explicitly initialized
143 
144     const auto *BraceElidedSubobject = llvm::dyn_cast<InitListExpr>(Init);
145     if (BraceElidedSubobject &&
146         NestedBraces.contains(BraceElidedSubobject->getLBraceLoc()))
147       BraceElidedSubobject = nullptr; // there were braces!
148 
149     if (!Fields.append(Prefix, BraceElidedSubobject != nullptr))
150       continue; // no designator available for this subobject
151     if (BraceElidedSubobject) {
152       // If the braces were elided, this aggregate subobject is initialized
153       // inline in the same syntactic list.
154       // Descend into the semantic list describing the subobject.
155       // (NestedBraces are still correct, they're from the same syntactic list).
156       collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix);
157       continue;
158     }
159     Out.try_emplace(Init->getBeginLoc(), Prefix);
160   }
161 }
162 
163 // Get designators describing the elements of a (syntactic) init list.
164 // This does not produce designators for any explicitly-written nested lists.
165 llvm::DenseMap<SourceLocation, std::string>
166 getDesignators(const InitListExpr *Syn) {
167   assert(Syn->isSyntacticForm());
168 
169   // collectDesignators needs to know which InitListExprs in the semantic tree
170   // were actually written, but InitListExpr::isExplicit() lies.
171   // Instead, record where braces of sub-init-lists occur in the syntactic form.
172   llvm::DenseSet<SourceLocation> NestedBraces;
173   for (const Expr *Init : Syn->inits())
174     if (auto *Nested = llvm::dyn_cast<InitListExpr>(Init))
175       NestedBraces.insert(Nested->getLBraceLoc());
176 
177   // Traverse the semantic form to find the designators.
178   // We use their SourceLocation to correlate with the syntactic form later.
179   llvm::DenseMap<SourceLocation, std::string> Designators;
180   std::string EmptyPrefix;
181   collectDesignators(Syn->isSemanticForm() ? Syn : Syn->getSemanticForm(),
182                      Designators, NestedBraces, EmptyPrefix);
183   return Designators;
184 }
185 
186 class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
187 public:
188   InlayHintVisitor(std::vector<InlayHint> &Results, ParsedAST &AST,
189                    const Config &Cfg, llvm::Optional<Range> RestrictRange)
190       : Results(Results), AST(AST.getASTContext()), Cfg(Cfg),
191         RestrictRange(std::move(RestrictRange)),
192         MainFileID(AST.getSourceManager().getMainFileID()),
193         Resolver(AST.getHeuristicResolver()),
194         TypeHintPolicy(this->AST.getPrintingPolicy()),
195         StructuredBindingPolicy(this->AST.getPrintingPolicy()) {
196     bool Invalid = false;
197     llvm::StringRef Buf =
198         AST.getSourceManager().getBufferData(MainFileID, &Invalid);
199     MainFileBuf = Invalid ? StringRef{} : Buf;
200 
201     TypeHintPolicy.SuppressScope = true; // keep type names short
202     TypeHintPolicy.AnonymousTagLocations =
203         false; // do not print lambda locations
204 
205     // For structured bindings, print canonical types. This is important because
206     // for bindings that use the tuple_element protocol, the non-canonical types
207     // would be "tuple_element<I, A>::type".
208     // For "auto", we often prefer sugared types.
209     // Not setting PrintCanonicalTypes for "auto" allows
210     // SuppressDefaultTemplateArgs (set by default) to have an effect.
211     StructuredBindingPolicy = TypeHintPolicy;
212     StructuredBindingPolicy.PrintCanonicalTypes = true;
213   }
214 
215   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
216     // Weed out constructor calls that don't look like a function call with
217     // an argument list, by checking the validity of getParenOrBraceRange().
218     // Also weed out std::initializer_list constructors as there are no names
219     // for the individual arguments.
220     if (!E->getParenOrBraceRange().isValid() ||
221         E->isStdInitListInitialization()) {
222       return true;
223     }
224 
225     processCall(E->getParenOrBraceRange().getBegin(), E->getConstructor(),
226                 {E->getArgs(), E->getNumArgs()});
227     return true;
228   }
229 
230   bool VisitCallExpr(CallExpr *E) {
231     if (!Cfg.InlayHints.Parameters)
232       return true;
233 
234     // Do not show parameter hints for operator calls written using operator
235     // syntax or user-defined literals. (Among other reasons, the resulting
236     // hints can look awkard, e.g. the expression can itself be a function
237     // argument and then we'd get two hints side by side).
238     if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
239       return true;
240 
241     auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E);
242     if (CalleeDecls.size() != 1)
243       return true;
244     const FunctionDecl *Callee = nullptr;
245     if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecls[0]))
246       Callee = FD;
247     else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CalleeDecls[0]))
248       Callee = FTD->getTemplatedDecl();
249     if (!Callee)
250       return true;
251 
252     processCall(E->getRParenLoc(), Callee, {E->getArgs(), E->getNumArgs()});
253     return true;
254   }
255 
256   bool VisitFunctionDecl(FunctionDecl *D) {
257     if (auto *FPT =
258             llvm::dyn_cast<FunctionProtoType>(D->getType().getTypePtr())) {
259       if (!FPT->hasTrailingReturn())
260         addReturnTypeHint(D, D->getFunctionTypeLoc().getRParenLoc());
261     }
262     return true;
263   }
264 
265   bool VisitLambdaExpr(LambdaExpr *E) {
266     FunctionDecl *D = E->getCallOperator();
267     if (!E->hasExplicitResultType())
268       addReturnTypeHint(D, E->hasExplicitParameters()
269                                ? D->getFunctionTypeLoc().getRParenLoc()
270                                : E->getIntroducerRange().getEnd());
271     return true;
272   }
273 
274   void addReturnTypeHint(FunctionDecl *D, SourceLocation Loc) {
275     auto *AT = D->getReturnType()->getContainedAutoType();
276     if (!AT || AT->getDeducedType().isNull())
277       return;
278     addTypeHint(Loc, D->getReturnType(), /*Prefix=*/"-> ");
279   }
280 
281   bool VisitVarDecl(VarDecl *D) {
282     // Do not show hints for the aggregate in a structured binding,
283     // but show hints for the individual bindings.
284     if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
285       for (auto *Binding : DD->bindings()) {
286         addTypeHint(Binding->getLocation(), Binding->getType(), /*Prefix=*/": ",
287                     StructuredBindingPolicy);
288       }
289       return true;
290     }
291 
292     if (D->getType()->getContainedAutoType()) {
293       if (!D->getType()->isDependentType()) {
294         // Our current approach is to place the hint on the variable
295         // and accordingly print the full type
296         // (e.g. for `const auto& x = 42`, print `const int&`).
297         // Alternatively, we could place the hint on the `auto`
298         // (and then just print the type deduced for the `auto`).
299         addTypeHint(D->getLocation(), D->getType(), /*Prefix=*/": ");
300       }
301     }
302     return true;
303   }
304 
305   bool VisitInitListExpr(InitListExpr *Syn) {
306     // We receive the syntactic form here (shouldVisitImplicitCode() is false).
307     // This is the one we will ultimately attach designators to.
308     // It may have subobject initializers inlined without braces. The *semantic*
309     // form of the init-list has nested init-lists for these.
310     // getDesignators will look at the semantic form to determine the labels.
311     assert(Syn->isSyntacticForm() && "RAV should not visit implicit code!");
312     if (!Cfg.InlayHints.Designators)
313       return true;
314     if (Syn->isIdiomaticZeroInitializer(AST.getLangOpts()))
315       return true;
316     llvm::DenseMap<SourceLocation, std::string> Designators =
317         getDesignators(Syn);
318     for (const Expr *Init : Syn->inits()) {
319       if (llvm::isa<DesignatedInitExpr>(Init))
320         continue;
321       auto It = Designators.find(Init->getBeginLoc());
322       if (It != Designators.end() &&
323           !isPrecededByParamNameComment(Init, It->second))
324         addDesignatorHint(Init->getSourceRange(), It->second);
325     }
326     return true;
327   }
328 
329   // FIXME: Handle RecoveryExpr to try to hint some invalid calls.
330 
331 private:
332   using NameVec = SmallVector<StringRef, 8>;
333 
334   // The purpose of Anchor is to deal with macros. It should be the call's
335   // opening or closing parenthesis or brace. (Always using the opening would
336   // make more sense but CallExpr only exposes the closing.) We heuristically
337   // assume that if this location does not come from a macro definition, then
338   // the entire argument list likely appears in the main file and can be hinted.
339   void processCall(SourceLocation Anchor, const FunctionDecl *Callee,
340                    llvm::ArrayRef<const Expr *const> Args) {
341     if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee)
342       return;
343 
344     // If the anchor location comes from a macro defintion, there's nowhere to
345     // put hints.
346     if (!AST.getSourceManager().getTopMacroCallerLoc(Anchor).isFileID())
347       return;
348 
349     // The parameter name of a move or copy constructor is not very interesting.
350     if (auto *Ctor = dyn_cast<CXXConstructorDecl>(Callee))
351       if (Ctor->isCopyOrMoveConstructor())
352         return;
353 
354     // Don't show hints for variadic parameters.
355     size_t FixedParamCount = getFixedParamCount(Callee);
356     size_t ArgCount = std::min(FixedParamCount, Args.size());
357 
358     NameVec ParameterNames = chooseParameterNames(Callee, ArgCount);
359 
360     // Exclude setters (i.e. functions with one argument whose name begins with
361     // "set"), as their parameter name is also not likely to be interesting.
362     if (isSetter(Callee, ParameterNames))
363       return;
364 
365     for (size_t I = 0; I < ArgCount; ++I) {
366       StringRef Name = ParameterNames[I];
367       if (!shouldHint(Args[I], Name))
368         continue;
369 
370       addInlayHint(Args[I]->getSourceRange(), HintSide::Left,
371                    InlayHintKind::ParameterHint, /*Prefix=*/"", Name,
372                    /*Suffix=*/": ");
373     }
374   }
375 
376   static bool isSetter(const FunctionDecl *Callee, const NameVec &ParamNames) {
377     if (ParamNames.size() != 1)
378       return false;
379 
380     StringRef Name = getSimpleName(*Callee);
381     if (!Name.startswith_insensitive("set"))
382       return false;
383 
384     // In addition to checking that the function has one parameter and its
385     // name starts with "set", also check that the part after "set" matches
386     // the name of the parameter (ignoring case). The idea here is that if
387     // the parameter name differs, it may contain extra information that
388     // may be useful to show in a hint, as in:
389     //   void setTimeout(int timeoutMillis);
390     // This currently doesn't handle cases where params use snake_case
391     // and functions don't, e.g.
392     //   void setExceptionHandler(EHFunc exception_handler);
393     // We could improve this by replacing `equals_insensitive` with some
394     // `sloppy_equals` which ignores case and also skips underscores.
395     StringRef WhatItIsSetting = Name.substr(3).ltrim("_");
396     return WhatItIsSetting.equals_insensitive(ParamNames[0]);
397   }
398 
399   bool shouldHint(const Expr *Arg, StringRef ParamName) {
400     if (ParamName.empty())
401       return false;
402 
403     // If the argument expression is a single name and it matches the
404     // parameter name exactly, omit the hint.
405     if (ParamName == getSpelledIdentifier(Arg))
406       return false;
407 
408     // Exclude argument expressions preceded by a /*paramName*/.
409     if (isPrecededByParamNameComment(Arg, ParamName))
410       return false;
411 
412     return true;
413   }
414 
415   // Checks if "E" is spelled in the main file and preceded by a C-style comment
416   // whose contents match ParamName (allowing for whitespace and an optional "="
417   // at the end.
418   bool isPrecededByParamNameComment(const Expr *E, StringRef ParamName) {
419     auto &SM = AST.getSourceManager();
420     auto ExprStartLoc = SM.getTopMacroCallerLoc(E->getBeginLoc());
421     auto Decomposed = SM.getDecomposedLoc(ExprStartLoc);
422     if (Decomposed.first != MainFileID)
423       return false;
424 
425     StringRef SourcePrefix = MainFileBuf.substr(0, Decomposed.second);
426     // Allow whitespace between comment and expression.
427     SourcePrefix = SourcePrefix.rtrim();
428     // Check for comment ending.
429     if (!SourcePrefix.consume_back("*/"))
430       return false;
431     // Ignore some punctuation and whitespace around comment.
432     // In particular this allows designators to match nicely.
433     llvm::StringLiteral IgnoreChars = " =.";
434     SourcePrefix = SourcePrefix.rtrim(IgnoreChars);
435     ParamName = ParamName.trim(IgnoreChars);
436     // Other than that, the comment must contain exactly ParamName.
437     if (!SourcePrefix.consume_back(ParamName))
438       return false;
439     SourcePrefix = SourcePrefix.rtrim(IgnoreChars);
440     return SourcePrefix.endswith("/*");
441   }
442 
443   // If "E" spells a single unqualified identifier, return that name.
444   // Otherwise, return an empty string.
445   static StringRef getSpelledIdentifier(const Expr *E) {
446     E = E->IgnoreUnlessSpelledInSource();
447 
448     if (auto *DRE = dyn_cast<DeclRefExpr>(E))
449       if (!DRE->getQualifier())
450         return getSimpleName(*DRE->getDecl());
451 
452     if (auto *ME = dyn_cast<MemberExpr>(E))
453       if (!ME->getQualifier() && ME->isImplicitAccess())
454         return getSimpleName(*ME->getMemberDecl());
455 
456     return {};
457   }
458 
459   NameVec chooseParameterNames(const FunctionDecl *Callee, size_t ArgCount) {
460     // The current strategy here is to use all the parameter names from the
461     // canonical declaration, unless they're all empty, in which case we
462     // use all the parameter names from the definition (in present in the
463     // translation unit).
464     // We could try a bit harder, e.g.:
465     //   - try all re-declarations, not just canonical + definition
466     //   - fall back arg-by-arg rather than wholesale
467 
468     NameVec ParameterNames = getParameterNamesForDecl(Callee, ArgCount);
469 
470     if (llvm::all_of(ParameterNames, std::mem_fn(&StringRef::empty))) {
471       if (const FunctionDecl *Def = Callee->getDefinition()) {
472         ParameterNames = getParameterNamesForDecl(Def, ArgCount);
473       }
474     }
475     assert(ParameterNames.size() == ArgCount);
476 
477     // Standard library functions often have parameter names that start
478     // with underscores, which makes the hints noisy, so strip them out.
479     for (auto &Name : ParameterNames)
480       stripLeadingUnderscores(Name);
481 
482     return ParameterNames;
483   }
484 
485   static void stripLeadingUnderscores(StringRef &Name) {
486     Name = Name.ltrim('_');
487   }
488 
489   // Return the number of fixed parameters Function has, that is, not counting
490   // parameters that are variadic (instantiated from a parameter pack) or
491   // C-style varargs.
492   static size_t getFixedParamCount(const FunctionDecl *Function) {
493     if (FunctionTemplateDecl *Template = Function->getPrimaryTemplate()) {
494       FunctionDecl *F = Template->getTemplatedDecl();
495       size_t Result = 0;
496       for (ParmVarDecl *Parm : F->parameters()) {
497         if (Parm->isParameterPack()) {
498           break;
499         }
500         ++Result;
501       }
502       return Result;
503     }
504     // C-style varargs don't need special handling, they're already
505     // not included in getNumParams().
506     return Function->getNumParams();
507   }
508 
509   static StringRef getSimpleName(const NamedDecl &D) {
510     if (IdentifierInfo *Ident = D.getDeclName().getAsIdentifierInfo()) {
511       return Ident->getName();
512     }
513 
514     return StringRef();
515   }
516 
517   NameVec getParameterNamesForDecl(const FunctionDecl *Function,
518                                    size_t ArgCount) {
519     NameVec Result;
520     for (size_t I = 0; I < ArgCount; ++I) {
521       const ParmVarDecl *Parm = Function->getParamDecl(I);
522       assert(Parm);
523       Result.emplace_back(getSimpleName(*Parm));
524     }
525     return Result;
526   }
527 
528   // We pass HintSide rather than SourceLocation because we want to ensure
529   // it is in the same file as the common file range.
530   void addInlayHint(SourceRange R, HintSide Side, InlayHintKind Kind,
531                     llvm::StringRef Prefix, llvm::StringRef Label,
532                     llvm::StringRef Suffix) {
533     // We shouldn't get as far as adding a hint if the category is disabled.
534     // We'd like to disable as much of the analysis as possible above instead.
535     // Assert in debug mode but add a dynamic check in production.
536     assert(Cfg.InlayHints.Enabled && "Shouldn't get here if disabled!");
537     switch (Kind) {
538 #define CHECK_KIND(Enumerator, ConfigProperty)                                 \
539   case InlayHintKind::Enumerator:                                              \
540     assert(Cfg.InlayHints.ConfigProperty &&                                    \
541            "Shouldn't get here if kind is disabled!");                         \
542     if (!Cfg.InlayHints.ConfigProperty)                                        \
543       return;                                                                  \
544     break
545       CHECK_KIND(ParameterHint, Parameters);
546       CHECK_KIND(TypeHint, DeducedTypes);
547       CHECK_KIND(DesignatorHint, Designators);
548 #undef CHECK_KIND
549     }
550 
551     auto FileRange =
552         toHalfOpenFileRange(AST.getSourceManager(), AST.getLangOpts(), R);
553     if (!FileRange)
554       return;
555     Range LSPRange{
556         sourceLocToPosition(AST.getSourceManager(), FileRange->getBegin()),
557         sourceLocToPosition(AST.getSourceManager(), FileRange->getEnd())};
558     Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end;
559     if (RestrictRange &&
560         (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end)))
561       return;
562     // The hint may be in a file other than the main file (for example, a header
563     // file that was included after the preamble), do not show in that case.
564     if (!AST.getSourceManager().isWrittenInMainFile(FileRange->getBegin()))
565       return;
566     Results.push_back(
567         InlayHint{LSPPos, LSPRange, Kind, (Prefix + Label + Suffix).str()});
568   }
569 
570   void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) {
571     addTypeHint(R, T, Prefix, TypeHintPolicy);
572   }
573 
574   void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix,
575                    const PrintingPolicy &Policy) {
576     if (!Cfg.InlayHints.DeducedTypes || T.isNull())
577       return;
578 
579     std::string TypeName = T.getAsString(Policy);
580     if (TypeName.length() < TypeNameLimit)
581       addInlayHint(R, HintSide::Right, InlayHintKind::TypeHint, Prefix,
582                    TypeName, /*Suffix=*/"");
583   }
584 
585   void addDesignatorHint(SourceRange R, llvm::StringRef Text) {
586     addInlayHint(R, HintSide::Left, InlayHintKind::DesignatorHint,
587                  /*Prefix=*/"", Text, /*Suffix=*/"=");
588   }
589 
590   std::vector<InlayHint> &Results;
591   ASTContext &AST;
592   const Config &Cfg;
593   llvm::Optional<Range> RestrictRange;
594   FileID MainFileID;
595   StringRef MainFileBuf;
596   const HeuristicResolver *Resolver;
597   // We want to suppress default template arguments, but otherwise print
598   // canonical types. Unfortunately, they're conflicting policies so we can't
599   // have both. For regular types, suppressing template arguments is more
600   // important, whereas printing canonical types is crucial for structured
601   // bindings, so we use two separate policies. (See the constructor where
602   // the policies are initialized for more details.)
603   PrintingPolicy TypeHintPolicy;
604   PrintingPolicy StructuredBindingPolicy;
605 
606   static const size_t TypeNameLimit = 32;
607 };
608 
609 } // namespace
610 
611 std::vector<InlayHint> inlayHints(ParsedAST &AST,
612                                   llvm::Optional<Range> RestrictRange) {
613   std::vector<InlayHint> Results;
614   const auto &Cfg = Config::current();
615   if (!Cfg.InlayHints.Enabled)
616     return Results;
617   InlayHintVisitor Visitor(Results, AST, Cfg, std::move(RestrictRange));
618   Visitor.TraverseAST(AST.getASTContext());
619 
620   // De-duplicate hints. Duplicates can sometimes occur due to e.g. explicit
621   // template instantiations.
622   llvm::sort(Results);
623   Results.erase(std::unique(Results.begin(), Results.end()), Results.end());
624 
625   return Results;
626 }
627 
628 } // namespace clangd
629 } // namespace clang
630