1 //===--- XRefs.cpp -----------------------------------------------*- C++-*-===//
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
7 //===----------------------------------------------------------------------===//
10 #include "FindSymbols.h"
11 #include "FindTarget.h"
13 #include "HeuristicResolver.h"
14 #include "IncludeCleaner.h"
15 #include "ParsedAST.h"
18 #include "Selection.h"
19 #include "SourceCode.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"
76 // Returns the single definition of the entity declared by D, if visible.
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
) {
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())
97 // Look for the method definition inside the implementation decl.
98 auto *DeclCtx
= cast
<Decl
>(MD
->getDeclContext());
99 if (DeclCtx
->isInvalidDecl())
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
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
125 std::optional
<Location
> toLSPLocation(const SymbolLocation
&Loc
,
126 llvm::StringRef TUPath
) {
129 auto Uri
= URI::parse(Loc
.FileURI
);
131 elog("Could not parse URI {0}: {1}", Loc
.FileURI
, Uri
.takeError());
134 auto U
= URIForFile::fromURI(*Uri
, TUPath
);
136 elog("Could not resolve URI {0}: {1}", Loc
.FileURI
, U
.takeError());
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();
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
);
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()) {
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
)
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
);
202 std::vector
<const NamedDecl
*>
203 getDeclAtPosition(ParsedAST
&AST
, SourceLocation Pos
, DeclRelationSet Relations
,
204 ASTNodeKind
*NodeKind
= nullptr) {
205 std::vector
<const NamedDecl
*> Result
;
207 getDeclAtPositionWithRelations(AST
, Pos
, Relations
, NodeKind
))
208 Result
.push_back(Entry
.first
);
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
));
220 auto FilePath
= getCanonicalPath(*F
, SM
.getFileManager());
222 log("failed to get path!");
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
)));
235 // Treat #included files as symbols, to enable go-to-definition on them.
236 std::optional
<LocatedSymbol
> locateFileReferent(const Position
&Pos
,
238 llvm::StringRef MainFilePath
) {
239 for (auto &Inc
: AST
.getIncludeStructure().MainFileIncludes
) {
240 if (!Inc
.Resolved
.empty() && Inc
.HashLine
== Pos
.line
) {
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.
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())) {
260 makeLocation(AST
.getASTContext(), M
->NameLoc
, MainFilePath
)) {
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());
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
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())
296 if (const auto *PD
= dyn_cast
<ObjCProtocolDecl
>(D
))
297 if (const auto *DefinitionID
= PD
->getDefinition())
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
)
309 static constexpr trace::Metric
FindImplementorsMetric(
310 "find_implementors", trace::Metric::Counter
, "case");
312 case RelationKind::BaseOf
:
313 FindImplementorsMetric
.record(1, "find-base");
315 case RelationKind::OverriddenBy
:
316 FindImplementorsMetric
.record(1, "find-override");
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
) {
326 indexToLSPLocation(Object
.CanonicalDeclaration
, MainFilePath
);
328 elog("Find overrides: {0}", DeclLoc
.takeError());
331 Results
.emplace_back();
332 Results
.back().Name
= Object
.Name
.str();
333 Results
.back().PreferredDeclaration
= *DeclLoc
;
334 auto DefLoc
= indexToLSPLocation(Object
.Definition
, MainFilePath
);
336 elog("Failed to convert location: {0}", DefLoc
.takeError());
339 Results
.back().Definition
= *DefLoc
;
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
);
363 makeLocation(AST
.getASTContext(), nameLocation(*D
, SM
), MainFilePath
);
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
;
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
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())
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()
418 D
->getBeginLoc(), D
->getEndLoc()))
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());
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");
447 LocateASTReferentMetric
.record(1, "regular");
448 // Otherwise the target declaration is the right one.
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
);
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
),
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
),
481 R
.PreferredDeclaration
= *Loc
;
486 auto Overrides
= findImplementors(VirtualMethods
, RelationKind::OverriddenBy
,
487 Index
, MainFilePath
);
488 Result
.insert(Result
.end(), Overrides
.begin(), Overrides
.end());
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());
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
);
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
);
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())
539 return Buf
.substr(0, D
.second
);
542 bool isDependentName(ASTNodeKind NodeKind
) {
543 return NodeKind
.isSame(ASTNodeKind::getFromNodeKind
<OverloadExpr
>()) ||
545 ASTNodeKind::getFromNodeKind
<CXXDependentScopeMemberExpr
>()) ||
547 ASTNodeKind::getFromNodeKind
<DependentScopeDeclRefExpr
>());
552 std::vector
<LocatedSymbol
> locateSymbolTextually(const SpelledWord
&Word
,
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
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
)
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()))
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.
577 visibleNamespaces(sourcePrefix(Word
.Location
, SM
), AST
.getLangOpts());
578 // FIXME: For extra strictness, consider AnyScope=false.
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.
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
)
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
)
601 indexToLSPLocation(Sym
.CanonicalDeclaration
, MainFilePath
);
603 log("locateSymbolNamedTextuallyAt: {0}", MaybeDeclLoc
.takeError());
606 LocatedSymbol Located
;
607 Located
.PreferredDeclaration
= *MaybeDeclLoc
;
608 Located
.Name
= (Sym
.Name
+ Sym
.TemplateSpecializationArgs
).str();
610 if (Sym
.Definition
) {
611 auto MaybeDefLoc
= indexToLSPLocation(Sym
.Definition
, MainFilePath
);
613 log("locateSymbolNamedTextuallyAt: {0}", MaybeDefLoc
.takeError());
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?
628 SymbolQualitySignals Quality
;
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
)});
643 vlog("Heuristic index lookup for {0} returned too many candidates, ignored",
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
));
656 vlog("No heuristic index definition for {0}", Word
.Text
);
658 log("Found definition heuristically in index for {0}", Word
.Text
);
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
)
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()))
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
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
))
712 // No point guessing the same location we started with.
713 if (Tok
.location() == Word
.Location
)
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
)))
723 // We already verified this token is an improvement.
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()))
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
)))
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
));
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
);
763 elog("locateSymbolAt failed to convert position to source location: {0}",
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
777 return {*std::move(Macro
)};
779 TouchedIdentifier
= &Tok
;
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
786 if (auto Deduced
= getDeducedType(AST
.getASTContext(), Tok
.location())) {
787 auto LocSym
= locateSymbolForType(AST
, *Deduced
);
794 ASTNodeKind NodeKind
;
795 auto ASTResults
= locateASTReferent(*CurLoc
, TouchedIdentifier
, AST
,
796 MainFilePath
, Index
, NodeKind
);
797 if (!ASTResults
.empty())
800 // If the cursor can't be resolved directly, try fallback strategies.
802 SpelledWord::touching(*CurLoc
, AST
.getTokens(), AST
.getLangOpts());
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}",
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
));
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
;
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())
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.
848 syntax::FileRange(SM
, FileTok
->location(), Inc
.Written
.length())
852 DocumentLink({halfOpenToRange(SM
, FileRange
),
853 URIForFile::canonicalize(Inc
.Resolved
, AST
.tuPath())}));
861 /// Collects references to symbols within the main file.
862 class ReferenceFinder
: public index::IndexDataConsumer
{
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
,
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
);
897 return std::move(References
);
901 handleDeclOccurrence(const Decl
*D
, index::SymbolRoleSet Roles
,
902 llvm::ArrayRef
<index::SymbolRelation
> Relations
,
904 index::IndexDataConsumer::ASTNodeInfo ASTNode
) override
{
905 if (!TargetDecls
.contains(D
->getCanonicalDecl()))
907 const SourceManager
&SM
= AST
.getSourceManager();
908 if (!isInsideMainFile(Loc
, SM
))
910 const auto &TB
= AST
.getTokens();
912 llvm::SmallVector
<SourceLocation
, 1> Locs
;
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.
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(
937 SymbolCollector::getRefContainer(ASTNode
.Parent
, CollectorOpts
)});
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
,
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();
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();
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.
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
))
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
) {
1026 if (SM
.isBeforeInTranslationUnit(Loc
, Bounds
.getBegin()) ||
1027 SM
.isBeforeInTranslationUnit(Bounds
.getEnd(), Loc
))
1029 Result
.push_back(Loc
);
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());
1055 bool VisitBreakStmt(BreakStmt
*B
) {
1056 found(Break
, B
->getBreakLoc());
1059 bool VisitContinueStmt(ContinueStmt
*C
) {
1060 found(Continue
, C
->getContinueLoc());
1063 bool VisitSwitchCase(SwitchCase
*C
) {
1064 found(Case
, C
->getKeywordLoc());
1067 bool VisitCXXThrowExpr(CXXThrowExpr
*T
) {
1068 found(Throw
, T
->getThrowLoc());
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());
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
)
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
>()) {
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());
1150 const Stmt
*Root
= nullptr; // Loop or function body to traverse.
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
) {
1166 // Highlight the loop keyword itself.
1167 // FIXME: for do-while, this only covers the `do`..
1168 Result
.push_back(P
->ASTNode
.getSourceRange().getBegin());
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
);
1184 // If we didn't start at some interesting node, we're done.
1185 if (Cursor
== Cur::None
)
1189 if (!Bounds
.isValid())
1190 Bounds
= Root
->getSourceRange();
1191 FindControlFlow(Bounds
, Result
, SM
).TraverseStmt(const_cast<Stmt
*>(Root
));
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
;
1205 DH
.kind
= DocumentHighlightKind::Text
;
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(
1216 CharSourceRange::getCharRange(Tok
->location(), Tok
->endLocation()));
1219 return std::nullopt
;
1224 std::vector
<DocumentHighlight
> findDocumentHighlights(ParsedAST
&AST
,
1226 const SourceManager
&SM
= AST
.getSourceManager();
1227 // FIXME: show references to macro within file?
1228 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1230 llvm::consumeError(CurLoc
.takeError());
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
;
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
));
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
));
1259 AST
.getSourceManager().getDecomposedSpellingLoc(*CurLoc
).second
;
1260 SelectionTree::createEach(AST
.getASTContext(), AST
.getTokens(), Offset
,
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
1272 const SourceManager
&SM
= AST
.getSourceManager();
1273 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1275 elog("Failed to convert position to source location: {0}",
1276 CurLoc
.takeError());
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());
1298 // Recursively finds all the overridden methods of `CMD` in complete type
1300 void getOverriddenMethods(const CXXMethodDecl
*CMD
,
1301 llvm::DenseSet
<SymbolID
> &OverriddenMethods
) {
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
);
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
)
1344 firstMatchedProvider(ConvertedMainFileIncludes
, Providers
);
1345 if (!Provider
|| ReferencedInclude
.match(*Provider
).empty())
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
;
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
);
1386 llvm::consumeError(CurLoc
.takeError());
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());
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
);
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
);
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())
1440 IDsToQuery
.insert(ID
);
1443 RelationsRequest OverriddenBy
;
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
;
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;
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
};
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
));
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
)
1538 Req
.IDs
= std::move(IDs
);
1540 if (Limit
< Results
.References
.size()) {
1541 // We've already filled our quota, still check the index to correctly
1542 // return the `HasMore` info.
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.
1555 (!AllowMainFileSymbols
&& LSPLoc
->uri
.file() == MainFilePath
))
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
;
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
1590 QueryIndex(std::move(OverriddenMethods
), /*AllowAttributes=*/false,
1591 /*AllowMainFileSymbols=*/true);
1595 std::vector
<SymbolDetails
> getSymbolInfo(ParsedAST
&AST
, Position Pos
) {
1596 const SourceManager
&SM
= AST
.getSourceManager();
1597 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1599 llvm::consumeError(CurLoc
.takeError());
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
)
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(),
1648 NewMacro
.USR
= std::string(USR
.str());
1649 NewMacro
.ID
= SymbolID(NewMacro
.USR
);
1651 Results
.push_back(std::move(NewMacro
));
1657 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const LocatedSymbol
&S
) {
1658 OS
<< S
.Name
<< ": " << S
.PreferredDeclaration
;
1660 OS
<< " def=" << *S
.Definition
;
1664 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
,
1665 const ReferencesResult::Reference
&R
) {
1667 if (R
.Attributes
& ReferencesResult::Declaration
)
1669 if (R
.Attributes
& ReferencesResult::Definition
)
1671 if (R
.Attributes
& ReferencesResult::Override
)
1672 OS
<< " [override]";
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
});
1687 return std::nullopt
;
1688 const auto FE
= SM
.getFileEntryRefForID(SM
.getFileID(NameLoc
));
1690 return std::nullopt
;
1691 auto FilePath
= getCanonicalPath(*FE
, SM
.getFileManager());
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
1702 SymbolKind SK
= indexSymbolKindToSymbolKind(SymInfo
.Kind
);
1705 HI
.name
= printName(Ctx
, ND
);
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
);
1721 static std::optional
<TypeHierarchyItem
>
1722 declToTypeHierarchyItem(const NamedDecl
&ND
, llvm::StringRef TUPath
) {
1723 auto Result
= declToHierarchyItem
<TypeHierarchyItem
>(ND
, TUPath
);
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
1730 Result
->data
.symbolID
= getSymbolID(&ND
);
1735 static std::optional
<CallHierarchyItem
>
1736 declToCallHierarchyItem(const NamedDecl
&ND
, llvm::StringRef TUPath
) {
1737 auto Result
= declToHierarchyItem
<CallHierarchyItem
>(ND
, TUPath
);
1740 if (ND
.isDeprecated())
1741 Result
->tags
.push_back(SymbolTag::Deprecated
);
1742 if (auto ID
= getSymbolID(&ND
))
1743 Result
->data
= ID
.str();
1747 template <typename HierarchyItem
>
1748 static std::optional
<HierarchyItem
> symbolToHierarchyItem(const Symbol
&S
,
1750 auto Loc
= symbolToLocation(S
, TUPath
);
1752 elog("Failed to convert symbol to hierarchy item: {0}", Loc
.takeError());
1753 return std::nullopt
;
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
;
1767 static std::optional
<TypeHierarchyItem
>
1768 symbolToTypeHierarchyItem(const Symbol
&S
, PathRef TUPath
) {
1769 auto Result
= symbolToHierarchyItem
<TypeHierarchyItem
>(S
, TUPath
);
1771 Result
->deprecated
= (S
.Flags
& Symbol::Deprecated
);
1772 Result
->data
.symbolID
= S
.ID
;
1777 static std::optional
<CallHierarchyItem
>
1778 symbolToCallHierarchyItem(const Symbol
&S
, PathRef TUPath
) {
1779 auto Result
= symbolToHierarchyItem
<CallHierarchyItem
>(S
, TUPath
);
1782 Result
->data
= S
.ID
.str();
1783 if (S
.Flags
& Symbol::Deprecated
)
1784 Result
->tags
.push_back(SymbolTag::Deprecated
);
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
)) {
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;
1821 if (!RPSet
.insert(Pattern
).second
) {
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
));
1836 RPSet
.erase(Pattern
);
1840 std::vector
<const CXXRecordDecl
*> findRecordTypeAt(ParsedAST
&AST
,
1842 auto RecordFromNode
= [&AST
](const SelectionTree::Node
*N
) {
1843 std::vector
<const CXXRecordDecl
*> 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
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());
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());
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
);
1877 const SourceManager
&SM
= AST
.getSourceManager();
1878 std::vector
<const CXXRecordDecl
*> Result
;
1879 auto Offset
= positionToOffset(SM
.getBufferData(SM
.getMainFileID()), Pos
);
1881 llvm::consumeError(Offset
.takeError());
1884 SelectionTree::createEach(AST
.getASTContext(), AST
.getTokens(), *Offset
,
1885 *Offset
, [&](SelectionTree ST
) {
1886 Result
= RecordFromNode(ST
.commonAncestor());
1887 return !Result
.empty();
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
>())
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()))
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());
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();
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()
2017 // Given a type targeted by the cursor, return one or more types that are more interesting
2019 static void unwrapFindType(
2020 QualType T
, const HeuristicResolver
* H
, llvm::SmallVector
<QualType
>& Out
) {
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
,
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
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
);
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
;
2071 elog("failed to convert position {0} for findTypes: {1}", Pos
,
2072 Offset
.takeError());
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();
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())
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();
2120 // Handle a dependent base such as "Base<T>" by using the primary
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());
2132 Result
.push_back(ParentDecl
);
2138 std::vector
<TypeHierarchyItem
>
2139 getTypeHierarchy(ParsedAST
&AST
, Position Pos
, int ResolveLevels
,
2140 TypeHierarchyDirection Direction
, const SymbolIndex
*Index
,
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.
2156 if (auto *CTSD
= dyn_cast
<ClassTemplateSpecializationDecl
>(CXXRD
))
2157 CXXRD
= CTSD
->getTemplateInstantiationPattern();
2160 std::optional
<TypeHierarchyItem
> Result
=
2161 declToTypeHierarchyItem(*CXXRD
, AST
.tuPath());
2165 RecursionProtectionSet RPSet
;
2166 fillSuperTypes(*CXXRD
, AST
.tuPath(), *Result
, RPSet
);
2168 if (WantChildren
&& ResolveLevels
> 0) {
2169 Result
->children
.emplace();
2172 if (auto ID
= getSymbolID(CXXRD
))
2173 fillSubTypes(ID
, *Result
->children
, Index
, ResolveLevels
, TUPath
);
2176 Results
.emplace_back(std::move(*Result
));
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())
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
));
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
};
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
||
2222 Item
.children
.emplace();
2223 fillSubTypes(Item
.data
.symbolID
, *Item
.children
, Index
, ResolveLevels
,
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
);
2233 elog("prepareCallHierarchy failed to convert position to source location: "
2238 for (const NamedDecl
*Decl
: getDeclAtPosition(AST
, *Loc
, {})) {
2239 if (!(isa
<DeclContext
>(Decl
) &&
2240 cast
<DeclContext
>(Decl
)->isFunctionOrMethod()) &&
2241 Decl
->getKind() != Decl::Kind::FunctionTemplate
)
2243 if (auto CHI
= declToCallHierarchyItem(*Decl
, AST
.tuPath()))
2244 Result
.emplace_back(std::move(*CHI
));
2249 std::vector
<CallHierarchyIncomingCall
>
2250 incomingCalls(const CallHierarchyItem
&Item
, const SymbolIndex
*Index
) {
2251 std::vector
<CallHierarchyIncomingCall
> Results
;
2252 if (!Index
|| Item
.data
.empty())
2254 auto ID
= SymbolID::fromStr(Item
.data
);
2256 elog("incomingCalls failed to find symbol: {0}", ID
.takeError());
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());
2282 elog("incomingCalls failed to convert location: {0}", Loc
.takeError());
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()))
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
;
2307 llvm::DenseSet
<const Decl
*> getNonLocalDeclRefs(ParsedAST
&AST
,
2308 const FunctionDecl
*FD
) {
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() &&
2321 AST
.getHeuristicResolver());
2325 } // namespace clangd
2326 } // namespace clang