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