14 #include "clang/AST/DeclTemplate.h" 15 #include "clang/AST/RecursiveASTVisitor.h" 16 #include "clang/Index/IndexDataConsumer.h" 17 #include "clang/Index/IndexingAction.h" 18 #include "clang/Index/USRGeneration.h" 19 #include "llvm/Support/Path.h" 28 const Decl *getDefinition(
const Decl *D) {
30 if (
const auto *TD = dyn_cast<TagDecl>(D))
31 return TD->getDefinition();
32 else if (
const auto *VD = dyn_cast<VarDecl>(D))
33 return VD->getDefinition();
34 else if (
const auto *FD = dyn_cast<FunctionDecl>(D))
35 return FD->getDefinition();
43 llvm::Optional<Location> toLSPLocation(
const SymbolLocation &
Loc,
44 llvm::StringRef HintPath) {
49 log(
"Could not parse URI: {0}", Loc.FileURI);
54 log(
"Could not resolve URI: {0}", Loc.FileURI);
58 LSPLoc.uri = URIForFile(*
Path);
59 LSPLoc.range.start.line = Loc.Start.
Line;
60 LSPLoc.range.start.character = Loc.Start.
Column;
61 LSPLoc.range.end.line = Loc.End.
Line;
62 LSPLoc.range.end.character = Loc.End.
Column;
72 class DeclarationAndMacrosFinder :
public index::IndexDataConsumer {
73 std::vector<const Decl *> Decls;
74 std::vector<MacroDecl> MacroInfos;
75 const SourceLocation &SearchedLocation;
76 const ASTContext &
AST;
80 DeclarationAndMacrosFinder(raw_ostream &OS,
81 const SourceLocation &SearchedLocation,
82 ASTContext &AST, Preprocessor &PP)
83 : SearchedLocation(SearchedLocation),
AST(AST), PP(PP) {}
85 std::vector<const Decl *> takeDecls() {
88 std::sort(Decls.begin(), Decls.end());
89 auto Last = std::unique(Decls.begin(), Decls.end());
90 Decls.erase(Last, Decls.end());
91 return std::move(Decls);
94 std::vector<MacroDecl> takeMacroInfos() {
96 std::sort(MacroInfos.begin(), MacroInfos.end(),
97 [](
const MacroDecl &Left,
const MacroDecl &Right) {
98 return Left.Info < Right.Info;
101 auto Last = std::unique(MacroInfos.begin(), MacroInfos.end(),
102 [](
const MacroDecl &Left,
const MacroDecl &Right) {
103 return Left.Info == Right.Info;
105 MacroInfos.erase(Last, MacroInfos.end());
106 return std::move(MacroInfos);
110 handleDeclOccurence(
const Decl *D, index::SymbolRoleSet Roles,
111 ArrayRef<index::SymbolRelation> Relations,
113 index::IndexDataConsumer::ASTNodeInfo ASTNode)
override {
114 if (Loc == SearchedLocation) {
119 if (
const auto *Def = getDefinition(D)) {
120 Decls.push_back(Def);
130 void finish()
override {
133 auto &Mgr = AST.getSourceManager();
134 if (!Lexer::getRawToken(Mgr.getSpellingLoc(SearchedLocation), Result, Mgr,
135 AST.getLangOpts(),
false)) {
136 if (Result.is(tok::raw_identifier)) {
137 PP.LookUpIdentifierInfo(Result);
139 IdentifierInfo *IdentifierInfo = Result.getIdentifierInfo();
140 if (IdentifierInfo && IdentifierInfo->hadMacroDefinition()) {
141 std::pair<FileID, unsigned int> DecLoc =
142 Mgr.getDecomposedExpansionLoc(SearchedLocation);
145 SourceLocation BeforeSearchedLocation = Mgr.getMacroArgExpandedLocation(
146 Mgr.getLocForStartOfFile(DecLoc.first)
147 .getLocWithOffset(DecLoc.second - 1));
148 MacroDefinition MacroDef =
149 PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
150 MacroInfo *MacroInf = MacroDef.getMacroInfo();
152 MacroInfos.push_back(MacroDecl{IdentifierInfo->getName(), MacroInf});
153 assert(Decls.empty());
160 struct IdentifiedSymbol {
161 std::vector<const Decl *> Decls;
165 IdentifiedSymbol getSymbolAtPosition(ParsedAST &
AST, SourceLocation
Pos) {
166 auto DeclMacrosFinder = DeclarationAndMacrosFinder(
167 llvm::errs(), Pos, AST.getASTContext(), AST.getPreprocessor());
168 index::IndexingOptions IndexOpts;
169 IndexOpts.SystemSymbolFilter =
170 index::IndexingOptions::SystemSymbolFilterKind::All;
171 IndexOpts.IndexFunctionLocals =
true;
172 indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
173 DeclMacrosFinder, IndexOpts);
175 return {DeclMacrosFinder.takeDecls(), DeclMacrosFinder.takeMacroInfos()};
178 llvm::Optional<Location>
179 makeLocation(ParsedAST &
AST,
const SourceRange &ValSourceRange) {
180 const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
181 const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
182 SourceLocation LocStart = ValSourceRange.getBegin();
185 SourceMgr.getFileEntryForID(SourceMgr.getFileID(LocStart));
188 SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(), 0,
189 SourceMgr, LangOpts);
192 Range R = {Begin, End};
197 log(
"failed to get path!");
200 L.uri = URIForFile(*FilePath);
206 llvm::Optional<SymbolID> getSymbolID(
const Decl *D) {
207 llvm::SmallString<128> USR;
208 if (index::generateUSRForDecl(D, USR)) {
218 const SourceManager &SourceMgr = AST.
getASTContext().getSourceManager();
220 std::vector<Location> Result;
223 if (!Inc.Resolved.empty() && Inc.R.contains(Pos))
224 Result.push_back(
Location{URIForFile{Inc.Resolved}, {}});
230 SourceLocation SourceLocationBeg =
232 auto Symbols = getSymbolAtPosition(
AST, SourceLocationBeg);
234 for (
auto Item : Symbols.Macros) {
235 auto Loc = Item.Info->getDefinitionLoc();
236 auto L = makeLocation(
AST, SourceRange(Loc, Loc));
238 Result.push_back(*L);
261 struct CandidateLocation {
262 llvm::Optional<Location> Def;
263 llvm::Optional<Location> Decl;
265 llvm::DenseMap<SymbolID, CandidateLocation> ResultCandidates;
268 for (
const auto *D : Symbols.Decls) {
274 if (
auto ID = getSymbolID(D))
277 auto &Candidate = ResultCandidates[
Key];
279 auto L = makeLocation(
AST, SourceRange(Loc, Loc));
282 bool IsDef = getDefinition(D) == D;
293 for (
auto It : ResultCandidates)
294 QueryRequest.
IDs.insert(It.first);
295 std::string HintPath;
296 const FileEntry *FE =
297 SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
302 QueryRequest, [&HintPath, &ResultCandidates](
const Symbol &Sym) {
303 auto It = ResultCandidates.find(Sym.
ID);
304 assert(It != ResultCandidates.end());
305 auto &
Value = It->second;
308 Value.Def = toLSPLocation(Sym.
Definition, HintPath);
315 for (
auto It : ResultCandidates) {
316 const auto &Candidate = It.second;
318 Result.push_back(*Candidate.Def);
319 if (Candidate.Decl &&
320 Candidate.Decl != Candidate.Def)
321 Result.push_back(*Candidate.Decl);
330 class DocumentHighlightsFinder :
public index::IndexDataConsumer {
331 std::vector<const Decl *> &Decls;
332 std::vector<DocumentHighlight> DocumentHighlights;
333 const ASTContext &
AST;
336 DocumentHighlightsFinder(raw_ostream &OS, ASTContext &AST, Preprocessor &PP,
337 std::vector<const Decl *> &Decls)
338 : Decls(Decls),
AST(AST) {}
339 std::vector<DocumentHighlight> takeHighlights() {
342 std::sort(DocumentHighlights.begin(), DocumentHighlights.end());
344 std::unique(DocumentHighlights.begin(), DocumentHighlights.end());
345 DocumentHighlights.erase(Last, DocumentHighlights.end());
346 return std::move(DocumentHighlights);
350 handleDeclOccurence(
const Decl *D, index::SymbolRoleSet Roles,
351 ArrayRef<index::SymbolRelation> Relations,
353 index::IndexDataConsumer::ASTNodeInfo ASTNode)
override {
354 const SourceManager &SourceMgr = AST.getSourceManager();
355 SourceLocation HighlightStartLoc = SourceMgr.getFileLoc(Loc);
356 if (SourceMgr.getMainFileID() != SourceMgr.getFileID(HighlightStartLoc) ||
357 std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
361 const LangOptions &LangOpts = AST.getLangOpts();
362 End = Lexer::getLocForEndOfToken(HighlightStartLoc, 0, SourceMgr, LangOpts);
363 SourceRange SR(HighlightStartLoc, End);
366 if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Write) & Roles)
368 else if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Read) & Roles)
371 DocumentHighlights.push_back(getDocumentHighlight(SR, Kind));
378 const SourceManager &SourceMgr = AST.getSourceManager();
381 Range R = {Begin, End};
393 const SourceManager &SourceMgr = AST.
getASTContext().getSourceManager();
394 SourceLocation SourceLocationBeg =
397 auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
398 std::vector<const Decl *> SelectedDecls = Symbols.Decls;
400 DocumentHighlightsFinder DocHighlightsFinder(
403 index::IndexingOptions IndexOpts;
404 IndexOpts.SystemSymbolFilter =
405 index::IndexingOptions::SystemSymbolFilterKind::All;
406 IndexOpts.IndexFunctionLocals =
true;
408 DocHighlightsFinder, IndexOpts);
410 return DocHighlightsFinder.takeHighlights();
414 PrintingPolicy Policy(Base);
416 Policy.AnonymousTagLocations =
false;
417 Policy.TerseOutput =
true;
418 Policy.PolishForDeclaration =
true;
419 Policy.ConstantsAsWritten =
true;
420 Policy.SuppressTagKeyword =
false;
428 QualType Type = TD->getASTContext().getTypeDeclType(TD);
430 PrintingPolicy Policy =
434 llvm::raw_string_ostream Stream(Name);
435 Type.print(Stream, Policy);
444 PrintingPolicy Policy =
448 llvm::raw_string_ostream Stream(Name);
449 Stream << Prefix <<
' ';
450 ND->printQualifiedName(Stream, Policy);
459 const DeclContext *DC = D->getDeclContext();
461 if (isa<TranslationUnitDecl>(DC))
462 return std::string(
"global namespace");
463 if (
const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
465 else if (
const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
467 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
476 llvm::Optional<std::string> NamedScope =
getScopeName(D);
480 assert(!NamedScope->empty());
488 if (TemplateDecl *TD = D->getDescribedTemplate())
491 std::string DeclText;
492 llvm::raw_string_ostream OS(DeclText);
494 PrintingPolicy Policy =
497 D->print(OS, Policy);
508 std::string TypeText;
509 llvm::raw_string_ostream OS(TypeText);
536 class DeducedTypeVisitor :
public RecursiveASTVisitor<DeducedTypeVisitor> {
537 SourceLocation SearchedLocation;
538 llvm::Optional<QualType> DeducedType;
541 DeducedTypeVisitor(SourceLocation SearchedLocation)
542 : SearchedLocation(SearchedLocation) {}
550 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
551 if (!D->getTypeSourceInfo() ||
552 D->getTypeSourceInfo()->getTypeLoc().getLocStart() != SearchedLocation)
555 auto DeclT = D->getType();
557 if (
const ReferenceType *RT = dyn_cast<ReferenceType>(DeclT.getTypePtr()))
558 DeclT = RT->getPointeeType();
560 const AutoType *AT = dyn_cast<AutoType>(DeclT.getTypePtr());
561 if (AT && !AT->getDeducedType().isNull()) {
569 DeducedType = AT->isDecltypeAuto() ? DeclT : DeclT.getUnqualifiedType();
579 bool VisitFunctionDecl(FunctionDecl *D) {
580 if (!D->getTypeSourceInfo())
583 auto CurLoc = D->getReturnTypeSourceRange().getBegin();
585 if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(D))
586 CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
588 if (CurLoc.isInvalid())
589 CurLoc = D->getSourceRange().getBegin();
590 if (CurLoc != SearchedLocation)
593 auto T = D->getReturnType();
595 if (
const ReferenceType *RT = dyn_cast<ReferenceType>(T.getTypePtr()))
596 T = RT->getPointeeType();
598 const AutoType *AT = dyn_cast<AutoType>(T.getTypePtr());
599 if (AT && !AT->getDeducedType().isNull()) {
600 DeducedType = T.getUnqualifiedType();
602 const DecltypeType *DT = dyn_cast<DecltypeType>(T.getTypePtr());
603 if (!DT->getUnderlyingType().isNull())
604 DeducedType = DT->getUnderlyingType();
612 bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
613 if (TL.getBeginLoc() != SearchedLocation)
620 const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
621 while (DT && !DT->getUnderlyingType().isNull()) {
622 DeducedType = DT->getUnderlyingType();
623 DT = dyn_cast<DecltypeType>(DeducedType->getTypePtr());
632 SourceLocation SourceLocationBeg) {
636 if (!SourceLocationBeg.isValid() ||
637 Lexer::getRawToken(SourceLocationBeg, Tok, ASTCtx.getSourceManager(),
638 ASTCtx.getLangOpts(),
false) ||
639 !Tok.is(tok::raw_identifier)) {
643 if (!(Tok.is(tok::kw_auto) || Tok.is(tok::kw_decltype)))
646 DeducedTypeVisitor V(SourceLocationBeg);
649 return V.getDeducedType();
653 const SourceManager &SourceMgr = AST.
getASTContext().getSourceManager();
654 SourceLocation SourceLocationBeg =
657 auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
659 if (!Symbols.Macros.empty())
662 if (!Symbols.Decls.empty())
666 if (DeducedType && !DeducedType->isNull())
SourceLocation Loc
'#' location in the include directive
Optional< Hover > getHover(ParsedAST &AST, Position Pos)
Get the hover information when hovering at Pos.
static llvm::Optional< std::string > getScopeName(const Decl *D)
Given a declaration D, return a human-readable string representing the scope in which it is declared...
std::vector< Location > findDefinitions(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Some operations such as code completion produce a set of candidates.
Preprocessor & getPreprocessor()
Range range
The range this highlight applies to.
static std::string namedDeclQualifiedName(const NamedDecl *ND, StringRef Prefix)
Return a string representation (e.g.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
static Hover getHoverContents(const Decl *D)
Generate a Hover object given the declaration D.
llvm::DenseSet< SymbolID > IDs
SourceLocation findNameLoc(const clang::Decl *D)
Find the identifier source location of the given D.
Documents should not be synced at all.
const IncludeStructure & getIncludeStructure() const
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
MarkupContent contents
The hover's content.
A document highlight is a range inside a text document which deserves special attention.
static std::string typeDeclToString(const TypeDecl *TD)
Return a string representation (e.g.
SymbolLocation Definition
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
void log(const char *Fmt, Ts &&... Vals)
std::string Path
A typedef to represent a file path.
SymbolLocation CanonicalDeclaration
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
std::vector< MacroDecl > Macros
Stores and provides access to parsed AST.
std::vector< Inclusion > MainFileIncludes
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos, const FileID FID)
Get the beginning SourceLocation at a specified Pos.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static PrintingPolicy printingPolicyForDecls(PrintingPolicy Base)
CharSourceRange Range
SourceRange for the file name.
DocumentHighlightKind kind
The highlight kind, default is DocumentHighlightKind.Text.
llvm::Optional< QualType > getDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg)
Retrieves the deduced type at a given location (auto, decltype).
llvm::Optional< std::string > getAbsoluteFilePath(const FileEntry *F, const SourceManager &SourceMgr)
Get the absolute file path of a given file entry.
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
std::array< uint8_t, 20 > SymbolID