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"
12 #include "HeuristicResolver.h"
13 #include "ParsedAST.h"
16 #include "Selection.h"
17 #include "SourceCode.h"
19 #include "index/Index.h"
20 #include "index/Merge.h"
21 #include "index/Relation.h"
22 #include "index/SymbolID.h"
23 #include "index/SymbolLocation.h"
24 #include "support/Logger.h"
25 #include "clang/AST/ASTContext.h"
26 #include "clang/AST/ASTTypeTraits.h"
27 #include "clang/AST/Attr.h"
28 #include "clang/AST/Attrs.inc"
29 #include "clang/AST/Decl.h"
30 #include "clang/AST/DeclCXX.h"
31 #include "clang/AST/DeclObjC.h"
32 #include "clang/AST/DeclTemplate.h"
33 #include "clang/AST/DeclVisitor.h"
34 #include "clang/AST/ExprCXX.h"
35 #include "clang/AST/RecursiveASTVisitor.h"
36 #include "clang/AST/Stmt.h"
37 #include "clang/AST/StmtCXX.h"
38 #include "clang/AST/StmtVisitor.h"
39 #include "clang/AST/Type.h"
40 #include "clang/Basic/LLVM.h"
41 #include "clang/Basic/LangOptions.h"
42 #include "clang/Basic/SourceLocation.h"
43 #include "clang/Basic/SourceManager.h"
44 #include "clang/Basic/TokenKinds.h"
45 #include "clang/Index/IndexDataConsumer.h"
46 #include "clang/Index/IndexSymbol.h"
47 #include "clang/Index/IndexingAction.h"
48 #include "clang/Index/IndexingOptions.h"
49 #include "clang/Index/USRGeneration.h"
50 #include "clang/Tooling/Syntax/Tokens.h"
51 #include "llvm/ADT/ArrayRef.h"
52 #include "llvm/ADT/DenseMap.h"
53 #include "llvm/ADT/None.h"
54 #include "llvm/ADT/Optional.h"
55 #include "llvm/ADT/STLExtras.h"
56 #include "llvm/ADT/ScopeExit.h"
57 #include "llvm/ADT/SmallSet.h"
58 #include "llvm/ADT/SmallVector.h"
59 #include "llvm/ADT/StringRef.h"
60 #include "llvm/Support/Casting.h"
61 #include "llvm/Support/Error.h"
62 #include "llvm/Support/Path.h"
63 #include "llvm/Support/raw_ostream.h"
70 // Returns the single definition of the entity declared by D, if visible.
72 // - for non-redeclarable kinds (e.g. local vars), return D
73 // - for kinds that allow multiple definitions (e.g. namespaces), return nullptr
74 // Kinds of nodes that always return nullptr here will not have definitions
75 // reported by locateSymbolAt().
76 const NamedDecl
*getDefinition(const NamedDecl
*D
) {
78 // Decl has one definition that we can find.
79 if (const auto *TD
= dyn_cast
<TagDecl
>(D
))
80 return TD
->getDefinition();
81 if (const auto *VD
= dyn_cast
<VarDecl
>(D
))
82 return VD
->getDefinition();
83 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
))
84 return FD
->getDefinition();
85 if (const auto *CTD
= dyn_cast
<ClassTemplateDecl
>(D
))
86 if (const auto *RD
= CTD
->getTemplatedDecl())
87 return RD
->getDefinition();
88 if (const auto *MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
89 if (MD
->isThisDeclarationADefinition())
91 // Look for the method definition inside the implementation decl.
92 auto *DeclCtx
= cast
<Decl
>(MD
->getDeclContext());
93 if (DeclCtx
->isInvalidDecl())
96 if (const auto *CD
= dyn_cast
<ObjCContainerDecl
>(DeclCtx
))
97 if (const auto *Impl
= getCorrespondingObjCImpl(CD
))
98 return Impl
->getMethod(MD
->getSelector(), MD
->isInstanceMethod());
100 if (const auto *CD
= dyn_cast
<ObjCContainerDecl
>(D
))
101 return getCorrespondingObjCImpl(CD
);
102 // Only a single declaration is allowed.
103 if (isa
<ValueDecl
>(D
) || isa
<TemplateTypeParmDecl
>(D
) ||
104 isa
<TemplateTemplateParmDecl
>(D
)) // except cases above
106 // Multiple definitions are allowed.
107 return nullptr; // except cases above
110 void logIfOverflow(const SymbolLocation
&Loc
) {
111 if (Loc
.Start
.hasOverflow() || Loc
.End
.hasOverflow())
112 log("Possible overflow in symbol location: {0}", Loc
);
115 // Convert a SymbolLocation to LSP's Location.
116 // TUPath is used to resolve the path of URI.
117 // FIXME: figure out a good home for it, and share the implementation with
119 llvm::Optional
<Location
> toLSPLocation(const SymbolLocation
&Loc
,
120 llvm::StringRef TUPath
) {
123 auto Uri
= URI::parse(Loc
.FileURI
);
125 elog("Could not parse URI {0}: {1}", Loc
.FileURI
, Uri
.takeError());
128 auto U
= URIForFile::fromURI(*Uri
, TUPath
);
130 elog("Could not resolve URI {0}: {1}", Loc
.FileURI
, U
.takeError());
135 LSPLoc
.uri
= std::move(*U
);
136 LSPLoc
.range
.start
.line
= Loc
.Start
.line();
137 LSPLoc
.range
.start
.character
= Loc
.Start
.column();
138 LSPLoc
.range
.end
.line
= Loc
.End
.line();
139 LSPLoc
.range
.end
.character
= Loc
.End
.column();
144 SymbolLocation
toIndexLocation(const Location
&Loc
, std::string
&URIStorage
) {
145 SymbolLocation SymLoc
;
146 URIStorage
= Loc
.uri
.uri();
147 SymLoc
.FileURI
= URIStorage
.c_str();
148 SymLoc
.Start
.setLine(Loc
.range
.start
.line
);
149 SymLoc
.Start
.setColumn(Loc
.range
.start
.character
);
150 SymLoc
.End
.setLine(Loc
.range
.end
.line
);
151 SymLoc
.End
.setColumn(Loc
.range
.end
.character
);
155 // Returns the preferred location between an AST location and an index location.
156 SymbolLocation
getPreferredLocation(const Location
&ASTLoc
,
157 const SymbolLocation
&IdxLoc
,
158 std::string
&Scratch
) {
159 // Also use a mock symbol for the index location so that other fields (e.g.
160 // definition) are not factored into the preference.
161 Symbol ASTSym
, IdxSym
;
162 ASTSym
.ID
= IdxSym
.ID
= SymbolID("mock_symbol_id");
163 ASTSym
.CanonicalDeclaration
= toIndexLocation(ASTLoc
, Scratch
);
164 IdxSym
.CanonicalDeclaration
= IdxLoc
;
165 auto Merged
= mergeSymbol(ASTSym
, IdxSym
);
166 return Merged
.CanonicalDeclaration
;
169 std::vector
<std::pair
<const NamedDecl
*, DeclRelationSet
>>
170 getDeclAtPositionWithRelations(ParsedAST
&AST
, SourceLocation Pos
,
171 DeclRelationSet Relations
,
172 ASTNodeKind
*NodeKind
= nullptr) {
173 unsigned Offset
= AST
.getSourceManager().getDecomposedSpellingLoc(Pos
).second
;
174 std::vector
<std::pair
<const NamedDecl
*, DeclRelationSet
>> Result
;
175 auto ResultFromTree
= [&](SelectionTree ST
) {
176 if (const SelectionTree::Node
*N
= ST
.commonAncestor()) {
178 *NodeKind
= N
->ASTNode
.getNodeKind();
179 // Attributes don't target decls, look at the
180 // thing it's attached to.
181 // We still report the original NodeKind!
182 // This makes the `override` hack work.
183 if (N
->ASTNode
.get
<Attr
>() && N
->Parent
)
185 llvm::copy_if(allTargetDecls(N
->ASTNode
, AST
.getHeuristicResolver()),
186 std::back_inserter(Result
),
187 [&](auto &Entry
) { return !(Entry
.second
& ~Relations
); });
189 return !Result
.empty();
191 SelectionTree::createEach(AST
.getASTContext(), AST
.getTokens(), Offset
,
192 Offset
, ResultFromTree
);
196 std::vector
<const NamedDecl
*>
197 getDeclAtPosition(ParsedAST
&AST
, SourceLocation Pos
, DeclRelationSet Relations
,
198 ASTNodeKind
*NodeKind
= nullptr) {
199 std::vector
<const NamedDecl
*> Result
;
201 getDeclAtPositionWithRelations(AST
, Pos
, Relations
, NodeKind
))
202 Result
.push_back(Entry
.first
);
206 // Expects Loc to be a SpellingLocation, will bail out otherwise as it can't
207 // figure out a filename.
208 llvm::Optional
<Location
> makeLocation(const ASTContext
&AST
, SourceLocation Loc
,
209 llvm::StringRef TUPath
) {
210 const auto &SM
= AST
.getSourceManager();
211 const FileEntry
*F
= SM
.getFileEntryForID(SM
.getFileID(Loc
));
214 auto FilePath
= getCanonicalPath(F
, SM
);
216 log("failed to get path!");
220 L
.uri
= URIForFile::canonicalize(*FilePath
, TUPath
);
221 // We call MeasureTokenLength here as TokenBuffer doesn't store spelled tokens
222 // outside the main file.
223 auto TokLen
= Lexer::MeasureTokenLength(Loc
, SM
, AST
.getLangOpts());
224 L
.range
= halfOpenToRange(
225 SM
, CharSourceRange::getCharRange(Loc
, Loc
.getLocWithOffset(TokLen
)));
229 // Treat #included files as symbols, to enable go-to-definition on them.
230 llvm::Optional
<LocatedSymbol
> locateFileReferent(const Position
&Pos
,
232 llvm::StringRef MainFilePath
) {
233 for (auto &Inc
: AST
.getIncludeStructure().MainFileIncludes
) {
234 if (!Inc
.Resolved
.empty() && Inc
.HashLine
== Pos
.line
) {
236 File
.Name
= std::string(llvm::sys::path::filename(Inc
.Resolved
));
237 File
.PreferredDeclaration
= {
238 URIForFile::canonicalize(Inc
.Resolved
, MainFilePath
), Range
{}};
239 File
.Definition
= File
.PreferredDeclaration
;
240 // We're not going to find any further symbols on #include lines.
247 // Macros are simple: there's no declaration/definition distinction.
248 // As a consequence, there's no need to look them up in the index either.
249 llvm::Optional
<LocatedSymbol
>
250 locateMacroReferent(const syntax::Token
&TouchedIdentifier
, ParsedAST
&AST
,
251 llvm::StringRef MainFilePath
) {
252 if (auto M
= locateMacroAt(TouchedIdentifier
, AST
.getPreprocessor())) {
254 makeLocation(AST
.getASTContext(), M
->NameLoc
, MainFilePath
)) {
256 Macro
.Name
= std::string(M
->Name
);
257 Macro
.PreferredDeclaration
= *Loc
;
258 Macro
.Definition
= Loc
;
259 Macro
.ID
= getSymbolID(M
->Name
, M
->Info
, AST
.getSourceManager());
266 // A wrapper around `Decl::getCanonicalDecl` to support cases where Clang's
267 // definition of a canonical declaration doesn't match up to what a programmer
268 // would expect. For example, Objective-C classes can have three types of
271 // - forward declaration(s): @class MyClass;
272 // - true declaration (interface definition): @interface MyClass ... @end
273 // - true definition (implementation): @implementation MyClass ... @end
275 // Clang will consider the forward declaration to be the canonical declaration
276 // because it is first. We actually want the class definition if it is
277 // available since that is what a programmer would consider the primary
278 // declaration to be.
279 const NamedDecl
*getPreferredDecl(const NamedDecl
*D
) {
280 // FIXME: Canonical declarations of some symbols might refer to built-in
281 // decls with possibly-invalid source locations (e.g. global new operator).
282 // In such cases we should pick up a redecl with valid source location
283 // instead of failing.
284 D
= llvm::cast
<NamedDecl
>(D
->getCanonicalDecl());
286 // Prefer Objective-C class/protocol definitions over the forward declaration.
287 if (const auto *ID
= dyn_cast
<ObjCInterfaceDecl
>(D
))
288 if (const auto *DefinitionID
= ID
->getDefinition())
290 if (const auto *PD
= dyn_cast
<ObjCProtocolDecl
>(D
))
291 if (const auto *DefinitionID
= PD
->getDefinition())
297 std::vector
<LocatedSymbol
> findImplementors(llvm::DenseSet
<SymbolID
> IDs
,
298 RelationKind Predicate
,
299 const SymbolIndex
*Index
,
300 llvm::StringRef MainFilePath
) {
301 if (IDs
.empty() || !Index
)
303 static constexpr trace::Metric
FindImplementorsMetric(
304 "find_implementors", trace::Metric::Counter
, "case");
306 case RelationKind::BaseOf
:
307 FindImplementorsMetric
.record(1, "find-base");
309 case RelationKind::OverriddenBy
:
310 FindImplementorsMetric
.record(1, "find-override");
314 RelationsRequest Req
;
315 Req
.Predicate
= Predicate
;
316 Req
.Subjects
= std::move(IDs
);
317 std::vector
<LocatedSymbol
> Results
;
318 Index
->relations(Req
, [&](const SymbolID
&Subject
, const Symbol
&Object
) {
320 indexToLSPLocation(Object
.CanonicalDeclaration
, MainFilePath
);
322 elog("Find overrides: {0}", DeclLoc
.takeError());
325 Results
.emplace_back();
326 Results
.back().Name
= Object
.Name
.str();
327 Results
.back().PreferredDeclaration
= *DeclLoc
;
328 auto DefLoc
= indexToLSPLocation(Object
.Definition
, MainFilePath
);
330 elog("Failed to convert location: {0}", DefLoc
.takeError());
333 Results
.back().Definition
= *DefLoc
;
338 // Decls are more complicated.
339 // The AST contains at least a declaration, maybe a definition.
340 // These are up-to-date, and so generally preferred over index results.
341 // We perform a single batch index lookup to find additional definitions.
342 std::vector
<LocatedSymbol
>
343 locateASTReferent(SourceLocation CurLoc
, const syntax::Token
*TouchedIdentifier
,
344 ParsedAST
&AST
, llvm::StringRef MainFilePath
,
345 const SymbolIndex
*Index
, ASTNodeKind
&NodeKind
) {
346 const SourceManager
&SM
= AST
.getSourceManager();
347 // Results follow the order of Symbols.Decls.
348 std::vector
<LocatedSymbol
> Result
;
349 // Keep track of SymbolID -> index mapping, to fill in index data later.
350 llvm::DenseMap
<SymbolID
, size_t> ResultIndex
;
352 static constexpr trace::Metric
LocateASTReferentMetric(
353 "locate_ast_referent", trace::Metric::Counter
, "case");
354 auto AddResultDecl
= [&](const NamedDecl
*D
) {
355 D
= getPreferredDecl(D
);
357 makeLocation(AST
.getASTContext(), nameLocation(*D
, SM
), MainFilePath
);
361 Result
.emplace_back();
362 Result
.back().Name
= printName(AST
.getASTContext(), *D
);
363 Result
.back().PreferredDeclaration
= *Loc
;
364 Result
.back().ID
= getSymbolID(D
);
365 if (const NamedDecl
*Def
= getDefinition(D
))
366 Result
.back().Definition
= makeLocation(
367 AST
.getASTContext(), nameLocation(*Def
, SM
), MainFilePath
);
369 // Record SymbolID for index lookup later.
370 if (auto ID
= getSymbolID(D
))
371 ResultIndex
[ID
] = Result
.size() - 1;
374 // Emit all symbol locations (declaration or definition) from AST.
375 DeclRelationSet Relations
=
376 DeclRelation::TemplatePattern
| DeclRelation::Alias
;
378 getDeclAtPositionWithRelations(AST
, CurLoc
, Relations
, &NodeKind
);
379 llvm::DenseSet
<SymbolID
> VirtualMethods
;
380 for (const auto &E
: Candidates
) {
381 const NamedDecl
*D
= E
.first
;
382 if (const auto *CMD
= llvm::dyn_cast
<CXXMethodDecl
>(D
)) {
383 // Special case: virtual void ^method() = 0: jump to all overrides.
384 // FIXME: extend it to ^virtual, unfortunately, virtual location is not
387 if (TouchedIdentifier
&& SM
.getSpellingLoc(CMD
->getLocation()) ==
388 TouchedIdentifier
->location()) {
389 VirtualMethods
.insert(getSymbolID(CMD
));
390 LocateASTReferentMetric
.record(1, "method-to-override");
393 // Special case: void foo() ^override: jump to the overridden method.
394 if (NodeKind
.isSame(ASTNodeKind::getFromNodeKind
<OverrideAttr
>()) ||
395 NodeKind
.isSame(ASTNodeKind::getFromNodeKind
<FinalAttr
>())) {
396 // We may be overridding multiple methods - offer them all.
397 for (const NamedDecl
*ND
: CMD
->overridden_methods())
403 // Special case: the cursor is on an alias, prefer other results.
404 // This targets "using ns::^Foo", where the target is more interesting.
405 // This does not trigger on renaming aliases:
406 // `using Foo = ^Bar` already targets Bar via a TypeLoc
407 // `using ^Foo = Bar` has no other results, as Underlying is filtered.
408 if (E
.second
& DeclRelation::Alias
&& Candidates
.size() > 1 &&
409 // beginLoc/endLoc are a token range, so rewind the identifier we're in.
410 SM
.isPointWithin(TouchedIdentifier
? TouchedIdentifier
->location()
412 D
->getBeginLoc(), D
->getEndLoc()))
415 // Special case: the point of declaration of a template specialization,
416 // it's more useful to navigate to the template declaration.
417 if (auto *CTSD
= dyn_cast
<ClassTemplateSpecializationDecl
>(D
)) {
418 if (TouchedIdentifier
&&
419 D
->getLocation() == TouchedIdentifier
->location()) {
420 LocateASTReferentMetric
.record(1, "template-specialization-to-primary");
421 AddResultDecl(CTSD
->getSpecializedTemplate());
426 // Special case: if the class name is selected, also map Objective-C
427 // categories and category implementations back to their class interface.
429 // Since `TouchedIdentifier` might refer to the `ObjCCategoryImplDecl`
430 // instead of the `ObjCCategoryDecl` we intentionally check the contents
431 // of the locs when checking for class name equivalence.
432 if (const auto *CD
= dyn_cast
<ObjCCategoryDecl
>(D
))
433 if (const auto *ID
= CD
->getClassInterface())
434 if (TouchedIdentifier
&&
435 (CD
->getLocation() == TouchedIdentifier
->location() ||
436 ID
->getName() == TouchedIdentifier
->text(SM
))) {
437 LocateASTReferentMetric
.record(1, "objc-category-to-class");
441 LocateASTReferentMetric
.record(1, "regular");
442 // Otherwise the target declaration is the right one.
446 // Now query the index for all Symbol IDs we found in the AST.
447 if (Index
&& !ResultIndex
.empty()) {
448 LookupRequest QueryRequest
;
449 for (auto It
: ResultIndex
)
450 QueryRequest
.IDs
.insert(It
.first
);
452 Index
->lookup(QueryRequest
, [&](const Symbol
&Sym
) {
453 auto &R
= Result
[ResultIndex
.lookup(Sym
.ID
)];
455 if (R
.Definition
) { // from AST
456 // Special case: if the AST yielded a definition, then it may not be
457 // the right *declaration*. Prefer the one from the index.
458 if (auto Loc
= toLSPLocation(Sym
.CanonicalDeclaration
, MainFilePath
))
459 R
.PreferredDeclaration
= *Loc
;
461 // We might still prefer the definition from the index, e.g. for
462 // generated symbols.
463 if (auto Loc
= toLSPLocation(
464 getPreferredLocation(*R
.Definition
, Sym
.Definition
, Scratch
),
468 R
.Definition
= toLSPLocation(Sym
.Definition
, MainFilePath
);
470 // Use merge logic to choose AST or index declaration.
471 if (auto Loc
= toLSPLocation(
472 getPreferredLocation(R
.PreferredDeclaration
,
473 Sym
.CanonicalDeclaration
, Scratch
),
475 R
.PreferredDeclaration
= *Loc
;
480 auto Overrides
= findImplementors(VirtualMethods
, RelationKind::OverriddenBy
,
481 Index
, MainFilePath
);
482 Result
.insert(Result
.end(), Overrides
.begin(), Overrides
.end());
486 std::vector
<LocatedSymbol
> locateSymbolForType(const ParsedAST
&AST
,
487 const QualType
&Type
) {
488 const auto &SM
= AST
.getSourceManager();
489 auto MainFilePath
= AST
.tuPath();
491 // FIXME: this sends unique_ptr<Foo> to unique_ptr<T>.
492 // Likely it would be better to send it to Foo (heuristically) or to both.
493 auto Decls
= targetDecl(DynTypedNode::create(Type
.getNonReferenceType()),
494 DeclRelation::TemplatePattern
| DeclRelation::Alias
,
495 AST
.getHeuristicResolver());
499 std::vector
<LocatedSymbol
> Results
;
500 const auto &ASTContext
= AST
.getASTContext();
502 for (const NamedDecl
*D
: Decls
) {
503 D
= getPreferredDecl(D
);
505 auto Loc
= makeLocation(ASTContext
, nameLocation(*D
, SM
), MainFilePath
);
509 Results
.emplace_back();
510 Results
.back().Name
= printName(ASTContext
, *D
);
511 Results
.back().PreferredDeclaration
= *Loc
;
512 Results
.back().ID
= getSymbolID(D
);
513 if (const NamedDecl
*Def
= getDefinition(D
))
514 Results
.back().Definition
=
515 makeLocation(ASTContext
, nameLocation(*Def
, SM
), MainFilePath
);
521 bool tokenSpelledAt(SourceLocation SpellingLoc
, const syntax::TokenBuffer
&TB
) {
522 auto ExpandedTokens
= TB
.expandedTokens(
523 TB
.sourceManager().getMacroArgExpandedLocation(SpellingLoc
));
524 return !ExpandedTokens
.empty();
527 llvm::StringRef
sourcePrefix(SourceLocation Loc
, const SourceManager
&SM
) {
528 auto D
= SM
.getDecomposedLoc(Loc
);
529 bool Invalid
= false;
530 llvm::StringRef Buf
= SM
.getBufferData(D
.first
, &Invalid
);
531 if (Invalid
|| D
.second
> Buf
.size())
533 return Buf
.substr(0, D
.second
);
536 bool isDependentName(ASTNodeKind NodeKind
) {
537 return NodeKind
.isSame(ASTNodeKind::getFromNodeKind
<OverloadExpr
>()) ||
539 ASTNodeKind::getFromNodeKind
<CXXDependentScopeMemberExpr
>()) ||
541 ASTNodeKind::getFromNodeKind
<DependentScopeDeclRefExpr
>());
546 std::vector
<LocatedSymbol
> locateSymbolTextually(const SpelledWord
&Word
,
548 const SymbolIndex
*Index
,
549 llvm::StringRef MainFilePath
,
550 ASTNodeKind NodeKind
) {
551 // Don't use heuristics if this is a real identifier, or not an
553 // Exception: dependent names, because those may have useful textual
554 // matches that AST-based heuristics cannot find.
555 if ((Word
.ExpandedToken
&& !isDependentName(NodeKind
)) ||
556 !Word
.LikelyIdentifier
|| !Index
)
558 // We don't want to handle words in string literals. (It'd be nice to list
559 // *allowed* token kinds explicitly, but comment Tokens aren't retained).
560 if (Word
.PartOfSpelledToken
&&
561 isStringLiteral(Word
.PartOfSpelledToken
->kind()))
564 const auto &SM
= AST
.getSourceManager();
565 // Look up the selected word in the index.
566 FuzzyFindRequest Req
;
567 Req
.Query
= Word
.Text
.str();
568 Req
.ProximityPaths
= {MainFilePath
.str()};
569 // Find the namespaces to query by lexing the file.
571 visibleNamespaces(sourcePrefix(Word
.Location
, SM
), AST
.getLangOpts());
572 // FIXME: For extra strictness, consider AnyScope=false.
574 // We limit the results to 3 further below. This limit is to avoid fetching
575 // too much data, while still likely having enough for 3 results to remain
576 // after additional filtering.
578 bool TooMany
= false;
579 using ScoredLocatedSymbol
= std::pair
<float, LocatedSymbol
>;
580 std::vector
<ScoredLocatedSymbol
> ScoredResults
;
581 Index
->fuzzyFind(Req
, [&](const Symbol
&Sym
) {
582 // Only consider exact name matches, including case.
583 // This is to avoid too many false positives.
584 // We could relax this in the future (e.g. to allow for typos) if we make
585 // the query more accurate by other means.
586 if (Sym
.Name
!= Word
.Text
)
589 // Exclude constructor results. They have the same name as the class,
590 // but we don't have enough context to prefer them over the class.
591 if (Sym
.SymInfo
.Kind
== index::SymbolKind::Constructor
)
595 indexToLSPLocation(Sym
.CanonicalDeclaration
, MainFilePath
);
597 log("locateSymbolNamedTextuallyAt: {0}", MaybeDeclLoc
.takeError());
600 LocatedSymbol Located
;
601 Located
.PreferredDeclaration
= *MaybeDeclLoc
;
602 Located
.Name
= (Sym
.Name
+ Sym
.TemplateSpecializationArgs
).str();
604 if (Sym
.Definition
) {
605 auto MaybeDefLoc
= indexToLSPLocation(Sym
.Definition
, MainFilePath
);
607 log("locateSymbolNamedTextuallyAt: {0}", MaybeDefLoc
.takeError());
610 Located
.PreferredDeclaration
= *MaybeDefLoc
;
611 Located
.Definition
= *MaybeDefLoc
;
614 if (ScoredResults
.size() >= 5) {
615 // If we have more than 5 results, don't return anything,
616 // as confidence is too low.
617 // FIXME: Alternatively, try a stricter query?
622 SymbolQualitySignals Quality
;
624 SymbolRelevanceSignals Relevance
;
625 Relevance
.Name
= Sym
.Name
;
626 Relevance
.Query
= SymbolRelevanceSignals::Generic
;
627 Relevance
.merge(Sym
);
628 auto Score
= evaluateSymbolAndRelevance(Quality
.evaluateHeuristics(),
629 Relevance
.evaluateHeuristics());
630 dlog("locateSymbolNamedTextuallyAt: {0}{1} = {2}\n{3}{4}\n", Sym
.Scope
,
631 Sym
.Name
, Score
, Quality
, Relevance
);
633 ScoredResults
.push_back({Score
, std::move(Located
)});
637 vlog("Heuristic index lookup for {0} returned too many candidates, ignored",
642 llvm::sort(ScoredResults
,
643 [](const ScoredLocatedSymbol
&A
, const ScoredLocatedSymbol
&B
) {
644 return A
.first
> B
.first
;
646 std::vector
<LocatedSymbol
> Results
;
647 for (auto &Res
: std::move(ScoredResults
))
648 Results
.push_back(std::move(Res
.second
));
650 vlog("No heuristic index definition for {0}", Word
.Text
);
652 log("Found definition heuristically in index for {0}", Word
.Text
);
656 const syntax::Token
*findNearbyIdentifier(const SpelledWord
&Word
,
657 const syntax::TokenBuffer
&TB
) {
658 // Don't use heuristics if this is a real identifier.
659 // Unlikely identifiers are OK if they were used as identifiers nearby.
660 if (Word
.ExpandedToken
)
662 // We don't want to handle words in string literals. (It'd be nice to list
663 // *allowed* token kinds explicitly, but comment Tokens aren't retained).
664 if (Word
.PartOfSpelledToken
&&
665 isStringLiteral(Word
.PartOfSpelledToken
->kind()))
668 const SourceManager
&SM
= TB
.sourceManager();
669 // We prefer the closest possible token, line-wise. Backwards is penalized.
670 // Ties are implicitly broken by traversal order (first-one-wins).
671 auto File
= SM
.getFileID(Word
.Location
);
672 unsigned WordLine
= SM
.getSpellingLineNumber(Word
.Location
);
673 auto Cost
= [&](SourceLocation Loc
) -> unsigned {
674 assert(SM
.getFileID(Loc
) == File
&& "spelled token in wrong file?");
675 unsigned Line
= SM
.getSpellingLineNumber(Loc
);
676 return Line
>= WordLine
? Line
- WordLine
: 2 * (WordLine
- Line
);
678 const syntax::Token
*BestTok
= nullptr;
679 unsigned BestCost
= -1;
680 // Search bounds are based on word length:
681 // - forward: 2^N lines
682 // - backward: 2^(N-1) lines.
683 unsigned MaxDistance
=
684 1U << std::min
<unsigned>(Word
.Text
.size(),
685 std::numeric_limits
<unsigned>::digits
- 1);
686 // Line number for SM.translateLineCol() should be one-based, also
687 // SM.translateLineCol() can handle line number greater than
688 // number of lines in the file.
689 // - LineMin = max(1, WordLine + 1 - 2^(N-1))
690 // - LineMax = WordLine + 1 + 2^N
692 WordLine
+ 1 <= MaxDistance
/ 2 ? 1 : WordLine
+ 1 - MaxDistance
/ 2;
693 unsigned LineMax
= WordLine
+ 1 + MaxDistance
;
694 SourceLocation LocMin
= SM
.translateLineCol(File
, LineMin
, 1);
695 assert(LocMin
.isValid());
696 SourceLocation LocMax
= SM
.translateLineCol(File
, LineMax
, 1);
697 assert(LocMax
.isValid());
699 // Updates BestTok and BestCost if Tok is a good candidate.
700 // May return true if the cost is too high for this token.
701 auto Consider
= [&](const syntax::Token
&Tok
) {
702 if (Tok
.location() < LocMin
|| Tok
.location() > LocMax
)
703 return true; // we are too far from the word, break the outer loop.
704 if (!(Tok
.kind() == tok::identifier
&& Tok
.text(SM
) == Word
.Text
))
706 // No point guessing the same location we started with.
707 if (Tok
.location() == Word
.Location
)
709 // We've done cheap checks, compute cost so we can break the caller's loop.
710 unsigned TokCost
= Cost(Tok
.location());
711 if (TokCost
>= BestCost
)
712 return true; // causes the outer loop to break.
713 // Allow locations that might be part of the AST, and macros (even if empty)
714 // but not things like disabled preprocessor sections.
715 if (!(tokenSpelledAt(Tok
.location(), TB
) || TB
.expansionStartingAt(&Tok
)))
717 // We already verified this token is an improvement.
722 auto SpelledTokens
= TB
.spelledTokens(File
);
723 // Find where the word occurred in the token stream, to search forward & back.
724 auto *I
= llvm::partition_point(SpelledTokens
, [&](const syntax::Token
&T
) {
725 assert(SM
.getFileID(T
.location()) == SM
.getFileID(Word
.Location
));
726 return T
.location() < Word
.Location
; // Comparison OK: same file.
728 // Search for matches after the cursor.
729 for (const syntax::Token
&Tok
: llvm::makeArrayRef(I
, SpelledTokens
.end()))
731 break; // costs of later tokens are greater...
732 // Search for matches before the cursor.
733 for (const syntax::Token
&Tok
:
734 llvm::reverse(llvm::makeArrayRef(SpelledTokens
.begin(), I
)))
740 "Word {0} under cursor {1} isn't a token (after PP), trying nearby {2}",
741 Word
.Text
, Word
.Location
.printToString(SM
),
742 BestTok
->location().printToString(SM
));
747 std::vector
<LocatedSymbol
> locateSymbolAt(ParsedAST
&AST
, Position Pos
,
748 const SymbolIndex
*Index
) {
749 const auto &SM
= AST
.getSourceManager();
750 auto MainFilePath
= AST
.tuPath();
752 if (auto File
= locateFileReferent(Pos
, AST
, MainFilePath
))
753 return {std::move(*File
)};
755 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
757 elog("locateSymbolAt failed to convert position to source location: {0}",
762 const syntax::Token
*TouchedIdentifier
= nullptr;
763 auto TokensTouchingCursor
=
764 syntax::spelledTokensTouching(*CurLoc
, AST
.getTokens());
765 for (const syntax::Token
&Tok
: TokensTouchingCursor
) {
766 if (Tok
.kind() == tok::identifier
) {
767 if (auto Macro
= locateMacroReferent(Tok
, AST
, MainFilePath
))
768 // Don't look at the AST or index if we have a macro result.
769 // (We'd just return declarations referenced from the macro's
771 return {*std::move(Macro
)};
773 TouchedIdentifier
= &Tok
;
777 if (Tok
.kind() == tok::kw_auto
|| Tok
.kind() == tok::kw_decltype
) {
778 // go-to-definition on auto should find the definition of the deduced
780 if (auto Deduced
= getDeducedType(AST
.getASTContext(), Tok
.location())) {
781 auto LocSym
= locateSymbolForType(AST
, *Deduced
);
788 ASTNodeKind NodeKind
;
789 auto ASTResults
= locateASTReferent(*CurLoc
, TouchedIdentifier
, AST
,
790 MainFilePath
, Index
, NodeKind
);
791 if (!ASTResults
.empty())
794 // If the cursor can't be resolved directly, try fallback strategies.
796 SpelledWord::touching(*CurLoc
, AST
.getTokens(), AST
.getLangOpts());
798 // Is the same word nearby a real identifier that might refer to something?
799 if (const syntax::Token
*NearbyIdent
=
800 findNearbyIdentifier(*Word
, AST
.getTokens())) {
801 if (auto Macro
= locateMacroReferent(*NearbyIdent
, AST
, MainFilePath
)) {
802 log("Found macro definition heuristically using nearby identifier {0}",
804 return {*std::move(Macro
)};
806 ASTResults
= locateASTReferent(NearbyIdent
->location(), NearbyIdent
, AST
,
807 MainFilePath
, Index
, NodeKind
);
808 if (!ASTResults
.empty()) {
809 log("Found definition heuristically using nearby identifier {0}",
810 NearbyIdent
->text(SM
));
813 vlog("No definition found using nearby identifier {0} at {1}", Word
->Text
,
814 Word
->Location
.printToString(SM
));
816 // No nearby word, or it didn't refer to anything either. Try the index.
817 auto TextualResults
=
818 locateSymbolTextually(*Word
, AST
, Index
, MainFilePath
, NodeKind
);
819 if (!TextualResults
.empty())
820 return TextualResults
;
826 std::vector
<DocumentLink
> getDocumentLinks(ParsedAST
&AST
) {
827 const auto &SM
= AST
.getSourceManager();
829 std::vector
<DocumentLink
> Result
;
830 for (auto &Inc
: AST
.getIncludeStructure().MainFileIncludes
) {
831 if (Inc
.Resolved
.empty())
833 auto HashLoc
= SM
.getComposedLoc(SM
.getMainFileID(), Inc
.HashOffset
);
834 const auto *HashTok
= AST
.getTokens().spelledTokenAt(HashLoc
);
835 assert(HashTok
&& "got inclusion at wrong offset");
836 const auto *IncludeTok
= std::next(HashTok
);
837 const auto *FileTok
= std::next(IncludeTok
);
838 // FileTok->range is not sufficient here, as raw lexing wouldn't yield
839 // correct tokens for angled filenames. Hence we explicitly use
840 // Inc.Written's length.
842 syntax::FileRange(SM
, FileTok
->location(), Inc
.Written
.length())
846 DocumentLink({halfOpenToRange(SM
, FileRange
),
847 URIForFile::canonicalize(Inc
.Resolved
, AST
.tuPath())}));
855 /// Collects references to symbols within the main file.
856 class ReferenceFinder
: public index::IndexDataConsumer
{
859 syntax::Token SpelledTok
;
860 index::SymbolRoleSet Role
;
863 Range
range(const SourceManager
&SM
) const {
864 return halfOpenToRange(SM
, SpelledTok
.range(SM
).toCharRange(SM
));
868 ReferenceFinder(const ParsedAST
&AST
,
869 const llvm::ArrayRef
<const NamedDecl
*> Targets
,
871 : PerToken(PerToken
), AST(AST
) {
872 for (const NamedDecl
*ND
: Targets
) {
873 const Decl
*CD
= ND
->getCanonicalDecl();
874 TargetDeclToID
[CD
] = getSymbolID(CD
);
878 std::vector
<Reference
> take() && {
879 llvm::sort(References
, [](const Reference
&L
, const Reference
&R
) {
880 auto LTok
= L
.SpelledTok
.location();
881 auto RTok
= R
.SpelledTok
.location();
882 return std::tie(LTok
, L
.Role
) < std::tie(RTok
, R
.Role
);
884 // We sometimes see duplicates when parts of the AST get traversed twice.
885 References
.erase(std::unique(References
.begin(), References
.end(),
886 [](const Reference
&L
, const Reference
&R
) {
887 auto LTok
= L
.SpelledTok
.location();
888 auto RTok
= R
.SpelledTok
.location();
889 return std::tie(LTok
, L
.Role
) ==
890 std::tie(RTok
, R
.Role
);
893 return std::move(References
);
897 handleDeclOccurrence(const Decl
*D
, index::SymbolRoleSet Roles
,
898 llvm::ArrayRef
<index::SymbolRelation
> Relations
,
900 index::IndexDataConsumer::ASTNodeInfo ASTNode
) override
{
901 auto DeclID
= TargetDeclToID
.find(D
->getCanonicalDecl());
902 if (DeclID
== TargetDeclToID
.end())
904 const SourceManager
&SM
= AST
.getSourceManager();
905 if (!isInsideMainFile(Loc
, SM
))
907 const auto &TB
= AST
.getTokens();
909 llvm::SmallVector
<SourceLocation
, 1> Locs
;
911 // Check whether this is one of the few constructs where the reference
912 // can be split over several tokens.
913 if (auto *OME
= llvm::dyn_cast_or_null
<ObjCMessageExpr
>(ASTNode
.OrigE
)) {
914 OME
->getSelectorLocs(Locs
);
915 } else if (auto *OMD
=
916 llvm::dyn_cast_or_null
<ObjCMethodDecl
>(ASTNode
.OrigD
)) {
917 OMD
->getSelectorLocs(Locs
);
919 // Sanity check: we expect the *first* token to match the reported loc.
920 // Otherwise, maybe it was e.g. some other kind of reference to a Decl.
921 if (!Locs
.empty() && Locs
.front() != Loc
)
922 Locs
.clear(); // First token doesn't match, assume our guess was wrong.
927 for (SourceLocation L
: Locs
) {
928 L
= SM
.getFileLoc(L
);
929 if (const auto *Tok
= TB
.spelledTokenAt(L
))
930 References
.push_back({*Tok
, Roles
, DeclID
->getSecond()});
936 bool PerToken
; // If true, report 3 references for split ObjC selector names.
937 std::vector
<Reference
> References
;
938 const ParsedAST
&AST
;
939 llvm::DenseMap
<const Decl
*, SymbolID
> TargetDeclToID
;
942 std::vector
<ReferenceFinder::Reference
>
943 findRefs(const llvm::ArrayRef
<const NamedDecl
*> TargetDecls
, ParsedAST
&AST
,
945 ReferenceFinder
RefFinder(AST
, TargetDecls
, PerToken
);
946 index::IndexingOptions IndexOpts
;
947 IndexOpts
.SystemSymbolFilter
=
948 index::IndexingOptions::SystemSymbolFilterKind::All
;
949 IndexOpts
.IndexFunctionLocals
= true;
950 IndexOpts
.IndexParametersInDeclarations
= true;
951 IndexOpts
.IndexTemplateParameters
= true;
952 indexTopLevelDecls(AST
.getASTContext(), AST
.getPreprocessor(),
953 AST
.getLocalTopLevelDecls(), RefFinder
, IndexOpts
);
954 return std::move(RefFinder
).take();
957 const Stmt
*getFunctionBody(DynTypedNode N
) {
958 if (const auto *FD
= N
.get
<FunctionDecl
>())
959 return FD
->getBody();
960 if (const auto *FD
= N
.get
<BlockDecl
>())
961 return FD
->getBody();
962 if (const auto *FD
= N
.get
<LambdaExpr
>())
963 return FD
->getBody();
964 if (const auto *FD
= N
.get
<ObjCMethodDecl
>())
965 return FD
->getBody();
969 const Stmt
*getLoopBody(DynTypedNode N
) {
970 if (const auto *LS
= N
.get
<ForStmt
>())
971 return LS
->getBody();
972 if (const auto *LS
= N
.get
<CXXForRangeStmt
>())
973 return LS
->getBody();
974 if (const auto *LS
= N
.get
<WhileStmt
>())
975 return LS
->getBody();
976 if (const auto *LS
= N
.get
<DoStmt
>())
977 return LS
->getBody();
981 // AST traversal to highlight control flow statements under some root.
982 // Once we hit further control flow we prune the tree (or at least restrict
983 // what we highlight) so we capture e.g. breaks from the outer loop only.
984 class FindControlFlow
: public RecursiveASTVisitor
<FindControlFlow
> {
985 // Types of control-flow statements we might highlight.
993 All
= Break
| Continue
| Return
| Case
| Throw
| Goto
,
995 int Ignore
= 0; // bitmask of Target - what are we *not* highlighting?
996 SourceRange Bounds
; // Half-open, restricts reported targets.
997 std::vector
<SourceLocation
> &Result
;
998 const SourceManager
&SM
;
1000 // Masks out targets for a traversal into D.
1001 // Traverses the subtree using Delegate() if any targets remain.
1002 template <typename Func
>
1003 bool filterAndTraverse(DynTypedNode D
, const Func
&Delegate
) {
1004 auto RestoreIgnore
= llvm::make_scope_exit(
1005 [OldIgnore(Ignore
), this] { Ignore
= OldIgnore
; });
1006 if (getFunctionBody(D
))
1008 else if (getLoopBody(D
))
1009 Ignore
|= Continue
| Break
;
1010 else if (D
.get
<SwitchStmt
>())
1011 Ignore
|= Break
| Case
;
1012 // Prune tree if we're not looking for anything.
1013 return (Ignore
== All
) ? true : Delegate();
1016 void found(Target T
, SourceLocation Loc
) {
1019 if (SM
.isBeforeInTranslationUnit(Loc
, Bounds
.getBegin()) ||
1020 SM
.isBeforeInTranslationUnit(Bounds
.getEnd(), Loc
))
1022 Result
.push_back(Loc
);
1026 FindControlFlow(SourceRange Bounds
, std::vector
<SourceLocation
> &Result
,
1027 const SourceManager
&SM
)
1028 : Bounds(Bounds
), Result(Result
), SM(SM
) {}
1030 // When traversing function or loops, limit targets to those that still
1031 // refer to the original root.
1032 bool TraverseDecl(Decl
*D
) {
1033 return !D
|| filterAndTraverse(DynTypedNode::create(*D
), [&] {
1034 return RecursiveASTVisitor::TraverseDecl(D
);
1037 bool TraverseStmt(Stmt
*S
) {
1038 return !S
|| filterAndTraverse(DynTypedNode::create(*S
), [&] {
1039 return RecursiveASTVisitor::TraverseStmt(S
);
1043 // Add leaves that we found and want.
1044 bool VisitReturnStmt(ReturnStmt
*R
) {
1045 found(Return
, R
->getReturnLoc());
1048 bool VisitBreakStmt(BreakStmt
*B
) {
1049 found(Break
, B
->getBreakLoc());
1052 bool VisitContinueStmt(ContinueStmt
*C
) {
1053 found(Continue
, C
->getContinueLoc());
1056 bool VisitSwitchCase(SwitchCase
*C
) {
1057 found(Case
, C
->getKeywordLoc());
1060 bool VisitCXXThrowExpr(CXXThrowExpr
*T
) {
1061 found(Throw
, T
->getThrowLoc());
1064 bool VisitGotoStmt(GotoStmt
*G
) {
1065 // Goto is interesting if its target is outside the root.
1066 if (const auto *LD
= G
->getLabel()) {
1067 if (SM
.isBeforeInTranslationUnit(LD
->getLocation(), Bounds
.getBegin()) ||
1068 SM
.isBeforeInTranslationUnit(Bounds
.getEnd(), LD
->getLocation()))
1069 found(Goto
, G
->getGotoLoc());
1075 // Given a location within a switch statement, return the half-open range that
1076 // covers the case it's contained in.
1077 // We treat `case X: case Y: ...` as one case, and assume no other fallthrough.
1078 SourceRange
findCaseBounds(const SwitchStmt
&Switch
, SourceLocation Loc
,
1079 const SourceManager
&SM
) {
1080 // Cases are not stored in order, sort them first.
1081 // (In fact they seem to be stored in reverse order, don't rely on this)
1082 std::vector
<const SwitchCase
*> Cases
;
1083 for (const SwitchCase
*Case
= Switch
.getSwitchCaseList(); Case
;
1084 Case
= Case
->getNextSwitchCase())
1085 Cases
.push_back(Case
);
1086 llvm::sort(Cases
, [&](const SwitchCase
*L
, const SwitchCase
*R
) {
1087 return SM
.isBeforeInTranslationUnit(L
->getKeywordLoc(), R
->getKeywordLoc());
1090 // Find the first case after the target location, the end of our range.
1091 auto CaseAfter
= llvm::partition_point(Cases
, [&](const SwitchCase
*C
) {
1092 return !SM
.isBeforeInTranslationUnit(Loc
, C
->getKeywordLoc());
1094 SourceLocation End
= CaseAfter
== Cases
.end() ? Switch
.getEndLoc()
1095 : (*CaseAfter
)->getKeywordLoc();
1097 // Our target can be before the first case - cases are optional!
1098 if (CaseAfter
== Cases
.begin())
1099 return SourceRange(Switch
.getBeginLoc(), End
);
1100 // The start of our range is usually the previous case, but...
1101 auto CaseBefore
= std::prev(CaseAfter
);
1102 // ... rewind CaseBefore to the first in a `case A: case B: ...` sequence.
1103 while (CaseBefore
!= Cases
.begin() &&
1104 (*std::prev(CaseBefore
))->getSubStmt() == *CaseBefore
)
1106 return SourceRange((*CaseBefore
)->getKeywordLoc(), End
);
1109 // Returns the locations of control flow statements related to N. e.g.:
1110 // for => branches: break/continue/return/throw
1111 // break => controlling loop (forwhile/do), and its related control flow
1112 // return => all returns/throws from the same function
1113 // When an inner block is selected, we include branches bound to outer blocks
1114 // as these are exits from the inner block. e.g. return in a for loop.
1115 // FIXME: We don't analyze catch blocks, throw is treated the same as return.
1116 std::vector
<SourceLocation
> relatedControlFlow(const SelectionTree::Node
&N
) {
1117 const SourceManager
&SM
=
1118 N
.getDeclContext().getParentASTContext().getSourceManager();
1119 std::vector
<SourceLocation
> Result
;
1121 // First, check if we're at a node that can resolve to a root.
1122 enum class Cur
{ None
, Break
, Continue
, Return
, Case
, Throw
} Cursor
;
1123 if (N
.ASTNode
.get
<BreakStmt
>()) {
1124 Cursor
= Cur::Break
;
1125 } else if (N
.ASTNode
.get
<ContinueStmt
>()) {
1126 Cursor
= Cur::Continue
;
1127 } else if (N
.ASTNode
.get
<ReturnStmt
>()) {
1128 Cursor
= Cur::Return
;
1129 } else if (N
.ASTNode
.get
<CXXThrowExpr
>()) {
1130 Cursor
= Cur::Throw
;
1131 } else if (N
.ASTNode
.get
<SwitchCase
>()) {
1133 } else if (const GotoStmt
*GS
= N
.ASTNode
.get
<GotoStmt
>()) {
1134 // We don't know what root to associate with, but highlight the goto/label.
1135 Result
.push_back(GS
->getGotoLoc());
1136 if (const auto *LD
= GS
->getLabel())
1137 Result
.push_back(LD
->getLocation());
1143 const Stmt
*Root
= nullptr; // Loop or function body to traverse.
1145 // Look up the tree for a root (or just at this node if we didn't find a leaf)
1146 for (const auto *P
= &N
; P
; P
= P
->Parent
) {
1147 // return associates with enclosing function
1148 if (const Stmt
*FunctionBody
= getFunctionBody(P
->ASTNode
)) {
1149 if (Cursor
== Cur::Return
|| Cursor
== Cur::Throw
) {
1150 Root
= FunctionBody
;
1152 break; // other leaves don't cross functions.
1154 // break/continue associate with enclosing loop.
1155 if (const Stmt
*LoopBody
= getLoopBody(P
->ASTNode
)) {
1156 if (Cursor
== Cur::None
|| Cursor
== Cur::Break
||
1157 Cursor
== Cur::Continue
) {
1159 // Highlight the loop keyword itself.
1160 // FIXME: for do-while, this only covers the `do`..
1161 Result
.push_back(P
->ASTNode
.getSourceRange().getBegin());
1165 // For switches, users think of case statements as control flow blocks.
1166 // We highlight only occurrences surrounded by the same case.
1167 // We don't detect fallthrough (other than 'case X, case Y').
1168 if (const auto *SS
= P
->ASTNode
.get
<SwitchStmt
>()) {
1169 if (Cursor
== Cur::Break
|| Cursor
== Cur::Case
) {
1170 Result
.push_back(SS
->getSwitchLoc()); // Highlight the switch.
1171 Root
= SS
->getBody();
1172 // Limit to enclosing case, if there is one.
1173 Bounds
= findCaseBounds(*SS
, N
.ASTNode
.getSourceRange().getBegin(), SM
);
1177 // If we didn't start at some interesting node, we're done.
1178 if (Cursor
== Cur::None
)
1182 if (!Bounds
.isValid())
1183 Bounds
= Root
->getSourceRange();
1184 FindControlFlow(Bounds
, Result
, SM
).TraverseStmt(const_cast<Stmt
*>(Root
));
1189 DocumentHighlight
toHighlight(const ReferenceFinder::Reference
&Ref
,
1190 const SourceManager
&SM
) {
1191 DocumentHighlight DH
;
1192 DH
.range
= Ref
.range(SM
);
1193 if (Ref
.Role
& index::SymbolRoleSet(index::SymbolRole::Write
))
1194 DH
.kind
= DocumentHighlightKind::Write
;
1195 else if (Ref
.Role
& index::SymbolRoleSet(index::SymbolRole::Read
))
1196 DH
.kind
= DocumentHighlightKind::Read
;
1198 DH
.kind
= DocumentHighlightKind::Text
;
1202 llvm::Optional
<DocumentHighlight
> toHighlight(SourceLocation Loc
,
1203 const syntax::TokenBuffer
&TB
) {
1204 Loc
= TB
.sourceManager().getFileLoc(Loc
);
1205 if (const auto *Tok
= TB
.spelledTokenAt(Loc
)) {
1206 DocumentHighlight Result
;
1207 Result
.range
= halfOpenToRange(
1209 CharSourceRange::getCharRange(Tok
->location(), Tok
->endLocation()));
1217 std::vector
<DocumentHighlight
> findDocumentHighlights(ParsedAST
&AST
,
1219 const SourceManager
&SM
= AST
.getSourceManager();
1220 // FIXME: show references to macro within file?
1221 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1223 llvm::consumeError(CurLoc
.takeError());
1226 std::vector
<DocumentHighlight
> Result
;
1227 auto TryTree
= [&](SelectionTree ST
) {
1228 if (const SelectionTree::Node
*N
= ST
.commonAncestor()) {
1229 DeclRelationSet Relations
=
1230 DeclRelation::TemplatePattern
| DeclRelation::Alias
;
1232 targetDecl(N
->ASTNode
, Relations
, AST
.getHeuristicResolver());
1233 if (!TargetDecls
.empty()) {
1234 // FIXME: we may get multiple DocumentHighlights with the same location
1235 // and different kinds, deduplicate them.
1236 for (const auto &Ref
: findRefs(TargetDecls
, AST
, /*PerToken=*/true))
1237 Result
.push_back(toHighlight(Ref
, SM
));
1240 auto ControlFlow
= relatedControlFlow(*N
);
1241 if (!ControlFlow
.empty()) {
1242 for (SourceLocation Loc
: ControlFlow
)
1243 if (auto Highlight
= toHighlight(Loc
, AST
.getTokens()))
1244 Result
.push_back(std::move(*Highlight
));
1252 AST
.getSourceManager().getDecomposedSpellingLoc(*CurLoc
).second
;
1253 SelectionTree::createEach(AST
.getASTContext(), AST
.getTokens(), Offset
,
1258 std::vector
<LocatedSymbol
> findImplementations(ParsedAST
&AST
, Position Pos
,
1259 const SymbolIndex
*Index
) {
1260 // We rely on index to find the implementations in subclasses.
1261 // FIXME: Index can be stale, so we may loose some latest results from the
1265 const SourceManager
&SM
= AST
.getSourceManager();
1266 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1268 elog("Failed to convert position to source location: {0}",
1269 CurLoc
.takeError());
1272 DeclRelationSet Relations
=
1273 DeclRelation::TemplatePattern
| DeclRelation::Alias
;
1274 llvm::DenseSet
<SymbolID
> IDs
;
1275 RelationKind QueryKind
= RelationKind::OverriddenBy
;
1276 for (const NamedDecl
*ND
: getDeclAtPosition(AST
, *CurLoc
, Relations
)) {
1277 if (const auto *CXXMD
= llvm::dyn_cast
<CXXMethodDecl
>(ND
)) {
1278 if (CXXMD
->isVirtual()) {
1279 IDs
.insert(getSymbolID(ND
));
1280 QueryKind
= RelationKind::OverriddenBy
;
1282 } else if (const auto *RD
= dyn_cast
<CXXRecordDecl
>(ND
)) {
1283 IDs
.insert(getSymbolID(RD
));
1284 QueryKind
= RelationKind::BaseOf
;
1287 return findImplementors(std::move(IDs
), QueryKind
, Index
, AST
.tuPath());
1291 // Recursively finds all the overridden methods of `CMD` in complete type
1293 void getOverriddenMethods(const CXXMethodDecl
*CMD
,
1294 llvm::DenseSet
<SymbolID
> &OverriddenMethods
) {
1297 for (const CXXMethodDecl
*Base
: CMD
->overridden_methods()) {
1298 if (auto ID
= getSymbolID(Base
))
1299 OverriddenMethods
.insert(ID
);
1300 getOverriddenMethods(Base
, OverriddenMethods
);
1305 ReferencesResult
findReferences(ParsedAST
&AST
, Position Pos
, uint32_t Limit
,
1306 const SymbolIndex
*Index
) {
1307 ReferencesResult Results
;
1308 const SourceManager
&SM
= AST
.getSourceManager();
1309 auto MainFilePath
= AST
.tuPath();
1310 auto URIMainFile
= URIForFile::canonicalize(MainFilePath
, MainFilePath
);
1311 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1313 llvm::consumeError(CurLoc
.takeError());
1317 llvm::DenseSet
<SymbolID
> IDsToQuery
, OverriddenMethods
;
1319 const auto *IdentifierAtCursor
=
1320 syntax::spelledIdentifierTouching(*CurLoc
, AST
.getTokens());
1321 llvm::Optional
<DefinedMacro
> Macro
;
1322 if (IdentifierAtCursor
)
1323 Macro
= locateMacroAt(*IdentifierAtCursor
, AST
.getPreprocessor());
1325 // Handle references to macro.
1326 if (auto MacroSID
= getSymbolID(Macro
->Name
, Macro
->Info
, SM
)) {
1327 // Collect macro references from main file.
1328 const auto &IDToRefs
= AST
.getMacros().MacroRefs
;
1329 auto Refs
= IDToRefs
.find(MacroSID
);
1330 if (Refs
!= IDToRefs
.end()) {
1331 for (const auto &Ref
: Refs
->second
) {
1332 ReferencesResult::Reference Result
;
1333 Result
.Loc
.range
= Ref
.Rng
;
1334 Result
.Loc
.uri
= URIMainFile
;
1335 if (Ref
.IsDefinition
) {
1336 Result
.Attributes
|= ReferencesResult::Declaration
;
1337 Result
.Attributes
|= ReferencesResult::Definition
;
1339 Results
.References
.push_back(std::move(Result
));
1342 IDsToQuery
.insert(MacroSID
);
1345 // Handle references to Decls.
1347 DeclRelationSet Relations
=
1348 DeclRelation::TemplatePattern
| DeclRelation::Alias
;
1349 std::vector
<const NamedDecl
*> Decls
=
1350 getDeclAtPosition(AST
, *CurLoc
, Relations
);
1351 llvm::SmallVector
<const NamedDecl
*> TargetsInMainFile
;
1352 for (const NamedDecl
*D
: Decls
) {
1353 auto ID
= getSymbolID(D
);
1356 TargetsInMainFile
.push_back(D
);
1357 // Not all symbols can be referenced from outside (e.g. function-locals).
1358 // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
1359 // we know this file isn't a header. The details might be tricky.
1360 if (D
->getParentFunctionOrMethod())
1362 IDsToQuery
.insert(ID
);
1365 RelationsRequest OverriddenBy
;
1367 OverriddenBy
.Predicate
= RelationKind::OverriddenBy
;
1368 for (const NamedDecl
*ND
: Decls
) {
1369 // Special case: For virtual methods, report decl/def of overrides and
1370 // references to all overridden methods in complete type hierarchy.
1371 if (const auto *CMD
= llvm::dyn_cast
<CXXMethodDecl
>(ND
)) {
1372 if (CMD
->isVirtual()) {
1373 if (auto ID
= getSymbolID(CMD
))
1374 OverriddenBy
.Subjects
.insert(ID
);
1375 getOverriddenMethods(CMD
, OverriddenMethods
);
1381 // We traverse the AST to find references in the main file.
1382 auto MainFileRefs
= findRefs(TargetsInMainFile
, AST
, /*PerToken=*/false);
1383 // We may get multiple refs with the same location and different Roles, as
1384 // cross-reference is only interested in locations, we deduplicate them
1385 // by the location to avoid emitting duplicated locations.
1386 MainFileRefs
.erase(std::unique(MainFileRefs
.begin(), MainFileRefs
.end(),
1387 [](const ReferenceFinder::Reference
&L
,
1388 const ReferenceFinder::Reference
&R
) {
1389 return L
.SpelledTok
.location() ==
1390 R
.SpelledTok
.location();
1392 MainFileRefs
.end());
1393 for (const auto &Ref
: MainFileRefs
) {
1394 ReferencesResult::Reference Result
;
1395 Result
.Loc
.range
= Ref
.range(SM
);
1396 Result
.Loc
.uri
= URIMainFile
;
1397 if (Ref
.Role
& static_cast<unsigned>(index::SymbolRole::Declaration
))
1398 Result
.Attributes
|= ReferencesResult::Declaration
;
1399 // clang-index doesn't report definitions as declarations, but they are.
1400 if (Ref
.Role
& static_cast<unsigned>(index::SymbolRole::Definition
))
1401 Result
.Attributes
|=
1402 ReferencesResult::Definition
| ReferencesResult::Declaration
;
1403 Results
.References
.push_back(std::move(Result
));
1405 // Add decl/def of overridding methods.
1406 if (Index
&& !OverriddenBy
.Subjects
.empty()) {
1407 Index
->relations(OverriddenBy
, [&](const SymbolID
&Subject
,
1408 const Symbol
&Object
) {
1409 if (Limit
&& Results
.References
.size() >= Limit
) {
1410 Results
.HasMore
= true;
1413 const auto LSPLocDecl
=
1414 toLSPLocation(Object
.CanonicalDeclaration
, MainFilePath
);
1415 const auto LSPLocDef
= toLSPLocation(Object
.Definition
, MainFilePath
);
1416 if (LSPLocDecl
&& LSPLocDecl
!= LSPLocDef
) {
1417 ReferencesResult::Reference Result
;
1418 Result
.Loc
= std::move(*LSPLocDecl
);
1420 ReferencesResult::Declaration
| ReferencesResult::Override
;
1421 Results
.References
.push_back(std::move(Result
));
1424 ReferencesResult::Reference Result
;
1425 Result
.Loc
= std::move(*LSPLocDef
);
1426 Result
.Attributes
= ReferencesResult::Declaration
|
1427 ReferencesResult::Definition
|
1428 ReferencesResult::Override
;
1429 Results
.References
.push_back(std::move(Result
));
1434 // Now query the index for references from other files.
1435 auto QueryIndex
= [&](llvm::DenseSet
<SymbolID
> IDs
, bool AllowAttributes
,
1436 bool AllowMainFileSymbols
) {
1437 if (IDs
.empty() || !Index
|| Results
.HasMore
)
1440 Req
.IDs
= std::move(IDs
);
1442 if (Limit
< Results
.References
.size()) {
1443 // We've already filled our quota, still check the index to correctly
1444 // return the `HasMore` info.
1447 // Query index only for the remaining size.
1448 Req
.Limit
= Limit
- Results
.References
.size();
1451 Results
.HasMore
|= Index
->refs(Req
, [&](const Ref
&R
) {
1452 auto LSPLoc
= toLSPLocation(R
.Location
, MainFilePath
);
1453 // Avoid indexed results for the main file - the AST is authoritative.
1455 (!AllowMainFileSymbols
&& LSPLoc
->uri
.file() == MainFilePath
))
1457 ReferencesResult::Reference Result
;
1458 Result
.Loc
= std::move(*LSPLoc
);
1459 if (AllowAttributes
) {
1460 if ((R
.Kind
& RefKind::Declaration
) == RefKind::Declaration
)
1461 Result
.Attributes
|= ReferencesResult::Declaration
;
1462 // FIXME: our index should definitely store def | decl separately!
1463 if ((R
.Kind
& RefKind::Definition
) == RefKind::Definition
)
1464 Result
.Attributes
|=
1465 ReferencesResult::Declaration
| ReferencesResult::Definition
;
1467 Results
.References
.push_back(std::move(Result
));
1470 QueryIndex(std::move(IDsToQuery
), /*AllowAttributes=*/true,
1471 /*AllowMainFileSymbols=*/false);
1472 // For a virtual method: Occurrences of BaseMethod should be treated as refs
1473 // and not as decl/def. Allow symbols from main file since AST does not report
1475 QueryIndex(std::move(OverriddenMethods
), /*AllowAttributes=*/false,
1476 /*AllowMainFileSymbols=*/true);
1480 std::vector
<SymbolDetails
> getSymbolInfo(ParsedAST
&AST
, Position Pos
) {
1481 const SourceManager
&SM
= AST
.getSourceManager();
1482 auto CurLoc
= sourceLocationInMainFile(SM
, Pos
);
1484 llvm::consumeError(CurLoc
.takeError());
1487 auto MainFilePath
= AST
.tuPath();
1488 std::vector
<SymbolDetails
> Results
;
1490 // We also want the targets of using-decls, so we include
1491 // DeclRelation::Underlying.
1492 DeclRelationSet Relations
= DeclRelation::TemplatePattern
|
1493 DeclRelation::Alias
| DeclRelation::Underlying
;
1494 for (const NamedDecl
*D
: getDeclAtPosition(AST
, *CurLoc
, Relations
)) {
1495 D
= getPreferredDecl(D
);
1497 SymbolDetails NewSymbol
;
1498 std::string QName
= printQualifiedName(*D
);
1499 auto SplitQName
= splitQualifiedName(QName
);
1500 NewSymbol
.containerName
= std::string(SplitQName
.first
);
1501 NewSymbol
.name
= std::string(SplitQName
.second
);
1503 if (NewSymbol
.containerName
.empty()) {
1504 if (const auto *ParentND
=
1505 dyn_cast_or_null
<NamedDecl
>(D
->getDeclContext()))
1506 NewSymbol
.containerName
= printQualifiedName(*ParentND
);
1508 llvm::SmallString
<32> USR
;
1509 if (!index::generateUSRForDecl(D
, USR
)) {
1510 NewSymbol
.USR
= std::string(USR
.str());
1511 NewSymbol
.ID
= SymbolID(NewSymbol
.USR
);
1513 if (const NamedDecl
*Def
= getDefinition(D
))
1514 NewSymbol
.definitionRange
= makeLocation(
1515 AST
.getASTContext(), nameLocation(*Def
, SM
), MainFilePath
);
1516 NewSymbol
.declarationRange
=
1517 makeLocation(AST
.getASTContext(), nameLocation(*D
, SM
), MainFilePath
);
1519 Results
.push_back(std::move(NewSymbol
));
1522 const auto *IdentifierAtCursor
=
1523 syntax::spelledIdentifierTouching(*CurLoc
, AST
.getTokens());
1524 if (!IdentifierAtCursor
)
1527 if (auto M
= locateMacroAt(*IdentifierAtCursor
, AST
.getPreprocessor())) {
1528 SymbolDetails NewMacro
;
1529 NewMacro
.name
= std::string(M
->Name
);
1530 llvm::SmallString
<32> USR
;
1531 if (!index::generateUSRForMacro(NewMacro
.name
, M
->Info
->getDefinitionLoc(),
1533 NewMacro
.USR
= std::string(USR
.str());
1534 NewMacro
.ID
= SymbolID(NewMacro
.USR
);
1536 Results
.push_back(std::move(NewMacro
));
1542 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const LocatedSymbol
&S
) {
1543 OS
<< S
.Name
<< ": " << S
.PreferredDeclaration
;
1545 OS
<< " def=" << *S
.Definition
;
1549 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
,
1550 const ReferencesResult::Reference
&R
) {
1552 if (R
.Attributes
& ReferencesResult::Declaration
)
1554 if (R
.Attributes
& ReferencesResult::Definition
)
1556 if (R
.Attributes
& ReferencesResult::Override
)
1557 OS
<< " [override]";
1561 template <typename HierarchyItem
>
1562 static llvm::Optional
<HierarchyItem
>
1563 declToHierarchyItem(const NamedDecl
&ND
, llvm::StringRef TUPath
) {
1564 ASTContext
&Ctx
= ND
.getASTContext();
1565 auto &SM
= Ctx
.getSourceManager();
1566 SourceLocation NameLoc
= nameLocation(ND
, Ctx
.getSourceManager());
1567 SourceLocation BeginLoc
= SM
.getSpellingLoc(SM
.getFileLoc(ND
.getBeginLoc()));
1568 SourceLocation EndLoc
= SM
.getSpellingLoc(SM
.getFileLoc(ND
.getEndLoc()));
1569 const auto DeclRange
=
1570 toHalfOpenFileRange(SM
, Ctx
.getLangOpts(), {BeginLoc
, EndLoc
});
1574 getCanonicalPath(SM
.getFileEntryForID(SM
.getFileID(NameLoc
)), SM
);
1576 return llvm::None
; // Not useful without a uri.
1578 Position NameBegin
= sourceLocToPosition(SM
, NameLoc
);
1579 Position NameEnd
= sourceLocToPosition(
1580 SM
, Lexer::getLocForEndOfToken(NameLoc
, 0, SM
, Ctx
.getLangOpts()));
1582 index::SymbolInfo SymInfo
= index::getSymbolInfo(&ND
);
1583 // FIXME: This is not classifying constructors, destructors and operators
1585 SymbolKind SK
= indexSymbolKindToSymbolKind(SymInfo
.Kind
);
1588 HI
.name
= printName(Ctx
, ND
);
1590 HI
.range
= Range
{sourceLocToPosition(SM
, DeclRange
->getBegin()),
1591 sourceLocToPosition(SM
, DeclRange
->getEnd())};
1592 HI
.selectionRange
= Range
{NameBegin
, NameEnd
};
1593 if (!HI
.range
.contains(HI
.selectionRange
)) {
1594 // 'selectionRange' must be contained in 'range', so in cases where clang
1595 // reports unrelated ranges we need to reconcile somehow.
1596 HI
.range
= HI
.selectionRange
;
1599 HI
.uri
= URIForFile::canonicalize(*FilePath
, TUPath
);
1604 static llvm::Optional
<TypeHierarchyItem
>
1605 declToTypeHierarchyItem(const NamedDecl
&ND
, llvm::StringRef TUPath
) {
1606 auto Result
= declToHierarchyItem
<TypeHierarchyItem
>(ND
, TUPath
);
1608 Result
->deprecated
= ND
.isDeprecated();
1609 // Compute the SymbolID and store it in the 'data' field.
1610 // This allows typeHierarchy/resolve to be used to
1611 // resolve children of items returned in a previous request
1613 Result
->data
.symbolID
= getSymbolID(&ND
);
1618 static llvm::Optional
<CallHierarchyItem
>
1619 declToCallHierarchyItem(const NamedDecl
&ND
, llvm::StringRef TUPath
) {
1620 auto Result
= declToHierarchyItem
<CallHierarchyItem
>(ND
, TUPath
);
1623 if (ND
.isDeprecated())
1624 Result
->tags
.push_back(SymbolTag::Deprecated
);
1625 if (auto ID
= getSymbolID(&ND
))
1626 Result
->data
= ID
.str();
1630 template <typename HierarchyItem
>
1631 static llvm::Optional
<HierarchyItem
> symbolToHierarchyItem(const Symbol
&S
,
1633 auto Loc
= symbolToLocation(S
, TUPath
);
1635 elog("Failed to convert symbol to hierarchy item: {0}", Loc
.takeError());
1639 HI
.name
= std::string(S
.Name
);
1640 HI
.kind
= indexSymbolKindToSymbolKind(S
.SymInfo
.Kind
);
1641 HI
.selectionRange
= Loc
->range
;
1642 // FIXME: Populate 'range' correctly
1643 // (https://github.com/clangd/clangd/issues/59).
1644 HI
.range
= HI
.selectionRange
;
1650 static llvm::Optional
<TypeHierarchyItem
>
1651 symbolToTypeHierarchyItem(const Symbol
&S
, PathRef TUPath
) {
1652 auto Result
= symbolToHierarchyItem
<TypeHierarchyItem
>(S
, TUPath
);
1654 Result
->deprecated
= (S
.Flags
& Symbol::Deprecated
);
1655 Result
->data
.symbolID
= S
.ID
;
1660 static llvm::Optional
<CallHierarchyItem
>
1661 symbolToCallHierarchyItem(const Symbol
&S
, PathRef TUPath
) {
1662 auto Result
= symbolToHierarchyItem
<CallHierarchyItem
>(S
, TUPath
);
1665 Result
->data
= S
.ID
.str();
1666 if (S
.Flags
& Symbol::Deprecated
)
1667 Result
->tags
.push_back(SymbolTag::Deprecated
);
1671 static void fillSubTypes(const SymbolID
&ID
,
1672 std::vector
<TypeHierarchyItem
> &SubTypes
,
1673 const SymbolIndex
*Index
, int Levels
, PathRef TUPath
) {
1674 RelationsRequest Req
;
1675 Req
.Subjects
.insert(ID
);
1676 Req
.Predicate
= RelationKind::BaseOf
;
1677 Index
->relations(Req
, [&](const SymbolID
&Subject
, const Symbol
&Object
) {
1678 if (Optional
<TypeHierarchyItem
> ChildSym
=
1679 symbolToTypeHierarchyItem(Object
, TUPath
)) {
1681 ChildSym
->children
.emplace();
1682 fillSubTypes(Object
.ID
, *ChildSym
->children
, Index
, Levels
- 1, TUPath
);
1684 SubTypes
.emplace_back(std::move(*ChildSym
));
1689 using RecursionProtectionSet
= llvm::SmallSet
<const CXXRecordDecl
*, 4>;
1691 // Extracts parents from AST and populates the type hierarchy item.
1692 static void fillSuperTypes(const CXXRecordDecl
&CXXRD
, llvm::StringRef TUPath
,
1693 TypeHierarchyItem
&Item
,
1694 RecursionProtectionSet
&RPSet
) {
1695 Item
.parents
.emplace();
1696 Item
.data
.parents
.emplace();
1697 // typeParents() will replace dependent template specializations
1698 // with their class template, so to avoid infinite recursion for
1699 // certain types of hierarchies, keep the templates encountered
1700 // along the parent chain in a set, and stop the recursion if one
1701 // starts to repeat.
1702 auto *Pattern
= CXXRD
.getDescribedTemplate() ? &CXXRD
: nullptr;
1704 if (!RPSet
.insert(Pattern
).second
) {
1709 for (const CXXRecordDecl
*ParentDecl
: typeParents(&CXXRD
)) {
1710 if (Optional
<TypeHierarchyItem
> ParentSym
=
1711 declToTypeHierarchyItem(*ParentDecl
, TUPath
)) {
1712 fillSuperTypes(*ParentDecl
, TUPath
, *ParentSym
, RPSet
);
1713 Item
.data
.parents
->emplace_back(ParentSym
->data
);
1714 Item
.parents
->emplace_back(std::move(*ParentSym
));
1719 RPSet
.erase(Pattern
);
1723 std::vector
<const CXXRecordDecl
*> findRecordTypeAt(ParsedAST
&AST
,
1725 auto RecordFromNode
= [&AST
](const SelectionTree::Node
*N
) {
1726 std::vector
<const CXXRecordDecl
*> Records
;
1730 // Note: explicitReferenceTargets() will search for both template
1731 // instantiations and template patterns, and prefer the former if available
1732 // (generally, one will be available for non-dependent specializations of a
1734 auto Decls
= explicitReferenceTargets(N
->ASTNode
, DeclRelation::Underlying
,
1735 AST
.getHeuristicResolver());
1736 for (const NamedDecl
*D
: Decls
) {
1738 if (const VarDecl
*VD
= dyn_cast
<VarDecl
>(D
)) {
1739 // If this is a variable, use the type of the variable.
1740 Records
.push_back(VD
->getType().getTypePtr()->getAsCXXRecordDecl());
1744 if (const CXXMethodDecl
*Method
= dyn_cast
<CXXMethodDecl
>(D
)) {
1745 // If this is a method, use the type of the class.
1746 Records
.push_back(Method
->getParent());
1750 // We don't handle FieldDecl because it's not clear what behaviour
1751 // the user would expect: the enclosing class type (as with a
1752 // method), or the field's type (as with a variable).
1754 if (auto *RD
= dyn_cast
<CXXRecordDecl
>(D
))
1755 Records
.push_back(RD
);
1760 const SourceManager
&SM
= AST
.getSourceManager();
1761 std::vector
<const CXXRecordDecl
*> Result
;
1762 auto Offset
= positionToOffset(SM
.getBufferData(SM
.getMainFileID()), Pos
);
1764 llvm::consumeError(Offset
.takeError());
1767 SelectionTree::createEach(AST
.getASTContext(), AST
.getTokens(), *Offset
,
1768 *Offset
, [&](SelectionTree ST
) {
1769 Result
= RecordFromNode(ST
.commonAncestor());
1770 return !Result
.empty();
1775 // Return the type most associated with an AST node.
1776 // This isn't precisely defined: we want "go to type" to do something useful.
1777 static QualType
typeForNode(const SelectionTree::Node
*N
) {
1778 // If we're looking at a namespace qualifier, walk up to what it's qualifying.
1779 // (If we're pointing at a *class* inside a NNS, N will be a TypeLoc).
1780 while (N
&& N
->ASTNode
.get
<NestedNameSpecifierLoc
>())
1785 // If we're pointing at a type => return it.
1786 if (const TypeLoc
*TL
= N
->ASTNode
.get
<TypeLoc
>()) {
1787 if (llvm::isa
<DeducedType
>(TL
->getTypePtr()))
1788 if (auto Deduced
= getDeducedType(
1789 N
->getDeclContext().getParentASTContext(), TL
->getBeginLoc()))
1791 // Exception: an alias => underlying type.
1792 if (llvm::isa
<TypedefType
>(TL
->getTypePtr()))
1793 return TL
->getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();
1794 return TL
->getType();
1797 // Constructor initializers => the type of thing being initialized.
1798 if (const auto *CCI
= N
->ASTNode
.get
<CXXCtorInitializer
>()) {
1799 if (const FieldDecl
*FD
= CCI
->getAnyMember())
1800 return FD
->getType();
1801 if (const Type
*Base
= CCI
->getBaseClass())
1802 return QualType(Base
, 0);
1805 // Base specifier => the base type.
1806 if (const auto *CBS
= N
->ASTNode
.get
<CXXBaseSpecifier
>())
1807 return CBS
->getType();
1809 if (const Decl
*D
= N
->ASTNode
.get
<Decl
>()) {
1810 struct Visitor
: ConstDeclVisitor
<Visitor
, QualType
> {
1811 QualType
VisitValueDecl(const ValueDecl
*D
) { return D
->getType(); }
1812 // Declaration of a type => that type.
1813 QualType
VisitTypeDecl(const TypeDecl
*D
) {
1814 return QualType(D
->getTypeForDecl(), 0);
1816 // Exception: alias declaration => the underlying type, not the alias.
1817 QualType
VisitTypedefNameDecl(const TypedefNameDecl
*D
) {
1818 return D
->getUnderlyingType();
1820 // Look inside templates.
1821 QualType
VisitTemplateDecl(const TemplateDecl
*D
) {
1822 return Visit(D
->getTemplatedDecl());
1828 if (const Stmt
*S
= N
->ASTNode
.get
<Stmt
>()) {
1829 struct Visitor
: ConstStmtVisitor
<Visitor
, QualType
> {
1830 // Null-safe version of visit simplifies recursive calls below.
1831 QualType
type(const Stmt
*S
) { return S
? Visit(S
) : QualType(); }
1833 // In general, expressions => type of expression.
1834 QualType
VisitExpr(const Expr
*S
) {
1835 return S
->IgnoreImplicitAsWritten()->getType();
1837 // Exceptions for void expressions that operate on a type in some way.
1838 QualType
VisitCXXDeleteExpr(const CXXDeleteExpr
*S
) {
1839 return S
->getDestroyedType();
1841 QualType
VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr
*S
) {
1842 return S
->getDestroyedType();
1844 QualType
VisitCXXThrowExpr(const CXXThrowExpr
*S
) {
1845 return S
->getSubExpr()->getType();
1847 QualType
VisitCoyieldExpr(const CoyieldExpr
*S
) {
1848 return type(S
->getOperand());
1850 // Treat a designated initializer like a reference to the field.
1851 QualType
VisitDesignatedInitExpr(const DesignatedInitExpr
*S
) {
1852 // In .foo.bar we want to jump to bar's type, so find *last* field.
1853 for (auto &D
: llvm::reverse(S
->designators()))
1854 if (D
.isFieldDesignator())
1855 if (const auto *FD
= D
.getField())
1856 return FD
->getType();
1860 // Control flow statements that operate on data: use the data type.
1861 QualType
VisitSwitchStmt(const SwitchStmt
*S
) {
1862 return type(S
->getCond());
1864 QualType
VisitWhileStmt(const WhileStmt
*S
) { return type(S
->getCond()); }
1865 QualType
VisitDoStmt(const DoStmt
*S
) { return type(S
->getCond()); }
1866 QualType
VisitIfStmt(const IfStmt
*S
) { return type(S
->getCond()); }
1867 QualType
VisitCaseStmt(const CaseStmt
*S
) { return type(S
->getLHS()); }
1868 QualType
VisitCXXForRangeStmt(const CXXForRangeStmt
*S
) {
1869 return S
->getLoopVariable()->getType();
1871 QualType
VisitReturnStmt(const ReturnStmt
*S
) {
1872 return type(S
->getRetValue());
1874 QualType
VisitCoreturnStmt(const CoreturnStmt
*S
) {
1875 return type(S
->getOperand());
1877 QualType
VisitCXXCatchStmt(const CXXCatchStmt
*S
) {
1878 return S
->getCaughtType();
1880 QualType
VisitObjCAtThrowStmt(const ObjCAtThrowStmt
*S
) {
1881 return type(S
->getThrowExpr());
1883 QualType
VisitObjCAtCatchStmt(const ObjCAtCatchStmt
*S
) {
1884 return S
->getCatchParamDecl() ? S
->getCatchParamDecl()->getType()
1894 // Given a type targeted by the cursor, return one or more types that are more interesting
1896 static void unwrapFindType(
1897 QualType T
, const HeuristicResolver
* H
, llvm::SmallVector
<QualType
>& Out
) {
1901 // If there's a specific type alias, point at that rather than unwrapping.
1902 if (const auto* TDT
= T
->getAs
<TypedefType
>())
1903 return Out
.push_back(QualType(TDT
, 0));
1905 // Pointers etc => pointee type.
1906 if (const auto *PT
= T
->getAs
<PointerType
>())
1907 return unwrapFindType(PT
->getPointeeType(), H
, Out
);
1908 if (const auto *RT
= T
->getAs
<ReferenceType
>())
1909 return unwrapFindType(RT
->getPointeeType(), H
, Out
);
1910 if (const auto *AT
= T
->getAsArrayTypeUnsafe())
1911 return unwrapFindType(AT
->getElementType(), H
, Out
);
1913 // Function type => return type.
1914 if (auto *FT
= T
->getAs
<FunctionType
>())
1915 return unwrapFindType(FT
->getReturnType(), H
, Out
);
1916 if (auto *CRD
= T
->getAsCXXRecordDecl()) {
1917 if (CRD
->isLambda())
1918 return unwrapFindType(CRD
->getLambdaCallOperator()->getReturnType(), H
, Out
);
1919 // FIXME: more cases we'd prefer the return type of the call operator?
1920 // std::function etc?
1923 // For smart pointer types, add the underlying type
1925 if (const auto* PointeeType
= H
->getPointeeType(T
.getNonReferenceType().getTypePtr())) {
1926 unwrapFindType(QualType(PointeeType
, 0), H
, Out
);
1927 return Out
.push_back(T
);
1930 return Out
.push_back(T
);
1933 // Convenience overload, to allow calling this without the out-parameter
1934 static llvm::SmallVector
<QualType
> unwrapFindType(
1935 QualType T
, const HeuristicResolver
* H
) {
1936 llvm::SmallVector
<QualType
> Result
;
1937 unwrapFindType(T
, H
, Result
);
1942 std::vector
<LocatedSymbol
> findType(ParsedAST
&AST
, Position Pos
) {
1943 const SourceManager
&SM
= AST
.getSourceManager();
1944 auto Offset
= positionToOffset(SM
.getBufferData(SM
.getMainFileID()), Pos
);
1945 std::vector
<LocatedSymbol
> Result
;
1947 elog("failed to convert position {0} for findTypes: {1}", Pos
,
1948 Offset
.takeError());
1951 // The general scheme is: position -> AST node -> type -> declaration.
1952 auto SymbolsFromNode
=
1953 [&AST
](const SelectionTree::Node
*N
) -> std::vector
<LocatedSymbol
> {
1954 std::vector
<LocatedSymbol
> LocatedSymbols
;
1956 // NOTE: unwrapFindType might return duplicates for something like
1957 // unique_ptr<unique_ptr<T>>. Let's *not* remove them, because it gives you some
1958 // information about the type you may have not known before
1959 // (since unique_ptr<unique_ptr<T>> != unique_ptr<T>).
1960 for (const QualType
& Type
: unwrapFindType(typeForNode(N
), AST
.getHeuristicResolver()))
1961 llvm::copy(locateSymbolForType(AST
, Type
), std::back_inserter(LocatedSymbols
));
1963 return LocatedSymbols
;
1965 SelectionTree::createEach(AST
.getASTContext(), AST
.getTokens(), *Offset
,
1966 *Offset
, [&](SelectionTree ST
) {
1967 Result
= SymbolsFromNode(ST
.commonAncestor());
1968 return !Result
.empty();
1973 std::vector
<const CXXRecordDecl
*> typeParents(const CXXRecordDecl
*CXXRD
) {
1974 std::vector
<const CXXRecordDecl
*> Result
;
1976 // If this is an invalid instantiation, instantiation of the bases
1977 // may not have succeeded, so fall back to the template pattern.
1978 if (auto *CTSD
= dyn_cast
<ClassTemplateSpecializationDecl
>(CXXRD
)) {
1979 if (CTSD
->isInvalidDecl())
1980 CXXRD
= CTSD
->getSpecializedTemplate()->getTemplatedDecl();
1983 // Can't query bases without a definition.
1984 if (!CXXRD
->hasDefinition())
1987 for (auto Base
: CXXRD
->bases()) {
1988 const CXXRecordDecl
*ParentDecl
= nullptr;
1990 const Type
*Type
= Base
.getType().getTypePtr();
1991 if (const RecordType
*RT
= Type
->getAs
<RecordType
>()) {
1992 ParentDecl
= RT
->getAsCXXRecordDecl();
1996 // Handle a dependent base such as "Base<T>" by using the primary
1998 if (const TemplateSpecializationType
*TS
=
1999 Type
->getAs
<TemplateSpecializationType
>()) {
2000 TemplateName TN
= TS
->getTemplateName();
2001 if (TemplateDecl
*TD
= TN
.getAsTemplateDecl()) {
2002 ParentDecl
= dyn_cast
<CXXRecordDecl
>(TD
->getTemplatedDecl());
2008 Result
.push_back(ParentDecl
);
2014 std::vector
<TypeHierarchyItem
>
2015 getTypeHierarchy(ParsedAST
&AST
, Position Pos
, int ResolveLevels
,
2016 TypeHierarchyDirection Direction
, const SymbolIndex
*Index
,
2018 std::vector
<TypeHierarchyItem
> Results
;
2019 for (const auto *CXXRD
: findRecordTypeAt(AST
, Pos
)) {
2021 bool WantChildren
= Direction
== TypeHierarchyDirection::Children
||
2022 Direction
== TypeHierarchyDirection::Both
;
2024 // If we're looking for children, we're doing the lookup in the index.
2025 // The index does not store relationships between implicit
2026 // specializations, so if we have one, use the template pattern instead.
2027 // Note that this needs to be done before the declToTypeHierarchyItem(),
2028 // otherwise the type hierarchy item would misleadingly contain the
2029 // specialization parameters, while the children would involve classes
2030 // that derive from other specializations of the template.
2032 if (auto *CTSD
= dyn_cast
<ClassTemplateSpecializationDecl
>(CXXRD
))
2033 CXXRD
= CTSD
->getTemplateInstantiationPattern();
2036 Optional
<TypeHierarchyItem
> Result
=
2037 declToTypeHierarchyItem(*CXXRD
, AST
.tuPath());
2041 RecursionProtectionSet RPSet
;
2042 fillSuperTypes(*CXXRD
, AST
.tuPath(), *Result
, RPSet
);
2044 if (WantChildren
&& ResolveLevels
> 0) {
2045 Result
->children
.emplace();
2048 if (auto ID
= getSymbolID(CXXRD
))
2049 fillSubTypes(ID
, *Result
->children
, Index
, ResolveLevels
, TUPath
);
2052 Results
.emplace_back(std::move(*Result
));
2058 llvm::Optional
<std::vector
<TypeHierarchyItem
>>
2059 superTypes(const TypeHierarchyItem
&Item
, const SymbolIndex
*Index
) {
2060 std::vector
<TypeHierarchyItem
> Results
;
2061 if (!Item
.data
.parents
)
2063 if (Item
.data
.parents
->empty())
2066 llvm::DenseMap
<SymbolID
, const TypeHierarchyItem::ResolveParams
*> IDToData
;
2067 for (const auto &Parent
: *Item
.data
.parents
) {
2068 Req
.IDs
.insert(Parent
.symbolID
);
2069 IDToData
[Parent
.symbolID
] = &Parent
;
2071 Index
->lookup(Req
, [&Item
, &Results
, &IDToData
](const Symbol
&S
) {
2072 if (auto THI
= symbolToTypeHierarchyItem(S
, Item
.uri
.file())) {
2073 THI
->data
= *IDToData
.lookup(S
.ID
);
2074 Results
.emplace_back(std::move(*THI
));
2080 std::vector
<TypeHierarchyItem
> subTypes(const TypeHierarchyItem
&Item
,
2081 const SymbolIndex
*Index
) {
2082 std::vector
<TypeHierarchyItem
> Results
;
2083 fillSubTypes(Item
.data
.symbolID
, Results
, Index
, 1, Item
.uri
.file());
2084 for (auto &ChildSym
: Results
)
2085 ChildSym
.data
.parents
= {Item
.data
};
2089 void resolveTypeHierarchy(TypeHierarchyItem
&Item
, int ResolveLevels
,
2090 TypeHierarchyDirection Direction
,
2091 const SymbolIndex
*Index
) {
2092 // We only support typeHierarchy/resolve for children, because for parents
2093 // we ignore ResolveLevels and return all levels of parents eagerly.
2094 if (!Index
|| Direction
== TypeHierarchyDirection::Parents
||
2098 Item
.children
.emplace();
2099 fillSubTypes(Item
.data
.symbolID
, *Item
.children
, Index
, ResolveLevels
,
2103 std::vector
<CallHierarchyItem
>
2104 prepareCallHierarchy(ParsedAST
&AST
, Position Pos
, PathRef TUPath
) {
2105 std::vector
<CallHierarchyItem
> Result
;
2106 const auto &SM
= AST
.getSourceManager();
2107 auto Loc
= sourceLocationInMainFile(SM
, Pos
);
2109 elog("prepareCallHierarchy failed to convert position to source location: "
2114 for (const NamedDecl
*Decl
: getDeclAtPosition(AST
, *Loc
, {})) {
2115 if (!(isa
<DeclContext
>(Decl
) &&
2116 cast
<DeclContext
>(Decl
)->isFunctionOrMethod()) &&
2117 Decl
->getKind() != Decl::Kind::FunctionTemplate
)
2119 if (auto CHI
= declToCallHierarchyItem(*Decl
, AST
.tuPath()))
2120 Result
.emplace_back(std::move(*CHI
));
2125 std::vector
<CallHierarchyIncomingCall
>
2126 incomingCalls(const CallHierarchyItem
&Item
, const SymbolIndex
*Index
) {
2127 std::vector
<CallHierarchyIncomingCall
> Results
;
2128 if (!Index
|| Item
.data
.empty())
2130 auto ID
= SymbolID::fromStr(Item
.data
);
2132 elog("incomingCalls failed to find symbol: {0}", ID
.takeError());
2135 // In this function, we find incoming calls based on the index only.
2136 // In principle, the AST could have more up-to-date information about
2137 // occurrences within the current file. However, going from a SymbolID
2138 // to an AST node isn't cheap, particularly when the declaration isn't
2139 // in the main file.
2140 // FIXME: Consider also using AST information when feasible.
2141 RefsRequest Request
;
2142 Request
.IDs
.insert(*ID
);
2143 Request
.WantContainer
= true;
2144 // We could restrict more specifically to calls by introducing a new RefKind,
2145 // but non-call references (such as address-of-function) can still be
2146 // interesting as they can indicate indirect calls.
2147 Request
.Filter
= RefKind::Reference
;
2148 // Initially store the ranges in a map keyed by SymbolID of the caller.
2149 // This allows us to group different calls with the same caller
2150 // into the same CallHierarchyIncomingCall.
2151 llvm::DenseMap
<SymbolID
, std::vector
<Range
>> CallsIn
;
2152 // We can populate the ranges based on a refs request only. As we do so, we
2153 // also accumulate the container IDs into a lookup request.
2154 LookupRequest ContainerLookup
;
2155 Index
->refs(Request
, [&](const Ref
&R
) {
2156 auto Loc
= indexToLSPLocation(R
.Location
, Item
.uri
.file());
2158 elog("incomingCalls failed to convert location: {0}", Loc
.takeError());
2161 auto It
= CallsIn
.try_emplace(R
.Container
, std::vector
<Range
>{}).first
;
2162 It
->second
.push_back(Loc
->range
);
2164 ContainerLookup
.IDs
.insert(R
.Container
);
2166 // Perform the lookup request and combine its results with CallsIn to
2167 // get complete CallHierarchyIncomingCall objects.
2168 Index
->lookup(ContainerLookup
, [&](const Symbol
&Caller
) {
2169 auto It
= CallsIn
.find(Caller
.ID
);
2170 assert(It
!= CallsIn
.end());
2171 if (auto CHI
= symbolToCallHierarchyItem(Caller
, Item
.uri
.file()))
2173 CallHierarchyIncomingCall
{std::move(*CHI
), std::move(It
->second
)});
2175 // Sort results by name of container.
2176 llvm::sort(Results
, [](const CallHierarchyIncomingCall
&A
,
2177 const CallHierarchyIncomingCall
&B
) {
2178 return A
.from
.name
< B
.from
.name
;
2183 llvm::DenseSet
<const Decl
*> getNonLocalDeclRefs(ParsedAST
&AST
,
2184 const FunctionDecl
*FD
) {
2187 llvm::DenseSet
<const Decl
*> DeclRefs
;
2188 findExplicitReferences(
2190 [&](ReferenceLoc Ref
) {
2191 for (const Decl
*D
: Ref
.Targets
) {
2192 if (!index::isFunctionLocalSymbol(D
) && !D
->isTemplateParameter() &&
2197 AST
.getHeuristicResolver());
2201 } // namespace clangd
2202 } // namespace clang