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 *const> 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 // Don't show hints for variadic parameters. 397 size_t FixedParamCount = getFixedParamCount(Callee); 398 size_t ArgCount = std::min(FixedParamCount, Args.size()); 399 auto Params = Callee->parameters(); 400 401 NameVec ParameterNames = chooseParameterNames(Callee, ArgCount); 402 403 // Exclude setters (i.e. functions with one argument whose name begins with 404 // "set"), and builtins like std::move/forward/... as their parameter name 405 // is also not likely to be interesting. 406 if (isSetter(Callee, ParameterNames) || isSimpleBuiltin(Callee)) 407 return; 408 409 for (size_t I = 0; I < ArgCount; ++I) { 410 StringRef Name = ParameterNames[I]; 411 bool NameHint = shouldHintName(Args[I], Name); 412 bool ReferenceHint = shouldHintReference(Params[I]); 413 414 if (NameHint || ReferenceHint) { 415 addInlayHint(Args[I]->getSourceRange(), HintSide::Left, 416 InlayHintKind::Parameter, ReferenceHint ? "&" : "", 417 NameHint ? Name : "", ": "); 418 } 419 } 420 } 421 422 static bool isSetter(const FunctionDecl *Callee, const NameVec &ParamNames) { 423 if (ParamNames.size() != 1) 424 return false; 425 426 StringRef Name = getSimpleName(*Callee); 427 if (!Name.startswith_insensitive("set")) 428 return false; 429 430 // In addition to checking that the function has one parameter and its 431 // name starts with "set", also check that the part after "set" matches 432 // the name of the parameter (ignoring case). The idea here is that if 433 // the parameter name differs, it may contain extra information that 434 // may be useful to show in a hint, as in: 435 // void setTimeout(int timeoutMillis); 436 // This currently doesn't handle cases where params use snake_case 437 // and functions don't, e.g. 438 // void setExceptionHandler(EHFunc exception_handler); 439 // We could improve this by replacing `equals_insensitive` with some 440 // `sloppy_equals` which ignores case and also skips underscores. 441 StringRef WhatItIsSetting = Name.substr(3).ltrim("_"); 442 return WhatItIsSetting.equals_insensitive(ParamNames[0]); 443 } 444 445 // Checks if the callee is one of the builtins 446 // addressof, as_const, forward, move(_if_noexcept) 447 static bool isSimpleBuiltin(const FunctionDecl *Callee) { 448 switch (Callee->getBuiltinID()) { 449 case Builtin::BIaddressof: 450 case Builtin::BIas_const: 451 case Builtin::BIforward: 452 case Builtin::BImove: 453 case Builtin::BImove_if_noexcept: 454 return true; 455 default: 456 return false; 457 } 458 } 459 460 bool shouldHintName(const Expr *Arg, StringRef ParamName) { 461 if (ParamName.empty()) 462 return false; 463 464 // If the argument expression is a single name and it matches the 465 // parameter name exactly, omit the name hint. 466 if (ParamName == getSpelledIdentifier(Arg)) 467 return false; 468 469 // Exclude argument expressions preceded by a /*paramName*/. 470 if (isPrecededByParamNameComment(Arg, ParamName)) 471 return false; 472 473 return true; 474 } 475 476 bool shouldHintReference(const ParmVarDecl *Param) { 477 // If the parameter is a non-const reference type, print an inlay hint 478 auto Type = Param->getType(); 479 return Type->isLValueReferenceType() && 480 !Type.getNonReferenceType().isConstQualified(); 481 } 482 483 // Checks if "E" is spelled in the main file and preceded by a C-style comment 484 // whose contents match ParamName (allowing for whitespace and an optional "=" 485 // at the end. 486 bool isPrecededByParamNameComment(const Expr *E, StringRef ParamName) { 487 auto &SM = AST.getSourceManager(); 488 auto ExprStartLoc = SM.getTopMacroCallerLoc(E->getBeginLoc()); 489 auto Decomposed = SM.getDecomposedLoc(ExprStartLoc); 490 if (Decomposed.first != MainFileID) 491 return false; 492 493 StringRef SourcePrefix = MainFileBuf.substr(0, Decomposed.second); 494 // Allow whitespace between comment and expression. 495 SourcePrefix = SourcePrefix.rtrim(); 496 // Check for comment ending. 497 if (!SourcePrefix.consume_back("*/")) 498 return false; 499 // Ignore some punctuation and whitespace around comment. 500 // In particular this allows designators to match nicely. 501 llvm::StringLiteral IgnoreChars = " =."; 502 SourcePrefix = SourcePrefix.rtrim(IgnoreChars); 503 ParamName = ParamName.trim(IgnoreChars); 504 // Other than that, the comment must contain exactly ParamName. 505 if (!SourcePrefix.consume_back(ParamName)) 506 return false; 507 SourcePrefix = SourcePrefix.rtrim(IgnoreChars); 508 return SourcePrefix.endswith("/*"); 509 } 510 511 // If "E" spells a single unqualified identifier, return that name. 512 // Otherwise, return an empty string. 513 static StringRef getSpelledIdentifier(const Expr *E) { 514 E = E->IgnoreUnlessSpelledInSource(); 515 516 if (auto *DRE = dyn_cast<DeclRefExpr>(E)) 517 if (!DRE->getQualifier()) 518 return getSimpleName(*DRE->getDecl()); 519 520 if (auto *ME = dyn_cast<MemberExpr>(E)) 521 if (!ME->getQualifier() && ME->isImplicitAccess()) 522 return getSimpleName(*ME->getMemberDecl()); 523 524 return {}; 525 } 526 527 NameVec chooseParameterNames(const FunctionDecl *Callee, size_t ArgCount) { 528 // The current strategy here is to use all the parameter names from the 529 // canonical declaration, unless they're all empty, in which case we 530 // use all the parameter names from the definition (in present in the 531 // translation unit). 532 // We could try a bit harder, e.g.: 533 // - try all re-declarations, not just canonical + definition 534 // - fall back arg-by-arg rather than wholesale 535 536 NameVec ParameterNames = getParameterNamesForDecl(Callee, ArgCount); 537 538 if (llvm::all_of(ParameterNames, std::mem_fn(&StringRef::empty))) { 539 if (const FunctionDecl *Def = Callee->getDefinition()) { 540 ParameterNames = getParameterNamesForDecl(Def, ArgCount); 541 } 542 } 543 assert(ParameterNames.size() == ArgCount); 544 545 // Standard library functions often have parameter names that start 546 // with underscores, which makes the hints noisy, so strip them out. 547 for (auto &Name : ParameterNames) 548 stripLeadingUnderscores(Name); 549 550 return ParameterNames; 551 } 552 553 static void stripLeadingUnderscores(StringRef &Name) { 554 Name = Name.ltrim('_'); 555 } 556 557 // Return the number of fixed parameters Function has, that is, not counting 558 // parameters that are variadic (instantiated from a parameter pack) or 559 // C-style varargs. 560 static size_t getFixedParamCount(const FunctionDecl *Function) { 561 if (FunctionTemplateDecl *Template = Function->getPrimaryTemplate()) { 562 FunctionDecl *F = Template->getTemplatedDecl(); 563 size_t Result = 0; 564 for (ParmVarDecl *Parm : F->parameters()) { 565 if (Parm->isParameterPack()) { 566 break; 567 } 568 ++Result; 569 } 570 return Result; 571 } 572 // C-style varargs don't need special handling, they're already 573 // not included in getNumParams(). 574 return Function->getNumParams(); 575 } 576 577 static StringRef getSimpleName(const NamedDecl &D) { 578 if (IdentifierInfo *Ident = D.getDeclName().getAsIdentifierInfo()) { 579 return Ident->getName(); 580 } 581 582 return StringRef(); 583 } 584 585 NameVec getParameterNamesForDecl(const FunctionDecl *Function, 586 size_t ArgCount) { 587 NameVec Result; 588 for (size_t I = 0; I < ArgCount; ++I) { 589 const ParmVarDecl *Parm = Function->getParamDecl(I); 590 assert(Parm); 591 Result.emplace_back(getSimpleName(*Parm)); 592 } 593 return Result; 594 } 595 596 // We pass HintSide rather than SourceLocation because we want to ensure 597 // it is in the same file as the common file range. 598 void addInlayHint(SourceRange R, HintSide Side, InlayHintKind Kind, 599 llvm::StringRef Prefix, llvm::StringRef Label, 600 llvm::StringRef Suffix) { 601 // We shouldn't get as far as adding a hint if the category is disabled. 602 // We'd like to disable as much of the analysis as possible above instead. 603 // Assert in debug mode but add a dynamic check in production. 604 assert(Cfg.InlayHints.Enabled && "Shouldn't get here if disabled!"); 605 switch (Kind) { 606 #define CHECK_KIND(Enumerator, ConfigProperty) \ 607 case InlayHintKind::Enumerator: \ 608 assert(Cfg.InlayHints.ConfigProperty && \ 609 "Shouldn't get here if kind is disabled!"); \ 610 if (!Cfg.InlayHints.ConfigProperty) \ 611 return; \ 612 break 613 CHECK_KIND(Parameter, Parameters); 614 CHECK_KIND(Type, DeducedTypes); 615 CHECK_KIND(Designator, Designators); 616 #undef CHECK_KIND 617 } 618 619 auto FileRange = 620 toHalfOpenFileRange(AST.getSourceManager(), AST.getLangOpts(), R); 621 if (!FileRange) 622 return; 623 Range LSPRange{ 624 sourceLocToPosition(AST.getSourceManager(), FileRange->getBegin()), 625 sourceLocToPosition(AST.getSourceManager(), FileRange->getEnd())}; 626 Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end; 627 if (RestrictRange && 628 (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end))) 629 return; 630 // The hint may be in a file other than the main file (for example, a header 631 // file that was included after the preamble), do not show in that case. 632 if (!AST.getSourceManager().isWrittenInMainFile(FileRange->getBegin())) 633 return; 634 bool PadLeft = Prefix.consume_front(" "); 635 bool PadRight = Suffix.consume_back(" "); 636 Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind, 637 PadLeft, PadRight, LSPRange}); 638 } 639 640 void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) { 641 addTypeHint(R, T, Prefix, TypeHintPolicy); 642 } 643 644 void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix, 645 const PrintingPolicy &Policy) { 646 if (!Cfg.InlayHints.DeducedTypes || T.isNull()) 647 return; 648 649 std::string TypeName = T.getAsString(Policy); 650 if (TypeName.length() < TypeNameLimit) 651 addInlayHint(R, HintSide::Right, InlayHintKind::Type, Prefix, TypeName, 652 /*Suffix=*/""); 653 } 654 655 void addDesignatorHint(SourceRange R, llvm::StringRef Text) { 656 addInlayHint(R, HintSide::Left, InlayHintKind::Designator, 657 /*Prefix=*/"", Text, /*Suffix=*/"="); 658 } 659 660 std::vector<InlayHint> &Results; 661 ASTContext &AST; 662 const Config &Cfg; 663 llvm::Optional<Range> RestrictRange; 664 FileID MainFileID; 665 StringRef MainFileBuf; 666 const HeuristicResolver *Resolver; 667 // We want to suppress default template arguments, but otherwise print 668 // canonical types. Unfortunately, they're conflicting policies so we can't 669 // have both. For regular types, suppressing template arguments is more 670 // important, whereas printing canonical types is crucial for structured 671 // bindings, so we use two separate policies. (See the constructor where 672 // the policies are initialized for more details.) 673 PrintingPolicy TypeHintPolicy; 674 PrintingPolicy StructuredBindingPolicy; 675 676 static const size_t TypeNameLimit = 32; 677 }; 678 679 } // namespace 680 681 std::vector<InlayHint> inlayHints(ParsedAST &AST, 682 llvm::Optional<Range> RestrictRange) { 683 std::vector<InlayHint> Results; 684 const auto &Cfg = Config::current(); 685 if (!Cfg.InlayHints.Enabled) 686 return Results; 687 InlayHintVisitor Visitor(Results, AST, Cfg, std::move(RestrictRange)); 688 Visitor.TraverseAST(AST.getASTContext()); 689 690 // De-duplicate hints. Duplicates can sometimes occur due to e.g. explicit 691 // template instantiations. 692 llvm::sort(Results); 693 Results.erase(std::unique(Results.begin(), Results.end()), Results.end()); 694 695 return Results; 696 } 697 698 } // namespace clangd 699 } // namespace clang 700