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