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().
getDefinition(const Decl * D)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 
logIfOverflow(const SymbolLocation & Loc)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.
toLSPLocation(const SymbolLocation & Loc,llvm::StringRef TUPath)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 
toIndexLocation(const Location & Loc,std::string & URIStorage)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.
getPreferredLocation(const Location & ASTLoc,const SymbolLocation & IdxLoc,std::string & Scratch)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:
DeclarationAndMacrosFinder(const SourceLocation & SearchedLocation,Preprocessor & PP)140   DeclarationAndMacrosFinder(const SourceLocation &SearchedLocation,
141                              Preprocessor &PP)
142       : SearchedLocation(SearchedLocation), PP(PP) {}
143 
144   // The results are sorted by declaration location.
getFoundDecls() const145   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 
takeMacroInfos()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
handleDeclOccurence(const Decl * D,index::SymbolRoleSet Roles,llvm::ArrayRef<index::SymbolRelation> Relations,SourceLocation Loc,index::IndexDataConsumer::ASTNodeInfo ASTNode)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:
finish()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 
getSymbolAtPosition(ParsedAST & AST,SourceLocation Pos)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 
makeLocation(ASTContext & AST,SourceLocation TokLoc,llvm::StringRef TUPath)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 
locateSymbolAt(ParsedAST & AST,Position Pos,const SymbolIndex * Index)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) {
274       LocatedSymbol File;
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 
ReferenceFinder(ASTContext & AST,Preprocessor & PP,const std::vector<const Decl * > & TargetDecls)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 
take()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
handleDeclOccurence(const Decl * D,index::SymbolRoleSet Roles,llvm::ArrayRef<index::SymbolRelation> Relations,SourceLocation Loc,index::IndexDataConsumer::ASTNodeInfo ASTNode)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 (isInsideMainFile(Loc, SM) && 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>
findRefs(const std::vector<const Decl * > & Decls,ParsedAST & AST)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 
findDocumentHighlights(ParsedAST & AST,Position Pos)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)) {
448       DocumentHighlight DH;
449       DH.range = *Range;
450       if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
451         DH.kind = DocumentHighlightKind::Write;
452       else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
453         DH.kind = DocumentHighlightKind::Read;
454       else
455         DH.kind = DocumentHighlightKind::Text;
456       Result.push_back(std::move(DH));
457     }
458   }
459   return Result;
460 }
461 
printingPolicyForDecls(PrintingPolicy Base)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.
getLocalScope(const Decl * D)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.
getNamespaceScope(const Decl * D)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 
printDefinition(const Decl * D)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 
printParams(llvm::raw_ostream & OS,const std::vector<HoverInfo::Param> & Params)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>
fetchTemplateParameters(const TemplateParameterList * Params,const PrintingPolicy & PP)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) {
541     HoverInfo::Param P;
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 
getUnderlyingFunction(const Decl * D)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.
enhanceFromIndex(HoverInfo & Hover,const Decl * D,const SymbolIndex * Index)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(),
617                                             SymbolCollector::Options(),
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.
getHoverContents(const Decl * D,const SymbolIndex * Index)630 static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) {
631   HoverInfo HI;
632   const ASTContext &Ctx = D->getASTContext();
633 
634   HI.NamespaceScope = getNamespaceScope(D);
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 
647   HI.Kind = indexSymbolKindToSymbolKind(index::getSymbolInfo(D).Kind);
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                                Init->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.
getHoverContents(QualType T,const Decl * D,ASTContext & ASTCtx,const SymbolIndex * Index)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) {
738     HI.Kind = indexSymbolKindToSymbolKind(index::getSymbolInfo(D).Kind);
739     enhanceFromIndex(HI, D, Index);
740   }
741   return HI;
742 }
743 
744 /// Generate a \p Hover object given the macro \p MacroDecl.
getHoverContents(const DefinedMacro & Macro,ParsedAST & AST)745 static HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) {
746   HoverInfo HI;
747   SourceManager &SM = AST.getSourceManager();
748   HI.Name = Macro.Name;
749   HI.Kind = indexSymbolKindToSymbolKind(
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:
DeducedTypeVisitor(SourceLocation SearchedLocation)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;
VisitDeclaratorDecl(DeclaratorDecl * D)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; }
VisitFunctionDecl(FunctionDecl * D)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);
VisitDecltypeTypeLoc(DecltypeTypeLoc TL)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
getDeducedType(ParsedAST & AST,SourceLocation SourceLocationBeg)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).
hasDeducedType(ParsedAST & AST,SourceLocation SourceLocationBeg)895 bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg) {
896   return (bool)getDeducedType(AST, SourceLocationBeg);
897 }
898 
getHover(ParsedAST & AST,Position Pos,format::FormatStyle Style,const SymbolIndex * Index)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 
findReferences(ParsedAST & AST,Position Pos,uint32_t Limit,const SymbolIndex * Index)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)) {
957       Location Result;
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 
getSymbolInfo(ParsedAST & AST,Position Pos)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 
operator <<(llvm::raw_ostream & OS,const LocatedSymbol & S)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>
declToTypeHierarchyItem(ASTContext & Ctx,const NamedDecl & ND)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>
symbolToTypeHierarchyItem(const Symbol & S,const SymbolIndex * Index,PathRef TUPath)1091 symbolToTypeHierarchyItem(const Symbol &S, const SymbolIndex *Index,
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;
1100   THI.kind = indexSymbolKindToSymbolKind(S.SymInfo.Kind);
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 
fillSubTypes(const SymbolID & ID,std::vector<TypeHierarchyItem> & SubTypes,const SymbolIndex * Index,int Levels,PathRef TUPath)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 
fillSuperTypes(const CXXRecordDecl & CXXRD,ASTContext & ASTCtx,std::vector<TypeHierarchyItem> & SuperTypes,RecursionProtectionSet & RPSet)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 
findRecordTypeAt(ParsedAST & AST,Position Pos)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 
typeParents(const CXXRecordDecl * CXXRD)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>
getTypeHierarchy(ParsedAST & AST,Position Pos,int ResolveLevels,TypeHierarchyDirection Direction,const SymbolIndex * Index,PathRef TUPath)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 
resolveTypeHierarchy(TypeHierarchyItem & Item,int ResolveLevels,TypeHierarchyDirection Direction,const SymbolIndex * Index)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 
present() const1274 FormattedString HoverInfo::present() const {
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 
operator <<(llvm::raw_ostream & OS,const HoverInfo::Param & P)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
1314