summaryrefslogtreecommitdiff
path: root/clang-tools-extra/clangd/ClangdUnit.cpp
diff options
context:
space:
mode:
authorIlya Biryukov <ibiryukov@google.com>2017-12-12 12:27:47 +0000
committerIlya Biryukov <ibiryukov@google.com>2017-12-12 12:27:47 +0000
commit3160e403066239ef61334dedf7d8093ba3d75fbc (patch)
tree3b718b39b281679e419b62dcc9215c1c977eebe4 /clang-tools-extra/clangd/ClangdUnit.cpp
parent9f15c9c728f9a4e4865f5f824f52d952eeaf0677 (diff)
[clangd] Document highlights for clangd
Summary: Implementation of Document Highlights Request as described in LSP. Contributed by William Enright (nebiroth). Reviewers: malaperle, krasimir, bkramer, ilya-biryukov Reviewed By: malaperle Subscribers: mgrang, sammccall, klimek, ioeric, rwols, cfe-commits, arphaman, ilya-biryukov Differential Revision: https://reviews.llvm.org/D38425
Diffstat (limited to 'clang-tools-extra/clangd/ClangdUnit.cpp')
-rw-r--r--clang-tools-extra/clangd/ClangdUnit.cpp214
1 files changed, 171 insertions, 43 deletions
diff --git a/clang-tools-extra/clangd/ClangdUnit.cpp b/clang-tools-extra/clangd/ClangdUnit.cpp
index 0a8661c301a..e369ea18a40 100644
--- a/clang-tools-extra/clangd/ClangdUnit.cpp
+++ b/clang-tools-extra/clangd/ClangdUnit.cpp
@@ -222,26 +222,34 @@ SourceLocation getMacroArgExpandedLocation(const SourceManager &Mgr,
}
/// Finds declarations locations that a given source location refers to.
-class DeclarationLocationsFinder : public index::IndexDataConsumer {
- std::vector<Location> DeclarationLocations;
+class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
+ std::vector<const Decl *> Decls;
+ std::vector<const MacroInfo *> MacroInfos;
const SourceLocation &SearchedLocation;
const ASTContext &AST;
Preprocessor &PP;
public:
- DeclarationLocationsFinder(raw_ostream &OS,
+ DeclarationAndMacrosFinder(raw_ostream &OS,
const SourceLocation &SearchedLocation,
ASTContext &AST, Preprocessor &PP)
: SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
- std::vector<Location> takeLocations() {
- // Don't keep the same location multiple times.
+ 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(DeclarationLocations.begin(), DeclarationLocations.end());
- auto last =
- std::unique(DeclarationLocations.begin(), DeclarationLocations.end());
- DeclarationLocations.erase(last, DeclarationLocations.end());
- return std::move(DeclarationLocations);
+ 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
@@ -249,9 +257,8 @@ public:
ArrayRef<index::SymbolRelation> Relations, FileID FID,
unsigned Offset,
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
- if (isSearchedLocation(FID, Offset)) {
- addDeclarationLocation(D->getSourceRange());
- }
+ if (isSearchedLocation(FID, Offset))
+ Decls.push_back(D);
return true;
}
@@ -262,31 +269,6 @@ private:
SourceMgr.getFileID(SearchedLocation) == FID;
}
- void addDeclarationLocation(const SourceRange &ValSourceRange) {
- const SourceManager &SourceMgr = AST.getSourceManager();
- const LangOptions &LangOpts = AST.getLangOpts();
- SourceLocation LocStart = ValSourceRange.getBegin();
- 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;
- if (const FileEntry *F =
- SourceMgr.getFileEntryForID(SourceMgr.getFileID(LocStart))) {
- StringRef FilePath = F->tryGetRealPathName();
- if (FilePath.empty())
- FilePath = F->getName();
- L.uri = URI::fromFile(FilePath);
- L.range = R;
- DeclarationLocations.push_back(L);
- }
- }
-
void finish() override {
// Also handle possible macro at the searched location.
Token Result;
@@ -309,16 +291,111 @@ private:
PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
MacroInfo *MacroInf = MacroDef.getMacroInfo();
if (MacroInf) {
- addDeclarationLocation(SourceRange(MacroInf->getDefinitionLoc(),
- MacroInf->getDefinitionEndLoc()));
+ 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 Begin, 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(ParsedAST &AST, Position Pos,
clangd::Logger &Logger) {
const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
@@ -328,7 +405,49 @@ std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos,
SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
- auto DeclLocationsFinder = std::make_shared<DeclarationLocationsFinder>(
+ 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(ParsedAST &AST, Position Pos,
+ clangd::Logger &Logger) {
+ 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;
@@ -336,10 +455,19 @@ std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos,
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(),
- DeclLocationsFinder, IndexOpts);
+ DocHighlightsFinder, IndexOpts);
- return DeclLocationsFinder->takeLocations();
+ return DocHighlightsFinder->takeHighlights();
}
void ParsedAST::ensurePreambleDeclsDeserialized() {