[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clangd / XRefs.cpp
blobb608296deefad586cde7693673ee99f492c26e89
1 //===--- XRefs.cpp -----------------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "XRefs.h"
9 #include "AST.h"
10 #include "FindSymbols.h"
11 #include "FindTarget.h"
12 #include "Headers.h"
13 #include "HeuristicResolver.h"
14 #include "IncludeCleaner.h"
15 #include "ParsedAST.h"
16 #include "Protocol.h"
17 #include "Quality.h"
18 #include "Selection.h"
19 #include "SourceCode.h"
20 #include "URI.h"
21 #include "clang-include-cleaner/Analysis.h"
22 #include "clang-include-cleaner/Types.h"
23 #include "index/Index.h"
24 #include "index/Merge.h"
25 #include "index/Relation.h"
26 #include "index/SymbolCollector.h"
27 #include "index/SymbolID.h"
28 #include "index/SymbolLocation.h"
29 #include "support/Logger.h"
30 #include "clang/AST/ASTContext.h"
31 #include "clang/AST/ASTTypeTraits.h"
32 #include "clang/AST/Attr.h"
33 #include "clang/AST/Attrs.inc"
34 #include "clang/AST/Decl.h"
35 #include "clang/AST/DeclCXX.h"
36 #include "clang/AST/DeclObjC.h"
37 #include "clang/AST/DeclTemplate.h"
38 #include "clang/AST/DeclVisitor.h"
39 #include "clang/AST/ExprCXX.h"
40 #include "clang/AST/RecursiveASTVisitor.h"
41 #include "clang/AST/Stmt.h"
42 #include "clang/AST/StmtCXX.h"
43 #include "clang/AST/StmtVisitor.h"
44 #include "clang/AST/Type.h"
45 #include "clang/Basic/LLVM.h"
46 #include "clang/Basic/LangOptions.h"
47 #include "clang/Basic/SourceLocation.h"
48 #include "clang/Basic/SourceManager.h"
49 #include "clang/Basic/TokenKinds.h"
50 #include "clang/Index/IndexDataConsumer.h"
51 #include "clang/Index/IndexSymbol.h"
52 #include "clang/Index/IndexingAction.h"
53 #include "clang/Index/IndexingOptions.h"
54 #include "clang/Index/USRGeneration.h"
55 #include "clang/Lex/Lexer.h"
56 #include "clang/Tooling/Syntax/Tokens.h"
57 #include "llvm/ADT/ArrayRef.h"
58 #include "llvm/ADT/DenseMap.h"
59 #include "llvm/ADT/STLExtras.h"
60 #include "llvm/ADT/ScopeExit.h"
61 #include "llvm/ADT/SmallSet.h"
62 #include "llvm/ADT/SmallVector.h"
63 #include "llvm/ADT/StringRef.h"
64 #include "llvm/Support/Casting.h"
65 #include "llvm/Support/Error.h"
66 #include "llvm/Support/Path.h"
67 #include "llvm/Support/raw_ostream.h"
68 #include <optional>
69 #include <string>
70 #include <vector>
72 namespace clang {
73 namespace clangd {
74 namespace {
76 // Returns the single definition of the entity declared by D, if visible.
77 // In particular:
78 // - for non-redeclarable kinds (e.g. local vars), return D
79 // - for kinds that allow multiple definitions (e.g. namespaces), return nullptr
80 // Kinds of nodes that always return nullptr here will not have definitions
81 // reported by locateSymbolAt().
82 const NamedDecl *getDefinition(const NamedDecl *D) {
83 assert(D);
84 // Decl has one definition that we can find.
85 if (const auto *TD = dyn_cast<TagDecl>(D))
86 return TD->getDefinition();
87 if (const auto *VD = dyn_cast<VarDecl>(D))
88 return VD->getDefinition();
89 if (const auto *FD = dyn_cast<FunctionDecl>(D))
90 return FD->getDefinition();
91 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(D))
92 if (const auto *RD = CTD->getTemplatedDecl())
93 return RD->getDefinition();
94 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
95 if (MD->isThisDeclarationADefinition())
96 return MD;
97 // Look for the method definition inside the implementation decl.
98 auto *DeclCtx = cast<Decl>(MD->getDeclContext());
99 if (DeclCtx->isInvalidDecl())
100 return nullptr;
102 if (const auto *CD = dyn_cast<ObjCContainerDecl>(DeclCtx))
103 if (const auto *Impl = getCorrespondingObjCImpl(CD))
104 return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod());
106 if (const auto *CD = dyn_cast<ObjCContainerDecl>(D))
107 return getCorrespondingObjCImpl(CD);
108 // Only a single declaration is allowed.
109 if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
110 isa<TemplateTemplateParmDecl>(D)) // except cases above
111 return D;
112 // Multiple definitions are allowed.
113 return nullptr; // except cases above
116 void logIfOverflow(const SymbolLocation &Loc) {
117 if (Loc.Start.hasOverflow() || Loc.End.hasOverflow())
118 log("Possible overflow in symbol location: {0}", Loc);
121 // Convert a SymbolLocation to LSP's Location.
122 // TUPath is used to resolve the path of URI.
123 // FIXME: figure out a good home for it, and share the implementation with
124 // FindSymbols.
125 std::optional<Location> toLSPLocation(const SymbolLocation &Loc,
126 llvm::StringRef TUPath) {
127 if (!Loc)
128 return std::nullopt;
129 auto Uri = URI::parse(Loc.FileURI);
130 if (!Uri) {
131 elog("Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError());
132 return std::nullopt;
134 auto U = URIForFile::fromURI(*Uri, TUPath);
135 if (!U) {
136 elog("Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError());
137 return std::nullopt;
140 Location LSPLoc;
141 LSPLoc.uri = std::move(*U);
142 LSPLoc.range.start.line = Loc.Start.line();
143 LSPLoc.range.start.character = Loc.Start.column();
144 LSPLoc.range.end.line = Loc.End.line();
145 LSPLoc.range.end.character = Loc.End.column();
146 logIfOverflow(Loc);
147 return LSPLoc;
150 SymbolLocation toIndexLocation(const Location &Loc, std::string &URIStorage) {
151 SymbolLocation SymLoc;
152 URIStorage = Loc.uri.uri();
153 SymLoc.FileURI = URIStorage.c_str();
154 SymLoc.Start.setLine(Loc.range.start.line);
155 SymLoc.Start.setColumn(Loc.range.start.character);
156 SymLoc.End.setLine(Loc.range.end.line);
157 SymLoc.End.setColumn(Loc.range.end.character);
158 return SymLoc;
161 // Returns the preferred location between an AST location and an index location.
162 SymbolLocation getPreferredLocation(const Location &ASTLoc,
163 const SymbolLocation &IdxLoc,
164 std::string &Scratch) {
165 // Also use a mock symbol for the index location so that other fields (e.g.
166 // definition) are not factored into the preference.
167 Symbol ASTSym, IdxSym;
168 ASTSym.ID = IdxSym.ID = SymbolID("mock_symbol_id");
169 ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch);
170 IdxSym.CanonicalDeclaration = IdxLoc;
171 auto Merged = mergeSymbol(ASTSym, IdxSym);
172 return Merged.CanonicalDeclaration;
175 std::vector<std::pair<const NamedDecl *, DeclRelationSet>>
176 getDeclAtPositionWithRelations(ParsedAST &AST, SourceLocation Pos,
177 DeclRelationSet Relations,
178 ASTNodeKind *NodeKind = nullptr) {
179 unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second;
180 std::vector<std::pair<const NamedDecl *, DeclRelationSet>> Result;
181 auto ResultFromTree = [&](SelectionTree ST) {
182 if (const SelectionTree::Node *N = ST.commonAncestor()) {
183 if (NodeKind)
184 *NodeKind = N->ASTNode.getNodeKind();
185 // Attributes don't target decls, look at the
186 // thing it's attached to.
187 // We still report the original NodeKind!
188 // This makes the `override` hack work.
189 if (N->ASTNode.get<Attr>() && N->Parent)
190 N = N->Parent;
191 llvm::copy_if(allTargetDecls(N->ASTNode, AST.getHeuristicResolver()),
192 std::back_inserter(Result),
193 [&](auto &Entry) { return !(Entry.second & ~Relations); });
195 return !Result.empty();
197 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset,
198 Offset, ResultFromTree);
199 return Result;
202 std::vector<const NamedDecl *>
203 getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations,
204 ASTNodeKind *NodeKind = nullptr) {
205 std::vector<const NamedDecl *> Result;
206 for (auto &Entry :
207 getDeclAtPositionWithRelations(AST, Pos, Relations, NodeKind))
208 Result.push_back(Entry.first);
209 return Result;
212 // Expects Loc to be a SpellingLocation, will bail out otherwise as it can't
213 // figure out a filename.
214 std::optional<Location> makeLocation(const ASTContext &AST, SourceLocation Loc,
215 llvm::StringRef TUPath) {
216 const auto &SM = AST.getSourceManager();
217 const auto F = SM.getFileEntryRefForID(SM.getFileID(Loc));
218 if (!F)
219 return std::nullopt;
220 auto FilePath = getCanonicalPath(*F, SM.getFileManager());
221 if (!FilePath) {
222 log("failed to get path!");
223 return std::nullopt;
225 Location L;
226 L.uri = URIForFile::canonicalize(*FilePath, TUPath);
227 // We call MeasureTokenLength here as TokenBuffer doesn't store spelled tokens
228 // outside the main file.
229 auto TokLen = Lexer::MeasureTokenLength(Loc, SM, AST.getLangOpts());
230 L.range = halfOpenToRange(
231 SM, CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(TokLen)));
232 return L;
235 // Treat #included files as symbols, to enable go-to-definition on them.
236 std::optional<LocatedSymbol> locateFileReferent(const Position &Pos,
237 ParsedAST &AST,
238 llvm::StringRef MainFilePath) {
239 for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
240 if (!Inc.Resolved.empty() && Inc.HashLine == Pos.line) {
241 LocatedSymbol File;
242 File.Name = std::string(llvm::sys::path::filename(Inc.Resolved));
243 File.PreferredDeclaration = {
244 URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}};
245 File.Definition = File.PreferredDeclaration;
246 // We're not going to find any further symbols on #include lines.
247 return File;
250 return std::nullopt;
253 // Macros are simple: there's no declaration/definition distinction.
254 // As a consequence, there's no need to look them up in the index either.
255 std::optional<LocatedSymbol>
256 locateMacroReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST,
257 llvm::StringRef MainFilePath) {
258 if (auto M = locateMacroAt(TouchedIdentifier, AST.getPreprocessor())) {
259 if (auto Loc =
260 makeLocation(AST.getASTContext(), M->NameLoc, MainFilePath)) {
261 LocatedSymbol Macro;
262 Macro.Name = std::string(M->Name);
263 Macro.PreferredDeclaration = *Loc;
264 Macro.Definition = Loc;
265 Macro.ID = getSymbolID(M->Name, M->Info, AST.getSourceManager());
266 return Macro;
269 return std::nullopt;
272 // A wrapper around `Decl::getCanonicalDecl` to support cases where Clang's
273 // definition of a canonical declaration doesn't match up to what a programmer
274 // would expect. For example, Objective-C classes can have three types of
275 // declarations:
277 // - forward declaration(s): @class MyClass;
278 // - true declaration (interface definition): @interface MyClass ... @end
279 // - true definition (implementation): @implementation MyClass ... @end
281 // Clang will consider the forward declaration to be the canonical declaration
282 // because it is first. We actually want the class definition if it is
283 // available since that is what a programmer would consider the primary
284 // declaration to be.
285 const NamedDecl *getPreferredDecl(const NamedDecl *D) {
286 // FIXME: Canonical declarations of some symbols might refer to built-in
287 // decls with possibly-invalid source locations (e.g. global new operator).
288 // In such cases we should pick up a redecl with valid source location
289 // instead of failing.
290 D = llvm::cast<NamedDecl>(D->getCanonicalDecl());
292 // Prefer Objective-C class/protocol definitions over the forward declaration.
293 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D))
294 if (const auto *DefinitionID = ID->getDefinition())
295 return DefinitionID;
296 if (const auto *PD = dyn_cast<ObjCProtocolDecl>(D))
297 if (const auto *DefinitionID = PD->getDefinition())
298 return DefinitionID;
300 return D;
303 std::vector<LocatedSymbol> findImplementors(llvm::DenseSet<SymbolID> IDs,
304 RelationKind Predicate,
305 const SymbolIndex *Index,
306 llvm::StringRef MainFilePath) {
307 if (IDs.empty() || !Index)
308 return {};
309 static constexpr trace::Metric FindImplementorsMetric(
310 "find_implementors", trace::Metric::Counter, "case");
311 switch (Predicate) {
312 case RelationKind::BaseOf:
313 FindImplementorsMetric.record(1, "find-base");
314 break;
315 case RelationKind::OverriddenBy:
316 FindImplementorsMetric.record(1, "find-override");
317 break;
320 RelationsRequest Req;
321 Req.Predicate = Predicate;
322 Req.Subjects = std::move(IDs);
323 std::vector<LocatedSymbol> Results;
324 Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
325 auto DeclLoc =
326 indexToLSPLocation(Object.CanonicalDeclaration, MainFilePath);
327 if (!DeclLoc) {
328 elog("Find overrides: {0}", DeclLoc.takeError());
329 return;
331 Results.emplace_back();
332 Results.back().Name = Object.Name.str();
333 Results.back().PreferredDeclaration = *DeclLoc;
334 auto DefLoc = indexToLSPLocation(Object.Definition, MainFilePath);
335 if (!DefLoc) {
336 elog("Failed to convert location: {0}", DefLoc.takeError());
337 return;
339 Results.back().Definition = *DefLoc;
341 return Results;
344 // Decls are more complicated.
345 // The AST contains at least a declaration, maybe a definition.
346 // These are up-to-date, and so generally preferred over index results.
347 // We perform a single batch index lookup to find additional definitions.
348 std::vector<LocatedSymbol>
349 locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
350 ParsedAST &AST, llvm::StringRef MainFilePath,
351 const SymbolIndex *Index, ASTNodeKind &NodeKind) {
352 const SourceManager &SM = AST.getSourceManager();
353 // Results follow the order of Symbols.Decls.
354 std::vector<LocatedSymbol> Result;
355 // Keep track of SymbolID -> index mapping, to fill in index data later.
356 llvm::DenseMap<SymbolID, size_t> ResultIndex;
358 static constexpr trace::Metric LocateASTReferentMetric(
359 "locate_ast_referent", trace::Metric::Counter, "case");
360 auto AddResultDecl = [&](const NamedDecl *D) {
361 D = getPreferredDecl(D);
362 auto Loc =
363 makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath);
364 if (!Loc)
365 return;
367 Result.emplace_back();
368 Result.back().Name = printName(AST.getASTContext(), *D);
369 Result.back().PreferredDeclaration = *Loc;
370 Result.back().ID = getSymbolID(D);
371 if (const NamedDecl *Def = getDefinition(D))
372 Result.back().Definition = makeLocation(
373 AST.getASTContext(), nameLocation(*Def, SM), MainFilePath);
375 // Record SymbolID for index lookup later.
376 if (auto ID = getSymbolID(D))
377 ResultIndex[ID] = Result.size() - 1;
380 // Emit all symbol locations (declaration or definition) from AST.
381 DeclRelationSet Relations =
382 DeclRelation::TemplatePattern | DeclRelation::Alias;
383 auto Candidates =
384 getDeclAtPositionWithRelations(AST, CurLoc, Relations, &NodeKind);
385 llvm::DenseSet<SymbolID> VirtualMethods;
386 for (const auto &E : Candidates) {
387 const NamedDecl *D = E.first;
388 if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
389 // Special case: virtual void ^method() = 0: jump to all overrides.
390 // FIXME: extend it to ^virtual, unfortunately, virtual location is not
391 // saved in the AST.
392 if (CMD->isPure()) {
393 if (TouchedIdentifier && SM.getSpellingLoc(CMD->getLocation()) ==
394 TouchedIdentifier->location()) {
395 VirtualMethods.insert(getSymbolID(CMD));
396 LocateASTReferentMetric.record(1, "method-to-override");
399 // Special case: void foo() ^override: jump to the overridden method.
400 if (NodeKind.isSame(ASTNodeKind::getFromNodeKind<OverrideAttr>()) ||
401 NodeKind.isSame(ASTNodeKind::getFromNodeKind<FinalAttr>())) {
402 // We may be overridding multiple methods - offer them all.
403 for (const NamedDecl *ND : CMD->overridden_methods())
404 AddResultDecl(ND);
405 continue;
409 // Special case: the cursor is on an alias, prefer other results.
410 // This targets "using ns::^Foo", where the target is more interesting.
411 // This does not trigger on renaming aliases:
412 // `using Foo = ^Bar` already targets Bar via a TypeLoc
413 // `using ^Foo = Bar` has no other results, as Underlying is filtered.
414 if (E.second & DeclRelation::Alias && Candidates.size() > 1 &&
415 // beginLoc/endLoc are a token range, so rewind the identifier we're in.
416 SM.isPointWithin(TouchedIdentifier ? TouchedIdentifier->location()
417 : CurLoc,
418 D->getBeginLoc(), D->getEndLoc()))
419 continue;
421 // Special case: the point of declaration of a template specialization,
422 // it's more useful to navigate to the template declaration.
423 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
424 if (TouchedIdentifier &&
425 D->getLocation() == TouchedIdentifier->location()) {
426 LocateASTReferentMetric.record(1, "template-specialization-to-primary");
427 AddResultDecl(CTSD->getSpecializedTemplate());
428 continue;
432 // Special case: if the class name is selected, also map Objective-C
433 // categories and category implementations back to their class interface.
435 // Since `TouchedIdentifier` might refer to the `ObjCCategoryImplDecl`
436 // instead of the `ObjCCategoryDecl` we intentionally check the contents
437 // of the locs when checking for class name equivalence.
438 if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D))
439 if (const auto *ID = CD->getClassInterface())
440 if (TouchedIdentifier &&
441 (CD->getLocation() == TouchedIdentifier->location() ||
442 ID->getName() == TouchedIdentifier->text(SM))) {
443 LocateASTReferentMetric.record(1, "objc-category-to-class");
444 AddResultDecl(ID);
447 LocateASTReferentMetric.record(1, "regular");
448 // Otherwise the target declaration is the right one.
449 AddResultDecl(D);
452 // Now query the index for all Symbol IDs we found in the AST.
453 if (Index && !ResultIndex.empty()) {
454 LookupRequest QueryRequest;
455 for (auto It : ResultIndex)
456 QueryRequest.IDs.insert(It.first);
457 std::string Scratch;
458 Index->lookup(QueryRequest, [&](const Symbol &Sym) {
459 auto &R = Result[ResultIndex.lookup(Sym.ID)];
461 if (R.Definition) { // from AST
462 // Special case: if the AST yielded a definition, then it may not be
463 // the right *declaration*. Prefer the one from the index.
464 if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, MainFilePath))
465 R.PreferredDeclaration = *Loc;
467 // We might still prefer the definition from the index, e.g. for
468 // generated symbols.
469 if (auto Loc = toLSPLocation(
470 getPreferredLocation(*R.Definition, Sym.Definition, Scratch),
471 MainFilePath))
472 R.Definition = *Loc;
473 } else {
474 R.Definition = toLSPLocation(Sym.Definition, MainFilePath);
476 // Use merge logic to choose AST or index declaration.
477 if (auto Loc = toLSPLocation(
478 getPreferredLocation(R.PreferredDeclaration,
479 Sym.CanonicalDeclaration, Scratch),
480 MainFilePath))
481 R.PreferredDeclaration = *Loc;
486 auto Overrides = findImplementors(VirtualMethods, RelationKind::OverriddenBy,
487 Index, MainFilePath);
488 Result.insert(Result.end(), Overrides.begin(), Overrides.end());
489 return Result;
492 std::vector<LocatedSymbol> locateSymbolForType(const ParsedAST &AST,
493 const QualType &Type) {
494 const auto &SM = AST.getSourceManager();
495 auto MainFilePath = AST.tuPath();
497 // FIXME: this sends unique_ptr<Foo> to unique_ptr<T>.
498 // Likely it would be better to send it to Foo (heuristically) or to both.
499 auto Decls = targetDecl(DynTypedNode::create(Type.getNonReferenceType()),
500 DeclRelation::TemplatePattern | DeclRelation::Alias,
501 AST.getHeuristicResolver());
502 if (Decls.empty())
503 return {};
505 std::vector<LocatedSymbol> Results;
506 const auto &ASTContext = AST.getASTContext();
508 for (const NamedDecl *D : Decls) {
509 D = getPreferredDecl(D);
511 auto Loc = makeLocation(ASTContext, nameLocation(*D, SM), MainFilePath);
512 if (!Loc)
513 continue;
515 Results.emplace_back();
516 Results.back().Name = printName(ASTContext, *D);
517 Results.back().PreferredDeclaration = *Loc;
518 Results.back().ID = getSymbolID(D);
519 if (const NamedDecl *Def = getDefinition(D))
520 Results.back().Definition =
521 makeLocation(ASTContext, nameLocation(*Def, SM), MainFilePath);
524 return Results;
527 bool tokenSpelledAt(SourceLocation SpellingLoc, const syntax::TokenBuffer &TB) {
528 auto ExpandedTokens = TB.expandedTokens(
529 TB.sourceManager().getMacroArgExpandedLocation(SpellingLoc));
530 return !ExpandedTokens.empty();
533 llvm::StringRef sourcePrefix(SourceLocation Loc, const SourceManager &SM) {
534 auto D = SM.getDecomposedLoc(Loc);
535 bool Invalid = false;
536 llvm::StringRef Buf = SM.getBufferData(D.first, &Invalid);
537 if (Invalid || D.second > Buf.size())
538 return "";
539 return Buf.substr(0, D.second);
542 bool isDependentName(ASTNodeKind NodeKind) {
543 return NodeKind.isSame(ASTNodeKind::getFromNodeKind<OverloadExpr>()) ||
544 NodeKind.isSame(
545 ASTNodeKind::getFromNodeKind<CXXDependentScopeMemberExpr>()) ||
546 NodeKind.isSame(
547 ASTNodeKind::getFromNodeKind<DependentScopeDeclRefExpr>());
550 } // namespace
552 std::vector<LocatedSymbol> locateSymbolTextually(const SpelledWord &Word,
553 ParsedAST &AST,
554 const SymbolIndex *Index,
555 llvm::StringRef MainFilePath,
556 ASTNodeKind NodeKind) {
557 // Don't use heuristics if this is a real identifier, or not an
558 // identifier.
559 // Exception: dependent names, because those may have useful textual
560 // matches that AST-based heuristics cannot find.
561 if ((Word.ExpandedToken && !isDependentName(NodeKind)) ||
562 !Word.LikelyIdentifier || !Index)
563 return {};
564 // We don't want to handle words in string literals. (It'd be nice to list
565 // *allowed* token kinds explicitly, but comment Tokens aren't retained).
566 if (Word.PartOfSpelledToken &&
567 isStringLiteral(Word.PartOfSpelledToken->kind()))
568 return {};
570 const auto &SM = AST.getSourceManager();
571 // Look up the selected word in the index.
572 FuzzyFindRequest Req;
573 Req.Query = Word.Text.str();
574 Req.ProximityPaths = {MainFilePath.str()};
575 // Find the namespaces to query by lexing the file.
576 Req.Scopes =
577 visibleNamespaces(sourcePrefix(Word.Location, SM), AST.getLangOpts());
578 // FIXME: For extra strictness, consider AnyScope=false.
579 Req.AnyScope = true;
580 // We limit the results to 3 further below. This limit is to avoid fetching
581 // too much data, while still likely having enough for 3 results to remain
582 // after additional filtering.
583 Req.Limit = 10;
584 bool TooMany = false;
585 using ScoredLocatedSymbol = std::pair<float, LocatedSymbol>;
586 std::vector<ScoredLocatedSymbol> ScoredResults;
587 Index->fuzzyFind(Req, [&](const Symbol &Sym) {
588 // Only consider exact name matches, including case.
589 // This is to avoid too many false positives.
590 // We could relax this in the future (e.g. to allow for typos) if we make
591 // the query more accurate by other means.
592 if (Sym.Name != Word.Text)
593 return;
595 // Exclude constructor results. They have the same name as the class,
596 // but we don't have enough context to prefer them over the class.
597 if (Sym.SymInfo.Kind == index::SymbolKind::Constructor)
598 return;
600 auto MaybeDeclLoc =
601 indexToLSPLocation(Sym.CanonicalDeclaration, MainFilePath);
602 if (!MaybeDeclLoc) {
603 log("locateSymbolNamedTextuallyAt: {0}", MaybeDeclLoc.takeError());
604 return;
606 LocatedSymbol Located;
607 Located.PreferredDeclaration = *MaybeDeclLoc;
608 Located.Name = (Sym.Name + Sym.TemplateSpecializationArgs).str();
609 Located.ID = Sym.ID;
610 if (Sym.Definition) {
611 auto MaybeDefLoc = indexToLSPLocation(Sym.Definition, MainFilePath);
612 if (!MaybeDefLoc) {
613 log("locateSymbolNamedTextuallyAt: {0}", MaybeDefLoc.takeError());
614 return;
616 Located.PreferredDeclaration = *MaybeDefLoc;
617 Located.Definition = *MaybeDefLoc;
620 if (ScoredResults.size() >= 5) {
621 // If we have more than 5 results, don't return anything,
622 // as confidence is too low.
623 // FIXME: Alternatively, try a stricter query?
624 TooMany = true;
625 return;
628 SymbolQualitySignals Quality;
629 Quality.merge(Sym);
630 SymbolRelevanceSignals Relevance;
631 Relevance.Name = Sym.Name;
632 Relevance.Query = SymbolRelevanceSignals::Generic;
633 Relevance.merge(Sym);
634 auto Score = evaluateSymbolAndRelevance(Quality.evaluateHeuristics(),
635 Relevance.evaluateHeuristics());
636 dlog("locateSymbolNamedTextuallyAt: {0}{1} = {2}\n{3}{4}\n", Sym.Scope,
637 Sym.Name, Score, Quality, Relevance);
639 ScoredResults.push_back({Score, std::move(Located)});
642 if (TooMany) {
643 vlog("Heuristic index lookup for {0} returned too many candidates, ignored",
644 Word.Text);
645 return {};
648 llvm::sort(ScoredResults,
649 [](const ScoredLocatedSymbol &A, const ScoredLocatedSymbol &B) {
650 return A.first > B.first;
652 std::vector<LocatedSymbol> Results;
653 for (auto &Res : std::move(ScoredResults))
654 Results.push_back(std::move(Res.second));
655 if (Results.empty())
656 vlog("No heuristic index definition for {0}", Word.Text);
657 else
658 log("Found definition heuristically in index for {0}", Word.Text);
659 return Results;
662 const syntax::Token *findNearbyIdentifier(const SpelledWord &Word,
663 const syntax::TokenBuffer &TB) {
664 // Don't use heuristics if this is a real identifier.
665 // Unlikely identifiers are OK if they were used as identifiers nearby.
666 if (Word.ExpandedToken)
667 return nullptr;
668 // We don't want to handle words in string literals. (It'd be nice to list
669 // *allowed* token kinds explicitly, but comment Tokens aren't retained).
670 if (Word.PartOfSpelledToken &&
671 isStringLiteral(Word.PartOfSpelledToken->kind()))
672 return {};
674 const SourceManager &SM = TB.sourceManager();
675 // We prefer the closest possible token, line-wise. Backwards is penalized.
676 // Ties are implicitly broken by traversal order (first-one-wins).
677 auto File = SM.getFileID(Word.Location);
678 unsigned WordLine = SM.getSpellingLineNumber(Word.Location);
679 auto Cost = [&](SourceLocation Loc) -> unsigned {
680 assert(SM.getFileID(Loc) == File && "spelled token in wrong file?");
681 unsigned Line = SM.getSpellingLineNumber(Loc);
682 return Line >= WordLine ? Line - WordLine : 2 * (WordLine - Line);
684 const syntax::Token *BestTok = nullptr;
685 unsigned BestCost = -1;
686 // Search bounds are based on word length:
687 // - forward: 2^N lines
688 // - backward: 2^(N-1) lines.
689 unsigned MaxDistance =
690 1U << std::min<unsigned>(Word.Text.size(),
691 std::numeric_limits<unsigned>::digits - 1);
692 // Line number for SM.translateLineCol() should be one-based, also
693 // SM.translateLineCol() can handle line number greater than
694 // number of lines in the file.
695 // - LineMin = max(1, WordLine + 1 - 2^(N-1))
696 // - LineMax = WordLine + 1 + 2^N
697 unsigned LineMin =
698 WordLine + 1 <= MaxDistance / 2 ? 1 : WordLine + 1 - MaxDistance / 2;
699 unsigned LineMax = WordLine + 1 + MaxDistance;
700 SourceLocation LocMin = SM.translateLineCol(File, LineMin, 1);
701 assert(LocMin.isValid());
702 SourceLocation LocMax = SM.translateLineCol(File, LineMax, 1);
703 assert(LocMax.isValid());
705 // Updates BestTok and BestCost if Tok is a good candidate.
706 // May return true if the cost is too high for this token.
707 auto Consider = [&](const syntax::Token &Tok) {
708 if (Tok.location() < LocMin || Tok.location() > LocMax)
709 return true; // we are too far from the word, break the outer loop.
710 if (!(Tok.kind() == tok::identifier && Tok.text(SM) == Word.Text))
711 return false;
712 // No point guessing the same location we started with.
713 if (Tok.location() == Word.Location)
714 return false;
715 // We've done cheap checks, compute cost so we can break the caller's loop.
716 unsigned TokCost = Cost(Tok.location());
717 if (TokCost >= BestCost)
718 return true; // causes the outer loop to break.
719 // Allow locations that might be part of the AST, and macros (even if empty)
720 // but not things like disabled preprocessor sections.
721 if (!(tokenSpelledAt(Tok.location(), TB) || TB.expansionStartingAt(&Tok)))
722 return false;
723 // We already verified this token is an improvement.
724 BestCost = TokCost;
725 BestTok = &Tok;
726 return false;
728 auto SpelledTokens = TB.spelledTokens(File);
729 // Find where the word occurred in the token stream, to search forward & back.
730 auto *I = llvm::partition_point(SpelledTokens, [&](const syntax::Token &T) {
731 assert(SM.getFileID(T.location()) == SM.getFileID(Word.Location));
732 return T.location() < Word.Location; // Comparison OK: same file.
734 // Search for matches after the cursor.
735 for (const syntax::Token &Tok : llvm::ArrayRef(I, SpelledTokens.end()))
736 if (Consider(Tok))
737 break; // costs of later tokens are greater...
738 // Search for matches before the cursor.
739 for (const syntax::Token &Tok :
740 llvm::reverse(llvm::ArrayRef(SpelledTokens.begin(), I)))
741 if (Consider(Tok))
742 break;
744 if (BestTok)
745 vlog(
746 "Word {0} under cursor {1} isn't a token (after PP), trying nearby {2}",
747 Word.Text, Word.Location.printToString(SM),
748 BestTok->location().printToString(SM));
750 return BestTok;
753 std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
754 const SymbolIndex *Index) {
755 const auto &SM = AST.getSourceManager();
756 auto MainFilePath = AST.tuPath();
758 if (auto File = locateFileReferent(Pos, AST, MainFilePath))
759 return {std::move(*File)};
761 auto CurLoc = sourceLocationInMainFile(SM, Pos);
762 if (!CurLoc) {
763 elog("locateSymbolAt failed to convert position to source location: {0}",
764 CurLoc.takeError());
765 return {};
768 const syntax::Token *TouchedIdentifier = nullptr;
769 auto TokensTouchingCursor =
770 syntax::spelledTokensTouching(*CurLoc, AST.getTokens());
771 for (const syntax::Token &Tok : TokensTouchingCursor) {
772 if (Tok.kind() == tok::identifier) {
773 if (auto Macro = locateMacroReferent(Tok, AST, MainFilePath))
774 // Don't look at the AST or index if we have a macro result.
775 // (We'd just return declarations referenced from the macro's
776 // expansion.)
777 return {*std::move(Macro)};
779 TouchedIdentifier = &Tok;
780 break;
783 if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) {
784 // go-to-definition on auto should find the definition of the deduced
785 // type, if possible
786 if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) {
787 auto LocSym = locateSymbolForType(AST, *Deduced);
788 if (!LocSym.empty())
789 return LocSym;
794 ASTNodeKind NodeKind;
795 auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST,
796 MainFilePath, Index, NodeKind);
797 if (!ASTResults.empty())
798 return ASTResults;
800 // If the cursor can't be resolved directly, try fallback strategies.
801 auto Word =
802 SpelledWord::touching(*CurLoc, AST.getTokens(), AST.getLangOpts());
803 if (Word) {
804 // Is the same word nearby a real identifier that might refer to something?
805 if (const syntax::Token *NearbyIdent =
806 findNearbyIdentifier(*Word, AST.getTokens())) {
807 if (auto Macro = locateMacroReferent(*NearbyIdent, AST, MainFilePath)) {
808 log("Found macro definition heuristically using nearby identifier {0}",
809 Word->Text);
810 return {*std::move(Macro)};
812 ASTResults = locateASTReferent(NearbyIdent->location(), NearbyIdent, AST,
813 MainFilePath, Index, NodeKind);
814 if (!ASTResults.empty()) {
815 log("Found definition heuristically using nearby identifier {0}",
816 NearbyIdent->text(SM));
817 return ASTResults;
819 vlog("No definition found using nearby identifier {0} at {1}", Word->Text,
820 Word->Location.printToString(SM));
822 // No nearby word, or it didn't refer to anything either. Try the index.
823 auto TextualResults =
824 locateSymbolTextually(*Word, AST, Index, MainFilePath, NodeKind);
825 if (!TextualResults.empty())
826 return TextualResults;
829 return {};
832 std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) {
833 const auto &SM = AST.getSourceManager();
835 std::vector<DocumentLink> Result;
836 for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
837 if (Inc.Resolved.empty())
838 continue;
839 auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
840 const auto *HashTok = AST.getTokens().spelledTokenAt(HashLoc);
841 assert(HashTok && "got inclusion at wrong offset");
842 const auto *IncludeTok = std::next(HashTok);
843 const auto *FileTok = std::next(IncludeTok);
844 // FileTok->range is not sufficient here, as raw lexing wouldn't yield
845 // correct tokens for angled filenames. Hence we explicitly use
846 // Inc.Written's length.
847 auto FileRange =
848 syntax::FileRange(SM, FileTok->location(), Inc.Written.length())
849 .toCharRange(SM);
851 Result.push_back(
852 DocumentLink({halfOpenToRange(SM, FileRange),
853 URIForFile::canonicalize(Inc.Resolved, AST.tuPath())}));
856 return Result;
859 namespace {
861 /// Collects references to symbols within the main file.
862 class ReferenceFinder : public index::IndexDataConsumer {
863 public:
864 struct Reference {
865 syntax::Token SpelledTok;
866 index::SymbolRoleSet Role;
867 const Decl *Container;
869 Range range(const SourceManager &SM) const {
870 return halfOpenToRange(SM, SpelledTok.range(SM).toCharRange(SM));
874 ReferenceFinder(const ParsedAST &AST,
875 const llvm::ArrayRef<const NamedDecl *> Targets,
876 bool PerToken)
877 : PerToken(PerToken), AST(AST) {
878 for (const NamedDecl *ND : Targets)
879 TargetDecls.insert(ND->getCanonicalDecl());
882 std::vector<Reference> take() && {
883 llvm::sort(References, [](const Reference &L, const Reference &R) {
884 auto LTok = L.SpelledTok.location();
885 auto RTok = R.SpelledTok.location();
886 return std::tie(LTok, L.Role) < std::tie(RTok, R.Role);
888 // We sometimes see duplicates when parts of the AST get traversed twice.
889 References.erase(std::unique(References.begin(), References.end(),
890 [](const Reference &L, const Reference &R) {
891 auto LTok = L.SpelledTok.location();
892 auto RTok = R.SpelledTok.location();
893 return std::tie(LTok, L.Role) ==
894 std::tie(RTok, R.Role);
896 References.end());
897 return std::move(References);
900 bool
901 handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
902 llvm::ArrayRef<index::SymbolRelation> Relations,
903 SourceLocation Loc,
904 index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
905 if (!TargetDecls.contains(D->getCanonicalDecl()))
906 return true;
907 const SourceManager &SM = AST.getSourceManager();
908 if (!isInsideMainFile(Loc, SM))
909 return true;
910 const auto &TB = AST.getTokens();
912 llvm::SmallVector<SourceLocation, 1> Locs;
913 if (PerToken) {
914 // Check whether this is one of the few constructs where the reference
915 // can be split over several tokens.
916 if (auto *OME = llvm::dyn_cast_or_null<ObjCMessageExpr>(ASTNode.OrigE)) {
917 OME->getSelectorLocs(Locs);
918 } else if (auto *OMD =
919 llvm::dyn_cast_or_null<ObjCMethodDecl>(ASTNode.OrigD)) {
920 OMD->getSelectorLocs(Locs);
922 // Sanity check: we expect the *first* token to match the reported loc.
923 // Otherwise, maybe it was e.g. some other kind of reference to a Decl.
924 if (!Locs.empty() && Locs.front() != Loc)
925 Locs.clear(); // First token doesn't match, assume our guess was wrong.
927 if (Locs.empty())
928 Locs.push_back(Loc);
930 SymbolCollector::Options CollectorOpts;
931 CollectorOpts.CollectMainFileSymbols = true;
932 for (SourceLocation L : Locs) {
933 L = SM.getFileLoc(L);
934 if (const auto *Tok = TB.spelledTokenAt(L))
935 References.push_back(
936 {*Tok, Roles,
937 SymbolCollector::getRefContainer(ASTNode.Parent, CollectorOpts)});
939 return true;
942 private:
943 bool PerToken; // If true, report 3 references for split ObjC selector names.
944 std::vector<Reference> References;
945 const ParsedAST &AST;
946 llvm::DenseSet<const Decl *> TargetDecls;
949 std::vector<ReferenceFinder::Reference>
950 findRefs(const llvm::ArrayRef<const NamedDecl *> TargetDecls, ParsedAST &AST,
951 bool PerToken) {
952 ReferenceFinder RefFinder(AST, TargetDecls, PerToken);
953 index::IndexingOptions IndexOpts;
954 IndexOpts.SystemSymbolFilter =
955 index::IndexingOptions::SystemSymbolFilterKind::All;
956 IndexOpts.IndexFunctionLocals = true;
957 IndexOpts.IndexParametersInDeclarations = true;
958 IndexOpts.IndexTemplateParameters = true;
959 indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
960 AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
961 return std::move(RefFinder).take();
964 const Stmt *getFunctionBody(DynTypedNode N) {
965 if (const auto *FD = N.get<FunctionDecl>())
966 return FD->getBody();
967 if (const auto *FD = N.get<BlockDecl>())
968 return FD->getBody();
969 if (const auto *FD = N.get<LambdaExpr>())
970 return FD->getBody();
971 if (const auto *FD = N.get<ObjCMethodDecl>())
972 return FD->getBody();
973 return nullptr;
976 const Stmt *getLoopBody(DynTypedNode N) {
977 if (const auto *LS = N.get<ForStmt>())
978 return LS->getBody();
979 if (const auto *LS = N.get<CXXForRangeStmt>())
980 return LS->getBody();
981 if (const auto *LS = N.get<WhileStmt>())
982 return LS->getBody();
983 if (const auto *LS = N.get<DoStmt>())
984 return LS->getBody();
985 return nullptr;
988 // AST traversal to highlight control flow statements under some root.
989 // Once we hit further control flow we prune the tree (or at least restrict
990 // what we highlight) so we capture e.g. breaks from the outer loop only.
991 class FindControlFlow : public RecursiveASTVisitor<FindControlFlow> {
992 // Types of control-flow statements we might highlight.
993 enum Target {
994 Break = 1,
995 Continue = 2,
996 Return = 4,
997 Case = 8,
998 Throw = 16,
999 Goto = 32,
1000 All = Break | Continue | Return | Case | Throw | Goto,
1002 int Ignore = 0; // bitmask of Target - what are we *not* highlighting?
1003 SourceRange Bounds; // Half-open, restricts reported targets.
1004 std::vector<SourceLocation> &Result;
1005 const SourceManager &SM;
1007 // Masks out targets for a traversal into D.
1008 // Traverses the subtree using Delegate() if any targets remain.
1009 template <typename Func>
1010 bool filterAndTraverse(DynTypedNode D, const Func &Delegate) {
1011 auto RestoreIgnore = llvm::make_scope_exit(
1012 [OldIgnore(Ignore), this] { Ignore = OldIgnore; });
1013 if (getFunctionBody(D))
1014 Ignore = All;
1015 else if (getLoopBody(D))
1016 Ignore |= Continue | Break;
1017 else if (D.get<SwitchStmt>())
1018 Ignore |= Break | Case;
1019 // Prune tree if we're not looking for anything.
1020 return (Ignore == All) ? true : Delegate();
1023 void found(Target T, SourceLocation Loc) {
1024 if (T & Ignore)
1025 return;
1026 if (SM.isBeforeInTranslationUnit(Loc, Bounds.getBegin()) ||
1027 SM.isBeforeInTranslationUnit(Bounds.getEnd(), Loc))
1028 return;
1029 Result.push_back(Loc);
1032 public:
1033 FindControlFlow(SourceRange Bounds, std::vector<SourceLocation> &Result,
1034 const SourceManager &SM)
1035 : Bounds(Bounds), Result(Result), SM(SM) {}
1037 // When traversing function or loops, limit targets to those that still
1038 // refer to the original root.
1039 bool TraverseDecl(Decl *D) {
1040 return !D || filterAndTraverse(DynTypedNode::create(*D), [&] {
1041 return RecursiveASTVisitor::TraverseDecl(D);
1044 bool TraverseStmt(Stmt *S) {
1045 return !S || filterAndTraverse(DynTypedNode::create(*S), [&] {
1046 return RecursiveASTVisitor::TraverseStmt(S);
1050 // Add leaves that we found and want.
1051 bool VisitReturnStmt(ReturnStmt *R) {
1052 found(Return, R->getReturnLoc());
1053 return true;
1055 bool VisitBreakStmt(BreakStmt *B) {
1056 found(Break, B->getBreakLoc());
1057 return true;
1059 bool VisitContinueStmt(ContinueStmt *C) {
1060 found(Continue, C->getContinueLoc());
1061 return true;
1063 bool VisitSwitchCase(SwitchCase *C) {
1064 found(Case, C->getKeywordLoc());
1065 return true;
1067 bool VisitCXXThrowExpr(CXXThrowExpr *T) {
1068 found(Throw, T->getThrowLoc());
1069 return true;
1071 bool VisitGotoStmt(GotoStmt *G) {
1072 // Goto is interesting if its target is outside the root.
1073 if (const auto *LD = G->getLabel()) {
1074 if (SM.isBeforeInTranslationUnit(LD->getLocation(), Bounds.getBegin()) ||
1075 SM.isBeforeInTranslationUnit(Bounds.getEnd(), LD->getLocation()))
1076 found(Goto, G->getGotoLoc());
1078 return true;
1082 // Given a location within a switch statement, return the half-open range that
1083 // covers the case it's contained in.
1084 // We treat `case X: case Y: ...` as one case, and assume no other fallthrough.
1085 SourceRange findCaseBounds(const SwitchStmt &Switch, SourceLocation Loc,
1086 const SourceManager &SM) {
1087 // Cases are not stored in order, sort them first.
1088 // (In fact they seem to be stored in reverse order, don't rely on this)
1089 std::vector<const SwitchCase *> Cases;
1090 for (const SwitchCase *Case = Switch.getSwitchCaseList(); Case;
1091 Case = Case->getNextSwitchCase())
1092 Cases.push_back(Case);
1093 llvm::sort(Cases, [&](const SwitchCase *L, const SwitchCase *R) {
1094 return SM.isBeforeInTranslationUnit(L->getKeywordLoc(), R->getKeywordLoc());
1097 // Find the first case after the target location, the end of our range.
1098 auto CaseAfter = llvm::partition_point(Cases, [&](const SwitchCase *C) {
1099 return !SM.isBeforeInTranslationUnit(Loc, C->getKeywordLoc());
1101 SourceLocation End = CaseAfter == Cases.end() ? Switch.getEndLoc()
1102 : (*CaseAfter)->getKeywordLoc();
1104 // Our target can be before the first case - cases are optional!
1105 if (CaseAfter == Cases.begin())
1106 return SourceRange(Switch.getBeginLoc(), End);
1107 // The start of our range is usually the previous case, but...
1108 auto CaseBefore = std::prev(CaseAfter);
1109 // ... rewind CaseBefore to the first in a `case A: case B: ...` sequence.
1110 while (CaseBefore != Cases.begin() &&
1111 (*std::prev(CaseBefore))->getSubStmt() == *CaseBefore)
1112 --CaseBefore;
1113 return SourceRange((*CaseBefore)->getKeywordLoc(), End);
1116 // Returns the locations of control flow statements related to N. e.g.:
1117 // for => branches: break/continue/return/throw
1118 // break => controlling loop (forwhile/do), and its related control flow
1119 // return => all returns/throws from the same function
1120 // When an inner block is selected, we include branches bound to outer blocks
1121 // as these are exits from the inner block. e.g. return in a for loop.
1122 // FIXME: We don't analyze catch blocks, throw is treated the same as return.
1123 std::vector<SourceLocation> relatedControlFlow(const SelectionTree::Node &N) {
1124 const SourceManager &SM =
1125 N.getDeclContext().getParentASTContext().getSourceManager();
1126 std::vector<SourceLocation> Result;
1128 // First, check if we're at a node that can resolve to a root.
1129 enum class Cur { None, Break, Continue, Return, Case, Throw } Cursor;
1130 if (N.ASTNode.get<BreakStmt>()) {
1131 Cursor = Cur::Break;
1132 } else if (N.ASTNode.get<ContinueStmt>()) {
1133 Cursor = Cur::Continue;
1134 } else if (N.ASTNode.get<ReturnStmt>()) {
1135 Cursor = Cur::Return;
1136 } else if (N.ASTNode.get<CXXThrowExpr>()) {
1137 Cursor = Cur::Throw;
1138 } else if (N.ASTNode.get<SwitchCase>()) {
1139 Cursor = Cur::Case;
1140 } else if (const GotoStmt *GS = N.ASTNode.get<GotoStmt>()) {
1141 // We don't know what root to associate with, but highlight the goto/label.
1142 Result.push_back(GS->getGotoLoc());
1143 if (const auto *LD = GS->getLabel())
1144 Result.push_back(LD->getLocation());
1145 Cursor = Cur::None;
1146 } else {
1147 Cursor = Cur::None;
1150 const Stmt *Root = nullptr; // Loop or function body to traverse.
1151 SourceRange Bounds;
1152 // Look up the tree for a root (or just at this node if we didn't find a leaf)
1153 for (const auto *P = &N; P; P = P->Parent) {
1154 // return associates with enclosing function
1155 if (const Stmt *FunctionBody = getFunctionBody(P->ASTNode)) {
1156 if (Cursor == Cur::Return || Cursor == Cur::Throw) {
1157 Root = FunctionBody;
1159 break; // other leaves don't cross functions.
1161 // break/continue associate with enclosing loop.
1162 if (const Stmt *LoopBody = getLoopBody(P->ASTNode)) {
1163 if (Cursor == Cur::None || Cursor == Cur::Break ||
1164 Cursor == Cur::Continue) {
1165 Root = LoopBody;
1166 // Highlight the loop keyword itself.
1167 // FIXME: for do-while, this only covers the `do`..
1168 Result.push_back(P->ASTNode.getSourceRange().getBegin());
1169 break;
1172 // For switches, users think of case statements as control flow blocks.
1173 // We highlight only occurrences surrounded by the same case.
1174 // We don't detect fallthrough (other than 'case X, case Y').
1175 if (const auto *SS = P->ASTNode.get<SwitchStmt>()) {
1176 if (Cursor == Cur::Break || Cursor == Cur::Case) {
1177 Result.push_back(SS->getSwitchLoc()); // Highlight the switch.
1178 Root = SS->getBody();
1179 // Limit to enclosing case, if there is one.
1180 Bounds = findCaseBounds(*SS, N.ASTNode.getSourceRange().getBegin(), SM);
1181 break;
1184 // If we didn't start at some interesting node, we're done.
1185 if (Cursor == Cur::None)
1186 break;
1188 if (Root) {
1189 if (!Bounds.isValid())
1190 Bounds = Root->getSourceRange();
1191 FindControlFlow(Bounds, Result, SM).TraverseStmt(const_cast<Stmt *>(Root));
1193 return Result;
1196 DocumentHighlight toHighlight(const ReferenceFinder::Reference &Ref,
1197 const SourceManager &SM) {
1198 DocumentHighlight DH;
1199 DH.range = Ref.range(SM);
1200 if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
1201 DH.kind = DocumentHighlightKind::Write;
1202 else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
1203 DH.kind = DocumentHighlightKind::Read;
1204 else
1205 DH.kind = DocumentHighlightKind::Text;
1206 return DH;
1209 std::optional<DocumentHighlight> toHighlight(SourceLocation Loc,
1210 const syntax::TokenBuffer &TB) {
1211 Loc = TB.sourceManager().getFileLoc(Loc);
1212 if (const auto *Tok = TB.spelledTokenAt(Loc)) {
1213 DocumentHighlight Result;
1214 Result.range = halfOpenToRange(
1215 TB.sourceManager(),
1216 CharSourceRange::getCharRange(Tok->location(), Tok->endLocation()));
1217 return Result;
1219 return std::nullopt;
1222 } // namespace
1224 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
1225 Position Pos) {
1226 const SourceManager &SM = AST.getSourceManager();
1227 // FIXME: show references to macro within file?
1228 auto CurLoc = sourceLocationInMainFile(SM, Pos);
1229 if (!CurLoc) {
1230 llvm::consumeError(CurLoc.takeError());
1231 return {};
1233 std::vector<DocumentHighlight> Result;
1234 auto TryTree = [&](SelectionTree ST) {
1235 if (const SelectionTree::Node *N = ST.commonAncestor()) {
1236 DeclRelationSet Relations =
1237 DeclRelation::TemplatePattern | DeclRelation::Alias;
1238 auto TargetDecls =
1239 targetDecl(N->ASTNode, Relations, AST.getHeuristicResolver());
1240 if (!TargetDecls.empty()) {
1241 // FIXME: we may get multiple DocumentHighlights with the same location
1242 // and different kinds, deduplicate them.
1243 for (const auto &Ref : findRefs(TargetDecls, AST, /*PerToken=*/true))
1244 Result.push_back(toHighlight(Ref, SM));
1245 return true;
1247 auto ControlFlow = relatedControlFlow(*N);
1248 if (!ControlFlow.empty()) {
1249 for (SourceLocation Loc : ControlFlow)
1250 if (auto Highlight = toHighlight(Loc, AST.getTokens()))
1251 Result.push_back(std::move(*Highlight));
1252 return true;
1255 return false;
1258 unsigned Offset =
1259 AST.getSourceManager().getDecomposedSpellingLoc(*CurLoc).second;
1260 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset,
1261 Offset, TryTree);
1262 return Result;
1265 std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
1266 const SymbolIndex *Index) {
1267 // We rely on index to find the implementations in subclasses.
1268 // FIXME: Index can be stale, so we may loose some latest results from the
1269 // main file.
1270 if (!Index)
1271 return {};
1272 const SourceManager &SM = AST.getSourceManager();
1273 auto CurLoc = sourceLocationInMainFile(SM, Pos);
1274 if (!CurLoc) {
1275 elog("Failed to convert position to source location: {0}",
1276 CurLoc.takeError());
1277 return {};
1279 DeclRelationSet Relations =
1280 DeclRelation::TemplatePattern | DeclRelation::Alias;
1281 llvm::DenseSet<SymbolID> IDs;
1282 RelationKind QueryKind = RelationKind::OverriddenBy;
1283 for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations)) {
1284 if (const auto *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
1285 if (CXXMD->isVirtual()) {
1286 IDs.insert(getSymbolID(ND));
1287 QueryKind = RelationKind::OverriddenBy;
1289 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
1290 IDs.insert(getSymbolID(RD));
1291 QueryKind = RelationKind::BaseOf;
1294 return findImplementors(std::move(IDs), QueryKind, Index, AST.tuPath());
1297 namespace {
1298 // Recursively finds all the overridden methods of `CMD` in complete type
1299 // hierarchy.
1300 void getOverriddenMethods(const CXXMethodDecl *CMD,
1301 llvm::DenseSet<SymbolID> &OverriddenMethods) {
1302 if (!CMD)
1303 return;
1304 for (const CXXMethodDecl *Base : CMD->overridden_methods()) {
1305 if (auto ID = getSymbolID(Base))
1306 OverriddenMethods.insert(ID);
1307 getOverriddenMethods(Base, OverriddenMethods);
1311 std::optional<std::string>
1312 stringifyContainerForMainFileRef(const Decl *Container) {
1313 // FIXME We might also want to display the signature here
1314 // When doing so, remember to also add the Signature to index results!
1315 if (auto *ND = llvm::dyn_cast_if_present<NamedDecl>(Container))
1316 return printQualifiedName(*ND);
1317 return {};
1320 std::optional<ReferencesResult>
1321 maybeFindIncludeReferences(ParsedAST &AST, Position Pos,
1322 URIForFile URIMainFile) {
1323 const auto &Includes = AST.getIncludeStructure().MainFileIncludes;
1324 auto IncludeOnLine = llvm::find_if(Includes, [&Pos](const Inclusion &Inc) {
1325 return Inc.HashLine == Pos.line;
1327 if (IncludeOnLine == Includes.end())
1328 return std::nullopt;
1330 const auto &Inc = *IncludeOnLine;
1331 const SourceManager &SM = AST.getSourceManager();
1332 ReferencesResult Results;
1333 auto ConvertedMainFileIncludes = convertIncludes(SM, Includes);
1334 auto ReferencedInclude = convertIncludes(SM, Inc);
1335 include_cleaner::walkUsed(
1336 AST.getLocalTopLevelDecls(), collectMacroReferences(AST),
1337 AST.getPragmaIncludes(), SM,
1338 [&](const include_cleaner::SymbolReference &Ref,
1339 llvm::ArrayRef<include_cleaner::Header> Providers) {
1340 if (Ref.RT != include_cleaner::RefType::Explicit)
1341 return;
1343 auto Provider =
1344 firstMatchedProvider(ConvertedMainFileIncludes, Providers);
1345 if (!Provider || ReferencedInclude.match(*Provider).empty())
1346 return;
1348 auto Loc = SM.getFileLoc(Ref.RefLocation);
1349 // File locations can be outside of the main file if macro is
1350 // expanded through an #include.
1351 while (SM.getFileID(Loc) != SM.getMainFileID())
1352 Loc = SM.getIncludeLoc(SM.getFileID(Loc));
1354 ReferencesResult::Reference Result;
1355 const auto *Token = AST.getTokens().spelledTokenAt(Loc);
1356 Result.Loc.range = Range{sourceLocToPosition(SM, Token->location()),
1357 sourceLocToPosition(SM, Token->endLocation())};
1358 Result.Loc.uri = URIMainFile;
1359 Results.References.push_back(std::move(Result));
1361 if (Results.References.empty())
1362 return std::nullopt;
1364 // Add the #include line to the references list.
1365 auto IncludeLen = std::string{"#include"}.length() + Inc.Written.length() + 1;
1366 ReferencesResult::Reference Result;
1367 Result.Loc.range = clangd::Range{Position{Inc.HashLine, 0},
1368 Position{Inc.HashLine, (int)IncludeLen}};
1369 Result.Loc.uri = URIMainFile;
1370 Results.References.push_back(std::move(Result));
1372 if (Results.References.empty())
1373 return std::nullopt;
1374 return Results;
1376 } // namespace
1378 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
1379 const SymbolIndex *Index, bool AddContext) {
1380 ReferencesResult Results;
1381 const SourceManager &SM = AST.getSourceManager();
1382 auto MainFilePath = AST.tuPath();
1383 auto URIMainFile = URIForFile::canonicalize(MainFilePath, MainFilePath);
1384 auto CurLoc = sourceLocationInMainFile(SM, Pos);
1385 if (!CurLoc) {
1386 llvm::consumeError(CurLoc.takeError());
1387 return {};
1390 const auto IncludeReferences =
1391 maybeFindIncludeReferences(AST, Pos, URIMainFile);
1392 if (IncludeReferences)
1393 return *IncludeReferences;
1395 llvm::DenseSet<SymbolID> IDsToQuery, OverriddenMethods;
1397 const auto *IdentifierAtCursor =
1398 syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens());
1399 std::optional<DefinedMacro> Macro;
1400 if (IdentifierAtCursor)
1401 Macro = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor());
1402 if (Macro) {
1403 // Handle references to macro.
1404 if (auto MacroSID = getSymbolID(Macro->Name, Macro->Info, SM)) {
1405 // Collect macro references from main file.
1406 const auto &IDToRefs = AST.getMacros().MacroRefs;
1407 auto Refs = IDToRefs.find(MacroSID);
1408 if (Refs != IDToRefs.end()) {
1409 for (const auto &Ref : Refs->second) {
1410 ReferencesResult::Reference Result;
1411 Result.Loc.range = Ref.toRange(SM);
1412 Result.Loc.uri = URIMainFile;
1413 if (Ref.IsDefinition) {
1414 Result.Attributes |= ReferencesResult::Declaration;
1415 Result.Attributes |= ReferencesResult::Definition;
1417 Results.References.push_back(std::move(Result));
1420 IDsToQuery.insert(MacroSID);
1422 } else {
1423 // Handle references to Decls.
1425 DeclRelationSet Relations =
1426 DeclRelation::TemplatePattern | DeclRelation::Alias;
1427 std::vector<const NamedDecl *> Decls =
1428 getDeclAtPosition(AST, *CurLoc, Relations);
1429 llvm::SmallVector<const NamedDecl *> TargetsInMainFile;
1430 for (const NamedDecl *D : Decls) {
1431 auto ID = getSymbolID(D);
1432 if (!ID)
1433 continue;
1434 TargetsInMainFile.push_back(D);
1435 // Not all symbols can be referenced from outside (e.g. function-locals).
1436 // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
1437 // we know this file isn't a header. The details might be tricky.
1438 if (D->getParentFunctionOrMethod())
1439 continue;
1440 IDsToQuery.insert(ID);
1443 RelationsRequest OverriddenBy;
1444 if (Index) {
1445 OverriddenBy.Predicate = RelationKind::OverriddenBy;
1446 for (const NamedDecl *ND : Decls) {
1447 // Special case: For virtual methods, report decl/def of overrides and
1448 // references to all overridden methods in complete type hierarchy.
1449 if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
1450 if (CMD->isVirtual()) {
1451 if (auto ID = getSymbolID(CMD))
1452 OverriddenBy.Subjects.insert(ID);
1453 getOverriddenMethods(CMD, OverriddenMethods);
1459 // We traverse the AST to find references in the main file.
1460 auto MainFileRefs = findRefs(TargetsInMainFile, AST, /*PerToken=*/false);
1461 // We may get multiple refs with the same location and different Roles, as
1462 // cross-reference is only interested in locations, we deduplicate them
1463 // by the location to avoid emitting duplicated locations.
1464 MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(),
1465 [](const ReferenceFinder::Reference &L,
1466 const ReferenceFinder::Reference &R) {
1467 return L.SpelledTok.location() ==
1468 R.SpelledTok.location();
1470 MainFileRefs.end());
1471 for (const auto &Ref : MainFileRefs) {
1472 ReferencesResult::Reference Result;
1473 Result.Loc.range = Ref.range(SM);
1474 Result.Loc.uri = URIMainFile;
1475 if (AddContext)
1476 Result.Loc.containerName =
1477 stringifyContainerForMainFileRef(Ref.Container);
1478 if (Ref.Role & static_cast<unsigned>(index::SymbolRole::Declaration))
1479 Result.Attributes |= ReferencesResult::Declaration;
1480 // clang-index doesn't report definitions as declarations, but they are.
1481 if (Ref.Role & static_cast<unsigned>(index::SymbolRole::Definition))
1482 Result.Attributes |=
1483 ReferencesResult::Definition | ReferencesResult::Declaration;
1484 Results.References.push_back(std::move(Result));
1486 // Add decl/def of overridding methods.
1487 if (Index && !OverriddenBy.Subjects.empty()) {
1488 LookupRequest ContainerLookup;
1489 // Different overrides will always be contained in different classes, so
1490 // we have a one-to-one mapping between SymbolID and index here, thus we
1491 // don't need to use std::vector as the map's value type.
1492 llvm::DenseMap<SymbolID, size_t> RefIndexForContainer;
1493 Index->relations(OverriddenBy, [&](const SymbolID &Subject,
1494 const Symbol &Object) {
1495 if (Limit && Results.References.size() >= Limit) {
1496 Results.HasMore = true;
1497 return;
1499 const auto LSPLocDecl =
1500 toLSPLocation(Object.CanonicalDeclaration, MainFilePath);
1501 const auto LSPLocDef = toLSPLocation(Object.Definition, MainFilePath);
1502 if (LSPLocDecl && LSPLocDecl != LSPLocDef) {
1503 ReferencesResult::Reference Result;
1504 Result.Loc = {std::move(*LSPLocDecl), std::nullopt};
1505 Result.Attributes =
1506 ReferencesResult::Declaration | ReferencesResult::Override;
1507 RefIndexForContainer.insert({Object.ID, Results.References.size()});
1508 ContainerLookup.IDs.insert(Object.ID);
1509 Results.References.push_back(std::move(Result));
1511 if (LSPLocDef) {
1512 ReferencesResult::Reference Result;
1513 Result.Loc = {std::move(*LSPLocDef), std::nullopt};
1514 Result.Attributes = ReferencesResult::Declaration |
1515 ReferencesResult::Definition |
1516 ReferencesResult::Override;
1517 RefIndexForContainer.insert({Object.ID, Results.References.size()});
1518 ContainerLookup.IDs.insert(Object.ID);
1519 Results.References.push_back(std::move(Result));
1523 if (!ContainerLookup.IDs.empty() && AddContext)
1524 Index->lookup(ContainerLookup, [&](const Symbol &Container) {
1525 auto Ref = RefIndexForContainer.find(Container.ID);
1526 assert(Ref != RefIndexForContainer.end());
1527 Results.References[Ref->getSecond()].Loc.containerName =
1528 Container.Scope.str() + Container.Name.str();
1532 // Now query the index for references from other files.
1533 auto QueryIndex = [&](llvm::DenseSet<SymbolID> IDs, bool AllowAttributes,
1534 bool AllowMainFileSymbols) {
1535 if (IDs.empty() || !Index || Results.HasMore)
1536 return;
1537 RefsRequest Req;
1538 Req.IDs = std::move(IDs);
1539 if (Limit) {
1540 if (Limit < Results.References.size()) {
1541 // We've already filled our quota, still check the index to correctly
1542 // return the `HasMore` info.
1543 Req.Limit = 0;
1544 } else {
1545 // Query index only for the remaining size.
1546 Req.Limit = Limit - Results.References.size();
1549 LookupRequest ContainerLookup;
1550 llvm::DenseMap<SymbolID, std::vector<size_t>> RefIndicesForContainer;
1551 Results.HasMore |= Index->refs(Req, [&](const Ref &R) {
1552 auto LSPLoc = toLSPLocation(R.Location, MainFilePath);
1553 // Avoid indexed results for the main file - the AST is authoritative.
1554 if (!LSPLoc ||
1555 (!AllowMainFileSymbols && LSPLoc->uri.file() == MainFilePath))
1556 return;
1557 ReferencesResult::Reference Result;
1558 Result.Loc = {std::move(*LSPLoc), std::nullopt};
1559 if (AllowAttributes) {
1560 if ((R.Kind & RefKind::Declaration) == RefKind::Declaration)
1561 Result.Attributes |= ReferencesResult::Declaration;
1562 // FIXME: our index should definitely store def | decl separately!
1563 if ((R.Kind & RefKind::Definition) == RefKind::Definition)
1564 Result.Attributes |=
1565 ReferencesResult::Declaration | ReferencesResult::Definition;
1567 if (AddContext) {
1568 SymbolID Container = R.Container;
1569 ContainerLookup.IDs.insert(Container);
1570 RefIndicesForContainer[Container].push_back(Results.References.size());
1572 Results.References.push_back(std::move(Result));
1575 if (!ContainerLookup.IDs.empty() && AddContext)
1576 Index->lookup(ContainerLookup, [&](const Symbol &Container) {
1577 auto Ref = RefIndicesForContainer.find(Container.ID);
1578 assert(Ref != RefIndicesForContainer.end());
1579 auto ContainerName = Container.Scope.str() + Container.Name.str();
1580 for (auto I : Ref->getSecond()) {
1581 Results.References[I].Loc.containerName = ContainerName;
1585 QueryIndex(std::move(IDsToQuery), /*AllowAttributes=*/true,
1586 /*AllowMainFileSymbols=*/false);
1587 // For a virtual method: Occurrences of BaseMethod should be treated as refs
1588 // and not as decl/def. Allow symbols from main file since AST does not report
1589 // these.
1590 QueryIndex(std::move(OverriddenMethods), /*AllowAttributes=*/false,
1591 /*AllowMainFileSymbols=*/true);
1592 return Results;
1595 std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
1596 const SourceManager &SM = AST.getSourceManager();
1597 auto CurLoc = sourceLocationInMainFile(SM, Pos);
1598 if (!CurLoc) {
1599 llvm::consumeError(CurLoc.takeError());
1600 return {};
1602 auto MainFilePath = AST.tuPath();
1603 std::vector<SymbolDetails> Results;
1605 // We also want the targets of using-decls, so we include
1606 // DeclRelation::Underlying.
1607 DeclRelationSet Relations = DeclRelation::TemplatePattern |
1608 DeclRelation::Alias | DeclRelation::Underlying;
1609 for (const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) {
1610 D = getPreferredDecl(D);
1612 SymbolDetails NewSymbol;
1613 std::string QName = printQualifiedName(*D);
1614 auto SplitQName = splitQualifiedName(QName);
1615 NewSymbol.containerName = std::string(SplitQName.first);
1616 NewSymbol.name = std::string(SplitQName.second);
1618 if (NewSymbol.containerName.empty()) {
1619 if (const auto *ParentND =
1620 dyn_cast_or_null<NamedDecl>(D->getDeclContext()))
1621 NewSymbol.containerName = printQualifiedName(*ParentND);
1623 llvm::SmallString<32> USR;
1624 if (!index::generateUSRForDecl(D, USR)) {
1625 NewSymbol.USR = std::string(USR.str());
1626 NewSymbol.ID = SymbolID(NewSymbol.USR);
1628 if (const NamedDecl *Def = getDefinition(D))
1629 NewSymbol.definitionRange = makeLocation(
1630 AST.getASTContext(), nameLocation(*Def, SM), MainFilePath);
1631 NewSymbol.declarationRange =
1632 makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath);
1634 Results.push_back(std::move(NewSymbol));
1637 const auto *IdentifierAtCursor =
1638 syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens());
1639 if (!IdentifierAtCursor)
1640 return Results;
1642 if (auto M = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor())) {
1643 SymbolDetails NewMacro;
1644 NewMacro.name = std::string(M->Name);
1645 llvm::SmallString<32> USR;
1646 if (!index::generateUSRForMacro(NewMacro.name, M->Info->getDefinitionLoc(),
1647 SM, USR)) {
1648 NewMacro.USR = std::string(USR.str());
1649 NewMacro.ID = SymbolID(NewMacro.USR);
1651 Results.push_back(std::move(NewMacro));
1654 return Results;
1657 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) {
1658 OS << S.Name << ": " << S.PreferredDeclaration;
1659 if (S.Definition)
1660 OS << " def=" << *S.Definition;
1661 return OS;
1664 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1665 const ReferencesResult::Reference &R) {
1666 OS << R.Loc;
1667 if (R.Attributes & ReferencesResult::Declaration)
1668 OS << " [decl]";
1669 if (R.Attributes & ReferencesResult::Definition)
1670 OS << " [def]";
1671 if (R.Attributes & ReferencesResult::Override)
1672 OS << " [override]";
1673 return OS;
1676 template <typename HierarchyItem>
1677 static std::optional<HierarchyItem>
1678 declToHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
1679 ASTContext &Ctx = ND.getASTContext();
1680 auto &SM = Ctx.getSourceManager();
1681 SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager());
1682 SourceLocation BeginLoc = SM.getFileLoc(ND.getBeginLoc());
1683 SourceLocation EndLoc = SM.getFileLoc(ND.getEndLoc());
1684 const auto DeclRange =
1685 toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc});
1686 if (!DeclRange)
1687 return std::nullopt;
1688 const auto FE = SM.getFileEntryRefForID(SM.getFileID(NameLoc));
1689 if (!FE)
1690 return std::nullopt;
1691 auto FilePath = getCanonicalPath(*FE, SM.getFileManager());
1692 if (!FilePath)
1693 return std::nullopt; // Not useful without a uri.
1695 Position NameBegin = sourceLocToPosition(SM, NameLoc);
1696 Position NameEnd = sourceLocToPosition(
1697 SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
1699 index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
1700 // FIXME: This is not classifying constructors, destructors and operators
1701 // correctly.
1702 SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
1704 HierarchyItem HI;
1705 HI.name = printName(Ctx, ND);
1706 HI.kind = SK;
1707 HI.range = Range{sourceLocToPosition(SM, DeclRange->getBegin()),
1708 sourceLocToPosition(SM, DeclRange->getEnd())};
1709 HI.selectionRange = Range{NameBegin, NameEnd};
1710 if (!HI.range.contains(HI.selectionRange)) {
1711 // 'selectionRange' must be contained in 'range', so in cases where clang
1712 // reports unrelated ranges we need to reconcile somehow.
1713 HI.range = HI.selectionRange;
1716 HI.uri = URIForFile::canonicalize(*FilePath, TUPath);
1718 return HI;
1721 static std::optional<TypeHierarchyItem>
1722 declToTypeHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
1723 auto Result = declToHierarchyItem<TypeHierarchyItem>(ND, TUPath);
1724 if (Result) {
1725 Result->deprecated = ND.isDeprecated();
1726 // Compute the SymbolID and store it in the 'data' field.
1727 // This allows typeHierarchy/resolve to be used to
1728 // resolve children of items returned in a previous request
1729 // for parents.
1730 Result->data.symbolID = getSymbolID(&ND);
1732 return Result;
1735 static std::optional<CallHierarchyItem>
1736 declToCallHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
1737 auto Result = declToHierarchyItem<CallHierarchyItem>(ND, TUPath);
1738 if (!Result)
1739 return Result;
1740 if (ND.isDeprecated())
1741 Result->tags.push_back(SymbolTag::Deprecated);
1742 if (auto ID = getSymbolID(&ND))
1743 Result->data = ID.str();
1744 return Result;
1747 template <typename HierarchyItem>
1748 static std::optional<HierarchyItem> symbolToHierarchyItem(const Symbol &S,
1749 PathRef TUPath) {
1750 auto Loc = symbolToLocation(S, TUPath);
1751 if (!Loc) {
1752 elog("Failed to convert symbol to hierarchy item: {0}", Loc.takeError());
1753 return std::nullopt;
1755 HierarchyItem HI;
1756 HI.name = std::string(S.Name);
1757 HI.kind = indexSymbolKindToSymbolKind(S.SymInfo.Kind);
1758 HI.selectionRange = Loc->range;
1759 // FIXME: Populate 'range' correctly
1760 // (https://github.com/clangd/clangd/issues/59).
1761 HI.range = HI.selectionRange;
1762 HI.uri = Loc->uri;
1764 return HI;
1767 static std::optional<TypeHierarchyItem>
1768 symbolToTypeHierarchyItem(const Symbol &S, PathRef TUPath) {
1769 auto Result = symbolToHierarchyItem<TypeHierarchyItem>(S, TUPath);
1770 if (Result) {
1771 Result->deprecated = (S.Flags & Symbol::Deprecated);
1772 Result->data.symbolID = S.ID;
1774 return Result;
1777 static std::optional<CallHierarchyItem>
1778 symbolToCallHierarchyItem(const Symbol &S, PathRef TUPath) {
1779 auto Result = symbolToHierarchyItem<CallHierarchyItem>(S, TUPath);
1780 if (!Result)
1781 return Result;
1782 Result->data = S.ID.str();
1783 if (S.Flags & Symbol::Deprecated)
1784 Result->tags.push_back(SymbolTag::Deprecated);
1785 return Result;
1788 static void fillSubTypes(const SymbolID &ID,
1789 std::vector<TypeHierarchyItem> &SubTypes,
1790 const SymbolIndex *Index, int Levels, PathRef TUPath) {
1791 RelationsRequest Req;
1792 Req.Subjects.insert(ID);
1793 Req.Predicate = RelationKind::BaseOf;
1794 Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
1795 if (std::optional<TypeHierarchyItem> ChildSym =
1796 symbolToTypeHierarchyItem(Object, TUPath)) {
1797 if (Levels > 1) {
1798 ChildSym->children.emplace();
1799 fillSubTypes(Object.ID, *ChildSym->children, Index, Levels - 1, TUPath);
1801 SubTypes.emplace_back(std::move(*ChildSym));
1806 using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>;
1808 // Extracts parents from AST and populates the type hierarchy item.
1809 static void fillSuperTypes(const CXXRecordDecl &CXXRD, llvm::StringRef TUPath,
1810 TypeHierarchyItem &Item,
1811 RecursionProtectionSet &RPSet) {
1812 Item.parents.emplace();
1813 Item.data.parents.emplace();
1814 // typeParents() will replace dependent template specializations
1815 // with their class template, so to avoid infinite recursion for
1816 // certain types of hierarchies, keep the templates encountered
1817 // along the parent chain in a set, and stop the recursion if one
1818 // starts to repeat.
1819 auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr;
1820 if (Pattern) {
1821 if (!RPSet.insert(Pattern).second) {
1822 return;
1826 for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) {
1827 if (std::optional<TypeHierarchyItem> ParentSym =
1828 declToTypeHierarchyItem(*ParentDecl, TUPath)) {
1829 fillSuperTypes(*ParentDecl, TUPath, *ParentSym, RPSet);
1830 Item.data.parents->emplace_back(ParentSym->data);
1831 Item.parents->emplace_back(std::move(*ParentSym));
1835 if (Pattern) {
1836 RPSet.erase(Pattern);
1840 std::vector<const CXXRecordDecl *> findRecordTypeAt(ParsedAST &AST,
1841 Position Pos) {
1842 auto RecordFromNode = [&AST](const SelectionTree::Node *N) {
1843 std::vector<const CXXRecordDecl *> Records;
1844 if (!N)
1845 return Records;
1847 // Note: explicitReferenceTargets() will search for both template
1848 // instantiations and template patterns, and prefer the former if available
1849 // (generally, one will be available for non-dependent specializations of a
1850 // class template).
1851 auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying,
1852 AST.getHeuristicResolver());
1853 for (const NamedDecl *D : Decls) {
1855 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1856 // If this is a variable, use the type of the variable.
1857 Records.push_back(VD->getType().getTypePtr()->getAsCXXRecordDecl());
1858 continue;
1861 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
1862 // If this is a method, use the type of the class.
1863 Records.push_back(Method->getParent());
1864 continue;
1867 // We don't handle FieldDecl because it's not clear what behaviour
1868 // the user would expect: the enclosing class type (as with a
1869 // method), or the field's type (as with a variable).
1871 if (auto *RD = dyn_cast<CXXRecordDecl>(D))
1872 Records.push_back(RD);
1874 return Records;
1877 const SourceManager &SM = AST.getSourceManager();
1878 std::vector<const CXXRecordDecl *> Result;
1879 auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos);
1880 if (!Offset) {
1881 llvm::consumeError(Offset.takeError());
1882 return Result;
1884 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), *Offset,
1885 *Offset, [&](SelectionTree ST) {
1886 Result = RecordFromNode(ST.commonAncestor());
1887 return !Result.empty();
1889 return Result;
1892 // Return the type most associated with an AST node.
1893 // This isn't precisely defined: we want "go to type" to do something useful.
1894 static QualType typeForNode(const SelectionTree::Node *N) {
1895 // If we're looking at a namespace qualifier, walk up to what it's qualifying.
1896 // (If we're pointing at a *class* inside a NNS, N will be a TypeLoc).
1897 while (N && N->ASTNode.get<NestedNameSpecifierLoc>())
1898 N = N->Parent;
1899 if (!N)
1900 return QualType();
1902 // If we're pointing at a type => return it.
1903 if (const TypeLoc *TL = N->ASTNode.get<TypeLoc>()) {
1904 if (llvm::isa<DeducedType>(TL->getTypePtr()))
1905 if (auto Deduced = getDeducedType(
1906 N->getDeclContext().getParentASTContext(), TL->getBeginLoc()))
1907 return *Deduced;
1908 // Exception: an alias => underlying type.
1909 if (llvm::isa<TypedefType>(TL->getTypePtr()))
1910 return TL->getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();
1911 return TL->getType();
1914 // Constructor initializers => the type of thing being initialized.
1915 if (const auto *CCI = N->ASTNode.get<CXXCtorInitializer>()) {
1916 if (const FieldDecl *FD = CCI->getAnyMember())
1917 return FD->getType();
1918 if (const Type *Base = CCI->getBaseClass())
1919 return QualType(Base, 0);
1922 // Base specifier => the base type.
1923 if (const auto *CBS = N->ASTNode.get<CXXBaseSpecifier>())
1924 return CBS->getType();
1926 if (const Decl *D = N->ASTNode.get<Decl>()) {
1927 struct Visitor : ConstDeclVisitor<Visitor, QualType> {
1928 QualType VisitValueDecl(const ValueDecl *D) { return D->getType(); }
1929 // Declaration of a type => that type.
1930 QualType VisitTypeDecl(const TypeDecl *D) {
1931 return QualType(D->getTypeForDecl(), 0);
1933 // Exception: alias declaration => the underlying type, not the alias.
1934 QualType VisitTypedefNameDecl(const TypedefNameDecl *D) {
1935 return D->getUnderlyingType();
1937 // Look inside templates.
1938 QualType VisitTemplateDecl(const TemplateDecl *D) {
1939 return Visit(D->getTemplatedDecl());
1941 } V;
1942 return V.Visit(D);
1945 if (const Stmt *S = N->ASTNode.get<Stmt>()) {
1946 struct Visitor : ConstStmtVisitor<Visitor, QualType> {
1947 // Null-safe version of visit simplifies recursive calls below.
1948 QualType type(const Stmt *S) { return S ? Visit(S) : QualType(); }
1950 // In general, expressions => type of expression.
1951 QualType VisitExpr(const Expr *S) {
1952 return S->IgnoreImplicitAsWritten()->getType();
1954 QualType VisitMemberExpr(const MemberExpr *S) {
1955 // The `foo` in `s.foo()` pretends not to have a real type!
1956 if (S->getType()->isSpecificBuiltinType(BuiltinType::BoundMember))
1957 return Expr::findBoundMemberType(S);
1958 return VisitExpr(S);
1960 // Exceptions for void expressions that operate on a type in some way.
1961 QualType VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
1962 return S->getDestroyedType();
1964 QualType VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) {
1965 return S->getDestroyedType();
1967 QualType VisitCXXThrowExpr(const CXXThrowExpr *S) {
1968 return S->getSubExpr()->getType();
1970 QualType VisitCoyieldExpr(const CoyieldExpr *S) {
1971 return type(S->getOperand());
1973 // Treat a designated initializer like a reference to the field.
1974 QualType VisitDesignatedInitExpr(const DesignatedInitExpr *S) {
1975 // In .foo.bar we want to jump to bar's type, so find *last* field.
1976 for (auto &D : llvm::reverse(S->designators()))
1977 if (D.isFieldDesignator())
1978 if (const auto *FD = D.getFieldDecl())
1979 return FD->getType();
1980 return QualType();
1983 // Control flow statements that operate on data: use the data type.
1984 QualType VisitSwitchStmt(const SwitchStmt *S) {
1985 return type(S->getCond());
1987 QualType VisitWhileStmt(const WhileStmt *S) { return type(S->getCond()); }
1988 QualType VisitDoStmt(const DoStmt *S) { return type(S->getCond()); }
1989 QualType VisitIfStmt(const IfStmt *S) { return type(S->getCond()); }
1990 QualType VisitCaseStmt(const CaseStmt *S) { return type(S->getLHS()); }
1991 QualType VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
1992 return S->getLoopVariable()->getType();
1994 QualType VisitReturnStmt(const ReturnStmt *S) {
1995 return type(S->getRetValue());
1997 QualType VisitCoreturnStmt(const CoreturnStmt *S) {
1998 return type(S->getOperand());
2000 QualType VisitCXXCatchStmt(const CXXCatchStmt *S) {
2001 return S->getCaughtType();
2003 QualType VisitObjCAtThrowStmt(const ObjCAtThrowStmt *S) {
2004 return type(S->getThrowExpr());
2006 QualType VisitObjCAtCatchStmt(const ObjCAtCatchStmt *S) {
2007 return S->getCatchParamDecl() ? S->getCatchParamDecl()->getType()
2008 : QualType();
2010 } V;
2011 return V.Visit(S);
2014 return QualType();
2017 // Given a type targeted by the cursor, return one or more types that are more interesting
2018 // to target.
2019 static void unwrapFindType(
2020 QualType T, const HeuristicResolver* H, llvm::SmallVector<QualType>& Out) {
2021 if (T.isNull())
2022 return;
2024 // If there's a specific type alias, point at that rather than unwrapping.
2025 if (const auto* TDT = T->getAs<TypedefType>())
2026 return Out.push_back(QualType(TDT, 0));
2028 // Pointers etc => pointee type.
2029 if (const auto *PT = T->getAs<PointerType>())
2030 return unwrapFindType(PT->getPointeeType(), H, Out);
2031 if (const auto *RT = T->getAs<ReferenceType>())
2032 return unwrapFindType(RT->getPointeeType(), H, Out);
2033 if (const auto *AT = T->getAsArrayTypeUnsafe())
2034 return unwrapFindType(AT->getElementType(), H, Out);
2036 // Function type => return type.
2037 if (auto *FT = T->getAs<FunctionType>())
2038 return unwrapFindType(FT->getReturnType(), H, Out);
2039 if (auto *CRD = T->getAsCXXRecordDecl()) {
2040 if (CRD->isLambda())
2041 return unwrapFindType(CRD->getLambdaCallOperator()->getReturnType(), H,
2042 Out);
2043 // FIXME: more cases we'd prefer the return type of the call operator?
2044 // std::function etc?
2047 // For smart pointer types, add the underlying type
2048 if (H)
2049 if (const auto* PointeeType = H->getPointeeType(T.getNonReferenceType().getTypePtr())) {
2050 unwrapFindType(QualType(PointeeType, 0), H, Out);
2051 return Out.push_back(T);
2054 return Out.push_back(T);
2057 // Convenience overload, to allow calling this without the out-parameter
2058 static llvm::SmallVector<QualType> unwrapFindType(
2059 QualType T, const HeuristicResolver* H) {
2060 llvm::SmallVector<QualType> Result;
2061 unwrapFindType(T, H, Result);
2062 return Result;
2066 std::vector<LocatedSymbol> findType(ParsedAST &AST, Position Pos) {
2067 const SourceManager &SM = AST.getSourceManager();
2068 auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos);
2069 std::vector<LocatedSymbol> Result;
2070 if (!Offset) {
2071 elog("failed to convert position {0} for findTypes: {1}", Pos,
2072 Offset.takeError());
2073 return Result;
2075 // The general scheme is: position -> AST node -> type -> declaration.
2076 auto SymbolsFromNode =
2077 [&AST](const SelectionTree::Node *N) -> std::vector<LocatedSymbol> {
2078 std::vector<LocatedSymbol> LocatedSymbols;
2080 // NOTE: unwrapFindType might return duplicates for something like
2081 // unique_ptr<unique_ptr<T>>. Let's *not* remove them, because it gives you some
2082 // information about the type you may have not known before
2083 // (since unique_ptr<unique_ptr<T>> != unique_ptr<T>).
2084 for (const QualType& Type : unwrapFindType(typeForNode(N), AST.getHeuristicResolver()))
2085 llvm::copy(locateSymbolForType(AST, Type), std::back_inserter(LocatedSymbols));
2087 return LocatedSymbols;
2089 SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), *Offset,
2090 *Offset, [&](SelectionTree ST) {
2091 Result = SymbolsFromNode(ST.commonAncestor());
2092 return !Result.empty();
2094 return Result;
2097 std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD) {
2098 std::vector<const CXXRecordDecl *> Result;
2100 // If this is an invalid instantiation, instantiation of the bases
2101 // may not have succeeded, so fall back to the template pattern.
2102 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
2103 if (CTSD->isInvalidDecl())
2104 CXXRD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
2107 // Can't query bases without a definition.
2108 if (!CXXRD->hasDefinition())
2109 return Result;
2111 for (auto Base : CXXRD->bases()) {
2112 const CXXRecordDecl *ParentDecl = nullptr;
2114 const Type *Type = Base.getType().getTypePtr();
2115 if (const RecordType *RT = Type->getAs<RecordType>()) {
2116 ParentDecl = RT->getAsCXXRecordDecl();
2119 if (!ParentDecl) {
2120 // Handle a dependent base such as "Base<T>" by using the primary
2121 // template.
2122 if (const TemplateSpecializationType *TS =
2123 Type->getAs<TemplateSpecializationType>()) {
2124 TemplateName TN = TS->getTemplateName();
2125 if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
2126 ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
2131 if (ParentDecl)
2132 Result.push_back(ParentDecl);
2135 return Result;
2138 std::vector<TypeHierarchyItem>
2139 getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
2140 TypeHierarchyDirection Direction, const SymbolIndex *Index,
2141 PathRef TUPath) {
2142 std::vector<TypeHierarchyItem> Results;
2143 for (const auto *CXXRD : findRecordTypeAt(AST, Pos)) {
2145 bool WantChildren = Direction == TypeHierarchyDirection::Children ||
2146 Direction == TypeHierarchyDirection::Both;
2148 // If we're looking for children, we're doing the lookup in the index.
2149 // The index does not store relationships between implicit
2150 // specializations, so if we have one, use the template pattern instead.
2151 // Note that this needs to be done before the declToTypeHierarchyItem(),
2152 // otherwise the type hierarchy item would misleadingly contain the
2153 // specialization parameters, while the children would involve classes
2154 // that derive from other specializations of the template.
2155 if (WantChildren) {
2156 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD))
2157 CXXRD = CTSD->getTemplateInstantiationPattern();
2160 std::optional<TypeHierarchyItem> Result =
2161 declToTypeHierarchyItem(*CXXRD, AST.tuPath());
2162 if (!Result)
2163 continue;
2165 RecursionProtectionSet RPSet;
2166 fillSuperTypes(*CXXRD, AST.tuPath(), *Result, RPSet);
2168 if (WantChildren && ResolveLevels > 0) {
2169 Result->children.emplace();
2171 if (Index) {
2172 if (auto ID = getSymbolID(CXXRD))
2173 fillSubTypes(ID, *Result->children, Index, ResolveLevels, TUPath);
2176 Results.emplace_back(std::move(*Result));
2179 return Results;
2182 std::optional<std::vector<TypeHierarchyItem>>
2183 superTypes(const TypeHierarchyItem &Item, const SymbolIndex *Index) {
2184 std::vector<TypeHierarchyItem> Results;
2185 if (!Item.data.parents)
2186 return std::nullopt;
2187 if (Item.data.parents->empty())
2188 return Results;
2189 LookupRequest Req;
2190 llvm::DenseMap<SymbolID, const TypeHierarchyItem::ResolveParams *> IDToData;
2191 for (const auto &Parent : *Item.data.parents) {
2192 Req.IDs.insert(Parent.symbolID);
2193 IDToData[Parent.symbolID] = &Parent;
2195 Index->lookup(Req, [&Item, &Results, &IDToData](const Symbol &S) {
2196 if (auto THI = symbolToTypeHierarchyItem(S, Item.uri.file())) {
2197 THI->data = *IDToData.lookup(S.ID);
2198 Results.emplace_back(std::move(*THI));
2201 return Results;
2204 std::vector<TypeHierarchyItem> subTypes(const TypeHierarchyItem &Item,
2205 const SymbolIndex *Index) {
2206 std::vector<TypeHierarchyItem> Results;
2207 fillSubTypes(Item.data.symbolID, Results, Index, 1, Item.uri.file());
2208 for (auto &ChildSym : Results)
2209 ChildSym.data.parents = {Item.data};
2210 return Results;
2213 void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels,
2214 TypeHierarchyDirection Direction,
2215 const SymbolIndex *Index) {
2216 // We only support typeHierarchy/resolve for children, because for parents
2217 // we ignore ResolveLevels and return all levels of parents eagerly.
2218 if (!Index || Direction == TypeHierarchyDirection::Parents ||
2219 ResolveLevels == 0)
2220 return;
2222 Item.children.emplace();
2223 fillSubTypes(Item.data.symbolID, *Item.children, Index, ResolveLevels,
2224 Item.uri.file());
2227 std::vector<CallHierarchyItem>
2228 prepareCallHierarchy(ParsedAST &AST, Position Pos, PathRef TUPath) {
2229 std::vector<CallHierarchyItem> Result;
2230 const auto &SM = AST.getSourceManager();
2231 auto Loc = sourceLocationInMainFile(SM, Pos);
2232 if (!Loc) {
2233 elog("prepareCallHierarchy failed to convert position to source location: "
2234 "{0}",
2235 Loc.takeError());
2236 return Result;
2238 for (const NamedDecl *Decl : getDeclAtPosition(AST, *Loc, {})) {
2239 if (!(isa<DeclContext>(Decl) &&
2240 cast<DeclContext>(Decl)->isFunctionOrMethod()) &&
2241 Decl->getKind() != Decl::Kind::FunctionTemplate)
2242 continue;
2243 if (auto CHI = declToCallHierarchyItem(*Decl, AST.tuPath()))
2244 Result.emplace_back(std::move(*CHI));
2246 return Result;
2249 std::vector<CallHierarchyIncomingCall>
2250 incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
2251 std::vector<CallHierarchyIncomingCall> Results;
2252 if (!Index || Item.data.empty())
2253 return Results;
2254 auto ID = SymbolID::fromStr(Item.data);
2255 if (!ID) {
2256 elog("incomingCalls failed to find symbol: {0}", ID.takeError());
2257 return Results;
2259 // In this function, we find incoming calls based on the index only.
2260 // In principle, the AST could have more up-to-date information about
2261 // occurrences within the current file. However, going from a SymbolID
2262 // to an AST node isn't cheap, particularly when the declaration isn't
2263 // in the main file.
2264 // FIXME: Consider also using AST information when feasible.
2265 RefsRequest Request;
2266 Request.IDs.insert(*ID);
2267 Request.WantContainer = true;
2268 // We could restrict more specifically to calls by introducing a new RefKind,
2269 // but non-call references (such as address-of-function) can still be
2270 // interesting as they can indicate indirect calls.
2271 Request.Filter = RefKind::Reference;
2272 // Initially store the ranges in a map keyed by SymbolID of the caller.
2273 // This allows us to group different calls with the same caller
2274 // into the same CallHierarchyIncomingCall.
2275 llvm::DenseMap<SymbolID, std::vector<Range>> CallsIn;
2276 // We can populate the ranges based on a refs request only. As we do so, we
2277 // also accumulate the container IDs into a lookup request.
2278 LookupRequest ContainerLookup;
2279 Index->refs(Request, [&](const Ref &R) {
2280 auto Loc = indexToLSPLocation(R.Location, Item.uri.file());
2281 if (!Loc) {
2282 elog("incomingCalls failed to convert location: {0}", Loc.takeError());
2283 return;
2285 auto It = CallsIn.try_emplace(R.Container, std::vector<Range>{}).first;
2286 It->second.push_back(Loc->range);
2288 ContainerLookup.IDs.insert(R.Container);
2290 // Perform the lookup request and combine its results with CallsIn to
2291 // get complete CallHierarchyIncomingCall objects.
2292 Index->lookup(ContainerLookup, [&](const Symbol &Caller) {
2293 auto It = CallsIn.find(Caller.ID);
2294 assert(It != CallsIn.end());
2295 if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file()))
2296 Results.push_back(
2297 CallHierarchyIncomingCall{std::move(*CHI), std::move(It->second)});
2299 // Sort results by name of container.
2300 llvm::sort(Results, [](const CallHierarchyIncomingCall &A,
2301 const CallHierarchyIncomingCall &B) {
2302 return A.from.name < B.from.name;
2304 return Results;
2307 llvm::DenseSet<const Decl *> getNonLocalDeclRefs(ParsedAST &AST,
2308 const FunctionDecl *FD) {
2309 if (!FD->hasBody())
2310 return {};
2311 llvm::DenseSet<const Decl *> DeclRefs;
2312 findExplicitReferences(
2314 [&](ReferenceLoc Ref) {
2315 for (const Decl *D : Ref.Targets) {
2316 if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() &&
2317 !Ref.IsDecl)
2318 DeclRefs.insert(D);
2321 AST.getHeuristicResolver());
2322 return DeclRefs;
2325 } // namespace clangd
2326 } // namespace clang