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