24 #include "clang/AST/ASTContext.h"
25 #include "clang/AST/ASTTypeTraits.h"
26 #include "clang/AST/Attr.h"
27 #include "clang/AST/Attrs.inc"
28 #include "clang/AST/Decl.h"
29 #include "clang/AST/DeclCXX.h"
30 #include "clang/AST/DeclObjC.h"
31 #include "clang/AST/DeclTemplate.h"
32 #include "clang/AST/ExprCXX.h"
33 #include "clang/AST/RecursiveASTVisitor.h"
34 #include "clang/AST/Stmt.h"
35 #include "clang/AST/StmtCXX.h"
36 #include "clang/AST/Type.h"
37 #include "clang/Basic/CharInfo.h"
38 #include "clang/Basic/LLVM.h"
39 #include "clang/Basic/LangOptions.h"
40 #include "clang/Basic/SourceLocation.h"
41 #include "clang/Basic/SourceManager.h"
42 #include "clang/Basic/TokenKinds.h"
43 #include "clang/Index/IndexDataConsumer.h"
44 #include "clang/Index/IndexSymbol.h"
45 #include "clang/Index/IndexingAction.h"
46 #include "clang/Index/IndexingOptions.h"
47 #include "clang/Index/USRGeneration.h"
48 #include "clang/Tooling/Syntax/Tokens.h"
49 #include "llvm/ADT/ArrayRef.h"
50 #include "llvm/ADT/None.h"
51 #include "llvm/ADT/STLExtras.h"
52 #include "llvm/ADT/ScopeExit.h"
53 #include "llvm/ADT/SmallSet.h"
54 #include "llvm/ADT/StringExtras.h"
55 #include "llvm/ADT/StringRef.h"
56 #include "llvm/Support/Casting.h"
57 #include "llvm/Support/Error.h"
58 #include "llvm/Support/MathExtras.h"
59 #include "llvm/Support/Path.h"
60 #include "llvm/Support/raw_ostream.h"
72 const NamedDecl *getDefinition(
const NamedDecl *D) {
75 if (
const auto *TD = dyn_cast<TagDecl>(D))
76 return TD->getDefinition();
77 if (
const auto *VD = dyn_cast<VarDecl>(D))
78 return VD->getDefinition();
79 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
80 return FD->getDefinition();
82 if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
83 isa<TemplateTemplateParmDecl>(D))
89 void logIfOverflow(
const SymbolLocation &
Loc) {
90 if (
Loc.Start.hasOverflow() ||
Loc.End.hasOverflow())
91 log(
"Possible overflow in symbol location: {0}",
Loc);
98 llvm::Optional<Location> toLSPLocation(
const SymbolLocation &
Loc,
99 llvm::StringRef TUPath) {
104 elog(
"Could not parse URI {0}: {1}",
Loc.FileURI, Uri.takeError());
109 elog(
"Could not resolve URI {0}: {1}",
Loc.FileURI, U.takeError());
114 LSPLoc.uri = std::move(*U);
115 LSPLoc.range.start.line =
Loc.Start.line();
116 LSPLoc.range.start.character =
Loc.Start.column();
117 LSPLoc.range.end.line =
Loc.End.line();
118 LSPLoc.range.end.character =
Loc.End.column();
123 SymbolLocation toIndexLocation(
const Location &
Loc, std::string &URIStorage) {
124 SymbolLocation SymLoc;
125 URIStorage =
Loc.uri.uri();
126 SymLoc.FileURI = URIStorage.c_str();
127 SymLoc.Start.setLine(
Loc.range.start.line);
128 SymLoc.Start.setColumn(
Loc.range.start.character);
129 SymLoc.End.setLine(
Loc.range.end.line);
130 SymLoc.End.setColumn(
Loc.range.end.character);
135 SymbolLocation getPreferredLocation(
const Location &ASTLoc,
136 const SymbolLocation &IdxLoc,
137 std::string &Scratch) {
140 Symbol ASTSym, IdxSym;
141 ASTSym.ID = IdxSym.ID =
SymbolID(
"dummy_id");
142 ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch);
143 IdxSym.CanonicalDeclaration = IdxLoc;
145 return Merged.CanonicalDeclaration;
148 std::vector<const NamedDecl *>
149 getDeclAtPosition(ParsedAST &AST, SourceLocation
Pos, DeclRelationSet Relations,
150 ASTNodeKind *NodeKind =
nullptr) {
152 std::vector<const NamedDecl *> Result;
154 Offset, [&](SelectionTree ST) {
155 if (
const SelectionTree::Node *N =
156 ST.commonAncestor()) {
158 *NodeKind = N->ASTNode.getNodeKind();
160 std::back_inserter(Result));
162 return !Result.empty();
169 llvm::Optional<Location> makeLocation(
const ASTContext &AST, SourceLocation
Loc,
170 llvm::StringRef TUPath) {
172 const FileEntry *F = SM.getFileEntryForID(SM.getFileID(
Loc));
177 log(
"failed to get path!");
184 auto TokLen = Lexer::MeasureTokenLength(
Loc, SM, AST.
getLangOpts());
186 SM, CharSourceRange::getCharRange(
Loc,
Loc.getLocWithOffset(TokLen)));
191 llvm::Optional<LocatedSymbol> locateFileReferent(
const Position &
Pos,
193 llvm::StringRef MainFilePath) {
195 if (!Inc.Resolved.empty() && Inc.HashLine ==
Pos.
line) {
197 File.Name = std::string(llvm::sys::path::filename(Inc.Resolved));
198 File.PreferredDeclaration = {
200 File.Definition = File.PreferredDeclaration;
210 llvm::Optional<LocatedSymbol>
211 locateMacroReferent(
const syntax::Token &TouchedIdentifier, ParsedAST &AST,
212 llvm::StringRef MainFilePath) {
215 makeLocation(AST.
getASTContext(), M->NameLoc, MainFilePath)) {
217 Macro.Name = std::string(M->Name);
230 std::vector<LocatedSymbol>
231 locateASTReferent(SourceLocation CurLoc,
const syntax::Token *TouchedIdentifier,
232 ParsedAST &AST, llvm::StringRef MainFilePath,
233 const SymbolIndex *
Index, ASTNodeKind *NodeKind) {
236 std::vector<LocatedSymbol> Result;
238 llvm::DenseMap<SymbolID, size_t> ResultIndex;
240 auto AddResultDecl = [&](
const NamedDecl *D) {
241 D = llvm::cast<NamedDecl>(D->getCanonicalDecl());
247 Result.emplace_back();
249 Result.back().PreferredDeclaration = *
Loc;
250 if (
const NamedDecl *Def = getDefinition(D))
251 Result.back().Definition = makeLocation(
256 ResultIndex[*ID] = Result.size() - 1;
260 DeclRelationSet Relations =
262 for (
const NamedDecl *D :
263 getDeclAtPosition(AST, CurLoc, Relations, NodeKind)) {
265 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
266 const InheritableAttr *Attr = D->getAttr<OverrideAttr>();
268 Attr = D->getAttr<FinalAttr>();
269 if (Attr && TouchedIdentifier &&
270 SM.getSpellingLoc(Attr->getLocation()) ==
271 TouchedIdentifier->location()) {
273 for (
const NamedDecl *ND : CMD->overridden_methods())
281 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
282 if (TouchedIdentifier &&
283 D->getLocation() == TouchedIdentifier->location()) {
284 AddResultDecl(CTSD->getSpecializedTemplate());
294 if (
Index && !ResultIndex.empty()) {
295 LookupRequest QueryRequest;
296 for (
auto It : ResultIndex)
297 QueryRequest.IDs.insert(It.first);
299 Index->
lookup(QueryRequest, [&](
const Symbol &Sym) {
300 auto &R = Result[ResultIndex.lookup(Sym.ID)];
305 if (
auto Loc = toLSPLocation(Sym.CanonicalDeclaration, MainFilePath))
306 R.PreferredDeclaration = *
Loc;
310 if (
auto Loc = toLSPLocation(
311 getPreferredLocation(*R.Definition, Sym.Definition, Scratch),
315 R.Definition = toLSPLocation(Sym.Definition, MainFilePath);
318 if (
auto Loc = toLSPLocation(
319 getPreferredLocation(R.PreferredDeclaration,
320 Sym.CanonicalDeclaration, Scratch),
322 R.PreferredDeclaration = *
Loc;
330 bool tokenSpelledAt(SourceLocation SpellingLoc,
const syntax::TokenBuffer &TB) {
331 auto ExpandedTokens = TB.expandedTokens(
332 TB.sourceManager().getMacroArgExpandedLocation(SpellingLoc));
333 return !ExpandedTokens.empty();
336 llvm::StringRef sourcePrefix(SourceLocation
Loc,
const SourceManager &SM) {
337 auto D = SM.getDecomposedLoc(
Loc);
338 bool Invalid =
false;
339 llvm::StringRef Buf = SM.getBufferData(D.first, &Invalid);
340 if (Invalid || D.second > Buf.size())
342 return Buf.substr(0, D.second);
345 bool isDependentName(ASTNodeKind NodeKind) {
346 return NodeKind.isSame(ASTNodeKind::getFromNodeKind<OverloadExpr>()) ||
348 ASTNodeKind::getFromNodeKind<CXXDependentScopeMemberExpr>()) ||
350 ASTNodeKind::getFromNodeKind<DependentScopeDeclRefExpr>());
355 std::vector<LocatedSymbol>
358 ASTNodeKind NodeKind) {
363 if ((
Word.ExpandedToken && !isDependentName(NodeKind)) ||
368 if (
Word.PartOfSpelledToken &&
369 isStringLiteral(
Word.PartOfSpelledToken->kind()))
386 bool TooMany =
false;
387 using ScoredLocatedSymbol = std::pair<float, LocatedSymbol>;
388 std::vector<ScoredLocatedSymbol> ScoredResults;
399 if (Sym.
SymInfo.Kind == index::SymbolKind::Constructor)
405 log(
"locateSymbolNamedTextuallyAt: {0}", MaybeDeclLoc.takeError());
413 log(
"locateSymbolNamedTextuallyAt: {0}", MaybeDefLoc.takeError());
416 DefLoc = *MaybeDefLoc;
419 if (ScoredResults.size() >= 3) {
437 Relevance.
merge(Sym);
440 dlog(
"locateSymbolNamedTextuallyAt: {0}{1} = {2}\n{3}{4}\n", Sym.
Scope,
443 ScoredResults.push_back({
Score, std::move(Located)});
447 vlog(
"Heuristic index lookup for {0} returned too many candidates, ignored",
452 llvm::sort(ScoredResults,
453 [](
const ScoredLocatedSymbol &A,
const ScoredLocatedSymbol &B) {
454 return A.first > B.first;
456 std::vector<LocatedSymbol>
Results;
457 for (
auto &Res : std::move(ScoredResults))
458 Results.push_back(std::move(Res.second));
460 vlog(
"No heuristic index definition for {0}",
Word.Text);
462 log(
"Found definition heuristically in index for {0}",
Word.Text);
467 const syntax::TokenBuffer &TB) {
470 if (
Word.ExpandedToken)
474 if (
Word.PartOfSpelledToken &&
475 isStringLiteral(
Word.PartOfSpelledToken->kind()))
478 const SourceManager &SM = TB.sourceManager();
481 auto File = SM.getFileID(
Word.Location);
482 unsigned WordLine = SM.getSpellingLineNumber(
Word.Location);
483 auto Cost = [&](SourceLocation
Loc) ->
unsigned {
484 assert(SM.getFileID(
Loc) == File &&
"spelled token in wrong file?");
485 unsigned Line = SM.getSpellingLineNumber(
Loc);
487 return 1 + llvm::Log2_64(
Line - WordLine);
489 return 2 + llvm::Log2_64(WordLine -
Line);
492 const syntax::Token *BestTok =
nullptr;
494 unsigned BestCost =
Word.Text.size() + 1;
498 auto Consider = [&](
const syntax::Token &Tok) {
499 if (!(Tok.kind() == tok::identifier && Tok.text(SM) ==
Word.Text))
502 if (Tok.location() ==
Word.Location)
505 unsigned TokCost = Cost(Tok.location());
506 if (TokCost >= BestCost)
510 if (!(tokenSpelledAt(Tok.location(), TB) || TB.expansionStartingAt(&Tok)))
517 auto SpelledTokens = TB.spelledTokens(File);
519 auto *I = llvm::partition_point(SpelledTokens, [&](
const syntax::Token &T) {
520 assert(SM.getFileID(T.location()) == SM.getFileID(
Word.Location));
521 return T.location() >=
Word.Location;
524 for (
const syntax::Token &Tok : llvm::makeArrayRef(I, SpelledTokens.end()))
528 for (
const syntax::Token &Tok :
529 llvm::reverse(llvm::makeArrayRef(SpelledTokens.begin(), I)))
535 "Word {0} under cursor {1} isn't a token (after PP), trying nearby {2}",
536 Word.Text,
Word.Location.printToString(SM),
537 BestTok->location().printToString(SM));
548 elog(
"Failed to get a path for the main file, so no references");
552 if (
auto File = locateFileReferent(
Pos, AST, *MainFilePath))
553 return {std::move(*File)};
557 elog(
"locateSymbolAt failed to convert position to source location: {0}",
562 const syntax::Token *TouchedIdentifier =
563 syntax::spelledIdentifierTouching(*CurLoc, AST.
getTokens());
564 if (TouchedIdentifier)
566 locateMacroReferent(*TouchedIdentifier, AST, *MainFilePath))
570 return {*std::move(
Macro)};
572 ASTNodeKind NodeKind;
573 auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST,
574 *MainFilePath,
Index, &NodeKind);
575 if (!ASTResults.empty())
583 if (
const syntax::Token *NearbyIdent =
585 if (
auto Macro = locateMacroReferent(*NearbyIdent, AST, *MainFilePath)) {
586 log(
"Found macro definition heuristically using nearby identifier {0}",
588 return {*std::move(
Macro)};
591 locateASTReferent(NearbyIdent->location(), NearbyIdent, AST,
592 *MainFilePath,
Index,
nullptr);
593 if (!ASTResults.empty()) {
594 log(
"Found definition heuristically using nearby identifier {0}",
595 NearbyIdent->text(SM));
598 vlog(
"No definition found using nearby identifier {0} at {1}",
599 Word->Text,
Word->Location.printToString(SM));
603 auto TextualResults =
605 if (!TextualResults.empty())
606 return TextualResults;
617 elog(
"Failed to get a path for the main file, so no links");
621 std::vector<DocumentLink> Result;
623 if (Inc.Resolved.empty())
625 auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
626 const auto *HashTok = AST.
getTokens().spelledTokenAt(HashLoc);
627 assert(HashTok &&
"got inclusion at wrong offset");
628 const auto *IncludeTok = std::next(HashTok);
629 const auto *FileTok = std::next(IncludeTok);
634 syntax::FileRange(SM, FileTok->location(), Inc.Written.length())
648 class ReferenceFinder :
public index::IndexDataConsumer {
654 Range range(
const SourceManager &SM)
const {
659 ReferenceFinder(
const ParsedAST &
AST,
660 const std::vector<const NamedDecl *> &TargetDecls)
662 for (
const NamedDecl *D : TargetDecls)
663 CanonicalTargets.insert(D->getCanonicalDecl());
666 std::vector<Reference> take() && {
668 auto LTok = L.SpelledTok.location();
669 auto RTok = R.SpelledTok.location();
670 return std::tie(LTok, L.Role) < std::tie(RTok, R.Role);
675 auto LTok = L.SpelledTok.location();
676 auto RTok = R.SpelledTok.location();
677 return std::tie(LTok, L.Role) ==
678 std::tie(RTok, R.Role);
685 handleDeclOccurrence(
const Decl *D, index::SymbolRoleSet Roles,
686 llvm::ArrayRef<index::SymbolRelation> Relations,
688 index::IndexDataConsumer::ASTNodeInfo ASTNode)
override {
689 assert(D->isCanonicalDecl() &&
"expect D to be a canonical declaration");
690 const SourceManager &SM =
AST.getSourceManager();
693 const auto &TB =
AST.getTokens();
695 if (
const auto *Tok = TB.spelledTokenAt(
Loc))
701 llvm::SmallSet<const Decl *, 4> CanonicalTargets;
703 const ParsedAST &
AST;
706 std::vector<ReferenceFinder::Reference>
707 findRefs(
const std::vector<const NamedDecl *> &Decls, ParsedAST &AST) {
708 ReferenceFinder RefFinder(AST, Decls);
709 index::IndexingOptions IndexOpts;
710 IndexOpts.SystemSymbolFilter =
711 index::IndexingOptions::SystemSymbolFilterKind::All;
712 IndexOpts.IndexFunctionLocals =
true;
713 IndexOpts.IndexParametersInDeclarations =
true;
714 IndexOpts.IndexTemplateParameters =
true;
717 return std::move(RefFinder).take();
720 const Stmt *getFunctionBody(DynTypedNode N) {
721 if (
const auto *FD = N.get<FunctionDecl>())
722 return FD->getBody();
723 if (
const auto *FD = N.get<BlockDecl>())
724 return FD->getBody();
725 if (
const auto *FD = N.get<LambdaExpr>())
726 return FD->getBody();
727 if (
const auto *FD = N.get<ObjCMethodDecl>())
728 return FD->getBody();
732 const Stmt *getLoopBody(DynTypedNode N) {
733 if (
const auto *LS = N.get<ForStmt>())
734 return LS->getBody();
735 if (
const auto *LS = N.get<CXXForRangeStmt>())
736 return LS->getBody();
737 if (
const auto *LS = N.get<WhileStmt>())
738 return LS->getBody();
739 if (
const auto *LS = N.get<DoStmt>())
740 return LS->getBody();
747 class FindControlFlow :
public RecursiveASTVisitor<FindControlFlow> {
756 All = Break | Continue | Return | Case | Throw | Goto,
760 std::vector<SourceLocation> &Result;
761 const SourceManager &SM;
765 template <
typename Func>
766 bool filterAndTraverse(DynTypedNode D,
const Func &Delegate) {
767 auto RestoreIgnore = llvm::make_scope_exit(
768 [OldIgnore(Ignore),
this] { Ignore = OldIgnore; });
769 if (getFunctionBody(D))
771 else if (getLoopBody(D))
772 Ignore |= Continue | Break;
773 else if (D.get<SwitchStmt>())
774 Ignore |= Break | Case;
776 return (Ignore ==
All) ? true : Delegate();
779 void found(Target T, SourceLocation
Loc) {
782 if (SM.isBeforeInTranslationUnit(
Loc,
Bounds.getBegin()) ||
783 SM.isBeforeInTranslationUnit(
Bounds.getEnd(),
Loc))
785 Result.push_back(
Loc);
789 FindControlFlow(SourceRange
Bounds, std::vector<SourceLocation> &Result,
790 const SourceManager &SM)
795 bool TraverseDecl(
Decl *D) {
796 return !D || filterAndTraverse(DynTypedNode::create(*D), [&] {
797 return RecursiveASTVisitor::TraverseDecl(D);
800 bool TraverseStmt(Stmt *S) {
801 return !S || filterAndTraverse(DynTypedNode::create(*S), [&] {
802 return RecursiveASTVisitor::TraverseStmt(S);
807 bool VisitReturnStmt(ReturnStmt *R) {
808 found(Return, R->getReturnLoc());
811 bool VisitBreakStmt(BreakStmt *B) {
812 found(Break, B->getBreakLoc());
815 bool VisitContinueStmt(ContinueStmt *C) {
816 found(Continue, C->getContinueLoc());
819 bool VisitSwitchCase(SwitchCase *C) {
820 found(Case, C->getKeywordLoc());
823 bool VisitCXXThrowExpr(CXXThrowExpr *T) {
824 found(Throw, T->getThrowLoc());
827 bool VisitGotoStmt(GotoStmt *G) {
829 if (
const auto *LD = G->getLabel()) {
830 if (SM.isBeforeInTranslationUnit(LD->getLocation(),
Bounds.getBegin()) ||
831 SM.isBeforeInTranslationUnit(
Bounds.getEnd(), LD->getLocation()))
832 found(Goto, G->getGotoLoc());
841 SourceRange findCaseBounds(
const SwitchStmt &Switch, SourceLocation
Loc,
842 const SourceManager &SM) {
845 std::vector<const SwitchCase *> Cases;
846 for (
const SwitchCase *Case = Switch.getSwitchCaseList(); Case;
847 Case = Case->getNextSwitchCase())
848 Cases.push_back(Case);
849 llvm::sort(Cases, [&](
const SwitchCase *L,
const SwitchCase *R) {
850 return SM.isBeforeInTranslationUnit(L->getKeywordLoc(), R->getKeywordLoc());
854 auto CaseAfter = llvm::partition_point(Cases, [&](
const SwitchCase *C) {
855 return !SM.isBeforeInTranslationUnit(
Loc, C->getKeywordLoc());
857 SourceLocation End = CaseAfter == Cases.end() ? Switch.getEndLoc()
858 : (*CaseAfter)->getKeywordLoc();
861 if (CaseAfter == Cases.begin())
862 return SourceRange(Switch.getBeginLoc(), End);
864 auto CaseBefore = std::prev(CaseAfter);
866 while (CaseBefore != Cases.begin() &&
867 (*std::prev(CaseBefore))->getSubStmt() == *CaseBefore)
869 return SourceRange((*CaseBefore)->getKeywordLoc(), End);
879 std::vector<SourceLocation> relatedControlFlow(
const SelectionTree::Node &N) {
880 const SourceManager &SM =
881 N.getDeclContext().getParentASTContext().getSourceManager();
882 std::vector<SourceLocation> Result;
885 enum class Cur {
None, Break, Continue, Return, Case, Throw } Cursor;
886 if (N.ASTNode.get<BreakStmt>()) {
888 }
else if (N.ASTNode.get<ContinueStmt>()) {
889 Cursor = Cur::Continue;
890 }
else if (N.ASTNode.get<ReturnStmt>()) {
891 Cursor = Cur::Return;
892 }
else if (N.ASTNode.get<CXXThrowExpr>()) {
894 }
else if (N.ASTNode.get<SwitchCase>()) {
896 }
else if (
const GotoStmt *GS = N.ASTNode.get<GotoStmt>()) {
898 Result.push_back(GS->getGotoLoc());
899 if (
const auto *LD = GS->getLabel())
900 Result.push_back(LD->getLocation());
906 const Stmt *Root =
nullptr;
909 for (
const auto *P = &N; P; P = P->Parent) {
911 if (
const Stmt *FunctionBody = getFunctionBody(P->ASTNode)) {
912 if (Cursor == Cur::Return || Cursor == Cur::Throw) {
918 if (
const Stmt *LoopBody = getLoopBody(P->ASTNode)) {
919 if (Cursor ==
Cur::None || Cursor == Cur::Break ||
920 Cursor == Cur::Continue) {
924 Result.push_back(P->ASTNode.getSourceRange().getBegin());
931 if (
const auto *SS = P->ASTNode.get<SwitchStmt>()) {
932 if (Cursor == Cur::Break || Cursor == Cur::Case) {
933 Result.push_back(SS->getSwitchLoc());
934 Root = SS->getBody();
936 Bounds = findCaseBounds(*SS, N.ASTNode.getSourceRange().getBegin(), SM);
946 Bounds = Root->getSourceRange();
947 FindControlFlow(
Bounds, Result, SM).TraverseStmt(const_cast<Stmt *>(Root));
953 const SourceManager &SM) {
954 DocumentHighlight DH;
955 DH.range = Ref.range(SM);
956 if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
958 else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
965 llvm::Optional<DocumentHighlight> toHighlight(SourceLocation
Loc,
966 const syntax::TokenBuffer &TB) {
967 Loc = TB.sourceManager().getFileLoc(
Loc);
968 if (
const auto *Tok = TB.spelledTokenAt(
Loc)) {
969 DocumentHighlight Result;
972 CharSourceRange::getCharRange(Tok->location(), Tok->endLocation()));
986 llvm::consumeError(CurLoc.takeError());
989 std::vector<DocumentHighlight> Result;
994 auto Decls =
targetDecl(N->ASTNode, Relations);
995 if (!Decls.empty()) {
998 for (
const auto &
Ref : findRefs({Decls.begin(), Decls.end()}, AST))
999 Result.push_back(toHighlight(
Ref, SM));
1002 auto ControlFlow = relatedControlFlow(*N);
1003 if (!ControlFlow.empty()) {
1004 for (SourceLocation
Loc : ControlFlow)
1005 if (
auto Highlight = toHighlight(
Loc, AST.
getTokens()))
1006 Result.push_back(std::move(*Highlight));
1023 Limit = std::numeric_limits<uint32_t>::max();
1028 if (!MainFilePath) {
1029 elog(
"Failed to get a path for the main file, so no references");
1035 llvm::consumeError(CurLoc.takeError());
1038 llvm::Optional<DefinedMacro>
Macro;
1039 if (
const auto *IdentifierAtCursor =
1040 syntax::spelledIdentifierTouching(*CurLoc, AST.
getTokens())) {
1050 auto Refs = IDToRefs.find(*MacroSID);
1052 for (
const auto &
Ref :
Refs->second) {
1055 Result.uri = URIMainFile;
1056 Results.References.push_back(std::move(Result));
1059 Req.
IDs.insert(*MacroSID);
1068 auto Decls = getDeclAtPosition(AST, *CurLoc, Relations);
1071 auto MainFileRefs = findRefs(Decls, AST);
1075 MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(),
1078 return L.SpelledTok.location() ==
1079 R.SpelledTok.location();
1081 MainFileRefs.end());
1082 for (
const auto &
Ref : MainFileRefs) {
1084 Result.range =
Ref.range(SM);
1085 Result.uri = URIMainFile;
1086 Results.References.push_back(std::move(Result));
1089 for (
const Decl *D : Decls) {
1094 if (D->getParentFunctionOrMethod())
1097 Req.
IDs.insert(*ID);
1102 if (!Req.
IDs.empty() &&
Index &&
Results.References.size() <= Limit) {
1106 if (
Results.References.size() > Limit)
1108 auto LSPLoc = toLSPLocation(R.
Location, *MainFilePath);
1110 if (!LSPLoc || LSPLoc->uri.file() == *MainFilePath)
1113 Results.References.push_back(std::move(*LSPLoc));
1116 if (
Results.References.size() > Limit) {
1118 Results.References.resize(Limit);
1127 llvm::consumeError(CurLoc.takeError());
1131 std::vector<SymbolDetails>
Results;
1137 for (
const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) {
1142 NewSymbol.
name = std::string(SplitQName.second);
1145 if (
const auto *ParentND =
1146 dyn_cast_or_null<NamedDecl>(D->getDeclContext()))
1149 llvm::SmallString<32> USR;
1150 if (!index::generateUSRForDecl(D, USR)) {
1151 NewSymbol.
USR = std::string(USR.str());
1154 Results.push_back(std::move(NewSymbol));
1157 const auto *IdentifierAtCursor =
1158 syntax::spelledIdentifierTouching(*CurLoc, AST.
getTokens());
1159 if (!IdentifierAtCursor)
1164 NewMacro.
name = std::string(M->Name);
1165 llvm::SmallString<32> USR;
1166 if (!index::generateUSRForMacro(NewMacro.
name, M->Info->getDefinitionLoc(),
1168 NewMacro.
USR = std::string(USR.str());
1171 Results.push_back(std::move(NewMacro));
1185 static llvm::Optional<TypeHierarchyItem>
1187 const syntax::TokenBuffer &TB) {
1188 auto &SM =
Ctx.getSourceManager();
1192 auto TUPath =
getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
1193 if (!FilePath || !TUPath)
1196 auto DeclToks = TB.spelledForExpanded(TB.expandedTokens(ND.getSourceRange()));
1197 if (!DeclToks || DeclToks->empty())
1200 auto NameToks = TB.spelledForExpanded(TB.expandedTokens(NameLoc));
1201 if (!NameToks || NameToks->empty())
1214 SM, syntax::Token::range(SM, DeclToks->front(), DeclToks->back())
1217 SM, syntax::Token::range(SM, NameToks->front(), NameToks->back())
1232 THI.
data = ID->str();
1238 static Optional<TypeHierarchyItem>
1243 log(
"Type hierarchy: {0}",
Loc.takeError());
1260 return std::move(THI);
1264 std::vector<TypeHierarchyItem> &SubTypes,
1270 if (Optional<TypeHierarchyItem> ChildSym =
1273 ChildSym->children.emplace();
1276 SubTypes.emplace_back(std::move(*ChildSym));
1284 std::vector<TypeHierarchyItem> &SuperTypes,
1286 const syntax::TokenBuffer &TB) {
1292 auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD :
nullptr;
1294 if (!RPSet.insert(Pattern).second) {
1299 for (
const CXXRecordDecl *ParentDecl :
typeParents(&CXXRD)) {
1300 if (Optional<TypeHierarchyItem> ParentSym =
1302 ParentSym->parents.emplace();
1303 fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet, TB);
1304 SuperTypes.emplace_back(std::move(*ParentSym));
1309 RPSet.erase(Pattern);
1314 auto RecordFromNode =
1327 const NamedDecl *D = Decls[0];
1329 if (
const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1331 return VD->getType().getTypePtr()->getAsCXXRecordDecl();
1334 if (
const CXXMethodDecl *
Method = dyn_cast<CXXMethodDecl>(D)) {
1336 return Method->getParent();
1343 return dyn_cast<CXXRecordDecl>(D);
1347 const CXXRecordDecl *Result =
nullptr;
1350 llvm::consumeError(
Offset.takeError());
1355 Result = RecordFromNode(ST.commonAncestor());
1356 return Result !=
nullptr;
1361 std::vector<const CXXRecordDecl *>
typeParents(
const CXXRecordDecl *CXXRD) {
1362 std::vector<const CXXRecordDecl *> Result;
1366 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
1367 if (CTSD->isInvalidDecl())
1368 CXXRD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
1371 for (
auto Base : CXXRD->bases()) {
1372 const CXXRecordDecl *ParentDecl =
nullptr;
1375 if (
const RecordType *RT =
Type->getAs<RecordType>()) {
1376 ParentDecl = RT->getAsCXXRecordDecl();
1382 if (
const TemplateSpecializationType *TS =
1383 Type->getAs<TemplateSpecializationType>()) {
1384 TemplateName TN = TS->getTemplateName();
1385 if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
1386 ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
1392 Result.push_back(ParentDecl);
1398 llvm::Optional<TypeHierarchyItem>
1406 Optional<TypeHierarchyItem> Result =
1413 Result->parents.emplace();
1422 ResolveLevels > 0) {
1423 Result->children.emplace();
1428 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD))
1429 CXXRD = CTSD->getTemplateInstantiationPattern();
1459 const FunctionDecl *FD) {
1462 llvm::DenseSet<const Decl *> DeclRefs;
1464 for (
const Decl *D :
Ref.Targets) {
1465 if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() &&