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