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