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