summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2017-12-19 17:06:07 +0000
committerSam McCall <sam.mccall@gmail.com>2017-12-19 17:06:07 +0000
commit553feab6bee651d07d4f707d7b9485f2476c521b (patch)
tree0447c54c20d9a5bb3a572056498f93ec3bb1e9fd
parent1686fcf87db079e17f0acc994ed5a3d0f690d4f0 (diff)
[clangd] Split findDefs/highlights into XRefs, from ClangdUnit. NFC
Going to add unit tests in the next patch. (Haha!) But seriously there's some work to do first - need to extract the markers-in-source-code parser from CodeComplete test and make it more flexible, to allow annotated ranges etc. git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@321087 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--clangd/CMakeLists.txt1
-rw-r--r--clangd/ClangdServer.cpp2
-rw-r--r--clangd/ClangdUnit.cpp253
-rw-r--r--clangd/ClangdUnit.h7
-rw-r--r--clangd/XRefs.cpp270
-rw-r--r--clangd/XRefs.h34
6 files changed, 307 insertions, 260 deletions
diff --git a/clangd/CMakeLists.txt b/clangd/CMakeLists.txt
index 69a0c684..df242da5 100644
--- a/clangd/CMakeLists.txt
+++ b/clangd/CMakeLists.txt
@@ -20,6 +20,7 @@ add_clang_library(clangDaemon
ProtocolHandlers.cpp
SourceCode.cpp
Trace.cpp
+ XRefs.cpp
index/FileIndex.cpp
index/Index.cpp
index/MemIndex.cpp
diff --git a/clangd/ClangdServer.cpp b/clangd/ClangdServer.cpp
index 4a9ee699..129fc074 100644
--- a/clangd/ClangdServer.cpp
+++ b/clangd/ClangdServer.cpp
@@ -8,7 +8,9 @@
//===-------------------------------------------------------------------===//
#include "ClangdServer.h"
+#include "CodeComplete.h"
#include "SourceCode.h"
+#include "XRefs.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
diff --git a/clangd/ClangdUnit.cpp b/clangd/ClangdUnit.cpp
index 5f45b2f4..f735e09f 100644
--- a/clangd/ClangdUnit.cpp
+++ b/clangd/ClangdUnit.cpp
@@ -267,268 +267,15 @@ ParsedAST::Build(const Context &Ctx,
namespace {
SourceLocation getMacroArgExpandedLocation(const SourceManager &Mgr,
- const FileEntry *FE,
- unsigned Offset) {
- SourceLocation FileLoc = Mgr.translateFileLineCol(FE, 1, 1);
- return Mgr.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
-}
-
-SourceLocation getMacroArgExpandedLocation(const SourceManager &Mgr,
const FileEntry *FE, Position Pos) {
SourceLocation InputLoc =
Mgr.translateFileLineCol(FE, Pos.line + 1, Pos.character + 1);
return Mgr.getMacroArgExpandedLocation(InputLoc);
}
-/// Finds declarations locations that a given source location refers to.
-class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
- std::vector<const Decl *> Decls;
- std::vector<const MacroInfo *> MacroInfos;
- const SourceLocation &SearchedLocation;
- const ASTContext &AST;
- Preprocessor &PP;
-
-public:
- DeclarationAndMacrosFinder(raw_ostream &OS,
- const SourceLocation &SearchedLocation,
- ASTContext &AST, Preprocessor &PP)
- : SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
-
- std::vector<const Decl *> takeDecls() {
- // Don't keep the same declaration multiple times.
- // This can happen when nodes in the AST are visited twice.
- std::sort(Decls.begin(), Decls.end());
- auto Last = std::unique(Decls.begin(), Decls.end());
- Decls.erase(Last, Decls.end());
- return std::move(Decls);
- }
-
- std::vector<const MacroInfo *> takeMacroInfos() {
- // Don't keep the same Macro info multiple times.
- std::sort(MacroInfos.begin(), MacroInfos.end());
- auto Last = std::unique(MacroInfos.begin(), MacroInfos.end());
- MacroInfos.erase(Last, MacroInfos.end());
- return std::move(MacroInfos);
- }
-
- bool
- handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
- ArrayRef<index::SymbolRelation> Relations, FileID FID,
- unsigned Offset,
- index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
- if (isSearchedLocation(FID, Offset))
- Decls.push_back(D);
- return true;
- }
-
-private:
- bool isSearchedLocation(FileID FID, unsigned Offset) const {
- const SourceManager &SourceMgr = AST.getSourceManager();
- return SourceMgr.getFileOffset(SearchedLocation) == Offset &&
- SourceMgr.getFileID(SearchedLocation) == FID;
- }
-
- void finish() override {
- // Also handle possible macro at the searched location.
- Token Result;
- if (!Lexer::getRawToken(SearchedLocation, Result, AST.getSourceManager(),
- AST.getLangOpts(), false)) {
- if (Result.is(tok::raw_identifier)) {
- PP.LookUpIdentifierInfo(Result);
- }
- IdentifierInfo *IdentifierInfo = Result.getIdentifierInfo();
- if (IdentifierInfo && IdentifierInfo->hadMacroDefinition()) {
- std::pair<FileID, unsigned int> DecLoc =
- AST.getSourceManager().getDecomposedExpansionLoc(SearchedLocation);
- // Get the definition just before the searched location so that a macro
- // referenced in a '#undef MACRO' can still be found.
- SourceLocation BeforeSearchedLocation = getMacroArgExpandedLocation(
- AST.getSourceManager(),
- AST.getSourceManager().getFileEntryForID(DecLoc.first),
- DecLoc.second - 1);
- MacroDefinition MacroDef =
- PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
- MacroInfo *MacroInf = MacroDef.getMacroInfo();
- if (MacroInf) {
- MacroInfos.push_back(MacroInf);
- }
- }
- }
- }
-};
-
-/// Finds document highlights that a given list of declarations refers to.
-class DocumentHighlightsFinder : public index::IndexDataConsumer {
- std::vector<const Decl *> &Decls;
- std::vector<DocumentHighlight> DocumentHighlights;
- const ASTContext &AST;
-
-public:
- DocumentHighlightsFinder(raw_ostream &OS, ASTContext &AST, Preprocessor &PP,
- std::vector<const Decl *> &Decls)
- : Decls(Decls), AST(AST) {}
- std::vector<DocumentHighlight> takeHighlights() {
- // Don't keep the same highlight multiple times.
- // This can happen when nodes in the AST are visited twice.
- std::sort(DocumentHighlights.begin(), DocumentHighlights.end());
- auto Last =
- std::unique(DocumentHighlights.begin(), DocumentHighlights.end());
- DocumentHighlights.erase(Last, DocumentHighlights.end());
- return std::move(DocumentHighlights);
- }
-
- bool
- handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
- ArrayRef<index::SymbolRelation> Relations, FileID FID,
- unsigned Offset,
- index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
- const SourceManager &SourceMgr = AST.getSourceManager();
- if (SourceMgr.getMainFileID() != FID ||
- std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
- return true;
- }
- SourceLocation End;
- const LangOptions &LangOpts = AST.getLangOpts();
- SourceLocation StartOfFileLoc = SourceMgr.getLocForStartOfFile(FID);
- SourceLocation HightlightStartLoc = StartOfFileLoc.getLocWithOffset(Offset);
- End =
- Lexer::getLocForEndOfToken(HightlightStartLoc, 0, SourceMgr, LangOpts);
- SourceRange SR(HightlightStartLoc, End);
-
- DocumentHighlightKind Kind = DocumentHighlightKind::Text;
- if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Write) & Roles)
- Kind = DocumentHighlightKind::Write;
- else if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Read) & Roles)
- Kind = DocumentHighlightKind::Read;
-
- DocumentHighlights.push_back(getDocumentHighlight(SR, Kind));
- return true;
- }
-
-private:
- DocumentHighlight getDocumentHighlight(SourceRange SR,
- DocumentHighlightKind Kind) {
- const SourceManager &SourceMgr = AST.getSourceManager();
- SourceLocation LocStart = SR.getBegin();
- Position Begin;
- Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
- Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
- Position End;
- End.line = SourceMgr.getSpellingLineNumber(SR.getEnd()) - 1;
- End.character = SourceMgr.getSpellingColumnNumber(SR.getEnd()) - 1;
- Range R = {Begin, End};
- DocumentHighlight DH;
- DH.range = R;
- DH.kind = Kind;
- return DH;
- }
-};
} // namespace
-llvm::Optional<Location>
-getDeclarationLocation(ParsedAST &AST, const SourceRange &ValSourceRange) {
- const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
- const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
- SourceLocation LocStart = ValSourceRange.getBegin();
-
- const FileEntry *F =
- SourceMgr.getFileEntryForID(SourceMgr.getFileID(LocStart));
- if (!F)
- return llvm::None;
- SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(), 0,
- SourceMgr, LangOpts);
- Position Begin;
- Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
- Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
- Position End;
- End.line = SourceMgr.getSpellingLineNumber(LocEnd) - 1;
- End.character = SourceMgr.getSpellingColumnNumber(LocEnd) - 1;
- Range R = {Begin, End};
- Location L;
-
- StringRef FilePath = F->tryGetRealPathName();
- if (FilePath.empty())
- FilePath = F->getName();
- L.uri = URI::fromFile(FilePath);
- L.range = R;
- return L;
-}
-
-std::vector<Location> clangd::findDefinitions(const Context &Ctx,
- ParsedAST &AST, Position Pos) {
- const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
- const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
- if (!FE)
- return {};
-
- SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
-
- auto DeclMacrosFinder = std::make_shared<DeclarationAndMacrosFinder>(
- llvm::errs(), SourceLocationBeg, AST.getASTContext(),
- AST.getPreprocessor());
- index::IndexingOptions IndexOpts;
- IndexOpts.SystemSymbolFilter =
- index::IndexingOptions::SystemSymbolFilterKind::All;
- IndexOpts.IndexFunctionLocals = true;
-
- indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
- DeclMacrosFinder, IndexOpts);
-
- std::vector<const Decl *> Decls = DeclMacrosFinder->takeDecls();
- std::vector<const MacroInfo *> MacroInfos =
- DeclMacrosFinder->takeMacroInfos();
- std::vector<Location> Result;
-
- for (auto Item : Decls) {
- auto L = getDeclarationLocation(AST, Item->getSourceRange());
- if (L)
- Result.push_back(*L);
- }
-
- for (auto Item : MacroInfos) {
- SourceRange SR(Item->getDefinitionLoc(), Item->getDefinitionEndLoc());
- auto L = getDeclarationLocation(AST, SR);
- if (L)
- Result.push_back(*L);
- }
-
- return Result;
-}
-
-std::vector<DocumentHighlight>
-clangd::findDocumentHighlights(const Context &Ctx, ParsedAST &AST,
- Position Pos) {
- const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
- const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
- if (!FE)
- return {};
-
- SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
-
- auto DeclMacrosFinder = std::make_shared<DeclarationAndMacrosFinder>(
- llvm::errs(), SourceLocationBeg, AST.getASTContext(),
- AST.getPreprocessor());
- index::IndexingOptions IndexOpts;
- IndexOpts.SystemSymbolFilter =
- index::IndexingOptions::SystemSymbolFilterKind::All;
- IndexOpts.IndexFunctionLocals = true;
-
- // Macro occurences are not currently handled.
- indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
- DeclMacrosFinder, IndexOpts);
-
- std::vector<const Decl *> SelectedDecls = DeclMacrosFinder->takeDecls();
-
- auto DocHighlightsFinder = std::make_shared<DocumentHighlightsFinder>(
- llvm::errs(), AST.getASTContext(), AST.getPreprocessor(), SelectedDecls);
-
- indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
- DocHighlightsFinder, IndexOpts);
-
- return DocHighlightsFinder->takeHighlights();
-}
-
void ParsedAST::ensurePreambleDeclsDeserialized() {
if (PreambleDeclsDeserialized || !Preamble)
return;
diff --git a/clangd/ClangdUnit.h b/clangd/ClangdUnit.h
index a8110de4..47902c54 100644
--- a/clangd/ClangdUnit.h
+++ b/clangd/ClangdUnit.h
@@ -258,13 +258,6 @@ private:
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
const FileEntry *FE);
-/// Get definition of symbol at a specified \p Pos.
-std::vector<Location> findDefinitions(const Context &Ctx, ParsedAST &AST,
- Position Pos);
-
-std::vector<DocumentHighlight>
-findDocumentHighlights(const Context &Ctx, ParsedAST &AST, Position Pos);
-
/// For testing/debugging purposes. Note that this method deserializes all
/// unserialized Decls, so use with care.
void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
diff --git a/clangd/XRefs.cpp b/clangd/XRefs.cpp
new file mode 100644
index 00000000..9bd4131b
--- /dev/null
+++ b/clangd/XRefs.cpp
@@ -0,0 +1,270 @@
+//===--- XRefs.cpp ----------------------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "XRefs.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexingAction.h"
+namespace clang {
+namespace clangd {
+using namespace llvm;
+namespace {
+
+/// Finds declarations locations that a given source location refers to.
+class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
+ std::vector<const Decl *> Decls;
+ std::vector<const MacroInfo *> MacroInfos;
+ const SourceLocation &SearchedLocation;
+ const ASTContext &AST;
+ Preprocessor &PP;
+
+public:
+ DeclarationAndMacrosFinder(raw_ostream &OS,
+ const SourceLocation &SearchedLocation,
+ ASTContext &AST, Preprocessor &PP)
+ : SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
+
+ std::vector<const Decl *> takeDecls() {
+ // Don't keep the same declaration multiple times.
+ // This can happen when nodes in the AST are visited twice.
+ std::sort(Decls.begin(), Decls.end());
+ auto Last = std::unique(Decls.begin(), Decls.end());
+ Decls.erase(Last, Decls.end());
+ return std::move(Decls);
+ }
+
+ std::vector<const MacroInfo *> takeMacroInfos() {
+ // Don't keep the same Macro info multiple times.
+ std::sort(MacroInfos.begin(), MacroInfos.end());
+ auto Last = std::unique(MacroInfos.begin(), MacroInfos.end());
+ MacroInfos.erase(Last, MacroInfos.end());
+ return std::move(MacroInfos);
+ }
+
+ bool
+ handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+ ArrayRef<index::SymbolRelation> Relations, FileID FID,
+ unsigned Offset,
+ index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+ if (isSearchedLocation(FID, Offset))
+ Decls.push_back(D);
+ return true;
+ }
+
+private:
+ bool isSearchedLocation(FileID FID, unsigned Offset) const {
+ const SourceManager &SourceMgr = AST.getSourceManager();
+ return SourceMgr.getFileOffset(SearchedLocation) == Offset &&
+ SourceMgr.getFileID(SearchedLocation) == FID;
+ }
+
+ void finish() override {
+ // Also handle possible macro at the searched location.
+ Token Result;
+ auto &Mgr = AST.getSourceManager();
+ if (!Lexer::getRawToken(SearchedLocation, Result, Mgr, AST.getLangOpts(),
+ false)) {
+ if (Result.is(tok::raw_identifier)) {
+ PP.LookUpIdentifierInfo(Result);
+ }
+ IdentifierInfo *IdentifierInfo = Result.getIdentifierInfo();
+ if (IdentifierInfo && IdentifierInfo->hadMacroDefinition()) {
+ std::pair<FileID, unsigned int> DecLoc =
+ Mgr.getDecomposedExpansionLoc(SearchedLocation);
+ // Get the definition just before the searched location so that a macro
+ // referenced in a '#undef MACRO' can still be found.
+ SourceLocation BeforeSearchedLocation = Mgr.getMacroArgExpandedLocation(
+ Mgr.getLocForStartOfFile(DecLoc.first)
+ .getLocWithOffset(DecLoc.second - 1));
+ MacroDefinition MacroDef =
+ PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
+ MacroInfo *MacroInf = MacroDef.getMacroInfo();
+ if (MacroInf) {
+ MacroInfos.push_back(MacroInf);
+ }
+ }
+ }
+ }
+};
+
+llvm::Optional<Location>
+getDeclarationLocation(ParsedAST &AST, const SourceRange &ValSourceRange) {
+ const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+ const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+ SourceLocation LocStart = ValSourceRange.getBegin();
+
+ const FileEntry *F =
+ SourceMgr.getFileEntryForID(SourceMgr.getFileID(LocStart));
+ if (!F)
+ return llvm::None;
+ SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(), 0,
+ SourceMgr, LangOpts);
+ Position Begin;
+ Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
+ Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
+ Position End;
+ End.line = SourceMgr.getSpellingLineNumber(LocEnd) - 1;
+ End.character = SourceMgr.getSpellingColumnNumber(LocEnd) - 1;
+ Range R = {Begin, End};
+ Location L;
+
+ StringRef FilePath = F->tryGetRealPathName();
+ if (FilePath.empty())
+ FilePath = F->getName();
+ L.uri = URI::fromFile(FilePath);
+ L.range = R;
+ return L;
+}
+
+} // namespace
+
+std::vector<Location> findDefinitions(const Context &Ctx, ParsedAST &AST,
+ Position Pos) {
+ const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+ const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+ if (!FE)
+ return {};
+
+ SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
+
+ auto DeclMacrosFinder = std::make_shared<DeclarationAndMacrosFinder>(
+ llvm::errs(), SourceLocationBeg, AST.getASTContext(),
+ AST.getPreprocessor());
+ index::IndexingOptions IndexOpts;
+ IndexOpts.SystemSymbolFilter =
+ index::IndexingOptions::SystemSymbolFilterKind::All;
+ IndexOpts.IndexFunctionLocals = true;
+
+ indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
+ DeclMacrosFinder, IndexOpts);
+
+ std::vector<const Decl *> Decls = DeclMacrosFinder->takeDecls();
+ std::vector<const MacroInfo *> MacroInfos =
+ DeclMacrosFinder->takeMacroInfos();
+ std::vector<Location> Result;
+
+ for (auto Item : Decls) {
+ auto L = getDeclarationLocation(AST, Item->getSourceRange());
+ if (L)
+ Result.push_back(*L);
+ }
+
+ for (auto Item : MacroInfos) {
+ SourceRange SR(Item->getDefinitionLoc(), Item->getDefinitionEndLoc());
+ auto L = getDeclarationLocation(AST, SR);
+ if (L)
+ Result.push_back(*L);
+ }
+
+ return Result;
+}
+
+namespace {
+
+/// Finds document highlights that a given list of declarations refers to.
+class DocumentHighlightsFinder : public index::IndexDataConsumer {
+ std::vector<const Decl *> &Decls;
+ std::vector<DocumentHighlight> DocumentHighlights;
+ const ASTContext &AST;
+
+public:
+ DocumentHighlightsFinder(raw_ostream &OS, ASTContext &AST, Preprocessor &PP,
+ std::vector<const Decl *> &Decls)
+ : Decls(Decls), AST(AST) {}
+ std::vector<DocumentHighlight> takeHighlights() {
+ // Don't keep the same highlight multiple times.
+ // This can happen when nodes in the AST are visited twice.
+ std::sort(DocumentHighlights.begin(), DocumentHighlights.end());
+ auto Last =
+ std::unique(DocumentHighlights.begin(), DocumentHighlights.end());
+ DocumentHighlights.erase(Last, DocumentHighlights.end());
+ return std::move(DocumentHighlights);
+ }
+
+ bool
+ handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+ ArrayRef<index::SymbolRelation> Relations, FileID FID,
+ unsigned Offset,
+ index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+ const SourceManager &SourceMgr = AST.getSourceManager();
+ if (SourceMgr.getMainFileID() != FID ||
+ std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
+ return true;
+ }
+ SourceLocation End;
+ const LangOptions &LangOpts = AST.getLangOpts();
+ SourceLocation StartOfFileLoc = SourceMgr.getLocForStartOfFile(FID);
+ SourceLocation HightlightStartLoc = StartOfFileLoc.getLocWithOffset(Offset);
+ End =
+ Lexer::getLocForEndOfToken(HightlightStartLoc, 0, SourceMgr, LangOpts);
+ SourceRange SR(HightlightStartLoc, End);
+
+ DocumentHighlightKind Kind = DocumentHighlightKind::Text;
+ if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Write) & Roles)
+ Kind = DocumentHighlightKind::Write;
+ else if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Read) & Roles)
+ Kind = DocumentHighlightKind::Read;
+
+ DocumentHighlights.push_back(getDocumentHighlight(SR, Kind));
+ return true;
+ }
+
+private:
+ DocumentHighlight getDocumentHighlight(SourceRange SR,
+ DocumentHighlightKind Kind) {
+ const SourceManager &SourceMgr = AST.getSourceManager();
+ SourceLocation LocStart = SR.getBegin();
+ Position Begin;
+ Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
+ Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
+ Position End;
+ End.line = SourceMgr.getSpellingLineNumber(SR.getEnd()) - 1;
+ End.character = SourceMgr.getSpellingColumnNumber(SR.getEnd()) - 1;
+ Range R = {Begin, End};
+ DocumentHighlight DH;
+ DH.range = R;
+ DH.kind = Kind;
+ return DH;
+ }
+};
+
+} // namespace
+
+std::vector<DocumentHighlight>
+findDocumentHighlights(const Context &Ctx, ParsedAST &AST, Position Pos) {
+ const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+ const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+ if (!FE)
+ return {};
+
+ SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
+
+ auto DeclMacrosFinder = std::make_shared<DeclarationAndMacrosFinder>(
+ llvm::errs(), SourceLocationBeg, AST.getASTContext(),
+ AST.getPreprocessor());
+ index::IndexingOptions IndexOpts;
+ IndexOpts.SystemSymbolFilter =
+ index::IndexingOptions::SystemSymbolFilterKind::All;
+ IndexOpts.IndexFunctionLocals = true;
+
+ // Macro occurences are not currently handled.
+ indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
+ DeclMacrosFinder, IndexOpts);
+
+ std::vector<const Decl *> SelectedDecls = DeclMacrosFinder->takeDecls();
+
+ auto DocHighlightsFinder = std::make_shared<DocumentHighlightsFinder>(
+ llvm::errs(), AST.getASTContext(), AST.getPreprocessor(), SelectedDecls);
+
+ indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
+ DocHighlightsFinder, IndexOpts);
+
+ return DocHighlightsFinder->takeHighlights();
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clangd/XRefs.h b/clangd/XRefs.h
new file mode 100644
index 00000000..04518a19
--- /dev/null
+++ b/clangd/XRefs.h
@@ -0,0 +1,34 @@
+//===--- XRefs.h ------------------------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Features that traverse references between symbols.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
+
+#include "ClangdUnit.h"
+#include "Context.h"
+#include "Protocol.h"
+#include <vector>
+
+namespace clang {
+namespace clangd {
+
+/// Get definition of symbol at a specified \p Pos.
+std::vector<Location> findDefinitions(const Context &Ctx, ParsedAST &AST,
+ Position Pos);
+
+/// Returns highlights for all usages of a symbol at \p Pos.
+std::vector<DocumentHighlight>
+findDocumentHighlights(const Context &Ctx, ParsedAST &AST, Position Pos);
+
+} // namespace clangd
+} // namespace clang
+#endif