clang-tools  10.0.0svn
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 "CodeCompletionStrings.h"
11 #include "FindSymbols.h"
12 #include "FindTarget.h"
13 #include "FormattedString.h"
14 #include "Logger.h"
15 #include "ParsedAST.h"
16 #include "Protocol.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/SymbolCollector.h"
23 #include "index/SymbolLocation.h"
24 #include "clang/AST/ASTContext.h"
25 #include "clang/AST/Decl.h"
26 #include "clang/AST/DeclCXX.h"
27 #include "clang/AST/DeclTemplate.h"
28 #include "clang/AST/ExprCXX.h"
29 #include "clang/AST/PrettyPrinter.h"
30 #include "clang/AST/RecursiveASTVisitor.h"
31 #include "clang/AST/Type.h"
32 #include "clang/Basic/LLVM.h"
33 #include "clang/Basic/SourceLocation.h"
34 #include "clang/Basic/SourceManager.h"
35 #include "clang/Index/IndexDataConsumer.h"
36 #include "clang/Index/IndexSymbol.h"
37 #include "clang/Index/IndexingAction.h"
38 #include "clang/Index/IndexingOptions.h"
39 #include "clang/Index/USRGeneration.h"
40 #include "llvm/ADT/ArrayRef.h"
41 #include "llvm/ADT/None.h"
42 #include "llvm/ADT/STLExtras.h"
43 #include "llvm/ADT/StringExtras.h"
44 #include "llvm/ADT/StringRef.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/FormatVariadic.h"
47 #include "llvm/Support/Path.h"
48 #include "llvm/Support/raw_ostream.h"
49 
50 namespace clang {
51 namespace clangd {
52 namespace {
53 
54 // Returns the single definition of the entity declared by D, if visible.
55 // In particular:
56 // - for non-redeclarable kinds (e.g. local vars), return D
57 // - for kinds that allow multiple definitions (e.g. namespaces), return nullptr
58 // Kinds of nodes that always return nullptr here will not have definitions
59 // reported by locateSymbolAt().
60 const Decl *getDefinition(const Decl *D) {
61  assert(D);
62  // Decl has one definition that we can find.
63  if (const auto *TD = dyn_cast<TagDecl>(D))
64  return TD->getDefinition();
65  if (const auto *VD = dyn_cast<VarDecl>(D))
66  return VD->getDefinition();
67  if (const auto *FD = dyn_cast<FunctionDecl>(D))
68  return FD->getDefinition();
69  // Only a single declaration is allowed.
70  if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
71  isa<TemplateTemplateParmDecl>(D)) // except cases above
72  return D;
73  // Multiple definitions are allowed.
74  return nullptr; // except cases above
75 }
76 
77 void logIfOverflow(const SymbolLocation &Loc) {
78  if (Loc.Start.hasOverflow() || Loc.End.hasOverflow())
79  log("Possible overflow in symbol location: {0}", Loc);
80 }
81 
82 // Convert a SymbolLocation to LSP's Location.
83 // TUPath is used to resolve the path of URI.
84 // FIXME: figure out a good home for it, and share the implementation with
85 // FindSymbols.
86 llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc,
87  llvm::StringRef TUPath) {
88  if (!Loc)
89  return None;
90  auto Uri = URI::parse(Loc.FileURI);
91  if (!Uri) {
92  elog("Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError());
93  return None;
94  }
95  auto U = URIForFile::fromURI(*Uri, TUPath);
96  if (!U) {
97  elog("Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError());
98  return None;
99  }
100 
101  Location LSPLoc;
102  LSPLoc.uri = std::move(*U);
103  LSPLoc.range.start.line = Loc.Start.line();
104  LSPLoc.range.start.character = Loc.Start.column();
105  LSPLoc.range.end.line = Loc.End.line();
106  LSPLoc.range.end.character = Loc.End.column();
107  logIfOverflow(Loc);
108  return LSPLoc;
109 }
110 
111 SymbolLocation toIndexLocation(const Location &Loc, std::string &URIStorage) {
112  SymbolLocation SymLoc;
113  URIStorage = Loc.uri.uri();
114  SymLoc.FileURI = URIStorage.c_str();
115  SymLoc.Start.setLine(Loc.range.start.line);
116  SymLoc.Start.setColumn(Loc.range.start.character);
117  SymLoc.End.setLine(Loc.range.end.line);
118  SymLoc.End.setColumn(Loc.range.end.character);
119  return SymLoc;
120 }
121 
122 // Returns the preferred location between an AST location and an index location.
123 SymbolLocation getPreferredLocation(const Location &ASTLoc,
124  const SymbolLocation &IdxLoc,
125  std::string &Scratch) {
126  // Also use a dummy symbol for the index location so that other fields (e.g.
127  // definition) are not factored into the preferrence.
128  Symbol ASTSym, IdxSym;
129  ASTSym.ID = IdxSym.ID = SymbolID("dummy_id");
130  ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch);
131  IdxSym.CanonicalDeclaration = IdxLoc;
132  auto Merged = mergeSymbol(ASTSym, IdxSym);
133  return Merged.CanonicalDeclaration;
134 }
135 
136 /// Finds declarations locations that a given source location refers to.
137 class DeclarationFinder : public index::IndexDataConsumer {
138  llvm::DenseSet<const Decl *> Decls;
139  const SourceLocation &SearchedLocation;
140 
141 public:
142  DeclarationFinder(const SourceLocation &SearchedLocation)
143  : SearchedLocation(SearchedLocation) {}
144 
145  // The results are sorted by declaration location.
146  std::vector<const Decl *> getFoundDecls() const {
147  std::vector<const Decl *> Result;
148  for (const Decl *D : Decls)
149  Result.push_back(D);
150 
151  llvm::sort(Result, [](const Decl *L, const Decl *R) {
152  return L->getBeginLoc() < R->getBeginLoc();
153  });
154  return Result;
155  }
156 
157  bool
158  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
159  llvm::ArrayRef<index::SymbolRelation> Relations,
160  SourceLocation Loc,
161  index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
162  // Skip non-semantic references.
163  if (Roles & static_cast<unsigned>(index::SymbolRole::NameReference))
164  return true;
165 
166  if (Loc == SearchedLocation) {
167  auto IsImplicitExpr = [](const Expr *E) {
168  if (!E)
169  return false;
170  // We assume that a constructor expression is implict (was inserted by
171  // clang) if it has an invalid paren/brace location, since such
172  // experssion is impossible to write down.
173  if (const auto *CtorExpr = dyn_cast<CXXConstructExpr>(E))
174  return CtorExpr->getParenOrBraceRange().isInvalid();
175  // Ignore implicit conversion-operator AST node.
176  if (const auto *ME = dyn_cast<MemberExpr>(E)) {
177  if (isa<CXXConversionDecl>(ME->getMemberDecl()))
178  return ME->getMemberLoc().isInvalid();
179  }
180  return isa<ImplicitCastExpr>(E);
181  };
182 
183  if (IsImplicitExpr(ASTNode.OrigE))
184  return true;
185  // Find and add definition declarations (for GoToDefinition).
186  // We don't use parameter `D`, as Parameter `D` is the canonical
187  // declaration, which is the first declaration of a redeclarable
188  // declaration, and it could be a forward declaration.
189  if (const auto *Def = getDefinition(D)) {
190  Decls.insert(Def);
191  } else {
192  // Couldn't find a definition, fall back to use `D`.
193  Decls.insert(D);
194  }
195  }
196  return true;
197  }
198 };
199 
200 std::vector<const Decl *> getDeclAtPosition(ParsedAST &AST,
201  SourceLocation Pos) {
202  DeclarationFinder Finder(Pos);
203  index::IndexingOptions IndexOpts;
204  IndexOpts.SystemSymbolFilter =
205  index::IndexingOptions::SystemSymbolFilterKind::All;
206  IndexOpts.IndexFunctionLocals = true;
207  IndexOpts.IndexParametersInDeclarations = true;
208  IndexOpts.IndexTemplateParameters = true;
209  indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
210  AST.getLocalTopLevelDecls(), Finder, IndexOpts);
211 
212  return Finder.getFoundDecls();
213 }
214 
215 llvm::Optional<Location> makeLocation(ASTContext &AST, SourceLocation TokLoc,
216  llvm::StringRef TUPath) {
217  const SourceManager &SourceMgr = AST.getSourceManager();
218  const FileEntry *F = SourceMgr.getFileEntryForID(SourceMgr.getFileID(TokLoc));
219  if (!F)
220  return None;
221  auto FilePath = getCanonicalPath(F, SourceMgr);
222  if (!FilePath) {
223  log("failed to get path!");
224  return None;
225  }
226  if (auto Range =
227  getTokenRange(AST.getSourceManager(), AST.getLangOpts(), TokLoc)) {
228  Location L;
229  L.uri = URIForFile::canonicalize(*FilePath, TUPath);
230  L.range = *Range;
231  return L;
232  }
233  return None;
234 }
235 
236 } // namespace
237 
238 std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
239  const SymbolIndex *Index) {
240  const auto &SM = AST.getSourceManager();
241  auto MainFilePath =
242  getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
243  if (!MainFilePath) {
244  elog("Failed to get a path for the main file, so no references");
245  return {};
246  }
247 
248  // Treat #included files as symbols, to enable go-to-definition on them.
249  for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
250  if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line) {
252  File.Name = llvm::sys::path::filename(Inc.Resolved);
253  File.PreferredDeclaration = {
254  URIForFile::canonicalize(Inc.Resolved, *MainFilePath), Range{}};
255  File.Definition = File.PreferredDeclaration;
256  // We're not going to find any further symbols on #include lines.
257  return {std::move(File)};
258  }
259  }
260 
261  SourceLocation SourceLocationBeg =
262  SM.getMacroArgExpandedLocation(getBeginningOfIdentifier(
263  Pos, AST.getSourceManager(), AST.getASTContext().getLangOpts()));
264 
265  // Macros are simple: there's no declaration/definition distinction.
266  // As a consequence, there's no need to look them up in the index either.
267  std::vector<LocatedSymbol> Result;
268  if (auto M = locateMacroAt(SourceLocationBeg, AST.getPreprocessor())) {
269  if (auto Loc = makeLocation(AST.getASTContext(),
270  M->Info->getDefinitionLoc(), *MainFilePath)) {
272  Macro.Name = M->Name;
273  Macro.PreferredDeclaration = *Loc;
274  Macro.Definition = Loc;
275  Result.push_back(std::move(Macro));
276  }
277  }
278 
279  // Decls are more complicated.
280  // The AST contains at least a declaration, maybe a definition.
281  // These are up-to-date, and so generally preferred over index results.
282  // We perform a single batch index lookup to find additional definitions.
283 
284  // Results follow the order of Symbols.Decls.
285  // Keep track of SymbolID -> index mapping, to fill in index data later.
286  llvm::DenseMap<SymbolID, size_t> ResultIndex;
287 
288  // Emit all symbol locations (declaration or definition) from AST.
289  for (const Decl *D : getDeclAtPosition(AST, SourceLocationBeg)) {
290  auto Loc =
291  makeLocation(AST.getASTContext(), spellingLocIfSpelled(findName(D), SM),
292  *MainFilePath);
293  if (!Loc)
294  continue;
295 
296  Result.emplace_back();
297  if (auto *ND = dyn_cast<NamedDecl>(D))
298  Result.back().Name = printName(AST.getASTContext(), *ND);
299  Result.back().PreferredDeclaration = *Loc;
300  // DeclInfo.D is always a definition if possible, so this check works.
301  if (getDefinition(D) == D)
302  Result.back().Definition = *Loc;
303 
304  // Record SymbolID for index lookup later.
305  if (auto ID = getSymbolID(D))
306  ResultIndex[*ID] = Result.size() - 1;
307  }
308 
309  // Now query the index for all Symbol IDs we found in the AST.
310  if (Index && !ResultIndex.empty()) {
311  LookupRequest QueryRequest;
312  for (auto It : ResultIndex)
313  QueryRequest.IDs.insert(It.first);
314  std::string Scratch;
315  Index->lookup(QueryRequest, [&](const Symbol &Sym) {
316  auto &R = Result[ResultIndex.lookup(Sym.ID)];
317 
318  if (R.Definition) { // from AST
319  // Special case: if the AST yielded a definition, then it may not be
320  // the right *declaration*. Prefer the one from the index.
321  if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, *MainFilePath))
322  R.PreferredDeclaration = *Loc;
323 
324  // We might still prefer the definition from the index, e.g. for
325  // generated symbols.
326  if (auto Loc = toLSPLocation(
327  getPreferredLocation(*R.Definition, Sym.Definition, Scratch),
328  *MainFilePath))
329  R.Definition = *Loc;
330  } else {
331  R.Definition = toLSPLocation(Sym.Definition, *MainFilePath);
332 
333  // Use merge logic to choose AST or index declaration.
334  if (auto Loc = toLSPLocation(
335  getPreferredLocation(R.PreferredDeclaration,
336  Sym.CanonicalDeclaration, Scratch),
337  *MainFilePath))
338  R.PreferredDeclaration = *Loc;
339  }
340  });
341  }
342 
343  return Result;
344 }
345 
346 namespace {
347 
348 /// Collects references to symbols within the main file.
349 class ReferenceFinder : public index::IndexDataConsumer {
350 public:
351  struct Reference {
352  SourceLocation Loc;
353  index::SymbolRoleSet Role;
354  };
355 
356  ReferenceFinder(ASTContext &AST, Preprocessor &PP,
357  const std::vector<const Decl *> &TargetDecls)
358  : AST(AST) {
359  for (const Decl *D : TargetDecls)
360  CanonicalTargets.insert(D->getCanonicalDecl());
361  }
362 
363  std::vector<Reference> take() && {
364  llvm::sort(References, [](const Reference &L, const Reference &R) {
365  return std::tie(L.Loc, L.Role) < std::tie(R.Loc, R.Role);
366  });
367  // We sometimes see duplicates when parts of the AST get traversed twice.
368  References.erase(std::unique(References.begin(), References.end(),
369  [](const Reference &L, const Reference &R) {
370  return std::tie(L.Loc, L.Role) ==
371  std::tie(R.Loc, R.Role);
372  }),
373  References.end());
374  return std::move(References);
375  }
376 
377  bool
378  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
379  llvm::ArrayRef<index::SymbolRelation> Relations,
380  SourceLocation Loc,
381  index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
382  assert(D->isCanonicalDecl() && "expect D to be a canonical declaration");
383  const SourceManager &SM = AST.getSourceManager();
384  Loc = SM.getFileLoc(Loc);
385  if (isInsideMainFile(Loc, SM) && CanonicalTargets.count(D))
386  References.push_back({Loc, Roles});
387  return true;
388  }
389 
390 private:
391  llvm::SmallSet<const Decl *, 4> CanonicalTargets;
392  std::vector<Reference> References;
393  const ASTContext &AST;
394 };
395 
396 std::vector<ReferenceFinder::Reference>
397 findRefs(const std::vector<const Decl *> &Decls, ParsedAST &AST) {
398  ReferenceFinder RefFinder(AST.getASTContext(), AST.getPreprocessor(), Decls);
399  index::IndexingOptions IndexOpts;
400  IndexOpts.SystemSymbolFilter =
401  index::IndexingOptions::SystemSymbolFilterKind::All;
402  IndexOpts.IndexFunctionLocals = true;
403  IndexOpts.IndexParametersInDeclarations = true;
404  IndexOpts.IndexTemplateParameters = true;
405  indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
406  AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
407  return std::move(RefFinder).take();
408 }
409 
410 } // namespace
411 
412 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
413  Position Pos) {
414  const SourceManager &SM = AST.getSourceManager();
415  // FIXME: show references to macro within file?
416  auto References =
417  findRefs(getDeclAtPosition(
418  AST, SM.getMacroArgExpandedLocation(getBeginningOfIdentifier(
419  Pos, SM, AST.getASTContext().getLangOpts()))),
420  AST);
421 
422  // FIXME: we may get multiple DocumentHighlights with the same location and
423  // different kinds, deduplicate them.
424  std::vector<DocumentHighlight> Result;
425  for (const auto &Ref : References) {
426  if (auto Range =
427  getTokenRange(AST.getASTContext().getSourceManager(),
428  AST.getASTContext().getLangOpts(), Ref.Loc)) {
430  DH.range = *Range;
431  if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
433  else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
435  else
437  Result.push_back(std::move(DH));
438  }
439  }
440  return Result;
441 }
442 
443 static PrintingPolicy printingPolicyForDecls(PrintingPolicy Base) {
444  PrintingPolicy Policy(Base);
445 
446  Policy.AnonymousTagLocations = false;
447  Policy.TerseOutput = true;
448  Policy.PolishForDeclaration = true;
449  Policy.ConstantsAsWritten = true;
450  Policy.SuppressTagKeyword = false;
451 
452  return Policy;
453 }
454 
455 /// Given a declaration \p D, return a human-readable string representing the
456 /// local scope in which it is declared, i.e. class(es) and method name. Returns
457 /// an empty string if it is not local.
458 static std::string getLocalScope(const Decl *D) {
459  std::vector<std::string> Scopes;
460  const DeclContext *DC = D->getDeclContext();
461  auto GetName = [](const Decl *D) {
462  const NamedDecl *ND = dyn_cast<NamedDecl>(D);
463  std::string Name = ND->getNameAsString();
464  if (!Name.empty())
465  return Name;
466  if (auto RD = dyn_cast<RecordDecl>(D))
467  return ("(anonymous " + RD->getKindName() + ")").str();
468  return std::string("");
469  };
470  while (DC) {
471  if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
472  Scopes.push_back(GetName(TD));
473  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
474  Scopes.push_back(FD->getNameAsString());
475  DC = DC->getParent();
476  }
477 
478  return llvm::join(llvm::reverse(Scopes), "::");
479 }
480 
481 /// Returns the human-readable representation for namespace containing the
482 /// declaration \p D. Returns empty if it is contained global namespace.
483 static std::string getNamespaceScope(const Decl *D) {
484  const DeclContext *DC = D->getDeclContext();
485 
486  if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
487  return getNamespaceScope(TD);
488  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
489  return getNamespaceScope(FD);
490  if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
491  return ND->getQualifiedNameAsString();
492 
493  return "";
494 }
495 
496 static std::string printDefinition(const Decl *D) {
497  std::string Definition;
498  llvm::raw_string_ostream OS(Definition);
499  PrintingPolicy Policy =
500  printingPolicyForDecls(D->getASTContext().getPrintingPolicy());
501  Policy.IncludeTagDefinition = false;
502  D->print(OS, Policy);
503  return Definition;
504 }
505 
506 static void printParams(llvm::raw_ostream &OS,
507  const std::vector<HoverInfo::Param> &Params) {
508  for (size_t I = 0, E = Params.size(); I != E; ++I) {
509  if (I)
510  OS << ", ";
511  OS << Params.at(I);
512  }
513 }
514 
515 static std::vector<HoverInfo::Param>
516 fetchTemplateParameters(const TemplateParameterList *Params,
517  const PrintingPolicy &PP) {
518  assert(Params);
519  std::vector<HoverInfo::Param> TempParameters;
520 
521  for (const Decl *Param : *Params) {
523  P.Type.emplace();
524  if (const auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
525  P.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
526  if (TTP->isParameterPack())
527  *P.Type += "...";
528 
529  if (!TTP->getName().empty())
530  P.Name = TTP->getNameAsString();
531  if (TTP->hasDefaultArgument())
532  P.Default = TTP->getDefaultArgument().getAsString(PP);
533  } else if (const auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
534  if (IdentifierInfo *II = NTTP->getIdentifier())
535  P.Name = II->getName().str();
536 
537  llvm::raw_string_ostream Out(*P.Type);
538  NTTP->getType().print(Out, PP);
539  if (NTTP->isParameterPack())
540  Out << "...";
541 
542  if (NTTP->hasDefaultArgument()) {
543  P.Default.emplace();
544  llvm::raw_string_ostream Out(*P.Default);
545  NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP);
546  }
547  } else if (const auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
548  llvm::raw_string_ostream OS(*P.Type);
549  OS << "template <";
550  printParams(OS,
551  fetchTemplateParameters(TTPD->getTemplateParameters(), PP));
552  OS << "> class"; // FIXME: TemplateTemplateParameter doesn't store the
553  // info on whether this param was a "typename" or
554  // "class".
555  if (!TTPD->getName().empty())
556  P.Name = TTPD->getNameAsString();
557  if (TTPD->hasDefaultArgument()) {
558  P.Default.emplace();
559  llvm::raw_string_ostream Out(*P.Default);
560  TTPD->getDefaultArgument().getArgument().print(PP, Out);
561  }
562  }
563  TempParameters.push_back(std::move(P));
564  }
565 
566  return TempParameters;
567 }
568 
569 static const FunctionDecl *getUnderlyingFunction(const Decl *D) {
570  // Extract lambda from variables.
571  if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) {
572  auto QT = VD->getType();
573  if (!QT.isNull()) {
574  while (!QT->getPointeeType().isNull())
575  QT = QT->getPointeeType();
576 
577  if (const auto *CD = QT->getAsCXXRecordDecl())
578  return CD->getLambdaCallOperator();
579  }
580  }
581 
582  // Non-lambda functions.
583  return D->getAsFunction();
584 }
585 
586 // Look up information about D from the index, and add it to Hover.
587 static void enhanceFromIndex(HoverInfo &Hover, const Decl *D,
588  const SymbolIndex *Index) {
589  if (!Index || !llvm::isa<NamedDecl>(D))
590  return;
591  const NamedDecl &ND = *cast<NamedDecl>(D);
592  // We only add documentation, so don't bother if we already have some.
593  if (!Hover.Documentation.empty())
594  return;
595  // Skip querying for non-indexable symbols, there's no point.
596  // We're searching for symbols that might be indexed outside this main file.
597  if (!SymbolCollector::shouldCollectSymbol(ND, ND.getASTContext(),
599  /*IsMainFileOnly=*/false))
600  return;
601  auto ID = getSymbolID(&ND);
602  if (!ID)
603  return;
604  LookupRequest Req;
605  Req.IDs.insert(*ID);
606  Index->lookup(
607  Req, [&](const Symbol &S) { Hover.Documentation = S.Documentation; });
608 }
609 
610 /// Generate a \p Hover object given the declaration \p D.
611 static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) {
612  HoverInfo HI;
613  const ASTContext &Ctx = D->getASTContext();
614 
616  if (!HI.NamespaceScope->empty())
617  HI.NamespaceScope->append("::");
618  HI.LocalScope = getLocalScope(D);
619  if (!HI.LocalScope.empty())
620  HI.LocalScope.append("::");
621 
622  PrintingPolicy Policy = printingPolicyForDecls(Ctx.getPrintingPolicy());
623  if (const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D)) {
624  HI.Documentation = getDeclComment(Ctx, *ND);
625  HI.Name = printName(Ctx, *ND);
626  }
627 
629 
630  // Fill in template params.
631  if (const TemplateDecl *TD = D->getDescribedTemplate()) {
632  HI.TemplateParameters =
633  fetchTemplateParameters(TD->getTemplateParameters(), Policy);
634  D = TD;
635  } else if (const FunctionDecl *FD = D->getAsFunction()) {
636  if (const auto FTD = FD->getDescribedTemplate()) {
637  HI.TemplateParameters =
638  fetchTemplateParameters(FTD->getTemplateParameters(), Policy);
639  D = FTD;
640  }
641  }
642 
643  // Fill in types and params.
644  if (const FunctionDecl *FD = getUnderlyingFunction(D)) {
645  HI.ReturnType.emplace();
646  {
647  llvm::raw_string_ostream OS(*HI.ReturnType);
648  FD->getReturnType().print(OS, Policy);
649  }
650 
651  HI.Parameters.emplace();
652  for (const ParmVarDecl *PVD : FD->parameters()) {
653  HI.Parameters->emplace_back();
654  auto &P = HI.Parameters->back();
655  if (!PVD->getType().isNull()) {
656  P.Type.emplace();
657  llvm::raw_string_ostream OS(*P.Type);
658  PVD->getType().print(OS, Policy);
659  } else {
660  std::string Param;
661  llvm::raw_string_ostream OS(Param);
662  PVD->dump(OS);
663  OS.flush();
664  elog("Got param with null type: {0}", Param);
665  }
666  if (!PVD->getName().empty())
667  P.Name = PVD->getNameAsString();
668  if (PVD->hasDefaultArg()) {
669  P.Default.emplace();
670  llvm::raw_string_ostream Out(*P.Default);
671  PVD->getDefaultArg()->printPretty(Out, nullptr, Policy);
672  }
673  }
674 
675  HI.Type.emplace();
676  llvm::raw_string_ostream TypeOS(*HI.Type);
677  // Lambdas
678  if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
679  VD->getType().getDesugaredType(D->getASTContext()).print(TypeOS, Policy);
680  // Functions
681  else
682  FD->getType().print(TypeOS, Policy);
683  // FIXME: handle variadics.
684  } else if (const auto *VD = dyn_cast<ValueDecl>(D)) {
685  HI.Type.emplace();
686  llvm::raw_string_ostream OS(*HI.Type);
687  VD->getType().print(OS, Policy);
688  }
689 
690  // Fill in value with evaluated initializer if possible.
691  // FIXME(kadircet): Also set Value field for expressions like "sizeof" and
692  // function calls.
693  if (const auto *Var = dyn_cast<VarDecl>(D)) {
694  if (const Expr *Init = Var->getInit()) {
695  Expr::EvalResult Result;
696  if (!Init->isValueDependent() && Init->EvaluateAsRValue(Result, Ctx)) {
697  HI.Value.emplace();
698  llvm::raw_string_ostream ValueOS(*HI.Value);
699  Result.Val.printPretty(ValueOS, const_cast<ASTContext &>(Ctx),
700  Init->getType());
701  }
702  }
703  }
704 
705  HI.Definition = printDefinition(D);
706  enhanceFromIndex(HI, D, Index);
707  return HI;
708 }
709 
710 /// Generate a \p Hover object given the type \p T.
711 static HoverInfo getHoverContents(QualType T, const Decl *D, ASTContext &ASTCtx,
712  const SymbolIndex *Index) {
713  HoverInfo HI;
714  llvm::raw_string_ostream OS(HI.Name);
715  PrintingPolicy Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
716  T.print(OS, Policy);
717 
718  if (D) {
720  enhanceFromIndex(HI, D, Index);
721  }
722  return HI;
723 }
724 
725 /// Generate a \p Hover object given the macro \p MacroDecl.
727  HoverInfo HI;
728  SourceManager &SM = AST.getSourceManager();
729  HI.Name = Macro.Name;
731  index::getSymbolInfoForMacro(*Macro.Info).Kind);
732  // FIXME: Populate documentation
733  // FIXME: Pupulate parameters
734 
735  // Try to get the full definition, not just the name
736  SourceLocation StartLoc = Macro.Info->getDefinitionLoc();
737  SourceLocation EndLoc = Macro.Info->getDefinitionEndLoc();
738  if (EndLoc.isValid()) {
739  EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, SM,
740  AST.getASTContext().getLangOpts());
741  bool Invalid;
742  StringRef Buffer = SM.getBufferData(SM.getFileID(StartLoc), &Invalid);
743  if (!Invalid) {
744  unsigned StartOffset = SM.getFileOffset(StartLoc);
745  unsigned EndOffset = SM.getFileOffset(EndLoc);
746  if (EndOffset <= Buffer.size() && StartOffset < EndOffset)
747  HI.Definition =
748  ("#define " + Buffer.substr(StartOffset, EndOffset - StartOffset))
749  .str();
750  }
751  }
752  return HI;
753 }
754 
755 namespace {
756 /// Computes the deduced type at a given location by visiting the relevant
757 /// nodes. We use this to display the actual type when hovering over an "auto"
758 /// keyword or "decltype()" expression.
759 /// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it
760 /// seems that the AutoTypeLocs that can be visited along with their AutoType do
761 /// not have the deduced type set. Instead, we have to go to the appropriate
762 /// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have
763 /// a deduced type set. The AST should be improved to simplify this scenario.
764 class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
765  SourceLocation SearchedLocation;
766 
767 public:
768  DeducedTypeVisitor(SourceLocation SearchedLocation)
769  : SearchedLocation(SearchedLocation) {}
770 
771  // Handle auto initializers:
772  //- auto i = 1;
773  //- decltype(auto) i = 1;
774  //- auto& i = 1;
775  //- auto* i = &a;
776  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
777  if (!D->getTypeSourceInfo() ||
778  D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation)
779  return true;
780 
781  if (auto *AT = D->getType()->getContainedAutoType()) {
782  if (!AT->getDeducedType().isNull()) {
783  DeducedType = AT->getDeducedType();
784  this->D = D;
785  }
786  }
787  return true;
788  }
789 
790  // Handle auto return types:
791  //- auto foo() {}
792  //- auto& foo() {}
793  //- auto foo() -> int {}
794  //- auto foo() -> decltype(1+1) {}
795  //- operator auto() const { return 10; }
796  bool VisitFunctionDecl(FunctionDecl *D) {
797  if (!D->getTypeSourceInfo())
798  return true;
799  // Loc of auto in return type (c++14).
800  auto CurLoc = D->getReturnTypeSourceRange().getBegin();
801  // Loc of "auto" in operator auto()
802  if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(D))
803  CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
804  // Loc of "auto" in function with traling return type (c++11).
805  if (CurLoc.isInvalid())
806  CurLoc = D->getSourceRange().getBegin();
807  if (CurLoc != SearchedLocation)
808  return true;
809 
810  const AutoType *AT = D->getReturnType()->getContainedAutoType();
811  if (AT && !AT->getDeducedType().isNull()) {
812  DeducedType = AT->getDeducedType();
813  this->D = D;
814  } else if (auto DT = dyn_cast<DecltypeType>(D->getReturnType())) {
815  // auto in a trailing return type just points to a DecltypeType and
816  // getContainedAutoType does not unwrap it.
817  if (!DT->getUnderlyingType().isNull()) {
818  DeducedType = DT->getUnderlyingType();
819  this->D = D;
820  }
821  } else if (!D->getReturnType().isNull()) {
822  DeducedType = D->getReturnType();
823  this->D = D;
824  }
825  return true;
826  }
827 
828  // Handle non-auto decltype, e.g.:
829  // - auto foo() -> decltype(expr) {}
830  // - decltype(expr);
831  bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
832  if (TL.getBeginLoc() != SearchedLocation)
833  return true;
834 
835  // A DecltypeType's underlying type can be another DecltypeType! E.g.
836  // int I = 0;
837  // decltype(I) J = I;
838  // decltype(J) K = J;
839  const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
840  while (DT && !DT->getUnderlyingType().isNull()) {
841  DeducedType = DT->getUnderlyingType();
842  D = DT->getAsTagDecl();
843  DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr());
844  }
845  return true;
846  }
847 
848  QualType DeducedType;
849  const Decl *D = nullptr;
850 };
851 } // namespace
852 
853 /// Retrieves the deduced type at a given location (auto, decltype).
854 /// SourceLocationBeg must point to the first character of the token
855 llvm::Optional<QualType> getDeducedType(ParsedAST &AST,
856  SourceLocation SourceLocationBeg) {
857  Token Tok;
858  auto &ASTCtx = AST.getASTContext();
859  // Only try to find a deduced type if the token is auto or decltype.
860  if (!SourceLocationBeg.isValid() ||
861  Lexer::getRawToken(SourceLocationBeg, Tok, ASTCtx.getSourceManager(),
862  ASTCtx.getLangOpts(), false) ||
863  !Tok.is(tok::raw_identifier)) {
864  return {};
865  }
866  AST.getPreprocessor().LookUpIdentifierInfo(Tok);
867  if (!(Tok.is(tok::kw_auto) || Tok.is(tok::kw_decltype)))
868  return {};
869 
870  DeducedTypeVisitor V(SourceLocationBeg);
871  V.TraverseAST(AST.getASTContext());
872  return V.DeducedType;
873 }
874 
875 /// Retrieves the deduced type at a given location (auto, decltype).
876 bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg) {
877  return (bool)getDeducedType(AST, SourceLocationBeg);
878 }
879 
880 llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
881  format::FormatStyle Style,
882  const SymbolIndex *Index) {
883  const SourceManager &SM = AST.getSourceManager();
884  llvm::Optional<HoverInfo> HI;
885  SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation(
886  getBeginningOfIdentifier(Pos, SM, AST.getASTContext().getLangOpts()));
887 
888  if (auto M = locateMacroAt(SourceLocationBeg, AST.getPreprocessor())) {
889  HI = getHoverContents(*M, AST);
890  } else {
891  auto Decls = getDeclAtPosition(AST, SourceLocationBeg);
892  if (!Decls.empty())
893  HI = getHoverContents(Decls.front(), Index);
894  }
895  if (!HI && hasDeducedType(AST, SourceLocationBeg)) {
896  DeducedTypeVisitor V(SourceLocationBeg);
897  V.TraverseAST(AST.getASTContext());
898  if (!V.DeducedType.isNull())
899  HI = getHoverContents(V.DeducedType, V.D, AST.getASTContext(), Index);
900  }
901  if (!HI)
902  return llvm::None;
903 
904  auto Replacements = format::reformat(
905  Style, HI->Definition, tooling::Range(0, HI->Definition.size()));
906  if (auto Formatted =
907  tooling::applyAllReplacements(HI->Definition, Replacements))
908  HI->Definition = *Formatted;
909 
910  HI->SymRange =
911  getTokenRange(AST.getASTContext().getSourceManager(),
912  AST.getASTContext().getLangOpts(), SourceLocationBeg);
913  return HI;
914 }
915 
916 std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
917  uint32_t Limit, const SymbolIndex *Index) {
918  if (!Limit)
919  Limit = std::numeric_limits<uint32_t>::max();
920  std::vector<Location> Results;
921  const SourceManager &SM = AST.getSourceManager();
922  auto MainFilePath =
923  getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
924  if (!MainFilePath) {
925  elog("Failed to get a path for the main file, so no references");
926  return Results;
927  }
928  auto Loc = SM.getMacroArgExpandedLocation(
929  getBeginningOfIdentifier(Pos, SM, AST.getASTContext().getLangOpts()));
930  // TODO: should we handle macros, too?
931  auto Decls = getDeclAtPosition(AST, Loc);
932 
933  // We traverse the AST to find references in the main file.
934  auto MainFileRefs = findRefs(Decls, AST);
935  // We may get multiple refs with the same location and different Roles, as
936  // cross-reference is only interested in locations, we deduplicate them
937  // by the location to avoid emitting duplicated locations.
938  MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(),
939  [](const ReferenceFinder::Reference &L,
940  const ReferenceFinder::Reference &R) {
941  return L.Loc == R.Loc;
942  }),
943  MainFileRefs.end());
944  for (const auto &Ref : MainFileRefs) {
945  if (auto Range =
946  getTokenRange(AST.getASTContext().getSourceManager(),
947  AST.getASTContext().getLangOpts(), Ref.Loc)) {
948  Location Result;
949  Result.range = *Range;
950  Result.uri = URIForFile::canonicalize(*MainFilePath, *MainFilePath);
951  Results.push_back(std::move(Result));
952  }
953  }
954 
955  // Now query the index for references from other files.
956  if (Index && Results.size() < Limit) {
957  RefsRequest Req;
958  Req.Limit = Limit;
959 
960  for (const Decl *D : Decls) {
961  // Not all symbols can be referenced from outside (e.g. function-locals).
962  // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
963  // we know this file isn't a header. The details might be tricky.
964  if (D->getParentFunctionOrMethod())
965  continue;
966  if (auto ID = getSymbolID(D))
967  Req.IDs.insert(*ID);
968  }
969  if (Req.IDs.empty())
970  return Results;
971  Index->refs(Req, [&](const Ref &R) {
972  auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
973  // Avoid indexed results for the main file - the AST is authoritative.
974  if (LSPLoc && LSPLoc->uri.file() != *MainFilePath)
975  Results.push_back(std::move(*LSPLoc));
976  });
977  }
978  if (Results.size() > Limit)
979  Results.resize(Limit);
980  return Results;
981 }
982 
983 std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
984  const SourceManager &SM = AST.getSourceManager();
985  auto Loc = SM.getMacroArgExpandedLocation(
986  getBeginningOfIdentifier(Pos, SM, AST.getASTContext().getLangOpts()));
987 
988  std::vector<SymbolDetails> Results;
989 
990  for (const Decl *D : getDeclAtPosition(AST, Loc)) {
991  SymbolDetails NewSymbol;
992  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
993  std::string QName = printQualifiedName(*ND);
994  std::tie(NewSymbol.containerName, NewSymbol.name) =
995  splitQualifiedName(QName);
996 
997  if (NewSymbol.containerName.empty()) {
998  if (const auto *ParentND =
999  dyn_cast_or_null<NamedDecl>(ND->getDeclContext()))
1000  NewSymbol.containerName = printQualifiedName(*ParentND);
1001  }
1002  }
1003  llvm::SmallString<32> USR;
1004  if (!index::generateUSRForDecl(D, USR)) {
1005  NewSymbol.USR = USR.str();
1006  NewSymbol.ID = SymbolID(NewSymbol.USR);
1007  }
1008  Results.push_back(std::move(NewSymbol));
1009  }
1010 
1011  if (auto M = locateMacroAt(Loc, AST.getPreprocessor())) {
1012  SymbolDetails NewMacro;
1013  NewMacro.name = M->Name;
1014  llvm::SmallString<32> USR;
1015  if (!index::generateUSRForMacro(NewMacro.name, M->Info->getDefinitionLoc(),
1016  SM, USR)) {
1017  NewMacro.USR = USR.str();
1018  NewMacro.ID = SymbolID(NewMacro.USR);
1019  }
1020  Results.push_back(std::move(NewMacro));
1021  }
1022 
1023  return Results;
1024 }
1025 
1026 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) {
1027  OS << S.Name << ": " << S.PreferredDeclaration;
1028  if (S.Definition)
1029  OS << " def=" << *S.Definition;
1030  return OS;
1031 }
1032 
1033 // FIXME(nridge): Reduce duplication between this function and declToSym().
1034 static llvm::Optional<TypeHierarchyItem>
1035 declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) {
1036  auto &SM = Ctx.getSourceManager();
1037 
1038  SourceLocation NameLoc =
1039  spellingLocIfSpelled(findName(&ND), Ctx.getSourceManager());
1040  // getFileLoc is a good choice for us, but we also need to make sure
1041  // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of
1042  // that to make sure it does not switch files.
1043  // FIXME: sourceLocToPosition should not switch files!
1044  SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
1045  SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
1046  if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
1047  return llvm::None;
1048 
1049  Position NameBegin = sourceLocToPosition(SM, NameLoc);
1050  Position NameEnd = sourceLocToPosition(
1051  SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
1052 
1053  index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
1054  // FIXME: this is not classifying constructors, destructors and operators
1055  // correctly (they're all "methods").
1056  SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
1057 
1058  TypeHierarchyItem THI;
1059  THI.name = printName(Ctx, ND);
1060  THI.kind = SK;
1061  THI.deprecated = ND.isDeprecated();
1062  THI.range =
1063  Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)};
1064  THI.selectionRange = Range{NameBegin, NameEnd};
1065  if (!THI.range.contains(THI.selectionRange)) {
1066  // 'selectionRange' must be contained in 'range', so in cases where clang
1067  // reports unrelated ranges we need to reconcile somehow.
1068  THI.range = THI.selectionRange;
1069  }
1070 
1071  auto FilePath =
1072  getCanonicalPath(SM.getFileEntryForID(SM.getFileID(BeginLoc)), SM);
1073  auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
1074  if (!FilePath || !TUPath)
1075  return llvm::None; // Not useful without a uri.
1076  THI.uri = URIForFile::canonicalize(*FilePath, *TUPath);
1077 
1078  return THI;
1079 }
1080 
1081 static Optional<TypeHierarchyItem>
1083  PathRef TUPath) {
1084  auto Loc = symbolToLocation(S, TUPath);
1085  if (!Loc) {
1086  log("Type hierarchy: {0}", Loc.takeError());
1087  return llvm::None;
1088  }
1089  TypeHierarchyItem THI;
1090  THI.name = S.Name;
1092  THI.deprecated = (S.Flags & Symbol::Deprecated);
1093  THI.selectionRange = Loc->range;
1094  // FIXME: Populate 'range' correctly
1095  // (https://github.com/clangd/clangd/issues/59).
1096  THI.range = THI.selectionRange;
1097  THI.uri = Loc->uri;
1098  // Store the SymbolID in the 'data' field. The client will
1099  // send this back in typeHierarchy/resolve, allowing us to
1100  // continue resolving additional levels of the type hierarchy.
1101  THI.data = S.ID.str();
1102 
1103  return std::move(THI);
1104 }
1105 
1106 static void fillSubTypes(const SymbolID &ID,
1107  std::vector<TypeHierarchyItem> &SubTypes,
1108  const SymbolIndex *Index, int Levels, PathRef TUPath) {
1109  RelationsRequest Req;
1110  Req.Subjects.insert(ID);
1112  Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
1113  if (Optional<TypeHierarchyItem> ChildSym =
1114  symbolToTypeHierarchyItem(Object, Index, TUPath)) {
1115  if (Levels > 1) {
1116  ChildSym->children.emplace();
1117  fillSubTypes(Object.ID, *ChildSym->children, Index, Levels - 1, TUPath);
1118  }
1119  SubTypes.emplace_back(std::move(*ChildSym));
1120  }
1121  });
1122 }
1123 
1124 using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>;
1125 
1126 static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
1127  std::vector<TypeHierarchyItem> &SuperTypes,
1128  RecursionProtectionSet &RPSet) {
1129  // typeParents() will replace dependent template specializations
1130  // with their class template, so to avoid infinite recursion for
1131  // certain types of hierarchies, keep the templates encountered
1132  // along the parent chain in a set, and stop the recursion if one
1133  // starts to repeat.
1134  auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr;
1135  if (Pattern) {
1136  if (!RPSet.insert(Pattern).second) {
1137  return;
1138  }
1139  }
1140 
1141  for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) {
1142  if (Optional<TypeHierarchyItem> ParentSym =
1143  declToTypeHierarchyItem(ASTCtx, *ParentDecl)) {
1144  ParentSym->parents.emplace();
1145  fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet);
1146  SuperTypes.emplace_back(std::move(*ParentSym));
1147  }
1148  }
1149 
1150  if (Pattern) {
1151  RPSet.erase(Pattern);
1152  }
1153 }
1154 
1155 const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) {
1156  const SourceManager &SM = AST.getSourceManager();
1157  SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation(
1158  getBeginningOfIdentifier(Pos, SM, AST.getASTContext().getLangOpts()));
1159  auto Decls = getDeclAtPosition(AST, SourceLocationBeg);
1160  if (Decls.empty())
1161  return nullptr;
1162 
1163  const Decl *D = Decls[0];
1164 
1165  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1166  // If this is a variable, use the type of the variable.
1167  return VD->getType().getTypePtr()->getAsCXXRecordDecl();
1168  }
1169 
1170  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
1171  // If this is a method, use the type of the class.
1172  return Method->getParent();
1173  }
1174 
1175  // We don't handle FieldDecl because it's not clear what behaviour
1176  // the user would expect: the enclosing class type (as with a
1177  // method), or the field's type (as with a variable).
1178 
1179  return dyn_cast<CXXRecordDecl>(D);
1180 }
1181 
1182 std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD) {
1183  std::vector<const CXXRecordDecl *> Result;
1184 
1185  for (auto Base : CXXRD->bases()) {
1186  const CXXRecordDecl *ParentDecl = nullptr;
1187 
1188  const Type *Type = Base.getType().getTypePtr();
1189  if (const RecordType *RT = Type->getAs<RecordType>()) {
1190  ParentDecl = RT->getAsCXXRecordDecl();
1191  }
1192 
1193  if (!ParentDecl) {
1194  // Handle a dependent base such as "Base<T>" by using the primary
1195  // template.
1196  if (const TemplateSpecializationType *TS =
1197  Type->getAs<TemplateSpecializationType>()) {
1198  TemplateName TN = TS->getTemplateName();
1199  if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
1200  ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
1201  }
1202  }
1203  }
1204 
1205  if (ParentDecl)
1206  Result.push_back(ParentDecl);
1207  }
1208 
1209  return Result;
1210 }
1211 
1212 llvm::Optional<TypeHierarchyItem>
1213 getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
1214  TypeHierarchyDirection Direction, const SymbolIndex *Index,
1215  PathRef TUPath) {
1216  const CXXRecordDecl *CXXRD = findRecordTypeAt(AST, Pos);
1217  if (!CXXRD)
1218  return llvm::None;
1219 
1220  Optional<TypeHierarchyItem> Result =
1221  declToTypeHierarchyItem(AST.getASTContext(), *CXXRD);
1222  if (!Result)
1223  return Result;
1224 
1225  if (Direction == TypeHierarchyDirection::Parents ||
1226  Direction == TypeHierarchyDirection::Both) {
1227  Result->parents.emplace();
1228 
1229  RecursionProtectionSet RPSet;
1230  fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet);
1231  }
1232 
1233  if ((Direction == TypeHierarchyDirection::Children ||
1234  Direction == TypeHierarchyDirection::Both) &&
1235  ResolveLevels > 0) {
1236  Result->children.emplace();
1237 
1238  if (Index) {
1239  if (Optional<SymbolID> ID = getSymbolID(CXXRD))
1240  fillSubTypes(*ID, *Result->children, Index, ResolveLevels, TUPath);
1241  }
1242  }
1243 
1244  return Result;
1245 }
1246 
1247 void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels,
1248  TypeHierarchyDirection Direction,
1249  const SymbolIndex *Index) {
1250  // We only support typeHierarchy/resolve for children, because for parents
1251  // we ignore ResolveLevels and return all levels of parents eagerly.
1252  if (Direction == TypeHierarchyDirection::Parents || ResolveLevels == 0)
1253  return;
1254 
1255  Item.children.emplace();
1256 
1257  if (Index && Item.data) {
1258  // We store the item's SymbolID in the 'data' field, and the client
1259  // passes it back to us in typeHierarchy/resolve.
1260  if (Expected<SymbolID> ID = SymbolID::fromStr(*Item.data)) {
1261  fillSubTypes(*ID, *Item.children, Index, ResolveLevels, Item.uri.file());
1262  }
1263  }
1264 }
1265 
1267  FormattedString Output;
1268  if (NamespaceScope) {
1269  Output.appendText("Declared in");
1270  // Drop trailing "::".
1271  if (!LocalScope.empty())
1272  Output.appendInlineCode(llvm::StringRef(LocalScope).drop_back(2));
1273  else if (NamespaceScope->empty())
1274  Output.appendInlineCode("global namespace");
1275  else
1276  Output.appendInlineCode(llvm::StringRef(*NamespaceScope).drop_back(2));
1277  }
1278 
1279  if (!Definition.empty()) {
1280  Output.appendCodeBlock(Definition);
1281  } else {
1282  // Builtin types
1283  Output.appendCodeBlock(Name);
1284  }
1285 
1286  if (!Documentation.empty())
1287  Output.appendText(Documentation);
1288  return Output;
1289 }
1290 
1291 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1292  const HoverInfo::Param &P) {
1293  std::vector<llvm::StringRef> Output;
1294  if (P.Type)
1295  Output.push_back(*P.Type);
1296  if (P.Name)
1297  Output.push_back(*P.Name);
1298  OS << llvm::join(Output, " ");
1299  if (P.Default)
1300  OS << " = " << *P.Default;
1301  return OS;
1302 }
1303 
1304 llvm::DenseSet<const Decl *> getNonLocalDeclRefs(ParsedAST &AST,
1305  const FunctionDecl *FD) {
1306  if (!FD->hasBody())
1307  return {};
1308  llvm::DenseSet<const Decl *> DeclRefs;
1310  for (const Decl *D : Ref.Targets) {
1311  if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() &&
1312  !Ref.IsDecl)
1313  DeclRefs.insert(D);
1314  }
1315  });
1316  return DeclRefs;
1317 }
1318 } // namespace clangd
1319 } // namespace clang
llvm::Optional< QualType > getDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg)
Retrieves the deduced type at a given location (auto, decltype).
Definition: XRefs.cpp:855
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...
std::string USR
Unified Symbol Resolution identifier This is an opaque string uniquely identifying a symbol...
Definition: Protocol.h:857
int Limit
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:126
static llvm::Optional< TypeHierarchyItem > declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND)
Definition: XRefs.cpp:1035
Contains detailed information about a Symbol.
Definition: XRefs.h:60
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:1165
SourceLocation findName(const clang::Decl *D)
Find the identifier source location of the given D.
Definition: AST.cpp:83
static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, std::vector< TypeHierarchyItem > &SuperTypes, RecursionProtectionSet &RPSet)
Definition: XRefs.cpp:1126
llvm::DenseSet< SymbolID > IDs
Definition: Index.h:68
static Optional< TypeHierarchyItem > symbolToTypeHierarchyItem(const Symbol &S, const SymbolIndex *Index, PathRef TUPath)
Definition: XRefs.cpp:1082
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:87
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Definition: AST.cpp:199
Range range
The range this highlight applies to.
Definition: Protocol.h:1094
Preprocessor & getPreprocessor()
Definition: ParsedAST.cpp:430
Information about a reference written in the source code, independent of the actual AST node that thi...
Definition: FindTarget.h:84
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
Definition: SymbolID.cpp:35
llvm::SmallSet< const CXXRecordDecl *, 4 > RecursionProtectionSet
Definition: XRefs.cpp:1124
const MacroInfo * Info
Definition: SourceCode.h:267
void appendText(std::string Text)
Append plain text to the end of the string.
void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index)
Definition: XRefs.cpp:1247
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:85
llvm::Optional< std::string > Name
None for unnamed parameters.
Definition: XRefs.h:71
llvm::DenseSet< SymbolID > IDs
Definition: Index.h:64
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
Definition: SourceCode.cpp:602
unsigned EndOffset
Definition: Selection.cpp:113
SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind)
Definition: Protocol.cpp:216
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
Definition: SourceCode.cpp:537
static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index)
Generate a Hover object given the declaration D.
Definition: XRefs.cpp:611
Represents a symbol occurrence in the source file.
Definition: Ref.h:52
llvm::Optional< Location > Definition
Definition: XRefs.h:44
SourceLocation getBeginningOfIdentifier(const Position &Pos, const SourceManager &SM, const LangOptions &LangOpts)
Get the beginning SourceLocation at a specified Pos in the main file.
Definition: SourceCode.cpp:279
llvm::Optional< std::string > data
An optional &#39;data&#39; filed, which can be used to identify a type hierarchy item in a resolve request...
Definition: Protocol.h:1169
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:184
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
std::vector< CodeCompletionResult > Results
std::string name
The human readable name of the hierarchy item.
Definition: Protocol.h:1131
llvm::Optional< std::string > Type
Pretty-printed variable type.
Definition: XRefs.h:102
Documents should not be synced at all.
Range selectionRange
The range that should be selected and revealed when this type hierarchy item is being picked...
Definition: Protocol.h:1155
llvm::Optional< std::vector< Param > > Parameters
Set for functions, lambdas and macros with parameters.
Definition: XRefs.h:106
FormattedString present() const
Produce a user-readable information.
Definition: XRefs.cpp:1266
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
A structured string representation that could be converted to markdown or plaintext upon requrest...
Range range
The range enclosing this type hierarchy item not including leading/trailing whitespace but everything...
Definition: Protocol.h:1150
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:424
Represents parameters of a function, a template or a macro.
Definition: XRefs.h:66
static std::string getNamespaceScope(const Decl *D)
Returns the human-readable representation for namespace containing the declaration D...
Definition: XRefs.cpp:483
SymbolID ID
The ID of the symbol.
Definition: Symbol.h:38
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
Definition: Symbol.h:40
std::string Definition
Source code containing the definition of the symbol.
Definition: XRefs.h:98
std::string uri() const
Definition: Protocol.h:96
BindArgumentKind Kind
llvm::Optional< std::string > Type
The pretty-printed parameter type, e.g.
Definition: XRefs.h:69
A document highlight is a range inside a text document which deserves special attention.
Definition: Protocol.h:1092
static void printParams(llvm::raw_ostream &OS, const std::vector< HoverInfo::Param > &Params)
Definition: XRefs.cpp:506
SymbolLocation Definition
The location of the symbol&#39;s definition, if one was found.
Definition: Symbol.h:47
llvm::Optional< SymbolID > ID
Definition: Protocol.h:859
Context Ctx
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:983
std::string Name
Name of the symbol, does not contain any "::".
Definition: XRefs.h:91
std::string QName
static std::string getLocalScope(const Decl *D)
Given a declaration D, return a human-readable string representing the local scope in which it is dec...
Definition: XRefs.cpp:458
llvm::Optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, format::FormatStyle Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition: XRefs.cpp:880
const IncludeStructure & getIncludeStructure() const
Definition: ParsedAST.cpp:480
clang::find_all_symbols::SymbolInfo SymbolInfo
static llvm::Expected< URIForFile > fromURI(const URI &U, llvm::StringRef HintPath)
Definition: Protocol.cpp:45
SymbolFlag Flags
Definition: Symbol.h:128
SymbolLocation Location
The source location where the symbol is named.
Definition: Ref.h:54
std::string str() const
Definition: SymbolID.cpp:33
void log(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
index::SymbolRoleSet Role
Definition: XRefs.cpp:353
llvm::Optional< std::string > Default
None if no default is provided.
Definition: XRefs.h:73
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
Definition: Symbol.h:76
static void enhanceFromIndex(HoverInfo &Hover, const Decl *D, const SymbolIndex *Index)
Definition: XRefs.cpp:587
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:32
static constexpr llvm::StringLiteral Name
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
Definition: Symbol.h:56
Location PreferredDeclaration
Definition: XRefs.h:42
Symbol mergeSymbol(const Symbol &L, const Symbol &R)
Definition: Merge.cpp:165
virtual void refs(const RefsRequest &Req, llvm::function_ref< void(const Ref &)> Callback) const =0
Finds all occurrences (e.g.
const Decl * D
Definition: XRefs.cpp:849
void appendInlineCode(std::string Code)
Append an inline block of C++ code.
static void fillSubTypes(const SymbolID &ID, std::vector< TypeHierarchyItem > &SubTypes, const SymbolIndex *Index, int Levels, PathRef TUPath)
Definition: XRefs.cpp:1106
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Definition: FindTarget.h:96
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:229
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition: XRefs.cpp:412
SourceLocation Loc
Definition: XRefs.cpp:352
llvm::DenseSet< SymbolID > Subjects
Definition: Index.h:77
llvm::Expected< Location > symbolToLocation(const Symbol &Sym, llvm::StringRef HintPath)
Helper function for deriving an LSP Location for a Symbol.
Definition: FindSymbols.cpp:42
std::string LocalScope
Remaining named contexts in symbol&#39;s qualified name, empty string means symbol is not local...
Definition: XRefs.h:89
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:194
llvm::Optional< std::string > NamespaceScope
For a variable named Bar, declared in clang::clangd::Foo::getFoo the following fields will hold: ...
Definition: XRefs.h:86
Stores and provides access to parsed AST.
Definition: ParsedAST.h:46
llvm::Optional< std::vector< Param > > TemplateParameters
Set for all templates(function, class, variable).
Definition: XRefs.h:108
SourceManager & getSourceManager()
Definition: ParsedAST.h:73
int line
Line position in a document (zero-based).
Definition: Protocol.h:129
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
static bool shouldCollectSymbol(const NamedDecl &ND, const ASTContext &ASTCtx, const Options &Opts, bool IsMainFileSymbol)
Returns true is ND should be collected.
llvm::SmallDenseMap< const Decl *, RelSet > Decls
Definition: FindTarget.cpp:88
bool contains(Position Pos) const
Definition: Protocol.h:173
std::vector< Location > findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index)
Returns reference locations of the symbol at a specified Pos.
Definition: XRefs.cpp:916
The class presents a C++ symbol, e.g.
Definition: Symbol.h:36
std::vector< Inclusion > MainFileIncludes
Definition: Headers.h:111
llvm::Optional< std::string > ReturnType
Set for functions and lambadas.
Definition: XRefs.h:104
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const CXXRecordDecl * findRecordTypeAt(ParsedAST &AST, Position Pos)
Find the record type references at Pos.
Definition: XRefs.cpp:1155
unsigned References
SymbolKind
A symbol kind.
Definition: Protocol.h:300
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out)
Recursively traverse S and report all references explicitly written in the code.
Definition: FindTarget.cpp:708
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
Definition: Symbol.h:42
static PrintingPolicy printingPolicyForDecls(PrintingPolicy Base)
Definition: XRefs.cpp:443
llvm::Optional< uint32_t > Limit
If set, limit the number of refers returned from the index.
Definition: Index.h:73
CharSourceRange Range
SourceRange for the file name.
SourceLocation spellingLocIfSpelled(SourceLocation Loc, const SourceManager &SM)
Returns the spelling location of the token at Loc if isSpelledInSource, otherwise its expansion locat...
Definition: SourceCode.cpp:221
DocumentHighlightKind kind
The highlight kind, default is DocumentHighlightKind.Text.
Definition: Protocol.h:1097
llvm::Optional< std::string > Value
Contains the evaluated value of the symbol if available.
Definition: XRefs.h:110
llvm::Optional< TypeHierarchyItem > getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index, PathRef TUPath)
Get type hierarchy information at Pos.
Definition: XRefs.cpp:1213
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
Definition: SourceCode.cpp:625
SymbolKind kind
The kind of the hierarchy item. For instance, class or interface.
Definition: Protocol.h:1138
static std::string printDefinition(const Decl *D)
Definition: XRefs.cpp:496
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:238
Indicates if the symbol is deprecated.
Definition: Symbol.h:121
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
Definition: URI.cpp:164
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg)
Retrieves the deduced type at a given location (auto, decltype).
Definition: XRefs.cpp:876
std::unique_ptr< GlobalCompilationDatabase > Base
SymbolKind Kind
Scope containing the symbol.
Definition: XRefs.h:95
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
URIForFile uri
The URI of the text document where this type hierarchy item belongs to.
Definition: Protocol.h:1144
unsigned StartOffset
Definition: Selection.cpp:112
std::string Documentation
Definition: XRefs.h:96
void appendCodeBlock(std::string Code, std::string Language="cpp")
Append a block of C++ code.
std::array< uint8_t, 20 > SymbolID
llvm::Optional< DefinedMacro > locateMacroAt(SourceLocation Loc, Preprocessor &PP)
Definition: SourceCode.cpp:965
static std::vector< HoverInfo::Param > fetchTemplateParameters(const TemplateParameterList *Params, const PrintingPolicy &PP)
Definition: XRefs.cpp:516
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...
NodeType Type
bool deprecated
true if the hierarchy item is deprecated. Otherwise, false.
Definition: Protocol.h:1141
Represents information about identifier.
Definition: Protocol.h:847
static const FunctionDecl * getUnderlyingFunction(const Decl *D)
Definition: XRefs.cpp:569
QualType DeducedType
Definition: XRefs.cpp:848
std::vector< const CXXRecordDecl * > typeParents(const CXXRecordDecl *CXXRD)
Given a record type declaration, find its base (parent) types.
Definition: XRefs.cpp:1182
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:1304
llvm::StringRef file() const
Retrieves absolute path to the file.
Definition: Protocol.h:93
const SymbolIndex * Index
Definition: Dexp.cpp:84
static cl::opt< std::string > FormatStyle("format-style", cl::desc(R"( Style for formatting code around applied fixes: - 'none' (default) turns off formatting - 'file' (literally 'file', not a placeholder) uses .clang-format file in the closest parent directory - '{ <json> }' specifies options inline, e.g. -format-style='{BasedOnStyle: llvm, IndentWidth: 8}' - 'llvm', 'google', 'webkit', 'mozilla' See clang-format documentation for the up-to-date information about formatting styles and options. This option overrides the 'FormatStyle` option in .clang-tidy file, if any. )"), cl::init("none"), cl::cat(ClangTidyCategory))