1 //===--- XRefs.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 "XRefs.h" 9 #include "AST.h" 10 #include "CodeCompletionStrings.h" 11 #include "FindSymbols.h" 12 #include "FindTarget.h" 13 #include "ParsedAST.h" 14 #include "Protocol.h" 15 #include "Quality.h" 16 #include "Selection.h" 17 #include "SourceCode.h" 18 #include "URI.h" 19 #include "index/Index.h" 20 #include "index/Merge.h" 21 #include "index/Relation.h" 22 #include "index/SymbolLocation.h" 23 #include "support/Logger.h" 24 #include "clang/AST/ASTContext.h" 25 #include "clang/AST/ASTTypeTraits.h" 26 #include "clang/AST/Attr.h" 27 #include "clang/AST/Attrs.inc" 28 #include "clang/AST/Decl.h" 29 #include "clang/AST/DeclCXX.h" 30 #include "clang/AST/DeclObjC.h" 31 #include "clang/AST/DeclTemplate.h" 32 #include "clang/AST/ExprCXX.h" 33 #include "clang/AST/ExternalASTSource.h" 34 #include "clang/AST/RecursiveASTVisitor.h" 35 #include "clang/AST/Stmt.h" 36 #include "clang/AST/StmtCXX.h" 37 #include "clang/AST/Type.h" 38 #include "clang/Basic/CharInfo.h" 39 #include "clang/Basic/LLVM.h" 40 #include "clang/Basic/LangOptions.h" 41 #include "clang/Basic/SourceLocation.h" 42 #include "clang/Basic/SourceManager.h" 43 #include "clang/Basic/TokenKinds.h" 44 #include "clang/Index/IndexDataConsumer.h" 45 #include "clang/Index/IndexSymbol.h" 46 #include "clang/Index/IndexingAction.h" 47 #include "clang/Index/IndexingOptions.h" 48 #include "clang/Index/USRGeneration.h" 49 #include "clang/Tooling/Syntax/Tokens.h" 50 #include "llvm/ADT/ArrayRef.h" 51 #include "llvm/ADT/MapVector.h" 52 #include "llvm/ADT/None.h" 53 #include "llvm/ADT/STLExtras.h" 54 #include "llvm/ADT/ScopeExit.h" 55 #include "llvm/ADT/SmallSet.h" 56 #include "llvm/ADT/StringExtras.h" 57 #include "llvm/ADT/StringRef.h" 58 #include "llvm/Support/Casting.h" 59 #include "llvm/Support/Error.h" 60 #include "llvm/Support/MathExtras.h" 61 #include "llvm/Support/Path.h" 62 #include "llvm/Support/raw_ostream.h" 63 64 namespace clang { 65 namespace clangd { 66 namespace { 67 68 // Returns the single definition of the entity declared by D, if visible. 69 // In particular: 70 // - for non-redeclarable kinds (e.g. local vars), return D 71 // - for kinds that allow multiple definitions (e.g. namespaces), return nullptr 72 // Kinds of nodes that always return nullptr here will not have definitions 73 // reported by locateSymbolAt(). 74 const NamedDecl *getDefinition(const NamedDecl *D) { 75 assert(D); 76 // Decl has one definition that we can find. 77 if (const auto *TD = dyn_cast<TagDecl>(D)) 78 return TD->getDefinition(); 79 if (const auto *VD = dyn_cast<VarDecl>(D)) 80 return VD->getDefinition(); 81 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 82 return FD->getDefinition(); 83 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(D)) 84 if (const auto *RD = CTD->getTemplatedDecl()) 85 return RD->getDefinition(); 86 // Objective-C classes can have three types of declarations: 87 // 88 // - forward declaration: @class MyClass; 89 // - true declaration (interface definition): @interface MyClass ... @end 90 // - true definition (implementation): @implementation MyClass ... @end 91 // 92 // Objective-C categories are extensions are on classes: 93 // 94 // - declaration: @interface MyClass (Ext) ... @end 95 // - definition: @implementation MyClass (Ext) ... @end 96 // 97 // With one special case, a class extension, which is normally used to keep 98 // some declarations internal to a file without exposing them in a header. 99 // 100 // - class extension declaration: @interface MyClass () ... @end 101 // - which really links to class definition: @implementation MyClass ... @end 102 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) 103 return ID->getImplementation(); 104 if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) { 105 if (CD->IsClassExtension()) { 106 if (const auto *ID = CD->getClassInterface()) 107 return ID->getImplementation(); 108 return nullptr; 109 } 110 return CD->getImplementation(); 111 } 112 // Only a single declaration is allowed. 113 if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) || 114 isa<TemplateTemplateParmDecl>(D)) // except cases above 115 return D; 116 // Multiple definitions are allowed. 117 return nullptr; // except cases above 118 } 119 120 void logIfOverflow(const SymbolLocation &Loc) { 121 if (Loc.Start.hasOverflow() || Loc.End.hasOverflow()) 122 log("Possible overflow in symbol location: {0}", Loc); 123 } 124 125 // Convert a SymbolLocation to LSP's Location. 126 // TUPath is used to resolve the path of URI. 127 // FIXME: figure out a good home for it, and share the implementation with 128 // FindSymbols. 129 llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc, 130 llvm::StringRef TUPath) { 131 if (!Loc) 132 return None; 133 auto Uri = URI::parse(Loc.FileURI); 134 if (!Uri) { 135 elog("Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError()); 136 return None; 137 } 138 auto U = URIForFile::fromURI(*Uri, TUPath); 139 if (!U) { 140 elog("Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError()); 141 return None; 142 } 143 144 Location LSPLoc; 145 LSPLoc.uri = std::move(*U); 146 LSPLoc.range.start.line = Loc.Start.line(); 147 LSPLoc.range.start.character = Loc.Start.column(); 148 LSPLoc.range.end.line = Loc.End.line(); 149 LSPLoc.range.end.character = Loc.End.column(); 150 logIfOverflow(Loc); 151 return LSPLoc; 152 } 153 154 SymbolLocation toIndexLocation(const Location &Loc, std::string &URIStorage) { 155 SymbolLocation SymLoc; 156 URIStorage = Loc.uri.uri(); 157 SymLoc.FileURI = URIStorage.c_str(); 158 SymLoc.Start.setLine(Loc.range.start.line); 159 SymLoc.Start.setColumn(Loc.range.start.character); 160 SymLoc.End.setLine(Loc.range.end.line); 161 SymLoc.End.setColumn(Loc.range.end.character); 162 return SymLoc; 163 } 164 165 // Returns the preferred location between an AST location and an index location. 166 SymbolLocation getPreferredLocation(const Location &ASTLoc, 167 const SymbolLocation &IdxLoc, 168 std::string &Scratch) { 169 // Also use a mock symbol for the index location so that other fields (e.g. 170 // definition) are not factored into the preference. 171 Symbol ASTSym, IdxSym; 172 ASTSym.ID = IdxSym.ID = SymbolID("mock_symbol_id"); 173 ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch); 174 IdxSym.CanonicalDeclaration = IdxLoc; 175 auto Merged = mergeSymbol(ASTSym, IdxSym); 176 return Merged.CanonicalDeclaration; 177 } 178 179 std::vector<std::pair<const NamedDecl *, DeclRelationSet>> 180 getDeclAtPositionWithRelations(ParsedAST &AST, SourceLocation Pos, 181 DeclRelationSet Relations, 182 ASTNodeKind *NodeKind = nullptr) { 183 unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second; 184 std::vector<std::pair<const NamedDecl *, DeclRelationSet>> Result; 185 auto ResultFromTree = [&](SelectionTree ST) { 186 if (const SelectionTree::Node *N = ST.commonAncestor()) { 187 if (NodeKind) 188 *NodeKind = N->ASTNode.getNodeKind(); 189 // Attributes don't target decls, look at the 190 // thing it's attached to. 191 // We still report the original NodeKind! 192 // This makes the `override` hack work. 193 if (N->ASTNode.get<Attr>() && N->Parent) 194 N = N->Parent; 195 llvm::copy_if(allTargetDecls(N->ASTNode, AST.getHeuristicResolver()), 196 std::back_inserter(Result), 197 [&](auto &Entry) { return !(Entry.second & ~Relations); }); 198 } 199 return !Result.empty(); 200 }; 201 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, 202 Offset, ResultFromTree); 203 return Result; 204 } 205 206 std::vector<const NamedDecl *> 207 getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations, 208 ASTNodeKind *NodeKind = nullptr) { 209 std::vector<const NamedDecl *> Result; 210 for (auto &Entry : 211 getDeclAtPositionWithRelations(AST, Pos, Relations, NodeKind)) 212 Result.push_back(Entry.first); 213 return Result; 214 } 215 216 // Expects Loc to be a SpellingLocation, will bail out otherwise as it can't 217 // figure out a filename. 218 llvm::Optional<Location> makeLocation(const ASTContext &AST, SourceLocation Loc, 219 llvm::StringRef TUPath) { 220 const auto &SM = AST.getSourceManager(); 221 const FileEntry *F = SM.getFileEntryForID(SM.getFileID(Loc)); 222 if (!F) 223 return None; 224 auto FilePath = getCanonicalPath(F, SM); 225 if (!FilePath) { 226 log("failed to get path!"); 227 return None; 228 } 229 Location L; 230 L.uri = URIForFile::canonicalize(*FilePath, TUPath); 231 // We call MeasureTokenLength here as TokenBuffer doesn't store spelled tokens 232 // outside the main file. 233 auto TokLen = Lexer::MeasureTokenLength(Loc, SM, AST.getLangOpts()); 234 L.range = halfOpenToRange( 235 SM, CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(TokLen))); 236 return L; 237 } 238 239 // Treat #included files as symbols, to enable go-to-definition on them. 240 llvm::Optional<LocatedSymbol> locateFileReferent(const Position &Pos, 241 ParsedAST &AST, 242 llvm::StringRef MainFilePath) { 243 for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { 244 if (!Inc.Resolved.empty() && Inc.HashLine == Pos.line) { 245 LocatedSymbol File; 246 File.Name = std::string(llvm::sys::path::filename(Inc.Resolved)); 247 File.PreferredDeclaration = { 248 URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}}; 249 File.Definition = File.PreferredDeclaration; 250 // We're not going to find any further symbols on #include lines. 251 return File; 252 } 253 } 254 return llvm::None; 255 } 256 257 // Macros are simple: there's no declaration/definition distinction. 258 // As a consequence, there's no need to look them up in the index either. 259 llvm::Optional<LocatedSymbol> 260 locateMacroReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST, 261 llvm::StringRef MainFilePath) { 262 if (auto M = locateMacroAt(TouchedIdentifier, AST.getPreprocessor())) { 263 if (auto Loc = 264 makeLocation(AST.getASTContext(), M->NameLoc, MainFilePath)) { 265 LocatedSymbol Macro; 266 Macro.Name = std::string(M->Name); 267 Macro.PreferredDeclaration = *Loc; 268 Macro.Definition = Loc; 269 Macro.ID = getSymbolID(M->Name, M->Info, AST.getSourceManager()); 270 return Macro; 271 } 272 } 273 return llvm::None; 274 } 275 276 // A wrapper around `Decl::getCanonicalDecl` to support cases where Clang's 277 // definition of a canonical declaration doesn't match up to what a programmer 278 // would expect. For example, Objective-C classes can have three types of 279 // declarations: 280 // 281 // - forward declaration(s): @class MyClass; 282 // - true declaration (interface definition): @interface MyClass ... @end 283 // - true definition (implementation): @implementation MyClass ... @end 284 // 285 // Clang will consider the forward declaration to be the canonical declaration 286 // because it is first. We actually want the class definition if it is 287 // available since that is what a programmer would consider the primary 288 // declaration to be. 289 const NamedDecl *getPreferredDecl(const NamedDecl *D) { 290 // FIXME: Canonical declarations of some symbols might refer to built-in 291 // decls with possibly-invalid source locations (e.g. global new operator). 292 // In such cases we should pick up a redecl with valid source location 293 // instead of failing. 294 D = llvm::cast<NamedDecl>(D->getCanonicalDecl()); 295 296 // Prefer Objective-C class/protocol definitions over the forward declaration. 297 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) 298 if (const auto *DefinitionID = ID->getDefinition()) 299 return DefinitionID; 300 if (const auto *PD = dyn_cast<ObjCProtocolDecl>(D)) 301 if (const auto *DefinitionID = PD->getDefinition()) 302 return DefinitionID; 303 304 return D; 305 } 306 307 std::vector<LocatedSymbol> findImplementors(llvm::DenseSet<SymbolID> IDs, 308 RelationKind Predicate, 309 const SymbolIndex *Index, 310 llvm::StringRef MainFilePath) { 311 if (IDs.empty() || !Index) 312 return {}; 313 static constexpr trace::Metric FindImplementorsMetric( 314 "find_implementors", trace::Metric::Counter, "case"); 315 switch (Predicate) { 316 case RelationKind::BaseOf: 317 FindImplementorsMetric.record(1, "find-base"); 318 break; 319 case RelationKind::OverriddenBy: 320 FindImplementorsMetric.record(1, "find-override"); 321 break; 322 } 323 324 RelationsRequest Req; 325 Req.Predicate = Predicate; 326 Req.Subjects = std::move(IDs); 327 std::vector<LocatedSymbol> Results; 328 Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) { 329 auto DeclLoc = 330 indexToLSPLocation(Object.CanonicalDeclaration, MainFilePath); 331 if (!DeclLoc) { 332 elog("Find overrides: {0}", DeclLoc.takeError()); 333 return; 334 } 335 Results.emplace_back(); 336 Results.back().Name = Object.Name.str(); 337 Results.back().PreferredDeclaration = *DeclLoc; 338 auto DefLoc = indexToLSPLocation(Object.Definition, MainFilePath); 339 if (!DefLoc) { 340 elog("Failed to convert location: {0}", DefLoc.takeError()); 341 return; 342 } 343 Results.back().Definition = *DefLoc; 344 }); 345 return Results; 346 } 347 348 // Decls are more complicated. 349 // The AST contains at least a declaration, maybe a definition. 350 // These are up-to-date, and so generally preferred over index results. 351 // We perform a single batch index lookup to find additional definitions. 352 std::vector<LocatedSymbol> 353 locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, 354 ParsedAST &AST, llvm::StringRef MainFilePath, 355 const SymbolIndex *Index, ASTNodeKind &NodeKind) { 356 const SourceManager &SM = AST.getSourceManager(); 357 // Results follow the order of Symbols.Decls. 358 std::vector<LocatedSymbol> Result; 359 // Keep track of SymbolID -> index mapping, to fill in index data later. 360 llvm::DenseMap<SymbolID, size_t> ResultIndex; 361 362 static constexpr trace::Metric LocateASTReferentMetric( 363 "locate_ast_referent", trace::Metric::Counter, "case"); 364 auto AddResultDecl = [&](const NamedDecl *D) { 365 D = getPreferredDecl(D); 366 auto Loc = 367 makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath); 368 if (!Loc) 369 return; 370 371 Result.emplace_back(); 372 Result.back().Name = printName(AST.getASTContext(), *D); 373 Result.back().PreferredDeclaration = *Loc; 374 Result.back().ID = getSymbolID(D); 375 if (const NamedDecl *Def = getDefinition(D)) 376 Result.back().Definition = makeLocation( 377 AST.getASTContext(), nameLocation(*Def, SM), MainFilePath); 378 379 // Record SymbolID for index lookup later. 380 if (auto ID = getSymbolID(D)) 381 ResultIndex[ID] = Result.size() - 1; 382 }; 383 384 // Emit all symbol locations (declaration or definition) from AST. 385 DeclRelationSet Relations = 386 DeclRelation::TemplatePattern | DeclRelation::Alias; 387 auto Candidates = 388 getDeclAtPositionWithRelations(AST, CurLoc, Relations, &NodeKind); 389 llvm::DenseSet<SymbolID> VirtualMethods; 390 for (const auto &E : Candidates) { 391 const NamedDecl *D = E.first; 392 if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) { 393 // Special case: virtual void ^method() = 0: jump to all overrides. 394 // FIXME: extend it to ^virtual, unfortunately, virtual location is not 395 // saved in the AST. 396 if (CMD->isPure()) { 397 if (TouchedIdentifier && SM.getSpellingLoc(CMD->getLocation()) == 398 TouchedIdentifier->location()) { 399 VirtualMethods.insert(getSymbolID(CMD)); 400 LocateASTReferentMetric.record(1, "method-to-override"); 401 } 402 } 403 // Special case: void foo() ^override: jump to the overridden method. 404 if (NodeKind.isSame(ASTNodeKind::getFromNodeKind<OverrideAttr>()) || 405 NodeKind.isSame(ASTNodeKind::getFromNodeKind<FinalAttr>())) { 406 // We may be overridding multiple methods - offer them all. 407 for (const NamedDecl *ND : CMD->overridden_methods()) 408 AddResultDecl(ND); 409 continue; 410 } 411 } 412 413 // Special case: the cursor is on an alias, prefer other results. 414 // This targets "using ns::^Foo", where the target is more interesting. 415 // This does not trigger on renaming aliases: 416 // `using Foo = ^Bar` already targets Bar via a TypeLoc 417 // `using ^Foo = Bar` has no other results, as Underlying is filtered. 418 if (E.second & DeclRelation::Alias && Candidates.size() > 1 && 419 // beginLoc/endLoc are a token range, so rewind the identifier we're in. 420 SM.isPointWithin(TouchedIdentifier ? TouchedIdentifier->location() 421 : CurLoc, 422 D->getBeginLoc(), D->getEndLoc())) 423 continue; 424 425 // Special case: the point of declaration of a template specialization, 426 // it's more useful to navigate to the template declaration. 427 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 428 if (TouchedIdentifier && 429 D->getLocation() == TouchedIdentifier->location()) { 430 LocateASTReferentMetric.record(1, "template-specialization-to-primary"); 431 AddResultDecl(CTSD->getSpecializedTemplate()); 432 continue; 433 } 434 } 435 436 // Special case: if the class name is selected, also map Objective-C 437 // categories and category implementations back to their class interface. 438 // 439 // Since `TouchedIdentifier` might refer to the `ObjCCategoryImplDecl` 440 // instead of the `ObjCCategoryDecl` we intentionally check the contents 441 // of the locs when checking for class name equivalence. 442 if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) 443 if (const auto *ID = CD->getClassInterface()) 444 if (TouchedIdentifier && 445 (CD->getLocation() == TouchedIdentifier->location() || 446 ID->getName() == TouchedIdentifier->text(SM))) { 447 LocateASTReferentMetric.record(1, "objc-category-to-class"); 448 AddResultDecl(ID); 449 } 450 451 LocateASTReferentMetric.record(1, "regular"); 452 // Otherwise the target declaration is the right one. 453 AddResultDecl(D); 454 } 455 456 // Now query the index for all Symbol IDs we found in the AST. 457 if (Index && !ResultIndex.empty()) { 458 LookupRequest QueryRequest; 459 for (auto It : ResultIndex) 460 QueryRequest.IDs.insert(It.first); 461 std::string Scratch; 462 Index->lookup(QueryRequest, [&](const Symbol &Sym) { 463 auto &R = Result[ResultIndex.lookup(Sym.ID)]; 464 465 if (R.Definition) { // from AST 466 // Special case: if the AST yielded a definition, then it may not be 467 // the right *declaration*. Prefer the one from the index. 468 if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, MainFilePath)) 469 R.PreferredDeclaration = *Loc; 470 471 // We might still prefer the definition from the index, e.g. for 472 // generated symbols. 473 if (auto Loc = toLSPLocation( 474 getPreferredLocation(*R.Definition, Sym.Definition, Scratch), 475 MainFilePath)) 476 R.Definition = *Loc; 477 } else { 478 R.Definition = toLSPLocation(Sym.Definition, MainFilePath); 479 480 // Use merge logic to choose AST or index declaration. 481 if (auto Loc = toLSPLocation( 482 getPreferredLocation(R.PreferredDeclaration, 483 Sym.CanonicalDeclaration, Scratch), 484 MainFilePath)) 485 R.PreferredDeclaration = *Loc; 486 } 487 }); 488 } 489 490 auto Overrides = findImplementors(VirtualMethods, RelationKind::OverriddenBy, 491 Index, MainFilePath); 492 Result.insert(Result.end(), Overrides.begin(), Overrides.end()); 493 return Result; 494 } 495 496 std::vector<LocatedSymbol> locateSymbolForType(const ParsedAST &AST, 497 const QualType &Type) { 498 const auto &SM = AST.getSourceManager(); 499 auto MainFilePath = 500 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); 501 if (!MainFilePath) { 502 elog("Failed to get a path for the main file, so no symbol."); 503 return {}; 504 } 505 506 auto Decls = targetDecl(DynTypedNode::create(Type.getNonReferenceType()), 507 DeclRelation::TemplatePattern | DeclRelation::Alias, 508 AST.getHeuristicResolver()); 509 if (Decls.empty()) 510 return {}; 511 512 std::vector<LocatedSymbol> Results; 513 const auto &ASTContext = AST.getASTContext(); 514 515 for (const NamedDecl *D : Decls) { 516 D = getPreferredDecl(D); 517 518 auto Loc = makeLocation(ASTContext, nameLocation(*D, SM), *MainFilePath); 519 if (!Loc) 520 continue; 521 522 Results.emplace_back(); 523 Results.back().Name = printName(ASTContext, *D); 524 Results.back().PreferredDeclaration = *Loc; 525 Results.back().ID = getSymbolID(D); 526 if (const NamedDecl *Def = getDefinition(D)) 527 Results.back().Definition = 528 makeLocation(ASTContext, nameLocation(*Def, SM), *MainFilePath); 529 } 530 531 return Results; 532 } 533 534 bool tokenSpelledAt(SourceLocation SpellingLoc, const syntax::TokenBuffer &TB) { 535 auto ExpandedTokens = TB.expandedTokens( 536 TB.sourceManager().getMacroArgExpandedLocation(SpellingLoc)); 537 return !ExpandedTokens.empty(); 538 } 539 540 llvm::StringRef sourcePrefix(SourceLocation Loc, const SourceManager &SM) { 541 auto D = SM.getDecomposedLoc(Loc); 542 bool Invalid = false; 543 llvm::StringRef Buf = SM.getBufferData(D.first, &Invalid); 544 if (Invalid || D.second > Buf.size()) 545 return ""; 546 return Buf.substr(0, D.second); 547 } 548 549 bool isDependentName(ASTNodeKind NodeKind) { 550 return NodeKind.isSame(ASTNodeKind::getFromNodeKind<OverloadExpr>()) || 551 NodeKind.isSame( 552 ASTNodeKind::getFromNodeKind<CXXDependentScopeMemberExpr>()) || 553 NodeKind.isSame( 554 ASTNodeKind::getFromNodeKind<DependentScopeDeclRefExpr>()); 555 } 556 557 } // namespace 558 559 std::vector<LocatedSymbol> 560 locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, 561 const SymbolIndex *Index, const std::string &MainFilePath, 562 ASTNodeKind NodeKind) { 563 // Don't use heuristics if this is a real identifier, or not an 564 // identifier. 565 // Exception: dependent names, because those may have useful textual 566 // matches that AST-based heuristics cannot find. 567 if ((Word.ExpandedToken && !isDependentName(NodeKind)) || 568 !Word.LikelyIdentifier || !Index) 569 return {}; 570 // We don't want to handle words in string literals. (It'd be nice to list 571 // *allowed* token kinds explicitly, but comment Tokens aren't retained). 572 if (Word.PartOfSpelledToken && 573 isStringLiteral(Word.PartOfSpelledToken->kind())) 574 return {}; 575 576 const auto &SM = AST.getSourceManager(); 577 // Look up the selected word in the index. 578 FuzzyFindRequest Req; 579 Req.Query = Word.Text.str(); 580 Req.ProximityPaths = {MainFilePath}; 581 // Find the namespaces to query by lexing the file. 582 Req.Scopes = 583 visibleNamespaces(sourcePrefix(Word.Location, SM), AST.getLangOpts()); 584 // FIXME: For extra strictness, consider AnyScope=false. 585 Req.AnyScope = true; 586 // We limit the results to 3 further below. This limit is to avoid fetching 587 // too much data, while still likely having enough for 3 results to remain 588 // after additional filtering. 589 Req.Limit = 10; 590 bool TooMany = false; 591 using ScoredLocatedSymbol = std::pair<float, LocatedSymbol>; 592 std::vector<ScoredLocatedSymbol> ScoredResults; 593 Index->fuzzyFind(Req, [&](const Symbol &Sym) { 594 // Only consider exact name matches, including case. 595 // This is to avoid too many false positives. 596 // We could relax this in the future (e.g. to allow for typos) if we make 597 // the query more accurate by other means. 598 if (Sym.Name != Word.Text) 599 return; 600 601 // Exclude constructor results. They have the same name as the class, 602 // but we don't have enough context to prefer them over the class. 603 if (Sym.SymInfo.Kind == index::SymbolKind::Constructor) 604 return; 605 606 auto MaybeDeclLoc = 607 indexToLSPLocation(Sym.CanonicalDeclaration, MainFilePath); 608 if (!MaybeDeclLoc) { 609 log("locateSymbolNamedTextuallyAt: {0}", MaybeDeclLoc.takeError()); 610 return; 611 } 612 LocatedSymbol Located; 613 Located.PreferredDeclaration = *MaybeDeclLoc; 614 Located.Name = (Sym.Name + Sym.TemplateSpecializationArgs).str(); 615 Located.ID = Sym.ID; 616 if (Sym.Definition) { 617 auto MaybeDefLoc = indexToLSPLocation(Sym.Definition, MainFilePath); 618 if (!MaybeDefLoc) { 619 log("locateSymbolNamedTextuallyAt: {0}", MaybeDefLoc.takeError()); 620 return; 621 } 622 Located.PreferredDeclaration = *MaybeDefLoc; 623 Located.Definition = *MaybeDefLoc; 624 } 625 626 if (ScoredResults.size() >= 5) { 627 // If we have more than 5 results, don't return anything, 628 // as confidence is too low. 629 // FIXME: Alternatively, try a stricter query? 630 TooMany = true; 631 return; 632 } 633 634 SymbolQualitySignals Quality; 635 Quality.merge(Sym); 636 SymbolRelevanceSignals Relevance; 637 Relevance.Name = Sym.Name; 638 Relevance.Query = SymbolRelevanceSignals::Generic; 639 Relevance.merge(Sym); 640 auto Score = evaluateSymbolAndRelevance(Quality.evaluateHeuristics(), 641 Relevance.evaluateHeuristics()); 642 dlog("locateSymbolNamedTextuallyAt: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, 643 Sym.Name, Score, Quality, Relevance); 644 645 ScoredResults.push_back({Score, std::move(Located)}); 646 }); 647 648 if (TooMany) { 649 vlog("Heuristic index lookup for {0} returned too many candidates, ignored", 650 Word.Text); 651 return {}; 652 } 653 654 llvm::sort(ScoredResults, 655 [](const ScoredLocatedSymbol &A, const ScoredLocatedSymbol &B) { 656 return A.first > B.first; 657 }); 658 std::vector<LocatedSymbol> Results; 659 for (auto &Res : std::move(ScoredResults)) 660 Results.push_back(std::move(Res.second)); 661 if (Results.empty()) 662 vlog("No heuristic index definition for {0}", Word.Text); 663 else 664 log("Found definition heuristically in index for {0}", Word.Text); 665 return Results; 666 } 667 668 const syntax::Token *findNearbyIdentifier(const SpelledWord &Word, 669 const syntax::TokenBuffer &TB) { 670 // Don't use heuristics if this is a real identifier. 671 // Unlikely identifiers are OK if they were used as identifiers nearby. 672 if (Word.ExpandedToken) 673 return nullptr; 674 // We don't want to handle words in string literals. (It'd be nice to list 675 // *allowed* token kinds explicitly, but comment Tokens aren't retained). 676 if (Word.PartOfSpelledToken && 677 isStringLiteral(Word.PartOfSpelledToken->kind())) 678 return {}; 679 680 const SourceManager &SM = TB.sourceManager(); 681 // We prefer the closest possible token, line-wise. Backwards is penalized. 682 // Ties are implicitly broken by traversal order (first-one-wins). 683 auto File = SM.getFileID(Word.Location); 684 unsigned WordLine = SM.getSpellingLineNumber(Word.Location); 685 auto Cost = [&](SourceLocation Loc) -> unsigned { 686 assert(SM.getFileID(Loc) == File && "spelled token in wrong file?"); 687 unsigned Line = SM.getSpellingLineNumber(Loc); 688 return Line >= WordLine ? Line - WordLine : 2 * (WordLine - Line); 689 }; 690 const syntax::Token *BestTok = nullptr; 691 unsigned BestCost = -1; 692 // Search bounds are based on word length: 693 // - forward: 2^N lines 694 // - backward: 2^(N-1) lines. 695 unsigned MaxDistance = 696 1U << std::min<unsigned>(Word.Text.size(), 697 std::numeric_limits<unsigned>::digits - 1); 698 // Line number for SM.translateLineCol() should be one-based, also 699 // SM.translateLineCol() can handle line number greater than 700 // number of lines in the file. 701 // - LineMin = max(1, WordLine + 1 - 2^(N-1)) 702 // - LineMax = WordLine + 1 + 2^N 703 unsigned LineMin = 704 WordLine + 1 <= MaxDistance / 2 ? 1 : WordLine + 1 - MaxDistance / 2; 705 unsigned LineMax = WordLine + 1 + MaxDistance; 706 SourceLocation LocMin = SM.translateLineCol(File, LineMin, 1); 707 assert(LocMin.isValid()); 708 SourceLocation LocMax = SM.translateLineCol(File, LineMax, 1); 709 assert(LocMax.isValid()); 710 711 // Updates BestTok and BestCost if Tok is a good candidate. 712 // May return true if the cost is too high for this token. 713 auto Consider = [&](const syntax::Token &Tok) { 714 if (Tok.location() < LocMin || Tok.location() > LocMax) 715 return true; // we are too far from the word, break the outer loop. 716 if (!(Tok.kind() == tok::identifier && Tok.text(SM) == Word.Text)) 717 return false; 718 // No point guessing the same location we started with. 719 if (Tok.location() == Word.Location) 720 return false; 721 // We've done cheap checks, compute cost so we can break the caller's loop. 722 unsigned TokCost = Cost(Tok.location()); 723 if (TokCost >= BestCost) 724 return true; // causes the outer loop to break. 725 // Allow locations that might be part of the AST, and macros (even if empty) 726 // but not things like disabled preprocessor sections. 727 if (!(tokenSpelledAt(Tok.location(), TB) || TB.expansionStartingAt(&Tok))) 728 return false; 729 // We already verified this token is an improvement. 730 BestCost = TokCost; 731 BestTok = &Tok; 732 return false; 733 }; 734 auto SpelledTokens = TB.spelledTokens(File); 735 // Find where the word occurred in the token stream, to search forward & back. 736 auto *I = llvm::partition_point(SpelledTokens, [&](const syntax::Token &T) { 737 assert(SM.getFileID(T.location()) == SM.getFileID(Word.Location)); 738 return T.location() < Word.Location; // Comparison OK: same file. 739 }); 740 // Search for matches after the cursor. 741 for (const syntax::Token &Tok : llvm::makeArrayRef(I, SpelledTokens.end())) 742 if (Consider(Tok)) 743 break; // costs of later tokens are greater... 744 // Search for matches before the cursor. 745 for (const syntax::Token &Tok : 746 llvm::reverse(llvm::makeArrayRef(SpelledTokens.begin(), I))) 747 if (Consider(Tok)) 748 break; 749 750 if (BestTok) 751 vlog( 752 "Word {0} under cursor {1} isn't a token (after PP), trying nearby {2}", 753 Word.Text, Word.Location.printToString(SM), 754 BestTok->location().printToString(SM)); 755 756 return BestTok; 757 } 758 759 std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, 760 const SymbolIndex *Index) { 761 const auto &SM = AST.getSourceManager(); 762 auto MainFilePath = 763 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); 764 if (!MainFilePath) { 765 elog("Failed to get a path for the main file, so no references"); 766 return {}; 767 } 768 769 if (auto File = locateFileReferent(Pos, AST, *MainFilePath)) 770 return {std::move(*File)}; 771 772 auto CurLoc = sourceLocationInMainFile(SM, Pos); 773 if (!CurLoc) { 774 elog("locateSymbolAt failed to convert position to source location: {0}", 775 CurLoc.takeError()); 776 return {}; 777 } 778 779 const syntax::Token *TouchedIdentifier = nullptr; 780 auto TokensTouchingCursor = 781 syntax::spelledTokensTouching(*CurLoc, AST.getTokens()); 782 for (const syntax::Token &Tok : TokensTouchingCursor) { 783 if (Tok.kind() == tok::identifier) { 784 if (auto Macro = locateMacroReferent(Tok, AST, *MainFilePath)) 785 // Don't look at the AST or index if we have a macro result. 786 // (We'd just return declarations referenced from the macro's 787 // expansion.) 788 return {*std::move(Macro)}; 789 790 TouchedIdentifier = &Tok; 791 break; 792 } 793 794 if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) { 795 // go-to-definition on auto should find the definition of the deduced 796 // type, if possible 797 if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) { 798 auto LocSym = locateSymbolForType(AST, *Deduced); 799 if (!LocSym.empty()) 800 return LocSym; 801 } 802 } 803 } 804 805 ASTNodeKind NodeKind; 806 auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST, 807 *MainFilePath, Index, NodeKind); 808 if (!ASTResults.empty()) 809 return ASTResults; 810 811 // If the cursor can't be resolved directly, try fallback strategies. 812 auto Word = 813 SpelledWord::touching(*CurLoc, AST.getTokens(), AST.getLangOpts()); 814 if (Word) { 815 // Is the same word nearby a real identifier that might refer to something? 816 if (const syntax::Token *NearbyIdent = 817 findNearbyIdentifier(*Word, AST.getTokens())) { 818 if (auto Macro = locateMacroReferent(*NearbyIdent, AST, *MainFilePath)) { 819 log("Found macro definition heuristically using nearby identifier {0}", 820 Word->Text); 821 return {*std::move(Macro)}; 822 } 823 ASTResults = locateASTReferent(NearbyIdent->location(), NearbyIdent, AST, 824 *MainFilePath, Index, NodeKind); 825 if (!ASTResults.empty()) { 826 log("Found definition heuristically using nearby identifier {0}", 827 NearbyIdent->text(SM)); 828 return ASTResults; 829 } 830 vlog("No definition found using nearby identifier {0} at {1}", Word->Text, 831 Word->Location.printToString(SM)); 832 } 833 // No nearby word, or it didn't refer to anything either. Try the index. 834 auto TextualResults = 835 locateSymbolTextually(*Word, AST, Index, *MainFilePath, NodeKind); 836 if (!TextualResults.empty()) 837 return TextualResults; 838 } 839 840 return {}; 841 } 842 843 std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) { 844 const auto &SM = AST.getSourceManager(); 845 auto MainFilePath = 846 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); 847 if (!MainFilePath) { 848 elog("Failed to get a path for the main file, so no links"); 849 return {}; 850 } 851 852 std::vector<DocumentLink> Result; 853 for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { 854 if (Inc.Resolved.empty()) 855 continue; 856 auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset); 857 const auto *HashTok = AST.getTokens().spelledTokenAt(HashLoc); 858 assert(HashTok && "got inclusion at wrong offset"); 859 const auto *IncludeTok = std::next(HashTok); 860 const auto *FileTok = std::next(IncludeTok); 861 // FileTok->range is not sufficient here, as raw lexing wouldn't yield 862 // correct tokens for angled filenames. Hence we explicitly use 863 // Inc.Written's length. 864 auto FileRange = 865 syntax::FileRange(SM, FileTok->location(), Inc.Written.length()) 866 .toCharRange(SM); 867 868 Result.push_back( 869 DocumentLink({halfOpenToRange(SM, FileRange), 870 URIForFile::canonicalize(Inc.Resolved, *MainFilePath)})); 871 } 872 873 return Result; 874 } 875 876 namespace { 877 878 /// Collects references to symbols within the main file. 879 class ReferenceFinder : public index::IndexDataConsumer { 880 public: 881 struct Reference { 882 syntax::Token SpelledTok; 883 index::SymbolRoleSet Role; 884 SymbolID Target; 885 886 Range range(const SourceManager &SM) const { 887 return halfOpenToRange(SM, SpelledTok.range(SM).toCharRange(SM)); 888 } 889 }; 890 891 ReferenceFinder(const ParsedAST &AST, 892 const llvm::DenseSet<SymbolID> &TargetIDs, bool PerToken) 893 : PerToken(PerToken), AST(AST), TargetIDs(TargetIDs) {} 894 895 std::vector<Reference> take() && { 896 llvm::sort(References, [](const Reference &L, const Reference &R) { 897 auto LTok = L.SpelledTok.location(); 898 auto RTok = R.SpelledTok.location(); 899 return std::tie(LTok, L.Role) < std::tie(RTok, R.Role); 900 }); 901 // We sometimes see duplicates when parts of the AST get traversed twice. 902 References.erase(std::unique(References.begin(), References.end(), 903 [](const Reference &L, const Reference &R) { 904 auto LTok = L.SpelledTok.location(); 905 auto RTok = R.SpelledTok.location(); 906 return std::tie(LTok, L.Role) == 907 std::tie(RTok, R.Role); 908 }), 909 References.end()); 910 return std::move(References); 911 } 912 913 bool 914 handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles, 915 llvm::ArrayRef<index::SymbolRelation> Relations, 916 SourceLocation Loc, 917 index::IndexDataConsumer::ASTNodeInfo ASTNode) override { 918 const SourceManager &SM = AST.getSourceManager(); 919 if (!isInsideMainFile(Loc, SM)) 920 return true; 921 SymbolID ID = getSymbolID(D); 922 if (!TargetIDs.contains(ID)) 923 return true; 924 const auto &TB = AST.getTokens(); 925 926 llvm::SmallVector<SourceLocation, 1> Locs; 927 if (PerToken) { 928 // Check whether this is one of the few constructs where the reference 929 // can be split over several tokens. 930 if (auto *OME = llvm::dyn_cast_or_null<ObjCMessageExpr>(ASTNode.OrigE)) { 931 OME->getSelectorLocs(Locs); 932 } else if (auto *OMD = 933 llvm::dyn_cast_or_null<ObjCMethodDecl>(ASTNode.OrigD)) { 934 OMD->getSelectorLocs(Locs); 935 } 936 // Sanity check: we expect the *first* token to match the reported loc. 937 // Otherwise, maybe it was e.g. some other kind of reference to a Decl. 938 if (!Locs.empty() && Locs.front() != Loc) 939 Locs.clear(); // First token doesn't match, assume our guess was wrong. 940 } 941 if (Locs.empty()) 942 Locs.push_back(Loc); 943 944 for (SourceLocation L : Locs) { 945 L = SM.getFileLoc(L); 946 if (const auto *Tok = TB.spelledTokenAt(L)) 947 References.push_back({*Tok, Roles, ID}); 948 } 949 return true; 950 } 951 952 private: 953 bool PerToken; // If true, report 3 references for split ObjC selector names. 954 std::vector<Reference> References; 955 const ParsedAST &AST; 956 const llvm::DenseSet<SymbolID> &TargetIDs; 957 }; 958 959 std::vector<ReferenceFinder::Reference> 960 findRefs(const llvm::DenseSet<SymbolID> &IDs, ParsedAST &AST, bool PerToken) { 961 ReferenceFinder RefFinder(AST, IDs, PerToken); 962 index::IndexingOptions IndexOpts; 963 IndexOpts.SystemSymbolFilter = 964 index::IndexingOptions::SystemSymbolFilterKind::All; 965 IndexOpts.IndexFunctionLocals = true; 966 IndexOpts.IndexParametersInDeclarations = true; 967 IndexOpts.IndexTemplateParameters = true; 968 indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(), 969 AST.getLocalTopLevelDecls(), RefFinder, IndexOpts); 970 return std::move(RefFinder).take(); 971 } 972 973 const Stmt *getFunctionBody(DynTypedNode N) { 974 if (const auto *FD = N.get<FunctionDecl>()) 975 return FD->getBody(); 976 if (const auto *FD = N.get<BlockDecl>()) 977 return FD->getBody(); 978 if (const auto *FD = N.get<LambdaExpr>()) 979 return FD->getBody(); 980 if (const auto *FD = N.get<ObjCMethodDecl>()) 981 return FD->getBody(); 982 return nullptr; 983 } 984 985 const Stmt *getLoopBody(DynTypedNode N) { 986 if (const auto *LS = N.get<ForStmt>()) 987 return LS->getBody(); 988 if (const auto *LS = N.get<CXXForRangeStmt>()) 989 return LS->getBody(); 990 if (const auto *LS = N.get<WhileStmt>()) 991 return LS->getBody(); 992 if (const auto *LS = N.get<DoStmt>()) 993 return LS->getBody(); 994 return nullptr; 995 } 996 997 // AST traversal to highlight control flow statements under some root. 998 // Once we hit further control flow we prune the tree (or at least restrict 999 // what we highlight) so we capture e.g. breaks from the outer loop only. 1000 class FindControlFlow : public RecursiveASTVisitor<FindControlFlow> { 1001 // Types of control-flow statements we might highlight. 1002 enum Target { 1003 Break = 1, 1004 Continue = 2, 1005 Return = 4, 1006 Case = 8, 1007 Throw = 16, 1008 Goto = 32, 1009 All = Break | Continue | Return | Case | Throw | Goto, 1010 }; 1011 int Ignore = 0; // bitmask of Target - what are we *not* highlighting? 1012 SourceRange Bounds; // Half-open, restricts reported targets. 1013 std::vector<SourceLocation> &Result; 1014 const SourceManager &SM; 1015 1016 // Masks out targets for a traversal into D. 1017 // Traverses the subtree using Delegate() if any targets remain. 1018 template <typename Func> 1019 bool filterAndTraverse(DynTypedNode D, const Func &Delegate) { 1020 auto RestoreIgnore = llvm::make_scope_exit( 1021 [OldIgnore(Ignore), this] { Ignore = OldIgnore; }); 1022 if (getFunctionBody(D)) 1023 Ignore = All; 1024 else if (getLoopBody(D)) 1025 Ignore |= Continue | Break; 1026 else if (D.get<SwitchStmt>()) 1027 Ignore |= Break | Case; 1028 // Prune tree if we're not looking for anything. 1029 return (Ignore == All) ? true : Delegate(); 1030 } 1031 1032 void found(Target T, SourceLocation Loc) { 1033 if (T & Ignore) 1034 return; 1035 if (SM.isBeforeInTranslationUnit(Loc, Bounds.getBegin()) || 1036 SM.isBeforeInTranslationUnit(Bounds.getEnd(), Loc)) 1037 return; 1038 Result.push_back(Loc); 1039 } 1040 1041 public: 1042 FindControlFlow(SourceRange Bounds, std::vector<SourceLocation> &Result, 1043 const SourceManager &SM) 1044 : Bounds(Bounds), Result(Result), SM(SM) {} 1045 1046 // When traversing function or loops, limit targets to those that still 1047 // refer to the original root. 1048 bool TraverseDecl(Decl *D) { 1049 return !D || filterAndTraverse(DynTypedNode::create(*D), [&] { 1050 return RecursiveASTVisitor::TraverseDecl(D); 1051 }); 1052 } 1053 bool TraverseStmt(Stmt *S) { 1054 return !S || filterAndTraverse(DynTypedNode::create(*S), [&] { 1055 return RecursiveASTVisitor::TraverseStmt(S); 1056 }); 1057 } 1058 1059 // Add leaves that we found and want. 1060 bool VisitReturnStmt(ReturnStmt *R) { 1061 found(Return, R->getReturnLoc()); 1062 return true; 1063 } 1064 bool VisitBreakStmt(BreakStmt *B) { 1065 found(Break, B->getBreakLoc()); 1066 return true; 1067 } 1068 bool VisitContinueStmt(ContinueStmt *C) { 1069 found(Continue, C->getContinueLoc()); 1070 return true; 1071 } 1072 bool VisitSwitchCase(SwitchCase *C) { 1073 found(Case, C->getKeywordLoc()); 1074 return true; 1075 } 1076 bool VisitCXXThrowExpr(CXXThrowExpr *T) { 1077 found(Throw, T->getThrowLoc()); 1078 return true; 1079 } 1080 bool VisitGotoStmt(GotoStmt *G) { 1081 // Goto is interesting if its target is outside the root. 1082 if (const auto *LD = G->getLabel()) { 1083 if (SM.isBeforeInTranslationUnit(LD->getLocation(), Bounds.getBegin()) || 1084 SM.isBeforeInTranslationUnit(Bounds.getEnd(), LD->getLocation())) 1085 found(Goto, G->getGotoLoc()); 1086 } 1087 return true; 1088 } 1089 }; 1090 1091 // Given a location within a switch statement, return the half-open range that 1092 // covers the case it's contained in. 1093 // We treat `case X: case Y: ...` as one case, and assume no other fallthrough. 1094 SourceRange findCaseBounds(const SwitchStmt &Switch, SourceLocation Loc, 1095 const SourceManager &SM) { 1096 // Cases are not stored in order, sort them first. 1097 // (In fact they seem to be stored in reverse order, don't rely on this) 1098 std::vector<const SwitchCase *> Cases; 1099 for (const SwitchCase *Case = Switch.getSwitchCaseList(); Case; 1100 Case = Case->getNextSwitchCase()) 1101 Cases.push_back(Case); 1102 llvm::sort(Cases, [&](const SwitchCase *L, const SwitchCase *R) { 1103 return SM.isBeforeInTranslationUnit(L->getKeywordLoc(), R->getKeywordLoc()); 1104 }); 1105 1106 // Find the first case after the target location, the end of our range. 1107 auto CaseAfter = llvm::partition_point(Cases, [&](const SwitchCase *C) { 1108 return !SM.isBeforeInTranslationUnit(Loc, C->getKeywordLoc()); 1109 }); 1110 SourceLocation End = CaseAfter == Cases.end() ? Switch.getEndLoc() 1111 : (*CaseAfter)->getKeywordLoc(); 1112 1113 // Our target can be before the first case - cases are optional! 1114 if (CaseAfter == Cases.begin()) 1115 return SourceRange(Switch.getBeginLoc(), End); 1116 // The start of our range is usually the previous case, but... 1117 auto CaseBefore = std::prev(CaseAfter); 1118 // ... rewind CaseBefore to the first in a `case A: case B: ...` sequence. 1119 while (CaseBefore != Cases.begin() && 1120 (*std::prev(CaseBefore))->getSubStmt() == *CaseBefore) 1121 --CaseBefore; 1122 return SourceRange((*CaseBefore)->getKeywordLoc(), End); 1123 } 1124 1125 // Returns the locations of control flow statements related to N. e.g.: 1126 // for => branches: break/continue/return/throw 1127 // break => controlling loop (forwhile/do), and its related control flow 1128 // return => all returns/throws from the same function 1129 // When an inner block is selected, we include branches bound to outer blocks 1130 // as these are exits from the inner block. e.g. return in a for loop. 1131 // FIXME: We don't analyze catch blocks, throw is treated the same as return. 1132 std::vector<SourceLocation> relatedControlFlow(const SelectionTree::Node &N) { 1133 const SourceManager &SM = 1134 N.getDeclContext().getParentASTContext().getSourceManager(); 1135 std::vector<SourceLocation> Result; 1136 1137 // First, check if we're at a node that can resolve to a root. 1138 enum class Cur { None, Break, Continue, Return, Case, Throw } Cursor; 1139 if (N.ASTNode.get<BreakStmt>()) { 1140 Cursor = Cur::Break; 1141 } else if (N.ASTNode.get<ContinueStmt>()) { 1142 Cursor = Cur::Continue; 1143 } else if (N.ASTNode.get<ReturnStmt>()) { 1144 Cursor = Cur::Return; 1145 } else if (N.ASTNode.get<CXXThrowExpr>()) { 1146 Cursor = Cur::Throw; 1147 } else if (N.ASTNode.get<SwitchCase>()) { 1148 Cursor = Cur::Case; 1149 } else if (const GotoStmt *GS = N.ASTNode.get<GotoStmt>()) { 1150 // We don't know what root to associate with, but highlight the goto/label. 1151 Result.push_back(GS->getGotoLoc()); 1152 if (const auto *LD = GS->getLabel()) 1153 Result.push_back(LD->getLocation()); 1154 Cursor = Cur::None; 1155 } else { 1156 Cursor = Cur::None; 1157 } 1158 1159 const Stmt *Root = nullptr; // Loop or function body to traverse. 1160 SourceRange Bounds; 1161 // Look up the tree for a root (or just at this node if we didn't find a leaf) 1162 for (const auto *P = &N; P; P = P->Parent) { 1163 // return associates with enclosing function 1164 if (const Stmt *FunctionBody = getFunctionBody(P->ASTNode)) { 1165 if (Cursor == Cur::Return || Cursor == Cur::Throw) { 1166 Root = FunctionBody; 1167 } 1168 break; // other leaves don't cross functions. 1169 } 1170 // break/continue associate with enclosing loop. 1171 if (const Stmt *LoopBody = getLoopBody(P->ASTNode)) { 1172 if (Cursor == Cur::None || Cursor == Cur::Break || 1173 Cursor == Cur::Continue) { 1174 Root = LoopBody; 1175 // Highlight the loop keyword itself. 1176 // FIXME: for do-while, this only covers the `do`.. 1177 Result.push_back(P->ASTNode.getSourceRange().getBegin()); 1178 break; 1179 } 1180 } 1181 // For switches, users think of case statements as control flow blocks. 1182 // We highlight only occurrences surrounded by the same case. 1183 // We don't detect fallthrough (other than 'case X, case Y'). 1184 if (const auto *SS = P->ASTNode.get<SwitchStmt>()) { 1185 if (Cursor == Cur::Break || Cursor == Cur::Case) { 1186 Result.push_back(SS->getSwitchLoc()); // Highlight the switch. 1187 Root = SS->getBody(); 1188 // Limit to enclosing case, if there is one. 1189 Bounds = findCaseBounds(*SS, N.ASTNode.getSourceRange().getBegin(), SM); 1190 break; 1191 } 1192 } 1193 // If we didn't start at some interesting node, we're done. 1194 if (Cursor == Cur::None) 1195 break; 1196 } 1197 if (Root) { 1198 if (!Bounds.isValid()) 1199 Bounds = Root->getSourceRange(); 1200 FindControlFlow(Bounds, Result, SM).TraverseStmt(const_cast<Stmt *>(Root)); 1201 } 1202 return Result; 1203 } 1204 1205 DocumentHighlight toHighlight(const ReferenceFinder::Reference &Ref, 1206 const SourceManager &SM) { 1207 DocumentHighlight DH; 1208 DH.range = Ref.range(SM); 1209 if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write)) 1210 DH.kind = DocumentHighlightKind::Write; 1211 else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read)) 1212 DH.kind = DocumentHighlightKind::Read; 1213 else 1214 DH.kind = DocumentHighlightKind::Text; 1215 return DH; 1216 } 1217 1218 llvm::Optional<DocumentHighlight> toHighlight(SourceLocation Loc, 1219 const syntax::TokenBuffer &TB) { 1220 Loc = TB.sourceManager().getFileLoc(Loc); 1221 if (const auto *Tok = TB.spelledTokenAt(Loc)) { 1222 DocumentHighlight Result; 1223 Result.range = halfOpenToRange( 1224 TB.sourceManager(), 1225 CharSourceRange::getCharRange(Tok->location(), Tok->endLocation())); 1226 return Result; 1227 } 1228 return llvm::None; 1229 } 1230 1231 } // namespace 1232 1233 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST, 1234 Position Pos) { 1235 const SourceManager &SM = AST.getSourceManager(); 1236 // FIXME: show references to macro within file? 1237 auto CurLoc = sourceLocationInMainFile(SM, Pos); 1238 if (!CurLoc) { 1239 llvm::consumeError(CurLoc.takeError()); 1240 return {}; 1241 } 1242 std::vector<DocumentHighlight> Result; 1243 auto TryTree = [&](SelectionTree ST) { 1244 if (const SelectionTree::Node *N = ST.commonAncestor()) { 1245 DeclRelationSet Relations = 1246 DeclRelation::TemplatePattern | DeclRelation::Alias; 1247 auto Decls = 1248 targetDecl(N->ASTNode, Relations, AST.getHeuristicResolver()); 1249 if (!Decls.empty()) { 1250 // FIXME: we may get multiple DocumentHighlights with the same location 1251 // and different kinds, deduplicate them. 1252 llvm::DenseSet<SymbolID> Targets; 1253 for (const NamedDecl *ND : Decls) 1254 if (auto ID = getSymbolID(ND)) 1255 Targets.insert(ID); 1256 for (const auto &Ref : findRefs(Targets, AST, /*PerToken=*/true)) 1257 Result.push_back(toHighlight(Ref, SM)); 1258 return true; 1259 } 1260 auto ControlFlow = relatedControlFlow(*N); 1261 if (!ControlFlow.empty()) { 1262 for (SourceLocation Loc : ControlFlow) 1263 if (auto Highlight = toHighlight(Loc, AST.getTokens())) 1264 Result.push_back(std::move(*Highlight)); 1265 return true; 1266 } 1267 } 1268 return false; 1269 }; 1270 1271 unsigned Offset = 1272 AST.getSourceManager().getDecomposedSpellingLoc(*CurLoc).second; 1273 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, 1274 Offset, TryTree); 1275 return Result; 1276 } 1277 1278 std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos, 1279 const SymbolIndex *Index) { 1280 // We rely on index to find the implementations in subclasses. 1281 // FIXME: Index can be stale, so we may loose some latest results from the 1282 // main file. 1283 if (!Index) 1284 return {}; 1285 const SourceManager &SM = AST.getSourceManager(); 1286 auto MainFilePath = 1287 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); 1288 if (!MainFilePath) { 1289 elog("Failed to get a path for the main file, so no implementations."); 1290 return {}; 1291 } 1292 auto CurLoc = sourceLocationInMainFile(SM, Pos); 1293 if (!CurLoc) { 1294 elog("Failed to convert position to source location: {0}", 1295 CurLoc.takeError()); 1296 return {}; 1297 } 1298 DeclRelationSet Relations = 1299 DeclRelation::TemplatePattern | DeclRelation::Alias; 1300 llvm::DenseSet<SymbolID> IDs; 1301 RelationKind QueryKind; 1302 for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations)) { 1303 if (const auto *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND)) { 1304 if (CXXMD->isVirtual()) { 1305 IDs.insert(getSymbolID(ND)); 1306 QueryKind = RelationKind::OverriddenBy; 1307 } 1308 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { 1309 IDs.insert(getSymbolID(RD)); 1310 QueryKind = RelationKind::BaseOf; 1311 } 1312 } 1313 return findImplementors(std::move(IDs), QueryKind, Index, *MainFilePath); 1314 } 1315 1316 namespace { 1317 // Recursively finds all the overridden methods of `CMD` in complete type 1318 // hierarchy. 1319 void getOverriddenMethods(const CXXMethodDecl *CMD, 1320 llvm::DenseSet<SymbolID> &OverriddenMethods) { 1321 if (!CMD) 1322 return; 1323 for (const CXXMethodDecl *Base : CMD->overridden_methods()) { 1324 if (auto ID = getSymbolID(Base)) 1325 OverriddenMethods.insert(ID); 1326 getOverriddenMethods(Base, OverriddenMethods); 1327 } 1328 } 1329 } // namespace 1330 1331 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, 1332 const SymbolIndex *Index) { 1333 if (!Limit) 1334 Limit = std::numeric_limits<uint32_t>::max(); 1335 ReferencesResult Results; 1336 const SourceManager &SM = AST.getSourceManager(); 1337 auto MainFilePath = 1338 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); 1339 if (!MainFilePath) { 1340 elog("Failed to get a path for the main file, so no references"); 1341 return Results; 1342 } 1343 auto URIMainFile = URIForFile::canonicalize(*MainFilePath, *MainFilePath); 1344 auto CurLoc = sourceLocationInMainFile(SM, Pos); 1345 if (!CurLoc) { 1346 llvm::consumeError(CurLoc.takeError()); 1347 return {}; 1348 } 1349 1350 llvm::DenseSet<SymbolID> IDs, OverriddenMethods; 1351 1352 const auto *IdentifierAtCursor = 1353 syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); 1354 llvm::Optional<DefinedMacro> Macro; 1355 if (IdentifierAtCursor) 1356 Macro = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor()); 1357 if (Macro) { 1358 // Handle references to macro. 1359 if (auto MacroSID = getSymbolID(Macro->Name, Macro->Info, SM)) { 1360 // Collect macro references from main file. 1361 const auto &IDToRefs = AST.getMacros().MacroRefs; 1362 auto Refs = IDToRefs.find(MacroSID); 1363 if (Refs != IDToRefs.end()) { 1364 for (const auto &Ref : Refs->second) { 1365 ReferencesResult::Reference Result; 1366 Result.Loc.range = Ref.Rng; 1367 Result.Loc.uri = URIMainFile; 1368 if (Ref.IsDefinition) { 1369 Result.Attributes |= ReferencesResult::Declaration; 1370 Result.Attributes |= ReferencesResult::Definition; 1371 } 1372 Results.References.push_back(std::move(Result)); 1373 } 1374 } 1375 IDs.insert(MacroSID); 1376 } 1377 } else { 1378 // Handle references to Decls. 1379 1380 DeclRelationSet Relations = 1381 DeclRelation::TemplatePattern | DeclRelation::Alias; 1382 std::vector<const NamedDecl *> Decls = 1383 getDeclAtPosition(AST, *CurLoc, Relations); 1384 llvm::DenseSet<SymbolID> Targets; 1385 for (const NamedDecl *D : Decls) 1386 if (auto ID = getSymbolID(D)) 1387 Targets.insert(ID); 1388 1389 RelationsRequest OverriddenBy; 1390 if (Index) { 1391 OverriddenBy.Predicate = RelationKind::OverriddenBy; 1392 for (const NamedDecl *ND : Decls) { 1393 // Special case: For virtual methods, report decl/def of overrides and 1394 // references to all overridden methods in complete type hierarchy. 1395 if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(ND)) { 1396 if (CMD->isVirtual()) { 1397 if (auto ID = getSymbolID(CMD)) 1398 OverriddenBy.Subjects.insert(ID); 1399 getOverriddenMethods(CMD, OverriddenMethods); 1400 } 1401 } 1402 } 1403 } 1404 1405 // We traverse the AST to find references in the main file. 1406 auto MainFileRefs = findRefs(Targets, AST, /*PerToken=*/false); 1407 // We may get multiple refs with the same location and different Roles, as 1408 // cross-reference is only interested in locations, we deduplicate them 1409 // by the location to avoid emitting duplicated locations. 1410 MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(), 1411 [](const ReferenceFinder::Reference &L, 1412 const ReferenceFinder::Reference &R) { 1413 return L.SpelledTok.location() == 1414 R.SpelledTok.location(); 1415 }), 1416 MainFileRefs.end()); 1417 for (const auto &Ref : MainFileRefs) { 1418 ReferencesResult::Reference Result; 1419 Result.Loc.range = Ref.range(SM); 1420 Result.Loc.uri = URIMainFile; 1421 if (Ref.Role & static_cast<unsigned>(index::SymbolRole::Declaration)) 1422 Result.Attributes |= ReferencesResult::Declaration; 1423 // clang-index doesn't report definitions as declarations, but they are. 1424 if (Ref.Role & static_cast<unsigned>(index::SymbolRole::Definition)) 1425 Result.Attributes |= 1426 ReferencesResult::Definition | ReferencesResult::Declaration; 1427 Results.References.push_back(std::move(Result)); 1428 } 1429 // Add decl/def of overridding methods. 1430 if (Index && Results.References.size() <= Limit && 1431 !OverriddenBy.Subjects.empty()) 1432 Index->relations( 1433 OverriddenBy, [&](const SymbolID &Subject, const Symbol &Object) { 1434 const auto LSPLocDecl = 1435 toLSPLocation(Object.CanonicalDeclaration, *MainFilePath); 1436 const auto LSPLocDef = 1437 toLSPLocation(Object.Definition, *MainFilePath); 1438 if (LSPLocDecl && LSPLocDecl != LSPLocDef) { 1439 ReferencesResult::Reference Result; 1440 Result.Loc = std::move(*LSPLocDecl); 1441 Result.Attributes = 1442 ReferencesResult::Declaration | ReferencesResult::Override; 1443 Results.References.push_back(std::move(Result)); 1444 } 1445 if (LSPLocDef) { 1446 ReferencesResult::Reference Result; 1447 Result.Loc = std::move(*LSPLocDef); 1448 Result.Attributes = ReferencesResult::Declaration | 1449 ReferencesResult::Definition | 1450 ReferencesResult::Override; 1451 Results.References.push_back(std::move(Result)); 1452 } 1453 }); 1454 1455 if (Index && Results.References.size() <= Limit) { 1456 for (const Decl *D : Decls) { 1457 // Not all symbols can be referenced from outside (e.g. 1458 // function-locals). 1459 // TODO: we could skip TU-scoped symbols here (e.g. static functions) if 1460 // we know this file isn't a header. The details might be tricky. 1461 if (D->getParentFunctionOrMethod()) 1462 continue; 1463 if (auto ID = getSymbolID(D)) 1464 IDs.insert(ID); 1465 } 1466 } 1467 } 1468 // Now query the index for references from other files. 1469 auto QueryIndex = [&](llvm::DenseSet<SymbolID> IDs, bool AllowAttributes, 1470 bool AllowMainFileSymbols) { 1471 RefsRequest Req; 1472 Req.IDs = std::move(IDs); 1473 Req.Limit = Limit; 1474 if (Req.IDs.empty() || !Index || Results.References.size() > Limit) 1475 return; 1476 Results.HasMore |= Index->refs(Req, [&](const Ref &R) { 1477 // No need to continue process if we reach the limit. 1478 if (Results.References.size() > Limit) 1479 return; 1480 auto LSPLoc = toLSPLocation(R.Location, *MainFilePath); 1481 // Avoid indexed results for the main file - the AST is authoritative. 1482 if (!LSPLoc || 1483 (!AllowMainFileSymbols && LSPLoc->uri.file() == *MainFilePath)) 1484 return; 1485 ReferencesResult::Reference Result; 1486 Result.Loc = std::move(*LSPLoc); 1487 if (AllowAttributes) { 1488 if ((R.Kind & RefKind::Declaration) == RefKind::Declaration) 1489 Result.Attributes |= ReferencesResult::Declaration; 1490 // FIXME: our index should definitely store def | decl separately! 1491 if ((R.Kind & RefKind::Definition) == RefKind::Definition) 1492 Result.Attributes |= 1493 ReferencesResult::Declaration | ReferencesResult::Definition; 1494 } 1495 Results.References.push_back(std::move(Result)); 1496 }); 1497 }; 1498 QueryIndex(std::move(IDs), /*AllowAttributes=*/true, 1499 /*AllowMainFileSymbols=*/false); 1500 // For a virtual method: Occurrences of BaseMethod should be treated as refs 1501 // and not as decl/def. Allow symbols from main file since AST does not report 1502 // these. 1503 QueryIndex(std::move(OverriddenMethods), /*AllowAttributes=*/false, 1504 /*AllowMainFileSymbols=*/true); 1505 if (Results.References.size() > Limit) { 1506 Results.HasMore = true; 1507 Results.References.resize(Limit); 1508 } 1509 return Results; 1510 } 1511 1512 std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) { 1513 const SourceManager &SM = AST.getSourceManager(); 1514 auto CurLoc = sourceLocationInMainFile(SM, Pos); 1515 if (!CurLoc) { 1516 llvm::consumeError(CurLoc.takeError()); 1517 return {}; 1518 } 1519 1520 std::vector<SymbolDetails> Results; 1521 1522 // We also want the targets of using-decls, so we include 1523 // DeclRelation::Underlying. 1524 DeclRelationSet Relations = DeclRelation::TemplatePattern | 1525 DeclRelation::Alias | DeclRelation::Underlying; 1526 for (const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) { 1527 SymbolDetails NewSymbol; 1528 std::string QName = printQualifiedName(*D); 1529 auto SplitQName = splitQualifiedName(QName); 1530 NewSymbol.containerName = std::string(SplitQName.first); 1531 NewSymbol.name = std::string(SplitQName.second); 1532 1533 if (NewSymbol.containerName.empty()) { 1534 if (const auto *ParentND = 1535 dyn_cast_or_null<NamedDecl>(D->getDeclContext())) 1536 NewSymbol.containerName = printQualifiedName(*ParentND); 1537 } 1538 llvm::SmallString<32> USR; 1539 if (!index::generateUSRForDecl(D, USR)) { 1540 NewSymbol.USR = std::string(USR.str()); 1541 NewSymbol.ID = SymbolID(NewSymbol.USR); 1542 } 1543 Results.push_back(std::move(NewSymbol)); 1544 } 1545 1546 const auto *IdentifierAtCursor = 1547 syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); 1548 if (!IdentifierAtCursor) 1549 return Results; 1550 1551 if (auto M = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor())) { 1552 SymbolDetails NewMacro; 1553 NewMacro.name = std::string(M->Name); 1554 llvm::SmallString<32> USR; 1555 if (!index::generateUSRForMacro(NewMacro.name, M->Info->getDefinitionLoc(), 1556 SM, USR)) { 1557 NewMacro.USR = std::string(USR.str()); 1558 NewMacro.ID = SymbolID(NewMacro.USR); 1559 } 1560 Results.push_back(std::move(NewMacro)); 1561 } 1562 1563 return Results; 1564 } 1565 1566 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) { 1567 OS << S.Name << ": " << S.PreferredDeclaration; 1568 if (S.Definition) 1569 OS << " def=" << *S.Definition; 1570 return OS; 1571 } 1572 1573 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 1574 const ReferencesResult::Reference &R) { 1575 OS << R.Loc; 1576 if (R.Attributes & ReferencesResult::Declaration) 1577 OS << " [decl]"; 1578 if (R.Attributes & ReferencesResult::Definition) 1579 OS << " [def]"; 1580 if (R.Attributes & ReferencesResult::Override) 1581 OS << " [override]"; 1582 return OS; 1583 } 1584 1585 template <typename HierarchyItem> 1586 static llvm::Optional<HierarchyItem> declToHierarchyItem(const NamedDecl &ND) { 1587 ASTContext &Ctx = ND.getASTContext(); 1588 auto &SM = Ctx.getSourceManager(); 1589 SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager()); 1590 SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc())); 1591 SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc())); 1592 const auto DeclRange = 1593 toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc}); 1594 if (!DeclRange) 1595 return llvm::None; 1596 auto FilePath = 1597 getCanonicalPath(SM.getFileEntryForID(SM.getFileID(NameLoc)), SM); 1598 auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); 1599 if (!FilePath || !TUPath) 1600 return llvm::None; // Not useful without a uri. 1601 1602 Position NameBegin = sourceLocToPosition(SM, NameLoc); 1603 Position NameEnd = sourceLocToPosition( 1604 SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts())); 1605 1606 index::SymbolInfo SymInfo = index::getSymbolInfo(&ND); 1607 // FIXME: This is not classifying constructors, destructors and operators 1608 // correctly. 1609 SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind); 1610 1611 HierarchyItem HI; 1612 HI.name = printName(Ctx, ND); 1613 HI.kind = SK; 1614 HI.range = Range{sourceLocToPosition(SM, DeclRange->getBegin()), 1615 sourceLocToPosition(SM, DeclRange->getEnd())}; 1616 HI.selectionRange = Range{NameBegin, NameEnd}; 1617 if (!HI.range.contains(HI.selectionRange)) { 1618 // 'selectionRange' must be contained in 'range', so in cases where clang 1619 // reports unrelated ranges we need to reconcile somehow. 1620 HI.range = HI.selectionRange; 1621 } 1622 1623 HI.uri = URIForFile::canonicalize(*FilePath, *TUPath); 1624 1625 // Compute the SymbolID and store it in the 'data' field. 1626 // This allows typeHierarchy/resolve to be used to 1627 // resolve children of items returned in a previous request 1628 // for parents. 1629 if (auto ID = getSymbolID(&ND)) 1630 HI.data = ID.str(); 1631 1632 return HI; 1633 } 1634 1635 static llvm::Optional<TypeHierarchyItem> 1636 declToTypeHierarchyItem(const NamedDecl &ND) { 1637 auto Result = declToHierarchyItem<TypeHierarchyItem>(ND); 1638 if (Result) 1639 Result->deprecated = ND.isDeprecated(); 1640 return Result; 1641 } 1642 1643 static llvm::Optional<CallHierarchyItem> 1644 declToCallHierarchyItem(const NamedDecl &ND) { 1645 auto Result = declToHierarchyItem<CallHierarchyItem>(ND); 1646 if (Result && ND.isDeprecated()) 1647 Result->tags.push_back(SymbolTag::Deprecated); 1648 return Result; 1649 } 1650 1651 template <typename HierarchyItem> 1652 static llvm::Optional<HierarchyItem> symbolToHierarchyItem(const Symbol &S, 1653 PathRef TUPath) { 1654 auto Loc = symbolToLocation(S, TUPath); 1655 if (!Loc) { 1656 elog("Failed to convert symbol to hierarchy item: {0}", Loc.takeError()); 1657 return llvm::None; 1658 } 1659 HierarchyItem HI; 1660 HI.name = std::string(S.Name); 1661 HI.kind = indexSymbolKindToSymbolKind(S.SymInfo.Kind); 1662 HI.selectionRange = Loc->range; 1663 // FIXME: Populate 'range' correctly 1664 // (https://github.com/clangd/clangd/issues/59). 1665 HI.range = HI.selectionRange; 1666 HI.uri = Loc->uri; 1667 // Store the SymbolID in the 'data' field. The client will 1668 // send this back in requests to resolve additional levels 1669 // of the hierarchy. 1670 HI.data = S.ID.str(); 1671 1672 return HI; 1673 } 1674 1675 static llvm::Optional<TypeHierarchyItem> 1676 symbolToTypeHierarchyItem(const Symbol &S, PathRef TUPath) { 1677 auto Result = symbolToHierarchyItem<TypeHierarchyItem>(S, TUPath); 1678 if (Result) 1679 Result->deprecated = (S.Flags & Symbol::Deprecated); 1680 return Result; 1681 } 1682 1683 static llvm::Optional<CallHierarchyItem> 1684 symbolToCallHierarchyItem(const Symbol &S, PathRef TUPath) { 1685 auto Result = symbolToHierarchyItem<CallHierarchyItem>(S, TUPath); 1686 if (Result && (S.Flags & Symbol::Deprecated)) 1687 Result->tags.push_back(SymbolTag::Deprecated); 1688 return Result; 1689 } 1690 1691 static void fillSubTypes(const SymbolID &ID, 1692 std::vector<TypeHierarchyItem> &SubTypes, 1693 const SymbolIndex *Index, int Levels, PathRef TUPath) { 1694 RelationsRequest Req; 1695 Req.Subjects.insert(ID); 1696 Req.Predicate = RelationKind::BaseOf; 1697 Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) { 1698 if (Optional<TypeHierarchyItem> ChildSym = 1699 symbolToTypeHierarchyItem(Object, TUPath)) { 1700 if (Levels > 1) { 1701 ChildSym->children.emplace(); 1702 fillSubTypes(Object.ID, *ChildSym->children, Index, Levels - 1, TUPath); 1703 } 1704 SubTypes.emplace_back(std::move(*ChildSym)); 1705 } 1706 }); 1707 } 1708 1709 using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>; 1710 1711 static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, 1712 std::vector<TypeHierarchyItem> &SuperTypes, 1713 RecursionProtectionSet &RPSet) { 1714 // typeParents() will replace dependent template specializations 1715 // with their class template, so to avoid infinite recursion for 1716 // certain types of hierarchies, keep the templates encountered 1717 // along the parent chain in a set, and stop the recursion if one 1718 // starts to repeat. 1719 auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr; 1720 if (Pattern) { 1721 if (!RPSet.insert(Pattern).second) { 1722 return; 1723 } 1724 } 1725 1726 for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) { 1727 if (Optional<TypeHierarchyItem> ParentSym = 1728 declToTypeHierarchyItem(*ParentDecl)) { 1729 ParentSym->parents.emplace(); 1730 fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet); 1731 SuperTypes.emplace_back(std::move(*ParentSym)); 1732 } 1733 } 1734 1735 if (Pattern) { 1736 RPSet.erase(Pattern); 1737 } 1738 } 1739 1740 const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { 1741 auto RecordFromNode = 1742 [&AST](const SelectionTree::Node *N) -> const CXXRecordDecl * { 1743 if (!N) 1744 return nullptr; 1745 1746 // Note: explicitReferenceTargets() will search for both template 1747 // instantiations and template patterns, and prefer the former if available 1748 // (generally, one will be available for non-dependent specializations of a 1749 // class template). 1750 auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying, 1751 AST.getHeuristicResolver()); 1752 if (Decls.empty()) 1753 return nullptr; 1754 1755 const NamedDecl *D = Decls[0]; 1756 1757 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 1758 // If this is a variable, use the type of the variable. 1759 return VD->getType().getTypePtr()->getAsCXXRecordDecl(); 1760 } 1761 1762 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { 1763 // If this is a method, use the type of the class. 1764 return Method->getParent(); 1765 } 1766 1767 // We don't handle FieldDecl because it's not clear what behaviour 1768 // the user would expect: the enclosing class type (as with a 1769 // method), or the field's type (as with a variable). 1770 1771 return dyn_cast<CXXRecordDecl>(D); 1772 }; 1773 1774 const SourceManager &SM = AST.getSourceManager(); 1775 const CXXRecordDecl *Result = nullptr; 1776 auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos); 1777 if (!Offset) { 1778 llvm::consumeError(Offset.takeError()); 1779 return Result; 1780 } 1781 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), *Offset, 1782 *Offset, [&](SelectionTree ST) { 1783 Result = RecordFromNode(ST.commonAncestor()); 1784 return Result != nullptr; 1785 }); 1786 return Result; 1787 } 1788 1789 std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD) { 1790 std::vector<const CXXRecordDecl *> Result; 1791 1792 // If this is an invalid instantiation, instantiation of the bases 1793 // may not have succeeded, so fall back to the template pattern. 1794 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) { 1795 if (CTSD->isInvalidDecl()) 1796 CXXRD = CTSD->getSpecializedTemplate()->getTemplatedDecl(); 1797 } 1798 1799 // Can't query bases without a definition. 1800 if (!CXXRD->hasDefinition()) 1801 return Result; 1802 1803 for (auto Base : CXXRD->bases()) { 1804 const CXXRecordDecl *ParentDecl = nullptr; 1805 1806 const Type *Type = Base.getType().getTypePtr(); 1807 if (const RecordType *RT = Type->getAs<RecordType>()) { 1808 ParentDecl = RT->getAsCXXRecordDecl(); 1809 } 1810 1811 if (!ParentDecl) { 1812 // Handle a dependent base such as "Base<T>" by using the primary 1813 // template. 1814 if (const TemplateSpecializationType *TS = 1815 Type->getAs<TemplateSpecializationType>()) { 1816 TemplateName TN = TS->getTemplateName(); 1817 if (TemplateDecl *TD = TN.getAsTemplateDecl()) { 1818 ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl()); 1819 } 1820 } 1821 } 1822 1823 if (ParentDecl) 1824 Result.push_back(ParentDecl); 1825 } 1826 1827 return Result; 1828 } 1829 1830 llvm::Optional<TypeHierarchyItem> 1831 getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, 1832 TypeHierarchyDirection Direction, const SymbolIndex *Index, 1833 PathRef TUPath) { 1834 const CXXRecordDecl *CXXRD = findRecordTypeAt(AST, Pos); 1835 if (!CXXRD) 1836 return llvm::None; 1837 1838 bool WantParents = Direction == TypeHierarchyDirection::Parents || 1839 Direction == TypeHierarchyDirection::Both; 1840 bool WantChildren = Direction == TypeHierarchyDirection::Children || 1841 Direction == TypeHierarchyDirection::Both; 1842 1843 // If we're looking for children, we're doing the lookup in the index. 1844 // The index does not store relationships between implicit 1845 // specializations, so if we have one, use the template pattern instead. 1846 // Note that this needs to be done before the declToTypeHierarchyItem(), 1847 // otherwise the type hierarchy item would misleadingly contain the 1848 // specialization parameters, while the children would involve classes 1849 // that derive from other specializations of the template. 1850 if (WantChildren) { 1851 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) 1852 CXXRD = CTSD->getTemplateInstantiationPattern(); 1853 } 1854 1855 Optional<TypeHierarchyItem> Result = declToTypeHierarchyItem(*CXXRD); 1856 if (!Result) 1857 return Result; 1858 1859 if (WantParents) { 1860 Result->parents.emplace(); 1861 1862 RecursionProtectionSet RPSet; 1863 fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet); 1864 } 1865 1866 if (WantChildren && ResolveLevels > 0) { 1867 Result->children.emplace(); 1868 1869 if (Index) { 1870 if (auto ID = getSymbolID(CXXRD)) 1871 fillSubTypes(ID, *Result->children, Index, ResolveLevels, TUPath); 1872 } 1873 } 1874 1875 return Result; 1876 } 1877 1878 void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, 1879 TypeHierarchyDirection Direction, 1880 const SymbolIndex *Index) { 1881 // We only support typeHierarchy/resolve for children, because for parents 1882 // we ignore ResolveLevels and return all levels of parents eagerly. 1883 if (Direction == TypeHierarchyDirection::Parents || ResolveLevels == 0) 1884 return; 1885 1886 Item.children.emplace(); 1887 1888 if (Index && Item.data) { 1889 // We store the item's SymbolID in the 'data' field, and the client 1890 // passes it back to us in typeHierarchy/resolve. 1891 if (Expected<SymbolID> ID = SymbolID::fromStr(*Item.data)) { 1892 fillSubTypes(*ID, *Item.children, Index, ResolveLevels, Item.uri.file()); 1893 } 1894 } 1895 } 1896 1897 std::vector<CallHierarchyItem> 1898 prepareCallHierarchy(ParsedAST &AST, Position Pos, PathRef TUPath) { 1899 std::vector<CallHierarchyItem> Result; 1900 const auto &SM = AST.getSourceManager(); 1901 auto Loc = sourceLocationInMainFile(SM, Pos); 1902 if (!Loc) { 1903 elog("prepareCallHierarchy failed to convert position to source location: " 1904 "{0}", 1905 Loc.takeError()); 1906 return Result; 1907 } 1908 for (const NamedDecl *Decl : getDeclAtPosition(AST, *Loc, {})) { 1909 if (!(isa<DeclContext>(Decl) && 1910 cast<DeclContext>(Decl)->isFunctionOrMethod()) && 1911 Decl->getKind() != Decl::Kind::FunctionTemplate) 1912 continue; 1913 if (auto CHI = declToCallHierarchyItem(*Decl)) 1914 Result.emplace_back(std::move(*CHI)); 1915 } 1916 return Result; 1917 } 1918 1919 std::vector<CallHierarchyIncomingCall> 1920 incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) { 1921 std::vector<CallHierarchyIncomingCall> Results; 1922 if (!Index || Item.data.empty()) 1923 return Results; 1924 auto ID = SymbolID::fromStr(Item.data); 1925 if (!ID) { 1926 elog("incomingCalls failed to find symbol: {0}", ID.takeError()); 1927 return Results; 1928 } 1929 // In this function, we find incoming calls based on the index only. 1930 // In principle, the AST could have more up-to-date information about 1931 // occurrences within the current file. However, going from a SymbolID 1932 // to an AST node isn't cheap, particularly when the declaration isn't 1933 // in the main file. 1934 // FIXME: Consider also using AST information when feasible. 1935 RefsRequest Request; 1936 Request.IDs.insert(*ID); 1937 // We could restrict more specifically to calls by introducing a new RefKind, 1938 // but non-call references (such as address-of-function) can still be 1939 // interesting as they can indicate indirect calls. 1940 Request.Filter = RefKind::Reference; 1941 // Initially store the ranges in a map keyed by SymbolID of the caller. 1942 // This allows us to group different calls with the same caller 1943 // into the same CallHierarchyIncomingCall. 1944 llvm::DenseMap<SymbolID, std::vector<Range>> CallsIn; 1945 // We can populate the ranges based on a refs request only. As we do so, we 1946 // also accumulate the container IDs into a lookup request. 1947 LookupRequest ContainerLookup; 1948 Index->refs(Request, [&](const Ref &R) { 1949 auto Loc = indexToLSPLocation(R.Location, Item.uri.file()); 1950 if (!Loc) { 1951 elog("incomingCalls failed to convert location: {0}", Loc.takeError()); 1952 return; 1953 } 1954 auto It = CallsIn.try_emplace(R.Container, std::vector<Range>{}).first; 1955 It->second.push_back(Loc->range); 1956 1957 ContainerLookup.IDs.insert(R.Container); 1958 }); 1959 // Perform the lookup request and combine its results with CallsIn to 1960 // get complete CallHierarchyIncomingCall objects. 1961 Index->lookup(ContainerLookup, [&](const Symbol &Caller) { 1962 auto It = CallsIn.find(Caller.ID); 1963 assert(It != CallsIn.end()); 1964 if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file())) 1965 Results.push_back( 1966 CallHierarchyIncomingCall{std::move(*CHI), std::move(It->second)}); 1967 }); 1968 // Sort results by name of container. 1969 llvm::sort(Results, [](const CallHierarchyIncomingCall &A, 1970 const CallHierarchyIncomingCall &B) { 1971 return A.from.name < B.from.name; 1972 }); 1973 return Results; 1974 } 1975 1976 llvm::DenseSet<const Decl *> getNonLocalDeclRefs(ParsedAST &AST, 1977 const FunctionDecl *FD) { 1978 if (!FD->hasBody()) 1979 return {}; 1980 llvm::DenseSet<const Decl *> DeclRefs; 1981 findExplicitReferences( 1982 FD, 1983 [&](ReferenceLoc Ref) { 1984 for (const Decl *D : Ref.Targets) { 1985 if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() && 1986 !Ref.IsDecl) 1987 DeclRefs.insert(D); 1988 } 1989 }, 1990 AST.getHeuristicResolver()); 1991 return DeclRefs; 1992 } 1993 1994 } // namespace clangd 1995 } // namespace clang 1996