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