Author: Sam McCall Date: 2020-03-02T18:45:25+01:00 New Revision: e7de00cf974a4e30d4900518ae8473a117efbd6c
URL: https://github.com/llvm/llvm-project/commit/e7de00cf974a4e30d4900518ae8473a117efbd6c DIFF: https://github.com/llvm/llvm-project/commit/e7de00cf974a4e30d4900518ae8473a117efbd6c.diff LOG: [clangd] Split locateSymbolAt into several component functions, to allow later reuse. NFC Added: Modified: clang-tools-extra/clangd/XRefs.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 29c2338f5bb5..560e39e13550 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -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. +// 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; } } + return llvm::None; +} - auto CurLoc = sourceLocationInMainFile(SM, Pos); - if (!CurLoc) { - elog("locateSymbolAt failed to convert position to source location: {0}", - CurLoc.takeError()); - return {}; - } - - // 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())) { - if (auto Loc = makeLocation(AST.getASTContext(), - 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; - } +// Macros are simple: there's no declaration/definition distinction. +// As a consequence, there's no need to look them up in the index either. +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)) { + LocatedSymbol Macro; + Macro.Name = std::string(M->Name); + Macro.PreferredDeclaration = *Loc; + Macro.Definition = Loc; + 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. - +// 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; @@ -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; @@ -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>(); @@ -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; } }); @@ -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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits