1 //===--- XRefs.cpp -----------------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "XRefs.h"
9 #include "AST.h"
10 #include "FindSymbols.h"
11 #include "FindTarget.h"
12 #include "HeuristicResolver.h"
13 #include "ParsedAST.h"
14 #include "Protocol.h"
15 #include "Quality.h"
16 #include "Selection.h"
17 #include "SourceCode.h"
18 #include "URI.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"
64 #include <vector>
65 
66 namespace clang {
67 namespace clangd {
68 namespace {
69 
70 // Returns the single definition of the entity declared by D, if visible.
71 // In particular:
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().
getDefinition(const NamedDecl * D)76 const NamedDecl *getDefinition(const NamedDecl *D) {
77   assert(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())
90       return MD;
91     // Look for the method definition inside the implementation decl.
92     auto *DeclCtx = cast<Decl>(MD->getDeclContext());
93     if (DeclCtx->isInvalidDecl())
94       return nullptr;
95 
96     if (const auto *CD = dyn_cast<ObjCContainerDecl>(DeclCtx))
97       if (const auto *Impl = getCorrespondingObjCImpl(CD))
98         return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod());
99   }
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
105     return D;
106   // Multiple definitions are allowed.
107   return nullptr; // except cases above
108 }
109 
logIfOverflow(const SymbolLocation & Loc)110 void logIfOverflow(const SymbolLocation &Loc) {
111   if (Loc.Start.hasOverflow() || Loc.End.hasOverflow())
112     log("Possible overflow in symbol location: {0}", Loc);
113 }
114 
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
118 // FindSymbols.
toLSPLocation(const SymbolLocation & Loc,llvm::StringRef TUPath)119 llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc,
120                                        llvm::StringRef TUPath) {
121   if (!Loc)
122     return None;
123   auto Uri = URI::parse(Loc.FileURI);
124   if (!Uri) {
125     elog("Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError());
126     return None;
127   }
128   auto U = URIForFile::fromURI(*Uri, TUPath);
129   if (!U) {
130     elog("Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError());
131     return None;
132   }
133 
134   Location LSPLoc;
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();
140   logIfOverflow(Loc);
141   return LSPLoc;
142 }
143 
toIndexLocation(const Location & Loc,std::string & URIStorage)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);
152   return SymLoc;
153 }
154 
155 // Returns the preferred location between an AST location and an index location.
getPreferredLocation(const Location & ASTLoc,const SymbolLocation & IdxLoc,std::string & Scratch)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;
167 }
168 
169 std::vector<std::pair<const NamedDecl *, DeclRelationSet>>
getDeclAtPositionWithRelations(ParsedAST & AST,SourceLocation Pos,DeclRelationSet Relations,ASTNodeKind * NodeKind=nullptr)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()) {
177       if (NodeKind)
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)
184         N = N->Parent;
185       llvm::copy_if(allTargetDecls(N->ASTNode, AST.getHeuristicResolver()),
186                     std::back_inserter(Result),
187                     [&](auto &Entry) { return !(Entry.second & ~Relations); });
188     }
189     return !Result.empty();
190   };
191   SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset,
192                             Offset, ResultFromTree);
193   return Result;
194 }
195 
196 std::vector<const NamedDecl *>
getDeclAtPosition(ParsedAST & AST,SourceLocation Pos,DeclRelationSet Relations,ASTNodeKind * NodeKind=nullptr)197 getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations,
198                   ASTNodeKind *NodeKind = nullptr) {
199   std::vector<const NamedDecl *> Result;
200   for (auto &Entry :
201        getDeclAtPositionWithRelations(AST, Pos, Relations, NodeKind))
202     Result.push_back(Entry.first);
203   return Result;
204 }
205 
206 // Expects Loc to be a SpellingLocation, will bail out otherwise as it can't
207 // figure out a filename.
makeLocation(const ASTContext & AST,SourceLocation Loc,llvm::StringRef TUPath)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));
212   if (!F)
213     return None;
214   auto FilePath = getCanonicalPath(F, SM);
215   if (!FilePath) {
216     log("failed to get path!");
217     return None;
218   }
219   Location L;
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)));
226   return L;
227 }
228 
229 // Treat #included files as symbols, to enable go-to-definition on them.
locateFileReferent(const Position & Pos,ParsedAST & AST,llvm::StringRef MainFilePath)230 llvm::Optional<LocatedSymbol> locateFileReferent(const Position &Pos,
231                                                  ParsedAST &AST,
232                                                  llvm::StringRef MainFilePath) {
233   for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
234     if (!Inc.Resolved.empty() && Inc.HashLine == Pos.line) {
235       LocatedSymbol File;
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.
241       return File;
242     }
243   }
244   return llvm::None;
245 }
246 
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>
locateMacroReferent(const syntax::Token & TouchedIdentifier,ParsedAST & AST,llvm::StringRef MainFilePath)250 locateMacroReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST,
251                     llvm::StringRef MainFilePath) {
252   if (auto M = locateMacroAt(TouchedIdentifier, AST.getPreprocessor())) {
253     if (auto Loc =
254             makeLocation(AST.getASTContext(), M->NameLoc, MainFilePath)) {
255       LocatedSymbol Macro;
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());
260       return Macro;
261     }
262   }
263   return llvm::None;
264 }
265 
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
269 // declarations:
270 //
271 // - forward declaration(s): @class MyClass;
272 // - true declaration (interface definition): @interface MyClass ... @end
273 // - true definition (implementation): @implementation MyClass ... @end
274 //
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.
getPreferredDecl(const NamedDecl * D)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());
285 
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())
289       return DefinitionID;
290   if (const auto *PD = dyn_cast<ObjCProtocolDecl>(D))
291     if (const auto *DefinitionID = PD->getDefinition())
292       return DefinitionID;
293 
294   return D;
295 }
296 
findImplementors(llvm::DenseSet<SymbolID> IDs,RelationKind Predicate,const SymbolIndex * Index,llvm::StringRef MainFilePath)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)
302     return {};
303   static constexpr trace::Metric FindImplementorsMetric(
304       "find_implementors", trace::Metric::Counter, "case");
305   switch (Predicate) {
306   case RelationKind::BaseOf:
307     FindImplementorsMetric.record(1, "find-base");
308     break;
309   case RelationKind::OverriddenBy:
310     FindImplementorsMetric.record(1, "find-override");
311     break;
312   }
313 
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) {
319     auto DeclLoc =
320         indexToLSPLocation(Object.CanonicalDeclaration, MainFilePath);
321     if (!DeclLoc) {
322       elog("Find overrides: {0}", DeclLoc.takeError());
323       return;
324     }
325     Results.emplace_back();
326     Results.back().Name = Object.Name.str();
327     Results.back().PreferredDeclaration = *DeclLoc;
328     auto DefLoc = indexToLSPLocation(Object.Definition, MainFilePath);
329     if (!DefLoc) {
330       elog("Failed to convert location: {0}", DefLoc.takeError());
331       return;
332     }
333     Results.back().Definition = *DefLoc;
334   });
335   return Results;
336 }
337 
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>
locateASTReferent(SourceLocation CurLoc,const syntax::Token * TouchedIdentifier,ParsedAST & AST,llvm::StringRef MainFilePath,const SymbolIndex * Index,ASTNodeKind & NodeKind)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;
351 
352   static constexpr trace::Metric LocateASTReferentMetric(
353       "locate_ast_referent", trace::Metric::Counter, "case");
354   auto AddResultDecl = [&](const NamedDecl *D) {
355     D = getPreferredDecl(D);
356     auto Loc =
357         makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath);
358     if (!Loc)
359       return;
360 
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);
368 
369     // Record SymbolID for index lookup later.
370     if (auto ID = getSymbolID(D))
371       ResultIndex[ID] = Result.size() - 1;
372   };
373 
374   // Emit all symbol locations (declaration or definition) from AST.
375   DeclRelationSet Relations =
376       DeclRelation::TemplatePattern | DeclRelation::Alias;
377   auto Candidates =
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
385       // saved in the AST.
386       if (CMD->isPure()) {
387         if (TouchedIdentifier && SM.getSpellingLoc(CMD->getLocation()) ==
388                                      TouchedIdentifier->location()) {
389           VirtualMethods.insert(getSymbolID(CMD));
390           LocateASTReferentMetric.record(1, "method-to-override");
391         }
392       }
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())
398           AddResultDecl(ND);
399         continue;
400       }
401     }
402 
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()
411                                            : CurLoc,
412                          D->getBeginLoc(), D->getEndLoc()))
413       continue;
414 
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());
422         continue;
423       }
424     }
425 
426     // Special case: if the class name is selected, also map Objective-C
427     // categories and category implementations back to their class interface.
428     //
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");
438           AddResultDecl(ID);
439         }
440 
441     LocateASTReferentMetric.record(1, "regular");
442     // Otherwise the target declaration is the right one.
443     AddResultDecl(D);
444   }
445 
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);
451     std::string Scratch;
452     Index->lookup(QueryRequest, [&](const Symbol &Sym) {
453       auto &R = Result[ResultIndex.lookup(Sym.ID)];
454 
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;
460 
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),
465                 MainFilePath))
466           R.Definition = *Loc;
467       } else {
468         R.Definition = toLSPLocation(Sym.Definition, MainFilePath);
469 
470         // Use merge logic to choose AST or index declaration.
471         if (auto Loc = toLSPLocation(
472                 getPreferredLocation(R.PreferredDeclaration,
473                                      Sym.CanonicalDeclaration, Scratch),
474                 MainFilePath))
475           R.PreferredDeclaration = *Loc;
476       }
477     });
478   }
479 
480   auto Overrides = findImplementors(VirtualMethods, RelationKind::OverriddenBy,
481                                     Index, MainFilePath);
482   Result.insert(Result.end(), Overrides.begin(), Overrides.end());
483   return Result;
484 }
485 
locateSymbolForType(const ParsedAST & AST,const QualType & Type)486 std::vector<LocatedSymbol> locateSymbolForType(const ParsedAST &AST,
487                                                const QualType &Type) {
488   const auto &SM = AST.getSourceManager();
489   auto MainFilePath =
490       getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
491   if (!MainFilePath) {
492     elog("Failed to get a path for the main file, so no symbol.");
493     return {};
494   }
495 
496   // FIXME: this sends unique_ptr<Foo> to unique_ptr<T>.
497   // Likely it would be better to send it to Foo (heuristically) or to both.
498   auto Decls = targetDecl(DynTypedNode::create(Type.getNonReferenceType()),
499                           DeclRelation::TemplatePattern | DeclRelation::Alias,
500                           AST.getHeuristicResolver());
501   if (Decls.empty())
502     return {};
503 
504   std::vector<LocatedSymbol> Results;
505   const auto &ASTContext = AST.getASTContext();
506 
507   for (const NamedDecl *D : Decls) {
508     D = getPreferredDecl(D);
509 
510     auto Loc = makeLocation(ASTContext, nameLocation(*D, SM), *MainFilePath);
511     if (!Loc)
512       continue;
513 
514     Results.emplace_back();
515     Results.back().Name = printName(ASTContext, *D);
516     Results.back().PreferredDeclaration = *Loc;
517     Results.back().ID = getSymbolID(D);
518     if (const NamedDecl *Def = getDefinition(D))
519       Results.back().Definition =
520           makeLocation(ASTContext, nameLocation(*Def, SM), *MainFilePath);
521   }
522 
523   return Results;
524 }
525 
tokenSpelledAt(SourceLocation SpellingLoc,const syntax::TokenBuffer & TB)526 bool tokenSpelledAt(SourceLocation SpellingLoc, const syntax::TokenBuffer &TB) {
527   auto ExpandedTokens = TB.expandedTokens(
528       TB.sourceManager().getMacroArgExpandedLocation(SpellingLoc));
529   return !ExpandedTokens.empty();
530 }
531 
sourcePrefix(SourceLocation Loc,const SourceManager & SM)532 llvm::StringRef sourcePrefix(SourceLocation Loc, const SourceManager &SM) {
533   auto D = SM.getDecomposedLoc(Loc);
534   bool Invalid = false;
535   llvm::StringRef Buf = SM.getBufferData(D.first, &Invalid);
536   if (Invalid || D.second > Buf.size())
537     return "";
538   return Buf.substr(0, D.second);
539 }
540 
isDependentName(ASTNodeKind NodeKind)541 bool isDependentName(ASTNodeKind NodeKind) {
542   return NodeKind.isSame(ASTNodeKind::getFromNodeKind<OverloadExpr>()) ||
543          NodeKind.isSame(
544              ASTNodeKind::getFromNodeKind<CXXDependentScopeMemberExpr>()) ||
545          NodeKind.isSame(
546              ASTNodeKind::getFromNodeKind<DependentScopeDeclRefExpr>());
547 }
548 
549 } // namespace
550 
551 std::vector<LocatedSymbol>
locateSymbolTextually(const SpelledWord & Word,ParsedAST & AST,const SymbolIndex * Index,const std::string & MainFilePath,ASTNodeKind NodeKind)552 locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST,
553                       const SymbolIndex *Index, const std::string &MainFilePath,
554                       ASTNodeKind NodeKind) {
555   // Don't use heuristics if this is a real identifier, or not an
556   // identifier.
557   // Exception: dependent names, because those may have useful textual
558   // matches that AST-based heuristics cannot find.
559   if ((Word.ExpandedToken && !isDependentName(NodeKind)) ||
560       !Word.LikelyIdentifier || !Index)
561     return {};
562   // We don't want to handle words in string literals. (It'd be nice to list
563   // *allowed* token kinds explicitly, but comment Tokens aren't retained).
564   if (Word.PartOfSpelledToken &&
565       isStringLiteral(Word.PartOfSpelledToken->kind()))
566     return {};
567 
568   const auto &SM = AST.getSourceManager();
569   // Look up the selected word in the index.
570   FuzzyFindRequest Req;
571   Req.Query = Word.Text.str();
572   Req.ProximityPaths = {MainFilePath};
573   // Find the namespaces to query by lexing the file.
574   Req.Scopes =
575       visibleNamespaces(sourcePrefix(Word.Location, SM), AST.getLangOpts());
576   // FIXME: For extra strictness, consider AnyScope=false.
577   Req.AnyScope = true;
578   // We limit the results to 3 further below. This limit is to avoid fetching
579   // too much data, while still likely having enough for 3 results to remain
580   // after additional filtering.
581   Req.Limit = 10;
582   bool TooMany = false;
583   using ScoredLocatedSymbol = std::pair<float, LocatedSymbol>;
584   std::vector<ScoredLocatedSymbol> ScoredResults;
585   Index->fuzzyFind(Req, [&](const Symbol &Sym) {
586     // Only consider exact name matches, including case.
587     // This is to avoid too many false positives.
588     // We could relax this in the future (e.g. to allow for typos) if we make
589     // the query more accurate by other means.
590     if (Sym.Name != Word.Text)
591       return;
592 
593     // Exclude constructor results. They have the same name as the class,
594     // but we don't have enough context to prefer them over the class.
595     if (Sym.SymInfo.Kind == index::SymbolKind::Constructor)
596       return;
597 
598     auto MaybeDeclLoc =
599         indexToLSPLocation(Sym.CanonicalDeclaration, MainFilePath);
600     if (!MaybeDeclLoc) {
601       log("locateSymbolNamedTextuallyAt: {0}", MaybeDeclLoc.takeError());
602       return;
603     }
604     LocatedSymbol Located;
605     Located.PreferredDeclaration = *MaybeDeclLoc;
606     Located.Name = (Sym.Name + Sym.TemplateSpecializationArgs).str();
607     Located.ID = Sym.ID;
608     if (Sym.Definition) {
609       auto MaybeDefLoc = indexToLSPLocation(Sym.Definition, MainFilePath);
610       if (!MaybeDefLoc) {
611         log("locateSymbolNamedTextuallyAt: {0}", MaybeDefLoc.takeError());
612         return;
613       }
614       Located.PreferredDeclaration = *MaybeDefLoc;
615       Located.Definition = *MaybeDefLoc;
616     }
617 
618     if (ScoredResults.size() >= 5) {
619       // If we have more than 5 results, don't return anything,
620       // as confidence is too low.
621       // FIXME: Alternatively, try a stricter query?
622       TooMany = true;
623       return;
624     }
625 
626     SymbolQualitySignals Quality;
627     Quality.merge(Sym);
628     SymbolRelevanceSignals Relevance;
629     Relevance.Name = Sym.Name;
630     Relevance.Query = SymbolRelevanceSignals::Generic;
631     Relevance.merge(Sym);
632     auto Score = evaluateSymbolAndRelevance(Quality.evaluateHeuristics(),
633                                             Relevance.evaluateHeuristics());
634     dlog("locateSymbolNamedTextuallyAt: {0}{1} = {2}\n{3}{4}\n", Sym.Scope,
635          Sym.Name, Score, Quality, Relevance);
636 
637     ScoredResults.push_back({Score, std::move(Located)});
638   });
639 
640   if (TooMany) {
641     vlog("Heuristic index lookup for {0} returned too many candidates, ignored",
642          Word.Text);
643     return {};
644   }
645 
646   llvm::sort(ScoredResults,
647              [](const ScoredLocatedSymbol &A, const ScoredLocatedSymbol &B) {
648                return A.first > B.first;
649              });
650   std::vector<LocatedSymbol> Results;
651   for (auto &Res : std::move(ScoredResults))
652     Results.push_back(std::move(Res.second));
653   if (Results.empty())
654     vlog("No heuristic index definition for {0}", Word.Text);
655   else
656     log("Found definition heuristically in index for {0}", Word.Text);
657   return Results;
658 }
659 
findNearbyIdentifier(const SpelledWord & Word,const syntax::TokenBuffer & TB)660 const syntax::Token *findNearbyIdentifier(const SpelledWord &Word,
661                                           const syntax::TokenBuffer &TB) {
662   // Don't use heuristics if this is a real identifier.
663   // Unlikely identifiers are OK if they were used as identifiers nearby.
664   if (Word.ExpandedToken)
665     return nullptr;
666   // We don't want to handle words in string literals. (It'd be nice to list
667   // *allowed* token kinds explicitly, but comment Tokens aren't retained).
668   if (Word.PartOfSpelledToken &&
669       isStringLiteral(Word.PartOfSpelledToken->kind()))
670     return {};
671 
672   const SourceManager &SM = TB.sourceManager();
673   // We prefer the closest possible token, line-wise. Backwards is penalized.
674   // Ties are implicitly broken by traversal order (first-one-wins).
675   auto File = SM.getFileID(Word.Location);
676   unsigned WordLine = SM.getSpellingLineNumber(Word.Location);
677   auto Cost = [&](SourceLocation Loc) -> unsigned {
678     assert(SM.getFileID(Loc) == File && "spelled token in wrong file?");
679     unsigned Line = SM.getSpellingLineNumber(Loc);
680     return Line >= WordLine ? Line - WordLine : 2 * (WordLine - Line);
681   };
682   const syntax::Token *BestTok = nullptr;
683   unsigned BestCost = -1;
684   // Search bounds are based on word length:
685   // - forward: 2^N lines
686   // - backward: 2^(N-1) lines.
687   unsigned MaxDistance =
688       1U << std::min<unsigned>(Word.Text.size(),
689                                std::numeric_limits<unsigned>::digits - 1);
690   // Line number for SM.translateLineCol() should be one-based, also
691   // SM.translateLineCol() can handle line number greater than
692   // number of lines in the file.
693   // - LineMin = max(1, WordLine + 1 - 2^(N-1))
694   // - LineMax = WordLine + 1 + 2^N
695   unsigned LineMin =
696       WordLine + 1 <= MaxDistance / 2 ? 1 : WordLine + 1 - MaxDistance / 2;
697   unsigned LineMax = WordLine + 1 + MaxDistance;
698   SourceLocation LocMin = SM.translateLineCol(File, LineMin, 1);
699   assert(LocMin.isValid());
700   SourceLocation LocMax = SM.translateLineCol(File, LineMax, 1);
701   assert(LocMax.isValid());
702 
703   // Updates BestTok and BestCost if Tok is a good candidate.
704   // May return true if the cost is too high for this token.
705   auto Consider = [&](const syntax::Token &Tok) {
706     if (Tok.location() < LocMin || Tok.location() > LocMax)
707       return true; // we are too far from the word, break the outer loop.
708     if (!(Tok.kind() == tok::identifier && Tok.text(SM) == Word.Text))
709       return false;
710     // No point guessing the same location we started with.
711     if (Tok.location() == Word.Location)
712       return false;
713     // We've done cheap checks, compute cost so we can break the caller's loop.
714     unsigned TokCost = Cost(Tok.location());
715     if (TokCost >= BestCost)
716       return true; // causes the outer loop to break.
717     // Allow locations that might be part of the AST, and macros (even if empty)
718     // but not things like disabled preprocessor sections.
719     if (!(tokenSpelledAt(Tok.location(), TB) || TB.expansionStartingAt(&Tok)))
720       return false;
721     // We already verified this token is an improvement.
722     BestCost = TokCost;
723     BestTok = &Tok;
724     return false;
725   };
726   auto SpelledTokens = TB.spelledTokens(File);
727   // Find where the word occurred in the token stream, to search forward & back.
728   auto *I = llvm::partition_point(SpelledTokens, [&](const syntax::Token &T) {
729     assert(SM.getFileID(T.location()) == SM.getFileID(Word.Location));
730     return T.location() < Word.Location; // Comparison OK: same file.
731   });
732   // Search for matches after the cursor.
733   for (const syntax::Token &Tok : llvm::makeArrayRef(I, SpelledTokens.end()))
734     if (Consider(Tok))
735       break; // costs of later tokens are greater...
736   // Search for matches before the cursor.
737   for (const syntax::Token &Tok :
738        llvm::reverse(llvm::makeArrayRef(SpelledTokens.begin(), I)))
739     if (Consider(Tok))
740       break;
741 
742   if (BestTok)
743     vlog(
744         "Word {0} under cursor {1} isn't a token (after PP), trying nearby {2}",
745         Word.Text, Word.Location.printToString(SM),
746         BestTok->location().printToString(SM));
747 
748   return BestTok;
749 }
750 
locateSymbolAt(ParsedAST & AST,Position Pos,const SymbolIndex * Index)751 std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
752                                           const SymbolIndex *Index) {
753   const auto &SM = AST.getSourceManager();
754   auto MainFilePath =
755       getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
756   if (!MainFilePath) {
757     elog("Failed to get a path for the main file, so no references");
758     return {};
759   }
760 
761   if (auto File = locateFileReferent(Pos, AST, *MainFilePath))
762     return {std::move(*File)};
763 
764   auto CurLoc = sourceLocationInMainFile(SM, Pos);
765   if (!CurLoc) {
766     elog("locateSymbolAt failed to convert position to source location: {0}",
767          CurLoc.takeError());
768     return {};
769   }
770 
771   const syntax::Token *TouchedIdentifier = nullptr;
772   auto TokensTouchingCursor =
773       syntax::spelledTokensTouching(*CurLoc, AST.getTokens());
774   for (const syntax::Token &Tok : TokensTouchingCursor) {
775     if (Tok.kind() == tok::identifier) {
776       if (auto Macro = locateMacroReferent(Tok, AST, *MainFilePath))
777         // Don't look at the AST or index if we have a macro result.
778         // (We'd just return declarations referenced from the macro's
779         // expansion.)
780         return {*std::move(Macro)};
781 
782       TouchedIdentifier = &Tok;
783       break;
784     }
785 
786     if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) {
787       // go-to-definition on auto should find the definition of the deduced
788       // type, if possible
789       if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) {
790         auto LocSym = locateSymbolForType(AST, *Deduced);
791         if (!LocSym.empty())
792           return LocSym;
793       }
794     }
795   }
796 
797   ASTNodeKind NodeKind;
798   auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST,
799                                       *MainFilePath, Index, NodeKind);
800   if (!ASTResults.empty())
801     return ASTResults;
802 
803   // If the cursor can't be resolved directly, try fallback strategies.
804   auto Word =
805       SpelledWord::touching(*CurLoc, AST.getTokens(), AST.getLangOpts());
806   if (Word) {
807     // Is the same word nearby a real identifier that might refer to something?
808     if (const syntax::Token *NearbyIdent =
809             findNearbyIdentifier(*Word, AST.getTokens())) {
810       if (auto Macro = locateMacroReferent(*NearbyIdent, AST, *MainFilePath)) {
811         log("Found macro definition heuristically using nearby identifier {0}",
812             Word->Text);
813         return {*std::move(Macro)};
814       }
815       ASTResults = locateASTReferent(NearbyIdent->location(), NearbyIdent, AST,
816                                      *MainFilePath, Index, NodeKind);
817       if (!ASTResults.empty()) {
818         log("Found definition heuristically using nearby identifier {0}",
819             NearbyIdent->text(SM));
820         return ASTResults;
821       }
822       vlog("No definition found using nearby identifier {0} at {1}", Word->Text,
823            Word->Location.printToString(SM));
824     }
825     // No nearby word, or it didn't refer to anything either. Try the index.
826     auto TextualResults =
827         locateSymbolTextually(*Word, AST, Index, *MainFilePath, NodeKind);
828     if (!TextualResults.empty())
829       return TextualResults;
830   }
831 
832   return {};
833 }
834 
getDocumentLinks(ParsedAST & AST)835 std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) {
836   const auto &SM = AST.getSourceManager();
837   auto MainFilePath =
838       getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
839   if (!MainFilePath) {
840     elog("Failed to get a path for the main file, so no links");
841     return {};
842   }
843 
844   std::vector<DocumentLink> Result;
845   for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
846     if (Inc.Resolved.empty())
847       continue;
848     auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
849     const auto *HashTok = AST.getTokens().spelledTokenAt(HashLoc);
850     assert(HashTok && "got inclusion at wrong offset");
851     const auto *IncludeTok = std::next(HashTok);
852     const auto *FileTok = std::next(IncludeTok);
853     // FileTok->range is not sufficient here, as raw lexing wouldn't yield
854     // correct tokens for angled filenames. Hence we explicitly use
855     // Inc.Written's length.
856     auto FileRange =
857         syntax::FileRange(SM, FileTok->location(), Inc.Written.length())
858             .toCharRange(SM);
859 
860     Result.push_back(
861         DocumentLink({halfOpenToRange(SM, FileRange),
862                       URIForFile::canonicalize(Inc.Resolved, *MainFilePath)}));
863   }
864 
865   return Result;
866 }
867 
868 namespace {
869 
870 /// Collects references to symbols within the main file.
871 class ReferenceFinder : public index::IndexDataConsumer {
872 public:
873   struct Reference {
874     syntax::Token SpelledTok;
875     index::SymbolRoleSet Role;
876     SymbolID Target;
877 
rangeclang::clangd::__anond43782d30c11::ReferenceFinder::Reference878     Range range(const SourceManager &SM) const {
879       return halfOpenToRange(SM, SpelledTok.range(SM).toCharRange(SM));
880     }
881   };
882 
ReferenceFinder(const ParsedAST & AST,const llvm::ArrayRef<const NamedDecl * > Targets,bool PerToken)883   ReferenceFinder(const ParsedAST &AST,
884                   const llvm::ArrayRef<const NamedDecl *> Targets,
885                   bool PerToken)
886       : PerToken(PerToken), AST(AST) {
887     for (const NamedDecl *ND : Targets) {
888       const Decl *CD = ND->getCanonicalDecl();
889       TargetDeclToID[CD] = getSymbolID(CD);
890     }
891   }
892 
take()893   std::vector<Reference> take() && {
894     llvm::sort(References, [](const Reference &L, const Reference &R) {
895       auto LTok = L.SpelledTok.location();
896       auto RTok = R.SpelledTok.location();
897       return std::tie(LTok, L.Role) < std::tie(RTok, R.Role);
898     });
899     // We sometimes see duplicates when parts of the AST get traversed twice.
900     References.erase(std::unique(References.begin(), References.end(),
901                                  [](const Reference &L, const Reference &R) {
902                                    auto LTok = L.SpelledTok.location();
903                                    auto RTok = R.SpelledTok.location();
904                                    return std::tie(LTok, L.Role) ==
905                                           std::tie(RTok, R.Role);
906                                  }),
907                      References.end());
908     return std::move(References);
909   }
910 
911   bool
handleDeclOccurrence(const Decl * D,index::SymbolRoleSet Roles,llvm::ArrayRef<index::SymbolRelation> Relations,SourceLocation Loc,index::IndexDataConsumer::ASTNodeInfo ASTNode)912   handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
913                        llvm::ArrayRef<index::SymbolRelation> Relations,
914                        SourceLocation Loc,
915                        index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
916     auto DeclID = TargetDeclToID.find(D->getCanonicalDecl());
917     if (DeclID == TargetDeclToID.end())
918       return true;
919     const SourceManager &SM = AST.getSourceManager();
920     if (!isInsideMainFile(Loc, SM))
921       return true;
922     const auto &TB = AST.getTokens();
923 
924     llvm::SmallVector<SourceLocation, 1> Locs;
925     if (PerToken) {
926       // Check whether this is one of the few constructs where the reference
927       // can be split over several tokens.
928       if (auto *OME = llvm::dyn_cast_or_null<ObjCMessageExpr>(ASTNode.OrigE)) {
929         OME->getSelectorLocs(Locs);
930       } else if (auto *OMD =
931                      llvm::dyn_cast_or_null<ObjCMethodDecl>(ASTNode.OrigD)) {
932         OMD->getSelectorLocs(Locs);
933       }
934       // Sanity check: we expect the *first* token to match the reported loc.
935       // Otherwise, maybe it was e.g. some other kind of reference to a Decl.
936       if (!Locs.empty() && Locs.front() != Loc)
937         Locs.clear(); // First token doesn't match, assume our guess was wrong.
938     }
939     if (Locs.empty())
940       Locs.push_back(Loc);
941 
942     for (SourceLocation L : Locs) {
943       L = SM.getFileLoc(L);
944       if (const auto *Tok = TB.spelledTokenAt(L))
945         References.push_back({*Tok, Roles, DeclID->getSecond()});
946     }
947     return true;
948   }
949 
950 private:
951   bool PerToken; // If true, report 3 references for split ObjC selector names.
952   std::vector<Reference> References;
953   const ParsedAST &AST;
954   llvm::DenseMap<const Decl *, SymbolID> TargetDeclToID;
955 };
956 
957 std::vector<ReferenceFinder::Reference>
findRefs(const llvm::ArrayRef<const NamedDecl * > TargetDecls,ParsedAST & AST,bool PerToken)958 findRefs(const llvm::ArrayRef<const NamedDecl *> TargetDecls, ParsedAST &AST,
959          bool PerToken) {
960   ReferenceFinder RefFinder(AST, TargetDecls, PerToken);
961   index::IndexingOptions IndexOpts;
962   IndexOpts.SystemSymbolFilter =
963       index::IndexingOptions::SystemSymbolFilterKind::All;
964   IndexOpts.IndexFunctionLocals = true;
965   IndexOpts.IndexParametersInDeclarations = true;
966   IndexOpts.IndexTemplateParameters = true;
967   indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
968                      AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
969   return std::move(RefFinder).take();
970 }
971 
getFunctionBody(DynTypedNode N)972 const Stmt *getFunctionBody(DynTypedNode N) {
973   if (const auto *FD = N.get<FunctionDecl>())
974     return FD->getBody();
975   if (const auto *FD = N.get<BlockDecl>())
976     return FD->getBody();
977   if (const auto *FD = N.get<LambdaExpr>())
978     return FD->getBody();
979   if (const auto *FD = N.get<ObjCMethodDecl>())
980     return FD->getBody();
981   return nullptr;
982 }
983 
getLoopBody(DynTypedNode N)984 const Stmt *getLoopBody(DynTypedNode N) {
985   if (const auto *LS = N.get<ForStmt>())
986     return LS->getBody();
987   if (const auto *LS = N.get<CXXForRangeStmt>())
988     return LS->getBody();
989   if (const auto *LS = N.get<WhileStmt>())
990     return LS->getBody();
991   if (const auto *LS = N.get<DoStmt>())
992     return LS->getBody();
993   return nullptr;
994 }
995 
996 // AST traversal to highlight control flow statements under some root.
997 // Once we hit further control flow we prune the tree (or at least restrict
998 // what we highlight) so we capture e.g. breaks from the outer loop only.
999 class FindControlFlow : public RecursiveASTVisitor<FindControlFlow> {
1000   // Types of control-flow statements we might highlight.
1001   enum Target {
1002     Break = 1,
1003     Continue = 2,
1004     Return = 4,
1005     Case = 8,
1006     Throw = 16,
1007     Goto = 32,
1008     All = Break | Continue | Return | Case | Throw | Goto,
1009   };
1010   int Ignore = 0;     // bitmask of Target - what are we *not* highlighting?
1011   SourceRange Bounds; // Half-open, restricts reported targets.
1012   std::vector<SourceLocation> &Result;
1013   const SourceManager &SM;
1014 
1015   // Masks out targets for a traversal into D.
1016   // Traverses the subtree using Delegate() if any targets remain.
1017   template <typename Func>
filterAndTraverse(DynTypedNode D,const Func & Delegate)1018   bool filterAndTraverse(DynTypedNode D, const Func &Delegate) {
1019     auto RestoreIgnore = llvm::make_scope_exit(
1020         [OldIgnore(Ignore), this] { Ignore = OldIgnore; });
1021     if (getFunctionBody(D))
1022       Ignore = All;
1023     else if (getLoopBody(D))
1024       Ignore |= Continue | Break;
1025     else if (D.get<SwitchStmt>())
1026       Ignore |= Break | Case;
1027     // Prune tree if we're not looking for anything.
1028     return (Ignore == All) ? true : Delegate();
1029   }
1030 
found(Target T,SourceLocation Loc)1031   void found(Target T, SourceLocation Loc) {
1032     if (T & Ignore)
1033       return;
1034     if (SM.isBeforeInTranslationUnit(Loc, Bounds.getBegin()) ||
1035         SM.isBeforeInTranslationUnit(Bounds.getEnd(), Loc))
1036       return;
1037     Result.push_back(Loc);
1038   }
1039 
1040 public:
FindControlFlow(SourceRange Bounds,std::vector<SourceLocation> & Result,const SourceManager & SM)1041   FindControlFlow(SourceRange Bounds, std::vector<SourceLocation> &Result,
1042                   const SourceManager &SM)
1043       : Bounds(Bounds), Result(Result), SM(SM) {}
1044 
1045   // When traversing function or loops, limit targets to those that still
1046   // refer to the original root.
TraverseDecl(Decl * D)1047   bool TraverseDecl(Decl *D) {
1048     return !D || filterAndTraverse(DynTypedNode::create(*D), [&] {
1049       return RecursiveASTVisitor::TraverseDecl(D);
1050     });
1051   }
TraverseStmt(Stmt * S)1052   bool TraverseStmt(Stmt *S) {
1053     return !S || filterAndTraverse(DynTypedNode::create(*S), [&] {
1054       return RecursiveASTVisitor::TraverseStmt(S);
1055     });
1056   }
1057 
1058   // Add leaves that we found and want.
VisitReturnStmt(ReturnStmt * R)1059   bool VisitReturnStmt(ReturnStmt *R) {
1060     found(Return, R->getReturnLoc());
1061     return true;
1062   }
VisitBreakStmt(BreakStmt * B)1063   bool VisitBreakStmt(BreakStmt *B) {
1064     found(Break, B->getBreakLoc());
1065     return true;
1066   }
VisitContinueStmt(ContinueStmt * C)1067   bool VisitContinueStmt(ContinueStmt *C) {
1068     found(Continue, C->getContinueLoc());
1069     return true;
1070   }
VisitSwitchCase(SwitchCase * C)1071   bool VisitSwitchCase(SwitchCase *C) {
1072     found(Case, C->getKeywordLoc());
1073     return true;
1074   }
VisitCXXThrowExpr(CXXThrowExpr * T)1075   bool VisitCXXThrowExpr(CXXThrowExpr *T) {
1076     found(Throw, T->getThrowLoc());
1077     return true;
1078   }
VisitGotoStmt(GotoStmt * G)1079   bool VisitGotoStmt(GotoStmt *G) {
1080     // Goto is interesting if its target is outside the root.
1081     if (const auto *LD = G->getLabel()) {
1082       if (SM.isBeforeInTranslationUnit(LD->getLocation(), Bounds.getBegin()) ||
1083           SM.isBeforeInTranslationUnit(Bounds.getEnd(), LD->getLocation()))
1084         found(Goto, G->getGotoLoc());
1085     }
1086     return true;
1087   }
1088 };
1089 
1090 // Given a location within a switch statement, return the half-open range that
1091 // covers the case it's contained in.
1092 // We treat `case X: case Y: ...` as one case, and assume no other fallthrough.
findCaseBounds(const SwitchStmt & Switch,SourceLocation Loc,const SourceManager & SM)1093 SourceRange findCaseBounds(const SwitchStmt &Switch, SourceLocation Loc,
1094                            const SourceManager &SM) {
1095   // Cases are not stored in order, sort them first.
1096   // (In fact they seem to be stored in reverse order, don't rely on this)
1097   std::vector<const SwitchCase *> Cases;
1098   for (const SwitchCase *Case = Switch.getSwitchCaseList(); Case;
1099        Case = Case->getNextSwitchCase())
1100     Cases.push_back(Case);
1101   llvm::sort(Cases, [&](const SwitchCase *L, const SwitchCase *R) {
1102     return SM.isBeforeInTranslationUnit(L->getKeywordLoc(), R->getKeywordLoc());
1103   });
1104 
1105   // Find the first case after the target location, the end of our range.
1106   auto CaseAfter = llvm::partition_point(Cases, [&](const SwitchCase *C) {
1107     return !SM.isBeforeInTranslationUnit(Loc, C->getKeywordLoc());
1108   });
1109   SourceLocation End = CaseAfter == Cases.end() ? Switch.getEndLoc()
1110                                                 : (*CaseAfter)->getKeywordLoc();
1111 
1112   // Our target can be before the first case - cases are optional!
1113   if (CaseAfter == Cases.begin())
1114     return SourceRange(Switch.getBeginLoc(), End);
1115   // The start of our range is usually the previous case, but...
1116   auto CaseBefore = std::prev(CaseAfter);
1117   // ... rewind CaseBefore to the first in a `case A: case B: ...` sequence.
1118   while (CaseBefore != Cases.begin() &&
1119          (*std::prev(CaseBefore))->getSubStmt() == *CaseBefore)
1120     --CaseBefore;
1121   return SourceRange((*CaseBefore)->getKeywordLoc(), End);
1122 }
1123 
1124 // Returns the locations of control flow statements related to N. e.g.:
1125 //   for    => branches: break/continue/return/throw
1126 //   break  => controlling loop (forwhile/do), and its related control flow
1127 //   return => all returns/throws from the same function
1128 // When an inner block is selected, we include branches bound to outer blocks
1129 // as these are exits from the inner block. e.g. return in a for loop.
1130 // FIXME: We don't analyze catch blocks, throw is treated the same as return.
relatedControlFlow(const SelectionTree::Node & N)1131 std::vector<SourceLocation> relatedControlFlow(const SelectionTree::Node &N) {
1132   const SourceManager &SM =
1133       N.getDeclContext().getParentASTContext().getSourceManager();
1134   std::vector<SourceLocation> Result;
1135 
1136   // First, check if we're at a node that can resolve to a root.
1137   enum class Cur { None, Break, Continue, Return, Case, Throw } Cursor;
1138   if (N.ASTNode.get<BreakStmt>()) {
1139     Cursor = Cur::Break;
1140   } else if (N.ASTNode.get<ContinueStmt>()) {
1141     Cursor = Cur::Continue;
1142   } else if (N.ASTNode.get<ReturnStmt>()) {
1143     Cursor = Cur::Return;
1144   } else if (N.ASTNode.get<CXXThrowExpr>()) {
1145     Cursor = Cur::Throw;
1146   } else if (N.ASTNode.get<SwitchCase>()) {
1147     Cursor = Cur::Case;
1148   } else if (const GotoStmt *GS = N.ASTNode.get<GotoStmt>()) {
1149     // We don't know what root to associate with, but highlight the goto/label.
1150     Result.push_back(GS->getGotoLoc());
1151     if (const auto *LD = GS->getLabel())
1152       Result.push_back(LD->getLocation());
1153     Cursor = Cur::None;
1154   } else {
1155     Cursor = Cur::None;
1156   }
1157 
1158   const Stmt *Root = nullptr; // Loop or function body to traverse.
1159   SourceRange Bounds;
1160   // Look up the tree for a root (or just at this node if we didn't find a leaf)
1161   for (const auto *P = &N; P; P = P->Parent) {
1162     // return associates with enclosing function
1163     if (const Stmt *FunctionBody = getFunctionBody(P->ASTNode)) {
1164       if (Cursor == Cur::Return || Cursor == Cur::Throw) {
1165         Root = FunctionBody;
1166       }
1167       break; // other leaves don't cross functions.
1168     }
1169     // break/continue associate with enclosing loop.
1170     if (const Stmt *LoopBody = getLoopBody(P->ASTNode)) {
1171       if (Cursor == Cur::None || Cursor == Cur::Break ||
1172           Cursor == Cur::Continue) {
1173         Root = LoopBody;
1174         // Highlight the loop keyword itself.
1175         // FIXME: for do-while, this only covers the `do`..
1176         Result.push_back(P->ASTNode.getSourceRange().getBegin());
1177         break;
1178       }
1179     }
1180     // For switches, users think of case statements as control flow blocks.
1181     // We highlight only occurrences surrounded by the same case.
1182     // We don't detect fallthrough (other than 'case X, case Y').
1183     if (const auto *SS = P->ASTNode.get<SwitchStmt>()) {
1184       if (Cursor == Cur::Break || Cursor == Cur::Case) {
1185         Result.push_back(SS->getSwitchLoc()); // Highlight the switch.
1186         Root = SS->getBody();
1187         // Limit to enclosing case, if there is one.
1188         Bounds = findCaseBounds(*SS, N.ASTNode.getSourceRange().getBegin(), SM);
1189         break;
1190       }
1191     }
1192     // If we didn't start at some interesting node, we're done.
1193     if (Cursor == Cur::None)
1194       break;
1195   }
1196   if (Root) {
1197     if (!Bounds.isValid())
1198       Bounds = Root->getSourceRange();
1199     FindControlFlow(Bounds, Result, SM).TraverseStmt(const_cast<Stmt *>(Root));
1200   }
1201   return Result;
1202 }
1203 
toHighlight(const ReferenceFinder::Reference & Ref,const SourceManager & SM)1204 DocumentHighlight toHighlight(const ReferenceFinder::Reference &Ref,
1205                               const SourceManager &SM) {
1206   DocumentHighlight DH;
1207   DH.range = Ref.range(SM);
1208   if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
1209     DH.kind = DocumentHighlightKind::Write;
1210   else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
1211     DH.kind = DocumentHighlightKind::Read;
1212   else
1213     DH.kind = DocumentHighlightKind::Text;
1214   return DH;
1215 }
1216 
toHighlight(SourceLocation Loc,const syntax::TokenBuffer & TB)1217 llvm::Optional<DocumentHighlight> toHighlight(SourceLocation Loc,
1218                                               const syntax::TokenBuffer &TB) {
1219   Loc = TB.sourceManager().getFileLoc(Loc);
1220   if (const auto *Tok = TB.spelledTokenAt(Loc)) {
1221     DocumentHighlight Result;
1222     Result.range = halfOpenToRange(
1223         TB.sourceManager(),
1224         CharSourceRange::getCharRange(Tok->location(), Tok->endLocation()));
1225     return Result;
1226   }
1227   return llvm::None;
1228 }
1229 
1230 } // namespace
1231 
findDocumentHighlights(ParsedAST & AST,Position Pos)1232 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
1233                                                       Position Pos) {
1234   const SourceManager &SM = AST.getSourceManager();
1235   // FIXME: show references to macro within file?
1236   auto CurLoc = sourceLocationInMainFile(SM, Pos);
1237   if (!CurLoc) {
1238     llvm::consumeError(CurLoc.takeError());
1239     return {};
1240   }
1241   std::vector<DocumentHighlight> Result;
1242   auto TryTree = [&](SelectionTree ST) {
1243     if (const SelectionTree::Node *N = ST.commonAncestor()) {
1244       DeclRelationSet Relations =
1245           DeclRelation::TemplatePattern | DeclRelation::Alias;
1246       auto TargetDecls =
1247           targetDecl(N->ASTNode, Relations, AST.getHeuristicResolver());
1248       if (!TargetDecls.empty()) {
1249         // FIXME: we may get multiple DocumentHighlights with the same location
1250         // and different kinds, deduplicate them.
1251         for (const auto &Ref : findRefs(TargetDecls, AST, /*PerToken=*/true))
1252           Result.push_back(toHighlight(Ref, SM));
1253         return true;
1254       }
1255       auto ControlFlow = relatedControlFlow(*N);
1256       if (!ControlFlow.empty()) {
1257         for (SourceLocation Loc : ControlFlow)
1258           if (auto Highlight = toHighlight(Loc, AST.getTokens()))
1259             Result.push_back(std::move(*Highlight));
1260         return true;
1261       }
1262     }
1263     return false;
1264   };
1265 
1266   unsigned Offset =
1267       AST.getSourceManager().getDecomposedSpellingLoc(*CurLoc).second;
1268   SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset,
1269                             Offset, TryTree);
1270   return Result;
1271 }
1272 
findImplementations(ParsedAST & AST,Position Pos,const SymbolIndex * Index)1273 std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
1274                                                const SymbolIndex *Index) {
1275   // We rely on index to find the implementations in subclasses.
1276   // FIXME: Index can be stale, so we may loose some latest results from the
1277   // main file.
1278   if (!Index)
1279     return {};
1280   const SourceManager &SM = AST.getSourceManager();
1281   auto MainFilePath =
1282       getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
1283   if (!MainFilePath) {
1284     elog("Failed to get a path for the main file, so no implementations.");
1285     return {};
1286   }
1287   auto CurLoc = sourceLocationInMainFile(SM, Pos);
1288   if (!CurLoc) {
1289     elog("Failed to convert position to source location: {0}",
1290          CurLoc.takeError());
1291     return {};
1292   }
1293   DeclRelationSet Relations =
1294       DeclRelation::TemplatePattern | DeclRelation::Alias;
1295   llvm::DenseSet<SymbolID> IDs;
1296   RelationKind QueryKind = RelationKind::OverriddenBy;
1297   for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations)) {
1298     if (const auto *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
1299       if (CXXMD->isVirtual()) {
1300         IDs.insert(getSymbolID(ND));
1301         QueryKind = RelationKind::OverriddenBy;
1302       }
1303     } else if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
1304       IDs.insert(getSymbolID(RD));
1305       QueryKind = RelationKind::BaseOf;
1306     }
1307   }
1308   return findImplementors(std::move(IDs), QueryKind, Index, *MainFilePath);
1309 }
1310 
1311 namespace {
1312 // Recursively finds all the overridden methods of `CMD` in complete type
1313 // hierarchy.
getOverriddenMethods(const CXXMethodDecl * CMD,llvm::DenseSet<SymbolID> & OverriddenMethods)1314 void getOverriddenMethods(const CXXMethodDecl *CMD,
1315                           llvm::DenseSet<SymbolID> &OverriddenMethods) {
1316   if (!CMD)
1317     return;
1318   for (const CXXMethodDecl *Base : CMD->overridden_methods()) {
1319     if (auto ID = getSymbolID(Base))
1320       OverriddenMethods.insert(ID);
1321     getOverriddenMethods(Base, OverriddenMethods);
1322   }
1323 }
1324 } // namespace
1325 
findReferences(ParsedAST & AST,Position Pos,uint32_t Limit,const SymbolIndex * Index)1326 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
1327                                 const SymbolIndex *Index) {
1328   ReferencesResult Results;
1329   const SourceManager &SM = AST.getSourceManager();
1330   auto MainFilePath =
1331       getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
1332   if (!MainFilePath) {
1333     elog("Failed to get a path for the main file, so no references");
1334     return Results;
1335   }
1336   auto URIMainFile = URIForFile::canonicalize(*MainFilePath, *MainFilePath);
1337   auto CurLoc = sourceLocationInMainFile(SM, Pos);
1338   if (!CurLoc) {
1339     llvm::consumeError(CurLoc.takeError());
1340     return {};
1341   }
1342 
1343   llvm::DenseSet<SymbolID> IDsToQuery, OverriddenMethods;
1344 
1345   const auto *IdentifierAtCursor =
1346       syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens());
1347   llvm::Optional<DefinedMacro> Macro;
1348   if (IdentifierAtCursor)
1349     Macro = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor());
1350   if (Macro) {
1351     // Handle references to macro.
1352     if (auto MacroSID = getSymbolID(Macro->Name, Macro->Info, SM)) {
1353       // Collect macro references from main file.
1354       const auto &IDToRefs = AST.getMacros().MacroRefs;
1355       auto Refs = IDToRefs.find(MacroSID);
1356       if (Refs != IDToRefs.end()) {
1357         for (const auto &Ref : Refs->second) {
1358           ReferencesResult::Reference Result;
1359           Result.Loc.range = Ref.Rng;
1360           Result.Loc.uri = URIMainFile;
1361           if (Ref.IsDefinition) {
1362             Result.Attributes |= ReferencesResult::Declaration;
1363             Result.Attributes |= ReferencesResult::Definition;
1364           }
1365           Results.References.push_back(std::move(Result));
1366         }
1367       }
1368       IDsToQuery.insert(MacroSID);
1369     }
1370   } else {
1371     // Handle references to Decls.
1372 
1373     DeclRelationSet Relations =
1374         DeclRelation::TemplatePattern | DeclRelation::Alias;
1375     std::vector<const NamedDecl *> Decls =
1376         getDeclAtPosition(AST, *CurLoc, Relations);
1377     llvm::SmallVector<const NamedDecl *> TargetsInMainFile;
1378     for (const NamedDecl *D : Decls) {
1379       auto ID = getSymbolID(D);
1380       if (!ID)
1381         continue;
1382       TargetsInMainFile.push_back(D);
1383       // Not all symbols can be referenced from outside (e.g. function-locals).
1384       // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
1385       // we know this file isn't a header. The details might be tricky.
1386       if (D->getParentFunctionOrMethod())
1387         continue;
1388       IDsToQuery.insert(ID);
1389     }
1390 
1391     RelationsRequest OverriddenBy;
1392     if (Index) {
1393       OverriddenBy.Predicate = RelationKind::OverriddenBy;
1394       for (const NamedDecl *ND : Decls) {
1395         // Special case: For virtual methods, report decl/def of overrides and
1396         // references to all overridden methods in complete type hierarchy.
1397         if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
1398           if (CMD->isVirtual()) {
1399             if (auto ID = getSymbolID(CMD))
1400               OverriddenBy.Subjects.insert(ID);
1401             getOverriddenMethods(CMD, OverriddenMethods);
1402           }
1403         }
1404       }
1405     }
1406 
1407     // We traverse the AST to find references in the main file.
1408     auto MainFileRefs = findRefs(TargetsInMainFile, AST, /*PerToken=*/false);
1409     // We may get multiple refs with the same location and different Roles, as
1410     // cross-reference is only interested in locations, we deduplicate them
1411     // by the location to avoid emitting duplicated locations.
1412     MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(),
1413                                    [](const ReferenceFinder::Reference &L,
1414                                       const ReferenceFinder::Reference &R) {
1415                                      return L.SpelledTok.location() ==
1416                                             R.SpelledTok.location();
1417                                    }),
1418                        MainFileRefs.end());
1419     for (const auto &Ref : MainFileRefs) {
1420       ReferencesResult::Reference Result;
1421       Result.Loc.range = Ref.range(SM);
1422       Result.Loc.uri = URIMainFile;
1423       if (Ref.Role & static_cast<unsigned>(index::SymbolRole::Declaration))
1424         Result.Attributes |= ReferencesResult::Declaration;
1425       // clang-index doesn't report definitions as declarations, but they are.
1426       if (Ref.Role & static_cast<unsigned>(index::SymbolRole::Definition))
1427         Result.Attributes |=
1428             ReferencesResult::Definition | ReferencesResult::Declaration;
1429       Results.References.push_back(std::move(Result));
1430     }
1431     // Add decl/def of overridding methods.
1432     if (Index && !OverriddenBy.Subjects.empty()) {
1433       Index->relations(OverriddenBy, [&](const SymbolID &Subject,
1434                                          const Symbol &Object) {
1435         if (Limit && Results.References.size() >= Limit) {
1436           Results.HasMore = true;
1437           return;
1438         }
1439         const auto LSPLocDecl =
1440             toLSPLocation(Object.CanonicalDeclaration, *MainFilePath);
1441         const auto LSPLocDef = toLSPLocation(Object.Definition, *MainFilePath);
1442         if (LSPLocDecl && LSPLocDecl != LSPLocDef) {
1443           ReferencesResult::Reference Result;
1444           Result.Loc = std::move(*LSPLocDecl);
1445           Result.Attributes =
1446               ReferencesResult::Declaration | ReferencesResult::Override;
1447           Results.References.push_back(std::move(Result));
1448         }
1449         if (LSPLocDef) {
1450           ReferencesResult::Reference Result;
1451           Result.Loc = std::move(*LSPLocDef);
1452           Result.Attributes = ReferencesResult::Declaration |
1453                               ReferencesResult::Definition |
1454                               ReferencesResult::Override;
1455           Results.References.push_back(std::move(Result));
1456         }
1457       });
1458     }
1459   }
1460   // Now query the index for references from other files.
1461   auto QueryIndex = [&](llvm::DenseSet<SymbolID> IDs, bool AllowAttributes,
1462                         bool AllowMainFileSymbols) {
1463     if (IDs.empty() || !Index || Results.HasMore)
1464       return;
1465     RefsRequest Req;
1466     Req.IDs = std::move(IDs);
1467     if (Limit) {
1468       if (Limit < Results.References.size()) {
1469         // We've already filled our quota, still check the index to correctly
1470         // return the `HasMore` info.
1471         Req.Limit = 0;
1472       } else {
1473         // Query index only for the remaining size.
1474         Req.Limit = Limit - Results.References.size();
1475       }
1476     }
1477     Results.HasMore |= Index->refs(Req, [&](const Ref &R) {
1478       auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
1479       // Avoid indexed results for the main file - the AST is authoritative.
1480       if (!LSPLoc ||
1481           (!AllowMainFileSymbols && LSPLoc->uri.file() == *MainFilePath))
1482         return;
1483       ReferencesResult::Reference Result;
1484       Result.Loc = std::move(*LSPLoc);
1485       if (AllowAttributes) {
1486         if ((R.Kind & RefKind::Declaration) == RefKind::Declaration)
1487           Result.Attributes |= ReferencesResult::Declaration;
1488         // FIXME: our index should definitely store def | decl separately!
1489         if ((R.Kind & RefKind::Definition) == RefKind::Definition)
1490           Result.Attributes |=
1491               ReferencesResult::Declaration | ReferencesResult::Definition;
1492       }
1493       Results.References.push_back(std::move(Result));
1494     });
1495   };
1496   QueryIndex(std::move(IDsToQuery), /*AllowAttributes=*/true,
1497              /*AllowMainFileSymbols=*/false);
1498   // For a virtual method: Occurrences of BaseMethod should be treated as refs
1499   // and not as decl/def. Allow symbols from main file since AST does not report
1500   // these.
1501   QueryIndex(std::move(OverriddenMethods), /*AllowAttributes=*/false,
1502              /*AllowMainFileSymbols=*/true);
1503   return Results;
1504 }
1505 
getSymbolInfo(ParsedAST & AST,Position Pos)1506 std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
1507   const SourceManager &SM = AST.getSourceManager();
1508   auto CurLoc = sourceLocationInMainFile(SM, Pos);
1509   if (!CurLoc) {
1510     llvm::consumeError(CurLoc.takeError());
1511     return {};
1512   }
1513 
1514   std::vector<SymbolDetails> Results;
1515 
1516   // We also want the targets of using-decls, so we include
1517   // DeclRelation::Underlying.
1518   DeclRelationSet Relations = DeclRelation::TemplatePattern |
1519                               DeclRelation::Alias | DeclRelation::Underlying;
1520   for (const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) {
1521     SymbolDetails NewSymbol;
1522     std::string QName = printQualifiedName(*D);
1523     auto SplitQName = splitQualifiedName(QName);
1524     NewSymbol.containerName = std::string(SplitQName.first);
1525     NewSymbol.name = std::string(SplitQName.second);
1526 
1527     if (NewSymbol.containerName.empty()) {
1528       if (const auto *ParentND =
1529               dyn_cast_or_null<NamedDecl>(D->getDeclContext()))
1530         NewSymbol.containerName = printQualifiedName(*ParentND);
1531     }
1532     llvm::SmallString<32> USR;
1533     if (!index::generateUSRForDecl(D, USR)) {
1534       NewSymbol.USR = std::string(USR.str());
1535       NewSymbol.ID = SymbolID(NewSymbol.USR);
1536     }
1537     Results.push_back(std::move(NewSymbol));
1538   }
1539 
1540   const auto *IdentifierAtCursor =
1541       syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens());
1542   if (!IdentifierAtCursor)
1543     return Results;
1544 
1545   if (auto M = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor())) {
1546     SymbolDetails NewMacro;
1547     NewMacro.name = std::string(M->Name);
1548     llvm::SmallString<32> USR;
1549     if (!index::generateUSRForMacro(NewMacro.name, M->Info->getDefinitionLoc(),
1550                                     SM, USR)) {
1551       NewMacro.USR = std::string(USR.str());
1552       NewMacro.ID = SymbolID(NewMacro.USR);
1553     }
1554     Results.push_back(std::move(NewMacro));
1555   }
1556 
1557   return Results;
1558 }
1559 
operator <<(llvm::raw_ostream & OS,const LocatedSymbol & S)1560 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) {
1561   OS << S.Name << ": " << S.PreferredDeclaration;
1562   if (S.Definition)
1563     OS << " def=" << *S.Definition;
1564   return OS;
1565 }
1566 
operator <<(llvm::raw_ostream & OS,const ReferencesResult::Reference & R)1567 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1568                               const ReferencesResult::Reference &R) {
1569   OS << R.Loc;
1570   if (R.Attributes & ReferencesResult::Declaration)
1571     OS << " [decl]";
1572   if (R.Attributes & ReferencesResult::Definition)
1573     OS << " [def]";
1574   if (R.Attributes & ReferencesResult::Override)
1575     OS << " [override]";
1576   return OS;
1577 }
1578 
1579 template <typename HierarchyItem>
declToHierarchyItem(const NamedDecl & ND)1580 static llvm::Optional<HierarchyItem> declToHierarchyItem(const NamedDecl &ND) {
1581   ASTContext &Ctx = ND.getASTContext();
1582   auto &SM = Ctx.getSourceManager();
1583   SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager());
1584   SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
1585   SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
1586   const auto DeclRange =
1587       toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc});
1588   if (!DeclRange)
1589     return llvm::None;
1590   auto FilePath =
1591       getCanonicalPath(SM.getFileEntryForID(SM.getFileID(NameLoc)), SM);
1592   auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
1593   if (!FilePath || !TUPath)
1594     return llvm::None; // Not useful without a uri.
1595 
1596   Position NameBegin = sourceLocToPosition(SM, NameLoc);
1597   Position NameEnd = sourceLocToPosition(
1598       SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
1599 
1600   index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
1601   // FIXME: This is not classifying constructors, destructors and operators
1602   // correctly.
1603   SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
1604 
1605   HierarchyItem HI;
1606   HI.name = printName(Ctx, ND);
1607   HI.kind = SK;
1608   HI.range = Range{sourceLocToPosition(SM, DeclRange->getBegin()),
1609                    sourceLocToPosition(SM, DeclRange->getEnd())};
1610   HI.selectionRange = Range{NameBegin, NameEnd};
1611   if (!HI.range.contains(HI.selectionRange)) {
1612     // 'selectionRange' must be contained in 'range', so in cases where clang
1613     // reports unrelated ranges we need to reconcile somehow.
1614     HI.range = HI.selectionRange;
1615   }
1616 
1617   HI.uri = URIForFile::canonicalize(*FilePath, *TUPath);
1618 
1619   return HI;
1620 }
1621 
1622 static llvm::Optional<TypeHierarchyItem>
declToTypeHierarchyItem(const NamedDecl & ND,llvm::StringRef TUPath)1623 declToTypeHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
1624   auto Result = declToHierarchyItem<TypeHierarchyItem>(ND);
1625   if (Result) {
1626     Result->deprecated = ND.isDeprecated();
1627     // Compute the SymbolID and store it in the 'data' field.
1628     // This allows typeHierarchy/resolve to be used to
1629     // resolve children of items returned in a previous request
1630     // for parents.
1631     Result->data.symbolID = getSymbolID(&ND);
1632   }
1633   return Result;
1634 }
1635 
1636 static llvm::Optional<CallHierarchyItem>
declToCallHierarchyItem(const NamedDecl & ND)1637 declToCallHierarchyItem(const NamedDecl &ND) {
1638   auto Result = declToHierarchyItem<CallHierarchyItem>(ND);
1639   if (!Result)
1640     return Result;
1641   if (ND.isDeprecated())
1642     Result->tags.push_back(SymbolTag::Deprecated);
1643   if (auto ID = getSymbolID(&ND))
1644     Result->data = ID.str();
1645   return Result;
1646 }
1647 
1648 template <typename HierarchyItem>
symbolToHierarchyItem(const Symbol & S,PathRef TUPath)1649 static llvm::Optional<HierarchyItem> symbolToHierarchyItem(const Symbol &S,
1650                                                            PathRef TUPath) {
1651   auto Loc = symbolToLocation(S, TUPath);
1652   if (!Loc) {
1653     elog("Failed to convert symbol to hierarchy item: {0}", Loc.takeError());
1654     return llvm::None;
1655   }
1656   HierarchyItem HI;
1657   HI.name = std::string(S.Name);
1658   HI.kind = indexSymbolKindToSymbolKind(S.SymInfo.Kind);
1659   HI.selectionRange = Loc->range;
1660   // FIXME: Populate 'range' correctly
1661   // (https://github.com/clangd/clangd/issues/59).
1662   HI.range = HI.selectionRange;
1663   HI.uri = Loc->uri;
1664 
1665   return HI;
1666 }
1667 
1668 static llvm::Optional<TypeHierarchyItem>
symbolToTypeHierarchyItem(const Symbol & S,PathRef TUPath)1669 symbolToTypeHierarchyItem(const Symbol &S, PathRef TUPath) {
1670   auto Result = symbolToHierarchyItem<TypeHierarchyItem>(S, TUPath);
1671   if (Result) {
1672     Result->deprecated = (S.Flags & Symbol::Deprecated);
1673     Result->data.symbolID = S.ID;
1674   }
1675   return Result;
1676 }
1677 
1678 static llvm::Optional<CallHierarchyItem>
symbolToCallHierarchyItem(const Symbol & S,PathRef TUPath)1679 symbolToCallHierarchyItem(const Symbol &S, PathRef TUPath) {
1680   auto Result = symbolToHierarchyItem<CallHierarchyItem>(S, TUPath);
1681   if (!Result)
1682     return Result;
1683   Result->data = S.ID.str();
1684   if (S.Flags & Symbol::Deprecated)
1685     Result->tags.push_back(SymbolTag::Deprecated);
1686   return Result;
1687 }
1688 
fillSubTypes(const SymbolID & ID,std::vector<TypeHierarchyItem> & SubTypes,const SymbolIndex * Index,int Levels,PathRef TUPath)1689 static void fillSubTypes(const SymbolID &ID,
1690                          std::vector<TypeHierarchyItem> &SubTypes,
1691                          const SymbolIndex *Index, int Levels, PathRef TUPath) {
1692   RelationsRequest Req;
1693   Req.Subjects.insert(ID);
1694   Req.Predicate = RelationKind::BaseOf;
1695   Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
1696     if (Optional<TypeHierarchyItem> ChildSym =
1697             symbolToTypeHierarchyItem(Object, TUPath)) {
1698       if (Levels > 1) {
1699         ChildSym->children.emplace();
1700         fillSubTypes(Object.ID, *ChildSym->children, Index, Levels - 1, TUPath);
1701       }
1702       SubTypes.emplace_back(std::move(*ChildSym));
1703     }
1704   });
1705 }
1706 
1707 using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>;
1708 
1709 // Extracts parents from AST and populates the type hierarchy item.
fillSuperTypes(const CXXRecordDecl & CXXRD,llvm::StringRef TUPath,TypeHierarchyItem & Item,RecursionProtectionSet & RPSet)1710 static void fillSuperTypes(const CXXRecordDecl &CXXRD, llvm::StringRef TUPath,
1711                            TypeHierarchyItem &Item,
1712                            RecursionProtectionSet &RPSet) {
1713   Item.parents.emplace();
1714   Item.data.parents.emplace();
1715   // typeParents() will replace dependent template specializations
1716   // with their class template, so to avoid infinite recursion for
1717   // certain types of hierarchies, keep the templates encountered
1718   // along the parent chain in a set, and stop the recursion if one
1719   // starts to repeat.
1720   auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr;
1721   if (Pattern) {
1722     if (!RPSet.insert(Pattern).second) {
1723       return;
1724     }
1725   }
1726 
1727   for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) {
1728     if (Optional<TypeHierarchyItem> ParentSym =
1729             declToTypeHierarchyItem(*ParentDecl, TUPath)) {
1730       fillSuperTypes(*ParentDecl, TUPath, *ParentSym, RPSet);
1731       Item.data.parents->emplace_back(ParentSym->data);
1732       Item.parents->emplace_back(std::move(*ParentSym));
1733     }
1734   }
1735 
1736   if (Pattern) {
1737     RPSet.erase(Pattern);
1738   }
1739 }
1740 
findRecordTypeAt(ParsedAST & AST,Position Pos)1741 std::vector<const CXXRecordDecl *> findRecordTypeAt(ParsedAST &AST,
1742                                                     Position Pos) {
1743   auto RecordFromNode = [&AST](const SelectionTree::Node *N) {
1744     std::vector<const CXXRecordDecl *> Records;
1745     if (!N)
1746       return Records;
1747 
1748     // Note: explicitReferenceTargets() will search for both template
1749     // instantiations and template patterns, and prefer the former if available
1750     // (generally, one will be available for non-dependent specializations of a
1751     // class template).
1752     auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying,
1753                                           AST.getHeuristicResolver());
1754     for (const NamedDecl *D : Decls) {
1755 
1756       if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1757         // If this is a variable, use the type of the variable.
1758         Records.push_back(VD->getType().getTypePtr()->getAsCXXRecordDecl());
1759         continue;
1760       }
1761 
1762       if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
1763         // If this is a method, use the type of the class.
1764         Records.push_back(Method->getParent());
1765         continue;
1766       }
1767 
1768       // We don't handle FieldDecl because it's not clear what behaviour
1769       // the user would expect: the enclosing class type (as with a
1770       // method), or the field's type (as with a variable).
1771 
1772       if (auto *RD = dyn_cast<CXXRecordDecl>(D))
1773         Records.push_back(RD);
1774     }
1775     return Records;
1776   };
1777 
1778   const SourceManager &SM = AST.getSourceManager();
1779   std::vector<const CXXRecordDecl *> Result;
1780   auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos);
1781   if (!Offset) {
1782     llvm::consumeError(Offset.takeError());
1783     return Result;
1784   }
1785   SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), *Offset,
1786                             *Offset, [&](SelectionTree ST) {
1787                               Result = RecordFromNode(ST.commonAncestor());
1788                               return !Result.empty();
1789                             });
1790   return Result;
1791 }
1792 
1793 // Return the type most associated with an AST node.
1794 // This isn't precisely defined: we want "go to type" to do something useful.
typeForNode(const SelectionTree::Node * N)1795 static QualType typeForNode(const SelectionTree::Node *N) {
1796   // If we're looking at a namespace qualifier, walk up to what it's qualifying.
1797   // (If we're pointing at a *class* inside a NNS, N will be a TypeLoc).
1798   while (N && N->ASTNode.get<NestedNameSpecifierLoc>())
1799     N = N->Parent;
1800   if (!N)
1801     return QualType();
1802 
1803   // If we're pointing at a type => return it.
1804   if (const TypeLoc *TL = N->ASTNode.get<TypeLoc>()) {
1805     if (llvm::isa<DeducedType>(TL->getTypePtr()))
1806       if (auto Deduced = getDeducedType(
1807               N->getDeclContext().getParentASTContext(), TL->getBeginLoc()))
1808         return *Deduced;
1809     // Exception: an alias => underlying type.
1810     if (llvm::isa<TypedefType>(TL->getTypePtr()))
1811       return TL->getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();
1812     return TL->getType();
1813   }
1814 
1815   // Constructor initializers => the type of thing being initialized.
1816   if (const auto *CCI = N->ASTNode.get<CXXCtorInitializer>()) {
1817     if (const FieldDecl *FD = CCI->getAnyMember())
1818       return FD->getType();
1819     if (const Type *Base = CCI->getBaseClass())
1820       return QualType(Base, 0);
1821   }
1822 
1823   // Base specifier => the base type.
1824   if (const auto *CBS = N->ASTNode.get<CXXBaseSpecifier>())
1825     return CBS->getType();
1826 
1827   if (const Decl *D = N->ASTNode.get<Decl>()) {
1828     struct Visitor : ConstDeclVisitor<Visitor, QualType> {
1829       QualType VisitValueDecl(const ValueDecl *D) { return D->getType(); }
1830       // Declaration of a type => that type.
1831       QualType VisitTypeDecl(const TypeDecl *D) {
1832         return QualType(D->getTypeForDecl(), 0);
1833       }
1834       // Exception: alias declaration => the underlying type, not the alias.
1835       QualType VisitTypedefNameDecl(const TypedefNameDecl *D) {
1836         return D->getUnderlyingType();
1837       }
1838       // Look inside templates.
1839       QualType VisitTemplateDecl(const TemplateDecl *D) {
1840         return Visit(D->getTemplatedDecl());
1841       }
1842     } V;
1843     return V.Visit(D);
1844   }
1845 
1846   if (const Stmt *S = N->ASTNode.get<Stmt>()) {
1847     struct Visitor : ConstStmtVisitor<Visitor, QualType> {
1848       // Null-safe version of visit simplifies recursive calls below.
1849       QualType type(const Stmt *S) { return S ? Visit(S) : QualType(); }
1850 
1851       // In general, expressions => type of expression.
1852       QualType VisitExpr(const Expr *S) {
1853         return S->IgnoreImplicitAsWritten()->getType();
1854       }
1855       // Exceptions for void expressions that operate on a type in some way.
1856       QualType VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
1857         return S->getDestroyedType();
1858       }
1859       QualType VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) {
1860         return S->getDestroyedType();
1861       }
1862       QualType VisitCXXThrowExpr(const CXXThrowExpr *S) {
1863         return S->getSubExpr()->getType();
1864       }
1865       QualType VisitCoyieldExpr(const CoyieldExpr *S) {
1866         return type(S->getOperand());
1867       }
1868       // Treat a designated initializer like a reference to the field.
1869       QualType VisitDesignatedInitExpr(const DesignatedInitExpr *S) {
1870         // In .foo.bar we want to jump to bar's type, so find *last* field.
1871         for (auto &D : llvm::reverse(S->designators()))
1872           if (D.isFieldDesignator())
1873             if (const auto *FD = D.getField())
1874               return FD->getType();
1875         return QualType();
1876       }
1877 
1878       // Control flow statements that operate on data: use the data type.
1879       QualType VisitSwitchStmt(const SwitchStmt *S) {
1880         return type(S->getCond());
1881       }
1882       QualType VisitWhileStmt(const WhileStmt *S) { return type(S->getCond()); }
1883       QualType VisitDoStmt(const DoStmt *S) { return type(S->getCond()); }
1884       QualType VisitIfStmt(const IfStmt *S) { return type(S->getCond()); }
1885       QualType VisitCaseStmt(const CaseStmt *S) { return type(S->getLHS()); }
1886       QualType VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
1887         return S->getLoopVariable()->getType();
1888       }
1889       QualType VisitReturnStmt(const ReturnStmt *S) {
1890         return type(S->getRetValue());
1891       }
1892       QualType VisitCoreturnStmt(const CoreturnStmt *S) {
1893         return type(S->getOperand());
1894       }
1895       QualType VisitCXXCatchStmt(const CXXCatchStmt *S) {
1896         return S->getCaughtType();
1897       }
1898       QualType VisitObjCAtThrowStmt(const ObjCAtThrowStmt *S) {
1899         return type(S->getThrowExpr());
1900       }
1901       QualType VisitObjCAtCatchStmt(const ObjCAtCatchStmt *S) {
1902         return S->getCatchParamDecl() ? S->getCatchParamDecl()->getType()
1903                                       : QualType();
1904       }
1905     } V;
1906     return V.Visit(S);
1907   }
1908 
1909   return QualType();
1910 }
1911 
1912 // Given a type targeted by the cursor, return one or more types that are more interesting
1913 // to target.
unwrapFindType(QualType T,const HeuristicResolver * H,llvm::SmallVector<QualType> & Out)1914 static void unwrapFindType(
1915     QualType T, const HeuristicResolver* H, llvm::SmallVector<QualType>& Out) {
1916   if (T.isNull())
1917     return;
1918 
1919   // If there's a specific type alias, point at that rather than unwrapping.
1920   if (const auto* TDT = T->getAs<TypedefType>())
1921     return Out.push_back(QualType(TDT, 0));
1922 
1923   // Pointers etc => pointee type.
1924   if (const auto *PT = T->getAs<PointerType>())
1925     return unwrapFindType(PT->getPointeeType(), H, Out);
1926   if (const auto *RT = T->getAs<ReferenceType>())
1927     return unwrapFindType(RT->getPointeeType(), H, Out);
1928   if (const auto *AT = T->getAsArrayTypeUnsafe())
1929     return unwrapFindType(AT->getElementType(), H, Out);
1930 
1931   // Function type => return type.
1932   if (auto *FT = T->getAs<FunctionType>())
1933     return unwrapFindType(FT->getReturnType(), H, Out);
1934   if (auto *CRD = T->getAsCXXRecordDecl()) {
1935     if (CRD->isLambda())
1936       return unwrapFindType(CRD->getLambdaCallOperator()->getReturnType(), H, Out);
1937     // FIXME: more cases we'd prefer the return type of the call operator?
1938     //        std::function etc?
1939   }
1940 
1941   // For smart pointer types, add the underlying type
1942   if (H)
1943     if (const auto* PointeeType = H->getPointeeType(T.getNonReferenceType().getTypePtr())) {
1944         unwrapFindType(QualType(PointeeType, 0), H, Out);
1945         return Out.push_back(T);
1946     }
1947 
1948   return Out.push_back(T);
1949 }
1950 
1951 // Convenience overload, to allow calling this without the out-parameter
unwrapFindType(QualType T,const HeuristicResolver * H)1952 static llvm::SmallVector<QualType> unwrapFindType(
1953     QualType T, const HeuristicResolver* H) {
1954     llvm::SmallVector<QualType> Result;
1955     unwrapFindType(T, H, Result);
1956     return Result;
1957 }
1958 
1959 
findType(ParsedAST & AST,Position Pos)1960 std::vector<LocatedSymbol> findType(ParsedAST &AST, Position Pos) {
1961   const SourceManager &SM = AST.getSourceManager();
1962   auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos);
1963   std::vector<LocatedSymbol> Result;
1964   if (!Offset) {
1965     elog("failed to convert position {0} for findTypes: {1}", Pos,
1966          Offset.takeError());
1967     return Result;
1968   }
1969   // The general scheme is: position -> AST node -> type -> declaration.
1970   auto SymbolsFromNode =
1971       [&AST](const SelectionTree::Node *N) -> std::vector<LocatedSymbol> {
1972     std::vector<LocatedSymbol> LocatedSymbols;
1973 
1974     // NOTE: unwrapFindType might return duplicates for something like
1975     // unique_ptr<unique_ptr<T>>. Let's *not* remove them, because it gives you some
1976     // information about the type you may have not known before
1977     // (since unique_ptr<unique_ptr<T>> != unique_ptr<T>).
1978     for (const QualType& Type : unwrapFindType(typeForNode(N), AST.getHeuristicResolver()))
1979         llvm::copy(locateSymbolForType(AST, Type), std::back_inserter(LocatedSymbols));
1980 
1981     return LocatedSymbols;
1982   };
1983   SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), *Offset,
1984                             *Offset, [&](SelectionTree ST) {
1985                               Result = SymbolsFromNode(ST.commonAncestor());
1986                               return !Result.empty();
1987                             });
1988   return Result;
1989 }
1990 
typeParents(const CXXRecordDecl * CXXRD)1991 std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD) {
1992   std::vector<const CXXRecordDecl *> Result;
1993 
1994   // If this is an invalid instantiation, instantiation of the bases
1995   // may not have succeeded, so fall back to the template pattern.
1996   if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
1997     if (CTSD->isInvalidDecl())
1998       CXXRD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
1999   }
2000 
2001   // Can't query bases without a definition.
2002   if (!CXXRD->hasDefinition())
2003     return Result;
2004 
2005   for (auto Base : CXXRD->bases()) {
2006     const CXXRecordDecl *ParentDecl = nullptr;
2007 
2008     const Type *Type = Base.getType().getTypePtr();
2009     if (const RecordType *RT = Type->getAs<RecordType>()) {
2010       ParentDecl = RT->getAsCXXRecordDecl();
2011     }
2012 
2013     if (!ParentDecl) {
2014       // Handle a dependent base such as "Base<T>" by using the primary
2015       // template.
2016       if (const TemplateSpecializationType *TS =
2017               Type->getAs<TemplateSpecializationType>()) {
2018         TemplateName TN = TS->getTemplateName();
2019         if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
2020           ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
2021         }
2022       }
2023     }
2024 
2025     if (ParentDecl)
2026       Result.push_back(ParentDecl);
2027   }
2028 
2029   return Result;
2030 }
2031 
2032 std::vector<TypeHierarchyItem>
getTypeHierarchy(ParsedAST & AST,Position Pos,int ResolveLevels,TypeHierarchyDirection Direction,const SymbolIndex * Index,PathRef TUPath)2033 getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
2034                  TypeHierarchyDirection Direction, const SymbolIndex *Index,
2035                  PathRef TUPath) {
2036   std::vector<TypeHierarchyItem> Results;
2037   for (const auto *CXXRD : findRecordTypeAt(AST, Pos)) {
2038 
2039     bool WantChildren = Direction == TypeHierarchyDirection::Children ||
2040                         Direction == TypeHierarchyDirection::Both;
2041 
2042     // If we're looking for children, we're doing the lookup in the index.
2043     // The index does not store relationships between implicit
2044     // specializations, so if we have one, use the template pattern instead.
2045     // Note that this needs to be done before the declToTypeHierarchyItem(),
2046     // otherwise the type hierarchy item would misleadingly contain the
2047     // specialization parameters, while the children would involve classes
2048     // that derive from other specializations of the template.
2049     if (WantChildren) {
2050       if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD))
2051         CXXRD = CTSD->getTemplateInstantiationPattern();
2052     }
2053 
2054     Optional<TypeHierarchyItem> Result =
2055         declToTypeHierarchyItem(*CXXRD, TUPath);
2056     if (!Result)
2057       continue;
2058 
2059     RecursionProtectionSet RPSet;
2060     fillSuperTypes(*CXXRD, TUPath, *Result, RPSet);
2061 
2062     if (WantChildren && ResolveLevels > 0) {
2063       Result->children.emplace();
2064 
2065       if (Index) {
2066         if (auto ID = getSymbolID(CXXRD))
2067           fillSubTypes(ID, *Result->children, Index, ResolveLevels, TUPath);
2068       }
2069     }
2070     Results.emplace_back(std::move(*Result));
2071   }
2072 
2073   return Results;
2074 }
2075 
2076 llvm::Optional<std::vector<TypeHierarchyItem>>
superTypes(const TypeHierarchyItem & Item,const SymbolIndex * Index)2077 superTypes(const TypeHierarchyItem &Item, const SymbolIndex *Index) {
2078   std::vector<TypeHierarchyItem> Results;
2079   if (!Item.data.parents)
2080     return llvm::None;
2081   if (Item.data.parents->empty())
2082     return Results;
2083   LookupRequest Req;
2084   llvm::DenseMap<SymbolID, const TypeHierarchyItem::ResolveParams *> IDToData;
2085   for (const auto &Parent : *Item.data.parents) {
2086     Req.IDs.insert(Parent.symbolID);
2087     IDToData[Parent.symbolID] = &Parent;
2088   }
2089   Index->lookup(Req, [&Item, &Results, &IDToData](const Symbol &S) {
2090     if (auto THI = symbolToTypeHierarchyItem(S, Item.uri.file())) {
2091       THI->data = *IDToData.lookup(S.ID);
2092       Results.emplace_back(std::move(*THI));
2093     }
2094   });
2095   return Results;
2096 }
2097 
subTypes(const TypeHierarchyItem & Item,const SymbolIndex * Index)2098 std::vector<TypeHierarchyItem> subTypes(const TypeHierarchyItem &Item,
2099                                         const SymbolIndex *Index) {
2100   std::vector<TypeHierarchyItem> Results;
2101   fillSubTypes(Item.data.symbolID, Results, Index, 1, Item.uri.file());
2102   for (auto &ChildSym : Results)
2103     ChildSym.data.parents = {Item.data};
2104   return Results;
2105 }
2106 
resolveTypeHierarchy(TypeHierarchyItem & Item,int ResolveLevels,TypeHierarchyDirection Direction,const SymbolIndex * Index)2107 void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels,
2108                           TypeHierarchyDirection Direction,
2109                           const SymbolIndex *Index) {
2110   // We only support typeHierarchy/resolve for children, because for parents
2111   // we ignore ResolveLevels and return all levels of parents eagerly.
2112   if (!Index || Direction == TypeHierarchyDirection::Parents ||
2113       ResolveLevels == 0)
2114     return;
2115 
2116   Item.children.emplace();
2117   fillSubTypes(Item.data.symbolID, *Item.children, Index, ResolveLevels,
2118                Item.uri.file());
2119 }
2120 
2121 std::vector<CallHierarchyItem>
prepareCallHierarchy(ParsedAST & AST,Position Pos,PathRef TUPath)2122 prepareCallHierarchy(ParsedAST &AST, Position Pos, PathRef TUPath) {
2123   std::vector<CallHierarchyItem> Result;
2124   const auto &SM = AST.getSourceManager();
2125   auto Loc = sourceLocationInMainFile(SM, Pos);
2126   if (!Loc) {
2127     elog("prepareCallHierarchy failed to convert position to source location: "
2128          "{0}",
2129          Loc.takeError());
2130     return Result;
2131   }
2132   for (const NamedDecl *Decl : getDeclAtPosition(AST, *Loc, {})) {
2133     if (!(isa<DeclContext>(Decl) &&
2134           cast<DeclContext>(Decl)->isFunctionOrMethod()) &&
2135         Decl->getKind() != Decl::Kind::FunctionTemplate)
2136       continue;
2137     if (auto CHI = declToCallHierarchyItem(*Decl))
2138       Result.emplace_back(std::move(*CHI));
2139   }
2140   return Result;
2141 }
2142 
2143 std::vector<CallHierarchyIncomingCall>
incomingCalls(const CallHierarchyItem & Item,const SymbolIndex * Index)2144 incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
2145   std::vector<CallHierarchyIncomingCall> Results;
2146   if (!Index || Item.data.empty())
2147     return Results;
2148   auto ID = SymbolID::fromStr(Item.data);
2149   if (!ID) {
2150     elog("incomingCalls failed to find symbol: {0}", ID.takeError());
2151     return Results;
2152   }
2153   // In this function, we find incoming calls based on the index only.
2154   // In principle, the AST could have more up-to-date information about
2155   // occurrences within the current file. However, going from a SymbolID
2156   // to an AST node isn't cheap, particularly when the declaration isn't
2157   // in the main file.
2158   // FIXME: Consider also using AST information when feasible.
2159   RefsRequest Request;
2160   Request.IDs.insert(*ID);
2161   Request.WantContainer = true;
2162   // We could restrict more specifically to calls by introducing a new RefKind,
2163   // but non-call references (such as address-of-function) can still be
2164   // interesting as they can indicate indirect calls.
2165   Request.Filter = RefKind::Reference;
2166   // Initially store the ranges in a map keyed by SymbolID of the caller.
2167   // This allows us to group different calls with the same caller
2168   // into the same CallHierarchyIncomingCall.
2169   llvm::DenseMap<SymbolID, std::vector<Range>> CallsIn;
2170   // We can populate the ranges based on a refs request only. As we do so, we
2171   // also accumulate the container IDs into a lookup request.
2172   LookupRequest ContainerLookup;
2173   Index->refs(Request, [&](const Ref &R) {
2174     auto Loc = indexToLSPLocation(R.Location, Item.uri.file());
2175     if (!Loc) {
2176       elog("incomingCalls failed to convert location: {0}", Loc.takeError());
2177       return;
2178     }
2179     auto It = CallsIn.try_emplace(R.Container, std::vector<Range>{}).first;
2180     It->second.push_back(Loc->range);
2181 
2182     ContainerLookup.IDs.insert(R.Container);
2183   });
2184   // Perform the lookup request and combine its results with CallsIn to
2185   // get complete CallHierarchyIncomingCall objects.
2186   Index->lookup(ContainerLookup, [&](const Symbol &Caller) {
2187     auto It = CallsIn.find(Caller.ID);
2188     assert(It != CallsIn.end());
2189     if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file()))
2190       Results.push_back(
2191           CallHierarchyIncomingCall{std::move(*CHI), std::move(It->second)});
2192   });
2193   // Sort results by name of container.
2194   llvm::sort(Results, [](const CallHierarchyIncomingCall &A,
2195                          const CallHierarchyIncomingCall &B) {
2196     return A.from.name < B.from.name;
2197   });
2198   return Results;
2199 }
2200 
getNonLocalDeclRefs(ParsedAST & AST,const FunctionDecl * FD)2201 llvm::DenseSet<const Decl *> getNonLocalDeclRefs(ParsedAST &AST,
2202                                                  const FunctionDecl *FD) {
2203   if (!FD->hasBody())
2204     return {};
2205   llvm::DenseSet<const Decl *> DeclRefs;
2206   findExplicitReferences(
2207       FD,
2208       [&](ReferenceLoc Ref) {
2209         for (const Decl *D : Ref.Targets) {
2210           if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() &&
2211               !Ref.IsDecl)
2212             DeclRefs.insert(D);
2213         }
2214       },
2215       AST.getHeuristicResolver());
2216   return DeclRefs;
2217 }
2218 
2219 } // namespace clangd
2220 } // namespace clang
2221