Loading clang-tools-extra/clangd/XRefs.cpp +93 −71 Original line number Diff line number Diff line Loading @@ -172,85 +172,53 @@ llvm::Optional<Location> makeLocation(ASTContext &AST, SourceLocation TokLoc, } // namespace std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no links"); return {}; } std::vector<DocumentLink> Result; for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { if (!Inc.Resolved.empty()) { Result.push_back(DocumentLink( {Inc.R, URIForFile::canonicalize(Inc.Resolved, *MainFilePath)})); } } return Result; } std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no references"); return {}; } // Treat #included files as symbols, to enable go-to-definition on them. static llvm::Optional<LocatedSymbol> locateFileReferent(const Position &Pos, ParsedAST &AST, llvm::StringRef MainFilePath) { for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line) { LocatedSymbol File; File.Name = std::string(llvm::sys::path::filename(Inc.Resolved)); File.PreferredDeclaration = { URIForFile::canonicalize(Inc.Resolved, *MainFilePath), Range{}}; URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}}; File.Definition = File.PreferredDeclaration; // We're not going to find any further symbols on #include lines. return {std::move(File)}; return File; } } auto CurLoc = sourceLocationInMainFile(SM, Pos); if (!CurLoc) { elog("locateSymbolAt failed to convert position to source location: {0}", CurLoc.takeError()); return {}; return llvm::None; } // Macros are simple: there's no declaration/definition distinction. // As a consequence, there's no need to look them up in the index either. std::vector<LocatedSymbol> Result; const auto *TouchedIdentifier = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); if (TouchedIdentifier) { if (auto M = locateMacroAt(*TouchedIdentifier, AST.getPreprocessor())) { static llvm::Optional<LocatedSymbol> locateMacroReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST, llvm::StringRef MainFilePath) { if (auto M = locateMacroAt(TouchedIdentifier, AST.getPreprocessor())) { if (auto Loc = makeLocation(AST.getASTContext(), M->Info->getDefinitionLoc(), *MainFilePath)) { M->Info->getDefinitionLoc(), MainFilePath)) { LocatedSymbol Macro; Macro.Name = std::string(M->Name); Macro.PreferredDeclaration = *Loc; Macro.Definition = Loc; Result.push_back(std::move(Macro)); // Don't look at the AST or index if we have a macro result. // (We'd just return declarations referenced from the macro's // expansion.) return Result; return Macro; } } return llvm::None; } // Decls are more complicated. // The AST contains at least a declaration, maybe a definition. // These are up-to-date, and so generally preferred over index results. // We perform a single batch index lookup to find additional definitions. static std::vector<LocatedSymbol> locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, ParsedAST &AST, llvm::StringRef MainFilePath, const SymbolIndex *Index) { const SourceManager &SM = AST.getSourceManager(); // Results follow the order of Symbols.Decls. std::vector<LocatedSymbol> Result; // Keep track of SymbolID -> index mapping, to fill in index data later. llvm::DenseMap<SymbolID, size_t> ResultIndex; Loading @@ -259,7 +227,7 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, const NamedDecl *Preferred = Def ? Def : D; auto Loc = makeLocation(AST.getASTContext(), nameLocation(*Preferred, SM), *MainFilePath); MainFilePath); if (!Loc) return; Loading @@ -278,7 +246,7 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, // Emit all symbol locations (declaration or definition) from AST. DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; for (const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) { for (const NamedDecl *D : getDeclAtPosition(AST, CurLoc, Relations)) { // Special case: void foo() ^override: jump to the overridden method. if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) { const InheritableAttr *Attr = D->getAttr<OverrideAttr>(); Loading Loading @@ -320,23 +288,23 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, if (R.Definition) { // from AST // Special case: if the AST yielded a definition, then it may not be // the right *declaration*. Prefer the one from the index. if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, *MainFilePath)) if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, MainFilePath)) R.PreferredDeclaration = *Loc; // We might still prefer the definition from the index, e.g. for // generated symbols. if (auto Loc = toLSPLocation( getPreferredLocation(*R.Definition, Sym.Definition, Scratch), *MainFilePath)) MainFilePath)) R.Definition = *Loc; } else { R.Definition = toLSPLocation(Sym.Definition, *MainFilePath); R.Definition = toLSPLocation(Sym.Definition, MainFilePath); // Use merge logic to choose AST or index declaration. if (auto Loc = toLSPLocation( getPreferredLocation(R.PreferredDeclaration, Sym.CanonicalDeclaration, Scratch), *MainFilePath)) MainFilePath)) R.PreferredDeclaration = *Loc; } }); Loading @@ -345,6 +313,60 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, return Result; } std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no references"); return {}; } if (auto File = locateFileReferent(Pos, AST, *MainFilePath)) return {std::move(*File)}; auto CurLoc = sourceLocationInMainFile(SM, Pos); if (!CurLoc) { elog("locateSymbolAt failed to convert position to source location: {0}", CurLoc.takeError()); return {}; } const syntax::Token *TouchedIdentifier = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); if (TouchedIdentifier) if (auto Macro = locateMacroReferent(*TouchedIdentifier, AST, *MainFilePath)) // Don't look at the AST or index if we have a macro result. // (We'd just return declarations referenced from the macro's // expansion.) return {*std::move(Macro)}; return locateASTReferent(*CurLoc, TouchedIdentifier, AST, *MainFilePath, Index); } std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no links"); return {}; } std::vector<DocumentLink> Result; for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { if (!Inc.Resolved.empty()) { Result.push_back(DocumentLink( {Inc.R, URIForFile::canonicalize(Inc.Resolved, *MainFilePath)})); } } return Result; } namespace { /// Collects references to symbols within the main file. Loading Loading
clang-tools-extra/clangd/XRefs.cpp +93 −71 Original line number Diff line number Diff line Loading @@ -172,85 +172,53 @@ llvm::Optional<Location> makeLocation(ASTContext &AST, SourceLocation TokLoc, } // namespace std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no links"); return {}; } std::vector<DocumentLink> Result; for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { if (!Inc.Resolved.empty()) { Result.push_back(DocumentLink( {Inc.R, URIForFile::canonicalize(Inc.Resolved, *MainFilePath)})); } } return Result; } std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no references"); return {}; } // Treat #included files as symbols, to enable go-to-definition on them. static llvm::Optional<LocatedSymbol> locateFileReferent(const Position &Pos, ParsedAST &AST, llvm::StringRef MainFilePath) { for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line) { LocatedSymbol File; File.Name = std::string(llvm::sys::path::filename(Inc.Resolved)); File.PreferredDeclaration = { URIForFile::canonicalize(Inc.Resolved, *MainFilePath), Range{}}; URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}}; File.Definition = File.PreferredDeclaration; // We're not going to find any further symbols on #include lines. return {std::move(File)}; return File; } } auto CurLoc = sourceLocationInMainFile(SM, Pos); if (!CurLoc) { elog("locateSymbolAt failed to convert position to source location: {0}", CurLoc.takeError()); return {}; return llvm::None; } // Macros are simple: there's no declaration/definition distinction. // As a consequence, there's no need to look them up in the index either. std::vector<LocatedSymbol> Result; const auto *TouchedIdentifier = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); if (TouchedIdentifier) { if (auto M = locateMacroAt(*TouchedIdentifier, AST.getPreprocessor())) { static llvm::Optional<LocatedSymbol> locateMacroReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST, llvm::StringRef MainFilePath) { if (auto M = locateMacroAt(TouchedIdentifier, AST.getPreprocessor())) { if (auto Loc = makeLocation(AST.getASTContext(), M->Info->getDefinitionLoc(), *MainFilePath)) { M->Info->getDefinitionLoc(), MainFilePath)) { LocatedSymbol Macro; Macro.Name = std::string(M->Name); Macro.PreferredDeclaration = *Loc; Macro.Definition = Loc; Result.push_back(std::move(Macro)); // Don't look at the AST or index if we have a macro result. // (We'd just return declarations referenced from the macro's // expansion.) return Result; return Macro; } } return llvm::None; } // Decls are more complicated. // The AST contains at least a declaration, maybe a definition. // These are up-to-date, and so generally preferred over index results. // We perform a single batch index lookup to find additional definitions. static std::vector<LocatedSymbol> locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, ParsedAST &AST, llvm::StringRef MainFilePath, const SymbolIndex *Index) { const SourceManager &SM = AST.getSourceManager(); // Results follow the order of Symbols.Decls. std::vector<LocatedSymbol> Result; // Keep track of SymbolID -> index mapping, to fill in index data later. llvm::DenseMap<SymbolID, size_t> ResultIndex; Loading @@ -259,7 +227,7 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, const NamedDecl *Preferred = Def ? Def : D; auto Loc = makeLocation(AST.getASTContext(), nameLocation(*Preferred, SM), *MainFilePath); MainFilePath); if (!Loc) return; Loading @@ -278,7 +246,7 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, // Emit all symbol locations (declaration or definition) from AST. DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; for (const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) { for (const NamedDecl *D : getDeclAtPosition(AST, CurLoc, Relations)) { // Special case: void foo() ^override: jump to the overridden method. if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) { const InheritableAttr *Attr = D->getAttr<OverrideAttr>(); Loading Loading @@ -320,23 +288,23 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, if (R.Definition) { // from AST // Special case: if the AST yielded a definition, then it may not be // the right *declaration*. Prefer the one from the index. if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, *MainFilePath)) if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, MainFilePath)) R.PreferredDeclaration = *Loc; // We might still prefer the definition from the index, e.g. for // generated symbols. if (auto Loc = toLSPLocation( getPreferredLocation(*R.Definition, Sym.Definition, Scratch), *MainFilePath)) MainFilePath)) R.Definition = *Loc; } else { R.Definition = toLSPLocation(Sym.Definition, *MainFilePath); R.Definition = toLSPLocation(Sym.Definition, MainFilePath); // Use merge logic to choose AST or index declaration. if (auto Loc = toLSPLocation( getPreferredLocation(R.PreferredDeclaration, Sym.CanonicalDeclaration, Scratch), *MainFilePath)) MainFilePath)) R.PreferredDeclaration = *Loc; } }); Loading @@ -345,6 +313,60 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, return Result; } std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no references"); return {}; } if (auto File = locateFileReferent(Pos, AST, *MainFilePath)) return {std::move(*File)}; auto CurLoc = sourceLocationInMainFile(SM, Pos); if (!CurLoc) { elog("locateSymbolAt failed to convert position to source location: {0}", CurLoc.takeError()); return {}; } const syntax::Token *TouchedIdentifier = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); if (TouchedIdentifier) if (auto Macro = locateMacroReferent(*TouchedIdentifier, AST, *MainFilePath)) // Don't look at the AST or index if we have a macro result. // (We'd just return declarations referenced from the macro's // expansion.) return {*std::move(Macro)}; return locateASTReferent(*CurLoc, TouchedIdentifier, AST, *MainFilePath, Index); } std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) { const auto &SM = AST.getSourceManager(); auto MainFilePath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); if (!MainFilePath) { elog("Failed to get a path for the main file, so no links"); return {}; } std::vector<DocumentLink> Result; for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { if (!Inc.Resolved.empty()) { Result.push_back(DocumentLink( {Inc.R, URIForFile::canonicalize(Inc.Resolved, *MainFilePath)})); } } return Result; } namespace { /// Collects references to symbols within the main file. Loading