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