1 //===--- SymbolCollector.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 
9 #include "SymbolCollector.h"
10 #include "AST.h"
11 #include "CodeComplete.h"
12 #include "CodeCompletionStrings.h"
13 #include "ExpectedTypes.h"
14 #include "SourceCode.h"
15 #include "URI.h"
16 #include "index/CanonicalIncludes.h"
17 #include "index/Relation.h"
18 #include "index/SymbolID.h"
19 #include "index/SymbolLocation.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/DeclBase.h"
22 #include "clang/AST/DeclObjC.h"
23 #include "clang/AST/DeclTemplate.h"
24 #include "clang/AST/DeclarationName.h"
25 #include "clang/Basic/LangOptions.h"
26 #include "clang/Basic/SourceLocation.h"
27 #include "clang/Basic/SourceManager.h"
28 #include "clang/Index/IndexSymbol.h"
29 #include "clang/Lex/Preprocessor.h"
30 #include "clang/Lex/Token.h"
31 #include "llvm/ADT/ArrayRef.h"
32 #include "llvm/Support/Casting.h"
33 #include "llvm/Support/FileSystem.h"
34 #include "llvm/Support/Path.h"
35 
36 namespace clang {
37 namespace clangd {
38 namespace {
39 
40 /// If \p ND is a template specialization, returns the described template.
41 /// Otherwise, returns \p ND.
getTemplateOrThis(const NamedDecl & ND)42 const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
43   if (auto *T = ND.getDescribedTemplate())
44     return *T;
45   return ND;
46 }
47 
48 // Checks whether the decl is a private symbol in a header generated by
49 // protobuf compiler.
50 // FIXME: make filtering extensible when there are more use cases for symbol
51 // filters.
isPrivateProtoDecl(const NamedDecl & ND)52 bool isPrivateProtoDecl(const NamedDecl &ND) {
53   const auto &SM = ND.getASTContext().getSourceManager();
54   if (!isProtoFile(nameLocation(ND, SM), SM))
55     return false;
56 
57   // ND without identifier can be operators.
58   if (ND.getIdentifier() == nullptr)
59     return false;
60   auto Name = ND.getIdentifier()->getName();
61   if (!Name.contains('_'))
62     return false;
63   // Nested proto entities (e.g. Message::Nested) have top-level decls
64   // that shouldn't be used (Message_Nested). Ignore them completely.
65   // The nested entities are dangling type aliases, we may want to reconsider
66   // including them in the future.
67   // For enum constants, SOME_ENUM_CONSTANT is not private and should be
68   // indexed. Outer_INNER is private. This heuristic relies on naming style, it
69   // will include OUTER_INNER and exclude some_enum_constant.
70   // FIXME: the heuristic relies on naming style (i.e. no underscore in
71   // user-defined names) and can be improved.
72   return (ND.getKind() != Decl::EnumConstant) || llvm::any_of(Name, islower);
73 }
74 
75 // We only collect #include paths for symbols that are suitable for global code
76 // completion, except for namespaces since #include path for a namespace is hard
77 // to define.
shouldCollectIncludePath(index::SymbolKind Kind)78 bool shouldCollectIncludePath(index::SymbolKind Kind) {
79   using SK = index::SymbolKind;
80   switch (Kind) {
81   case SK::Macro:
82   case SK::Enum:
83   case SK::Struct:
84   case SK::Class:
85   case SK::Union:
86   case SK::TypeAlias:
87   case SK::Using:
88   case SK::Function:
89   case SK::Variable:
90   case SK::EnumConstant:
91   case SK::Concept:
92     return true;
93   default:
94     return false;
95   }
96 }
97 
98 // Return the symbol range of the token at \p TokLoc.
99 std::pair<SymbolLocation::Position, SymbolLocation::Position>
getTokenRange(SourceLocation TokLoc,const SourceManager & SM,const LangOptions & LangOpts)100 getTokenRange(SourceLocation TokLoc, const SourceManager &SM,
101               const LangOptions &LangOpts) {
102   auto CreatePosition = [&SM](SourceLocation Loc) {
103     auto LSPLoc = sourceLocToPosition(SM, Loc);
104     SymbolLocation::Position Pos;
105     Pos.setLine(LSPLoc.line);
106     Pos.setColumn(LSPLoc.character);
107     return Pos;
108   };
109 
110   auto TokenLength = clang::Lexer::MeasureTokenLength(TokLoc, SM, LangOpts);
111   return {CreatePosition(TokLoc),
112           CreatePosition(TokLoc.getLocWithOffset(TokenLength))};
113 }
114 
115 // Checks whether \p ND is a good candidate to be the *canonical* declaration of
116 // its symbol (e.g. a go-to-declaration target). This overrides the default of
117 // using Clang's canonical declaration, which is the first in the TU.
118 //
119 // Example: preferring a class declaration over its forward declaration.
isPreferredDeclaration(const NamedDecl & ND,index::SymbolRoleSet Roles)120 bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) {
121   const auto &SM = ND.getASTContext().getSourceManager();
122   if (isa<TagDecl>(ND))
123     return (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) &&
124            !isInsideMainFile(ND.getLocation(), SM);
125   if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(&ND))
126     return ID->isThisDeclarationADefinition();
127   if (const auto *PD = dyn_cast<ObjCProtocolDecl>(&ND))
128     return PD->isThisDeclarationADefinition();
129   return false;
130 }
131 
toRefKind(index::SymbolRoleSet Roles,bool Spelled=false)132 RefKind toRefKind(index::SymbolRoleSet Roles, bool Spelled = false) {
133   RefKind Result = RefKind::Unknown;
134   if (Roles & static_cast<unsigned>(index::SymbolRole::Declaration))
135     Result |= RefKind::Declaration;
136   if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
137     Result |= RefKind::Definition;
138   if (Roles & static_cast<unsigned>(index::SymbolRole::Reference))
139     Result |= RefKind::Reference;
140   if (Spelled)
141     Result |= RefKind::Spelled;
142   return Result;
143 }
144 
indexableRelation(const index::SymbolRelation & R)145 llvm::Optional<RelationKind> indexableRelation(const index::SymbolRelation &R) {
146   if (R.Roles & static_cast<unsigned>(index::SymbolRole::RelationBaseOf))
147     return RelationKind::BaseOf;
148   if (R.Roles & static_cast<unsigned>(index::SymbolRole::RelationOverrideOf))
149     return RelationKind::OverriddenBy;
150   return None;
151 }
152 
153 // Given a ref contained in enclosing decl `Enclosing`, return
154 // the decl that should be used as that ref's Ref::Container. This is
155 // usually `Enclosing` itself, but in cases where `Enclosing` is not
156 // indexed, we walk further up because Ref::Container should always be
157 // an indexed symbol.
158 // Note: we don't use DeclContext as the container as in some cases
159 // it's useful to use a Decl which is not a DeclContext. For example,
160 // for a ref occurring in the initializer of a namespace-scope variable,
161 // it's useful to use that variable as the container, as otherwise the
162 // next enclosing DeclContext would be a NamespaceDecl or TranslationUnitDecl,
163 // which are both not indexed and less granular than we'd like for use cases
164 // like call hierarchy.
getRefContainer(const Decl * Enclosing,const SymbolCollector::Options & Opts)165 const Decl *getRefContainer(const Decl *Enclosing,
166                             const SymbolCollector::Options &Opts) {
167   while (Enclosing) {
168     const auto *ND = dyn_cast<NamedDecl>(Enclosing);
169     if (ND && SymbolCollector::shouldCollectSymbol(*ND, ND->getASTContext(),
170                                                    Opts, true)) {
171       break;
172     }
173     Enclosing = dyn_cast_or_null<Decl>(Enclosing->getDeclContext());
174   }
175   return Enclosing;
176 }
177 
178 // Check if there is an exact spelling of \p ND at \p Loc.
isSpelled(SourceLocation Loc,const NamedDecl & ND)179 bool isSpelled(SourceLocation Loc, const NamedDecl &ND) {
180   auto Name = ND.getDeclName();
181   const auto NameKind = Name.getNameKind();
182   if (NameKind != DeclarationName::Identifier &&
183       NameKind != DeclarationName::CXXConstructorName)
184     return false;
185   const auto &AST = ND.getASTContext();
186   const auto &SM = AST.getSourceManager();
187   const auto &LO = AST.getLangOpts();
188   clang::Token Tok;
189   if (clang::Lexer::getRawToken(Loc, Tok, SM, LO))
190     return false;
191   auto StrName = Name.getAsString();
192   return clang::Lexer::getSpelling(Tok, SM, LO) == StrName;
193 }
194 } // namespace
195 
196 // Encapsulates decisions about how to record header paths in the index,
197 // including filename normalization, URI conversion etc.
198 // Expensive checks are cached internally.
199 class SymbolCollector::HeaderFileURICache {
200   struct FrameworkUmbrellaSpelling {
201     // Spelling for the public umbrella header, e.g. <Foundation/Foundation.h>
202     llvm::Optional<std::string> PublicHeader;
203     // Spelling for the private umbrella header, e.g.
204     // <Foundation/Foundation_Private.h>
205     llvm::Optional<std::string> PrivateHeader;
206   };
207   // Weird double-indirect access to PP, which might not be ready yet when
208   // HeaderFiles is created but will be by the time it's used.
209   // (IndexDataConsumer::setPreprocessor can happen before or after initialize)
210   Preprocessor *&PP;
211   const SourceManager &SM;
212   const CanonicalIncludes *Includes;
213   llvm::StringRef FallbackDir;
214   llvm::DenseMap<const FileEntry *, const std::string *> CacheFEToURI;
215   llvm::StringMap<std::string> CachePathToURI;
216   llvm::DenseMap<FileID, llvm::StringRef> CacheFIDToInclude;
217   llvm::StringMap<std::string> CachePathToFrameworkSpelling;
218   llvm::StringMap<FrameworkUmbrellaSpelling>
219       CacheFrameworkToUmbrellaHeaderSpelling;
220 
221 public:
HeaderFileURICache(Preprocessor * & PP,const SourceManager & SM,const SymbolCollector::Options & Opts)222   HeaderFileURICache(Preprocessor *&PP, const SourceManager &SM,
223                      const SymbolCollector::Options &Opts)
224       : PP(PP), SM(SM), Includes(Opts.Includes), FallbackDir(Opts.FallbackDir) {
225   }
226 
227   // Returns a canonical URI for the file \p FE.
228   // We attempt to make the path absolute first.
toURI(const FileEntry * FE)229   const std::string &toURI(const FileEntry *FE) {
230     auto R = CacheFEToURI.try_emplace(FE);
231     if (R.second) {
232       auto CanonPath = getCanonicalPath(FE, SM);
233       R.first->second = &toURIInternal(CanonPath ? *CanonPath : FE->getName());
234     }
235     return *R.first->second;
236   }
237 
238   // Returns a canonical URI for \p Path.
239   // If the file is in the FileManager, use that to canonicalize the path.
240   // We attempt to make the path absolute in any case.
toURI(llvm::StringRef Path)241   const std::string &toURI(llvm::StringRef Path) {
242     if (auto File = SM.getFileManager().getFile(Path))
243       return toURI(*File);
244     return toURIInternal(Path);
245   }
246 
247   // Gets a canonical include (URI of the header or <header> or "header") for
248   // header of \p FID (which should usually be the *expansion* file).
249   // This does not account for any per-symbol overrides!
250   // Returns "" if includes should not be inserted for this file.
getIncludeHeader(FileID FID)251   llvm::StringRef getIncludeHeader(FileID FID) {
252     auto R = CacheFIDToInclude.try_emplace(FID);
253     if (R.second)
254       R.first->second = getIncludeHeaderUncached(FID);
255     return R.first->second;
256   }
257 
258 private:
259   // This takes care of making paths absolute and path->URI caching, but no
260   // FileManager-based canonicalization.
toURIInternal(llvm::StringRef Path)261   const std::string &toURIInternal(llvm::StringRef Path) {
262     auto R = CachePathToURI.try_emplace(Path);
263     if (R.second) {
264       llvm::SmallString<256> AbsPath = Path;
265       if (!llvm::sys::path::is_absolute(AbsPath) && !FallbackDir.empty())
266         llvm::sys::fs::make_absolute(FallbackDir, AbsPath);
267       assert(llvm::sys::path::is_absolute(AbsPath) &&
268              "If the VFS can't make paths absolute, a FallbackDir must be "
269              "provided");
270       llvm::sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true);
271       R.first->second = URI::create(AbsPath).toString();
272     }
273     return R.first->second;
274   }
275 
276   struct FrameworkHeaderPath {
277     // Path to the framework directory containing the Headers/PrivateHeaders
278     // directories  e.g. /Frameworks/Foundation.framework/
279     llvm::StringRef HeadersParentDir;
280     // Subpath relative to the Headers or PrivateHeaders dir, e.g. NSObject.h
281     // Note: This is NOT relative to the `HeadersParentDir`.
282     llvm::StringRef HeaderSubpath;
283     // Whether this header is under the PrivateHeaders dir
284     bool IsPrivateHeader;
285   };
286 
287   llvm::Optional<FrameworkHeaderPath>
splitFrameworkHeaderPath(llvm::StringRef Path)288   splitFrameworkHeaderPath(llvm::StringRef Path) {
289     using namespace llvm::sys;
290     path::reverse_iterator I = path::rbegin(Path);
291     path::reverse_iterator Prev = I;
292     path::reverse_iterator E = path::rend(Path);
293     while (I != E) {
294       if (*I == "Headers") {
295         FrameworkHeaderPath HeaderPath;
296         HeaderPath.HeadersParentDir = Path.substr(0, I - E);
297         HeaderPath.HeaderSubpath = Path.substr(Prev - E);
298         HeaderPath.IsPrivateHeader = false;
299         return HeaderPath;
300       }
301       if (*I == "PrivateHeaders") {
302         FrameworkHeaderPath HeaderPath;
303         HeaderPath.HeadersParentDir = Path.substr(0, I - E);
304         HeaderPath.HeaderSubpath = Path.substr(Prev - E);
305         HeaderPath.IsPrivateHeader = true;
306         return HeaderPath;
307       }
308       Prev = I;
309       ++I;
310     }
311     // Unexpected, must not be a framework header.
312     return llvm::None;
313   }
314 
315   // Frameworks typically have an umbrella header of the same name, e.g.
316   // <Foundation/Foundation.h> instead of <Foundation/NSObject.h> or
317   // <Foundation/Foundation_Private.h> instead of
318   // <Foundation/NSObject_Private.h> which should be used instead of directly
319   // importing the header.
getFrameworkUmbrellaSpelling(llvm::StringRef Framework,SrcMgr::CharacteristicKind HeadersDirKind,HeaderSearch & HS,FrameworkHeaderPath & HeaderPath)320   llvm::Optional<std::string> getFrameworkUmbrellaSpelling(
321       llvm::StringRef Framework, SrcMgr::CharacteristicKind HeadersDirKind,
322       HeaderSearch &HS, FrameworkHeaderPath &HeaderPath) {
323     auto Res = CacheFrameworkToUmbrellaHeaderSpelling.try_emplace(Framework);
324     auto *CachedSpelling = &Res.first->second;
325     if (!Res.second) {
326       return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
327                                         : CachedSpelling->PublicHeader;
328     }
329     bool IsSystem = isSystem(HeadersDirKind);
330     SmallString<256> UmbrellaPath(HeaderPath.HeadersParentDir);
331     llvm::sys::path::append(UmbrellaPath, "Headers", Framework + ".h");
332 
333     llvm::vfs::Status Status;
334     auto StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
335     if (!StatErr) {
336       if (IsSystem)
337         CachedSpelling->PublicHeader = llvm::formatv("<{0}/{0}.h>", Framework);
338       else
339         CachedSpelling->PublicHeader =
340             llvm::formatv("\"{0}/{0}.h\"", Framework);
341     }
342 
343     UmbrellaPath = HeaderPath.HeadersParentDir;
344     llvm::sys::path::append(UmbrellaPath, "PrivateHeaders",
345                             Framework + "_Private.h");
346 
347     StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
348     if (!StatErr) {
349       if (IsSystem)
350         CachedSpelling->PrivateHeader =
351             llvm::formatv("<{0}/{0}_Private.h>", Framework);
352       else
353         CachedSpelling->PrivateHeader =
354             llvm::formatv("\"{0}/{0}_Private.h\"", Framework);
355     }
356     return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
357                                       : CachedSpelling->PublicHeader;
358   }
359 
360   // Compute the framework include spelling for `FE` which is in a framework
361   // named `Framework`, e.g. `NSObject.h` in framework `Foundation` would
362   // give <Foundation/Foundation.h> if the umbrella header exists, otherwise
363   // <Foundation/NSObject.h>.
getFrameworkHeaderIncludeSpelling(const FileEntry * FE,llvm::StringRef Framework,HeaderSearch & HS)364   llvm::Optional<llvm::StringRef> getFrameworkHeaderIncludeSpelling(
365       const FileEntry *FE, llvm::StringRef Framework, HeaderSearch &HS) {
366     auto Res = CachePathToFrameworkSpelling.try_emplace(FE->getName());
367     auto *CachedHeaderSpelling = &Res.first->second;
368     if (!Res.second)
369       return llvm::StringRef(*CachedHeaderSpelling);
370 
371     auto HeaderPath = splitFrameworkHeaderPath(FE->getName());
372     if (!HeaderPath) {
373       // Unexpected: must not be a proper framework header, don't cache the
374       // failure.
375       CachePathToFrameworkSpelling.erase(Res.first);
376       return llvm::None;
377     }
378     auto DirKind = HS.getFileDirFlavor(FE);
379     if (auto UmbrellaSpelling =
380             getFrameworkUmbrellaSpelling(Framework, DirKind, HS, *HeaderPath)) {
381       *CachedHeaderSpelling = *UmbrellaSpelling;
382       return llvm::StringRef(*CachedHeaderSpelling);
383     }
384 
385     if (isSystem(DirKind))
386       *CachedHeaderSpelling =
387           llvm::formatv("<{0}/{1}>", Framework, HeaderPath->HeaderSubpath)
388               .str();
389     else
390       *CachedHeaderSpelling =
391           llvm::formatv("\"{0}/{1}\"", Framework, HeaderPath->HeaderSubpath)
392               .str();
393     return llvm::StringRef(*CachedHeaderSpelling);
394   }
395 
getIncludeHeaderUncached(FileID FID)396   llvm::StringRef getIncludeHeaderUncached(FileID FID) {
397     const FileEntry *FE = SM.getFileEntryForID(FID);
398     if (!FE || FE->getName().empty())
399       return "";
400     llvm::StringRef Filename = FE->getName();
401     // If a file is mapped by canonical headers, use that mapping, regardless
402     // of whether it's an otherwise-good header (header guards etc).
403     if (Includes) {
404       llvm::StringRef Canonical =
405           Includes->mapHeader(*SM.getFileEntryRefForID(FID));
406       if (!Canonical.empty()) {
407         // If we had a mapping, always use it.
408         if (Canonical.startswith("<") || Canonical.startswith("\""))
409           return Canonical;
410         return toURI(Canonical);
411       }
412     }
413     // Framework headers are spelled as <FrameworkName/Foo.h>, not
414     // "path/FrameworkName.framework/Headers/Foo.h".
415     auto &HS = PP->getHeaderSearchInfo();
416     if (const auto *HFI = HS.getExistingFileInfo(FE, /*WantExternal*/ false))
417       if (!HFI->Framework.empty())
418         if (auto Spelling =
419                 getFrameworkHeaderIncludeSpelling(FE, HFI->Framework, HS))
420           return *Spelling;
421 
422     if (!isSelfContainedHeader(FE, FID, PP->getSourceManager(),
423                                PP->getHeaderSearchInfo())) {
424       // A .inc or .def file is often included into a real header to define
425       // symbols (e.g. LLVM tablegen files).
426       if (Filename.endswith(".inc") || Filename.endswith(".def"))
427         // Don't use cache reentrantly due to iterator invalidation.
428         return getIncludeHeaderUncached(SM.getFileID(SM.getIncludeLoc(FID)));
429       // Conservatively refuse to insert #includes to files without guards.
430       return "";
431     }
432     // Standard case: just insert the file itself.
433     return toURI(FE);
434   }
435 };
436 
437 // Return the symbol location of the token at \p TokLoc.
438 llvm::Optional<SymbolLocation>
getTokenLocation(SourceLocation TokLoc)439 SymbolCollector::getTokenLocation(SourceLocation TokLoc) {
440   const auto &SM = ASTCtx->getSourceManager();
441   auto *FE = SM.getFileEntryForID(SM.getFileID(TokLoc));
442   if (!FE)
443     return None;
444 
445   SymbolLocation Result;
446   Result.FileURI = HeaderFileURIs->toURI(FE).c_str();
447   auto Range = getTokenRange(TokLoc, SM, ASTCtx->getLangOpts());
448   Result.Start = Range.first;
449   Result.End = Range.second;
450 
451   return Result;
452 }
453 
SymbolCollector(Options Opts)454 SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
455 SymbolCollector::~SymbolCollector() = default;
456 
initialize(ASTContext & Ctx)457 void SymbolCollector::initialize(ASTContext &Ctx) {
458   ASTCtx = &Ctx;
459   HeaderFileURIs = std::make_unique<HeaderFileURICache>(
460       this->PP, ASTCtx->getSourceManager(), Opts);
461   CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
462   CompletionTUInfo =
463       std::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
464 }
465 
shouldCollectSymbol(const NamedDecl & ND,const ASTContext & ASTCtx,const Options & Opts,bool IsMainFileOnly)466 bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
467                                           const ASTContext &ASTCtx,
468                                           const Options &Opts,
469                                           bool IsMainFileOnly) {
470   // Skip anonymous declarations, e.g (anonymous enum/class/struct).
471   if (ND.getDeclName().isEmpty())
472     return false;
473 
474   // Skip main-file symbols if we are not collecting them.
475   if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
476     return false;
477 
478   // Skip symbols in anonymous namespaces in header files.
479   if (!IsMainFileOnly && ND.isInAnonymousNamespace())
480     return false;
481 
482   // For function local symbols, index only classes and its member functions.
483   if (index::isFunctionLocalSymbol(&ND))
484     return isa<RecordDecl>(ND) ||
485            (ND.isCXXInstanceMember() && ND.isFunctionOrFunctionTemplate());
486 
487   // We want most things but not "local" symbols such as symbols inside
488   // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl.
489   // FIXME: Need a matcher for ExportDecl in order to include symbols declared
490   // within an export.
491   const auto *DeclCtx = ND.getDeclContext();
492   switch (DeclCtx->getDeclKind()) {
493   case Decl::TranslationUnit:
494   case Decl::Namespace:
495   case Decl::LinkageSpec:
496   case Decl::Enum:
497   case Decl::ObjCProtocol:
498   case Decl::ObjCInterface:
499   case Decl::ObjCCategory:
500   case Decl::ObjCCategoryImpl:
501   case Decl::ObjCImplementation:
502     break;
503   default:
504     // Record has a few derivations (e.g. CXXRecord, Class specialization), it's
505     // easier to cast.
506     if (!isa<RecordDecl>(DeclCtx))
507       return false;
508   }
509 
510   // Avoid indexing internal symbols in protobuf generated headers.
511   if (isPrivateProtoDecl(ND))
512     return false;
513   if (!Opts.CollectReserved &&
514       (hasReservedName(ND) || hasReservedScope(*ND.getDeclContext())))
515     return false;
516 
517   return true;
518 }
519 
520 // Always return true to continue indexing.
handleDeclOccurrence(const Decl * D,index::SymbolRoleSet Roles,llvm::ArrayRef<index::SymbolRelation> Relations,SourceLocation Loc,index::IndexDataConsumer::ASTNodeInfo ASTNode)521 bool SymbolCollector::handleDeclOccurrence(
522     const Decl *D, index::SymbolRoleSet Roles,
523     llvm::ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
524     index::IndexDataConsumer::ASTNodeInfo ASTNode) {
525   assert(ASTCtx && PP && HeaderFileURIs);
526   assert(CompletionAllocator && CompletionTUInfo);
527   assert(ASTNode.OrigD);
528   // Indexing API puts canonical decl into D, which might not have a valid
529   // source location for implicit/built-in decls. Fallback to original decl in
530   // such cases.
531   if (D->getLocation().isInvalid())
532     D = ASTNode.OrigD;
533   // If OrigD is an declaration associated with a friend declaration and it's
534   // not a definition, skip it. Note that OrigD is the occurrence that the
535   // collector is currently visiting.
536   if ((ASTNode.OrigD->getFriendObjectKind() !=
537        Decl::FriendObjectKind::FOK_None) &&
538       !(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
539     return true;
540   // A declaration created for a friend declaration should not be used as the
541   // canonical declaration in the index. Use OrigD instead, unless we've already
542   // picked a replacement for D
543   if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
544     D = CanonicalDecls.try_emplace(D, ASTNode.OrigD).first->second;
545   // Flag to mark that D should be considered canonical meaning its declaration
546   // will override any previous declaration for the Symbol.
547   bool DeclIsCanonical = false;
548   // Avoid treating ObjCImplementationDecl as a canonical declaration if it has
549   // a corresponding non-implicit and non-forward declared ObjcInterfaceDecl.
550   if (const auto *IID = dyn_cast<ObjCImplementationDecl>(D)) {
551     DeclIsCanonical = true;
552     if (const auto *CID = IID->getClassInterface())
553       if (const auto *DD = CID->getDefinition())
554         if (!DD->isImplicitInterfaceDecl())
555           D = DD;
556   }
557   // Avoid treating ObjCCategoryImplDecl as a canonical declaration in favor of
558   // its ObjCCategoryDecl if it has one.
559   if (const auto *CID = dyn_cast<ObjCCategoryImplDecl>(D)) {
560     DeclIsCanonical = true;
561     if (const auto *CD = CID->getCategoryDecl())
562       D = CD;
563   }
564   const NamedDecl *ND = dyn_cast<NamedDecl>(D);
565   if (!ND)
566     return true;
567 
568   auto ID = getSymbolIDCached(ND);
569   if (!ID)
570     return true;
571 
572   // Mark D as referenced if this is a reference coming from the main file.
573   // D may not be an interesting symbol, but it's cheaper to check at the end.
574   auto &SM = ASTCtx->getSourceManager();
575   if (Opts.CountReferences &&
576       (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
577       SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
578     ReferencedSymbols.insert(ID);
579 
580   // ND is the canonical (i.e. first) declaration. If it's in the main file
581   // (which is not a header), then no public declaration was visible, so assume
582   // it's main-file only.
583   bool IsMainFileOnly =
584       SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc())) &&
585       !isHeaderFile(SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
586                     ASTCtx->getLangOpts());
587   // In C, printf is a redecl of an implicit builtin! So check OrigD instead.
588   if (ASTNode.OrigD->isImplicit() ||
589       !shouldCollectSymbol(*ND, *ASTCtx, Opts, IsMainFileOnly))
590     return true;
591 
592   // Note: we need to process relations for all decl occurrences, including
593   // refs, because the indexing code only populates relations for specific
594   // occurrences. For example, RelationBaseOf is only populated for the
595   // occurrence inside the base-specifier.
596   processRelations(*ND, ID, Relations);
597 
598   bool CollectRef = static_cast<bool>(Opts.RefFilter & toRefKind(Roles));
599   // Unlike other fields, e.g. Symbols (which use spelling locations), we use
600   // file locations for references (as it aligns the behavior of clangd's
601   // AST-based xref).
602   // FIXME: we should try to use the file locations for other fields.
603   if (CollectRef &&
604       (!IsMainFileOnly || Opts.CollectMainFileRefs ||
605        ND->isExternallyVisible()) &&
606       !isa<NamespaceDecl>(ND)) {
607     auto FileLoc = SM.getFileLoc(Loc);
608     auto FID = SM.getFileID(FileLoc);
609     if (Opts.RefsInHeaders || FID == SM.getMainFileID()) {
610       addRef(ID, SymbolRef{FileLoc, FID, Roles,
611                            getRefContainer(ASTNode.Parent, Opts),
612                            isSpelled(FileLoc, *ND)});
613     }
614   }
615   // Don't continue indexing if this is a mere reference.
616   if (!(Roles & (static_cast<unsigned>(index::SymbolRole::Declaration) |
617                  static_cast<unsigned>(index::SymbolRole::Definition))))
618     return true;
619 
620   // FIXME: ObjCPropertyDecl are not properly indexed here:
621   // - ObjCPropertyDecl may have an OrigD of ObjCPropertyImplDecl, which is
622   // not a NamedDecl.
623   auto *OriginalDecl = dyn_cast<NamedDecl>(ASTNode.OrigD);
624   if (!OriginalDecl)
625     return true;
626 
627   const Symbol *BasicSymbol = Symbols.find(ID);
628   if (isPreferredDeclaration(*OriginalDecl, Roles))
629     // If OriginalDecl is preferred, replace/create the existing canonical
630     // declaration (e.g. a class forward declaration). There should be at most
631     // one duplicate as we expect to see only one preferred declaration per
632     // TU, because in practice they are definitions.
633     BasicSymbol = addDeclaration(*OriginalDecl, std::move(ID), IsMainFileOnly);
634   else if (!BasicSymbol || DeclIsCanonical)
635     BasicSymbol = addDeclaration(*ND, std::move(ID), IsMainFileOnly);
636 
637   if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
638     addDefinition(*OriginalDecl, *BasicSymbol);
639 
640   return true;
641 }
642 
handleMacros(const MainFileMacros & MacroRefsToIndex)643 void SymbolCollector::handleMacros(const MainFileMacros &MacroRefsToIndex) {
644   assert(HeaderFileURIs && PP);
645   const auto &SM = PP->getSourceManager();
646   const auto *MainFileEntry = SM.getFileEntryForID(SM.getMainFileID());
647   assert(MainFileEntry);
648 
649   const std::string &MainFileURI = HeaderFileURIs->toURI(MainFileEntry);
650   // Add macro references.
651   for (const auto &IDToRefs : MacroRefsToIndex.MacroRefs) {
652     for (const auto &MacroRef : IDToRefs.second) {
653       const auto &Range = MacroRef.Rng;
654       bool IsDefinition = MacroRef.IsDefinition;
655       Ref R;
656       R.Location.Start.setLine(Range.start.line);
657       R.Location.Start.setColumn(Range.start.character);
658       R.Location.End.setLine(Range.end.line);
659       R.Location.End.setColumn(Range.end.character);
660       R.Location.FileURI = MainFileURI.c_str();
661       R.Kind = IsDefinition ? RefKind::Definition : RefKind::Reference;
662       Refs.insert(IDToRefs.first, R);
663       if (IsDefinition) {
664         Symbol S;
665         S.ID = IDToRefs.first;
666         auto StartLoc = cantFail(sourceLocationInMainFile(SM, Range.start));
667         auto EndLoc = cantFail(sourceLocationInMainFile(SM, Range.end));
668         S.Name = toSourceCode(SM, SourceRange(StartLoc, EndLoc));
669         S.SymInfo.Kind = index::SymbolKind::Macro;
670         S.SymInfo.SubKind = index::SymbolSubKind::None;
671         S.SymInfo.Properties = index::SymbolPropertySet();
672         S.SymInfo.Lang = index::SymbolLanguage::C;
673         S.Origin = Opts.Origin;
674         S.CanonicalDeclaration = R.Location;
675         // Make the macro visible for code completion if main file is an
676         // include-able header.
677         if (!HeaderFileURIs->getIncludeHeader(SM.getMainFileID()).empty()) {
678           S.Flags |= Symbol::IndexedForCodeCompletion;
679           S.Flags |= Symbol::VisibleOutsideFile;
680         }
681         Symbols.insert(S);
682       }
683     }
684   }
685 }
686 
handleMacroOccurrence(const IdentifierInfo * Name,const MacroInfo * MI,index::SymbolRoleSet Roles,SourceLocation Loc)687 bool SymbolCollector::handleMacroOccurrence(const IdentifierInfo *Name,
688                                             const MacroInfo *MI,
689                                             index::SymbolRoleSet Roles,
690                                             SourceLocation Loc) {
691   assert(PP);
692   // Builtin macros don't have useful locations and aren't needed in completion.
693   if (MI->isBuiltinMacro())
694     return true;
695 
696   const auto &SM = PP->getSourceManager();
697   auto DefLoc = MI->getDefinitionLoc();
698   // Also avoid storing predefined macros like __DBL_MIN__.
699   if (SM.isWrittenInBuiltinFile(DefLoc) ||
700       Name->getName() == "__GCC_HAVE_DWARF2_CFI_ASM")
701     return true;
702 
703   auto ID = getSymbolIDCached(Name->getName(), MI, SM);
704   if (!ID)
705     return true;
706 
707   auto SpellingLoc = SM.getSpellingLoc(Loc);
708   bool IsMainFileOnly =
709       SM.isInMainFile(SM.getExpansionLoc(DefLoc)) &&
710       !isHeaderFile(SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
711                     ASTCtx->getLangOpts());
712   // Do not store references to main-file macros.
713   if ((static_cast<unsigned>(Opts.RefFilter) & Roles) && !IsMainFileOnly &&
714       (Opts.RefsInHeaders || SM.getFileID(SpellingLoc) == SM.getMainFileID())) {
715     // FIXME: Populate container information for macro references.
716     // FIXME: All MacroRefs are marked as Spelled now, but this should be
717     // checked.
718     addRef(ID, SymbolRef{Loc, SM.getFileID(Loc), Roles, /*Container=*/nullptr,
719                          /*Spelled=*/true});
720   }
721 
722   // Collect symbols.
723   if (!Opts.CollectMacro)
724     return true;
725 
726   // Skip main-file macros if we are not collecting them.
727   if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
728     return false;
729 
730   // Mark the macro as referenced if this is a reference coming from the main
731   // file. The macro may not be an interesting symbol, but it's cheaper to check
732   // at the end.
733   if (Opts.CountReferences &&
734       (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
735       SM.getFileID(SpellingLoc) == SM.getMainFileID())
736     ReferencedSymbols.insert(ID);
737 
738   // Don't continue indexing if this is a mere reference.
739   // FIXME: remove macro with ID if it is undefined.
740   if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
741         Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
742     return true;
743 
744   // Only collect one instance in case there are multiple.
745   if (Symbols.find(ID) != nullptr)
746     return true;
747 
748   Symbol S;
749   S.ID = std::move(ID);
750   S.Name = Name->getName();
751   if (!IsMainFileOnly) {
752     S.Flags |= Symbol::IndexedForCodeCompletion;
753     S.Flags |= Symbol::VisibleOutsideFile;
754   }
755   S.SymInfo = index::getSymbolInfoForMacro(*MI);
756   S.Origin = Opts.Origin;
757   // FIXME: use the result to filter out symbols.
758   shouldIndexFile(SM.getFileID(Loc));
759   if (auto DeclLoc = getTokenLocation(DefLoc))
760     S.CanonicalDeclaration = *DeclLoc;
761 
762   CodeCompletionResult SymbolCompletion(Name);
763   const auto *CCS = SymbolCompletion.CreateCodeCompletionStringForMacro(
764       *PP, *CompletionAllocator, *CompletionTUInfo);
765   std::string Signature;
766   std::string SnippetSuffix;
767   getSignature(*CCS, &Signature, &SnippetSuffix);
768   S.Signature = Signature;
769   S.CompletionSnippetSuffix = SnippetSuffix;
770 
771   IndexedMacros.insert(Name);
772   setIncludeLocation(S, DefLoc);
773   Symbols.insert(S);
774   return true;
775 }
776 
processRelations(const NamedDecl & ND,const SymbolID & ID,ArrayRef<index::SymbolRelation> Relations)777 void SymbolCollector::processRelations(
778     const NamedDecl &ND, const SymbolID &ID,
779     ArrayRef<index::SymbolRelation> Relations) {
780   for (const auto &R : Relations) {
781     auto RKind = indexableRelation(R);
782     if (!RKind)
783       continue;
784     const Decl *Object = R.RelatedSymbol;
785 
786     auto ObjectID = getSymbolIDCached(Object);
787     if (!ObjectID)
788       continue;
789 
790     // Record the relation.
791     // TODO: There may be cases where the object decl is not indexed for some
792     // reason. Those cases should probably be removed in due course, but for
793     // now there are two possible ways to handle it:
794     //   (A) Avoid storing the relation in such cases.
795     //   (B) Store it anyways. Clients will likely lookup() the SymbolID
796     //       in the index and find nothing, but that's a situation they
797     //       probably need to handle for other reasons anyways.
798     // We currently do (B) because it's simpler.
799     if (*RKind == RelationKind::BaseOf)
800       this->Relations.insert({ID, *RKind, ObjectID});
801     else if (*RKind == RelationKind::OverriddenBy)
802       this->Relations.insert({ObjectID, *RKind, ID});
803   }
804 }
805 
setIncludeLocation(const Symbol & S,SourceLocation Loc)806 void SymbolCollector::setIncludeLocation(const Symbol &S, SourceLocation Loc) {
807   if (Opts.CollectIncludePath)
808     if (shouldCollectIncludePath(S.SymInfo.Kind))
809       // Use the expansion location to get the #include header since this is
810       // where the symbol is exposed.
811       IncludeFiles[S.ID] =
812           PP->getSourceManager().getDecomposedExpansionLoc(Loc).first;
813 }
814 
finish()815 void SymbolCollector::finish() {
816   // At the end of the TU, add 1 to the refcount of all referenced symbols.
817   for (const auto &ID : ReferencedSymbols) {
818     if (const auto *S = Symbols.find(ID)) {
819       // SymbolSlab::Builder returns const symbols because strings are interned
820       // and modifying returned symbols without inserting again wouldn't go
821       // well. const_cast is safe here as we're modifying a data owned by the
822       // Symbol. This reduces time spent in SymbolCollector by ~1%.
823       ++const_cast<Symbol *>(S)->References;
824     }
825   }
826   if (Opts.CollectMacro) {
827     assert(PP);
828     // First, drop header guards. We can't identify these until EOF.
829     for (const IdentifierInfo *II : IndexedMacros) {
830       if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
831         if (auto ID =
832                 getSymbolIDCached(II->getName(), MI, PP->getSourceManager()))
833           if (MI->isUsedForHeaderGuard())
834             Symbols.erase(ID);
835     }
836   }
837   // Fill in IncludeHeaders.
838   // We delay this until end of TU so header guards are all resolved.
839   llvm::SmallString<128> QName;
840   for (const auto &Entry : IncludeFiles) {
841     if (const Symbol *S = Symbols.find(Entry.first)) {
842       llvm::StringRef IncludeHeader;
843       // Look for an overridden include header for this symbol specifically.
844       if (Opts.Includes) {
845         QName = S->Scope;
846         QName.append(S->Name);
847         IncludeHeader = Opts.Includes->mapSymbol(QName);
848         if (!IncludeHeader.empty()) {
849           if (IncludeHeader.front() != '"' && IncludeHeader.front() != '<')
850             IncludeHeader = HeaderFileURIs->toURI(IncludeHeader);
851           else if (IncludeHeader == "<utility>" && QName == "std::move" &&
852                    S->Signature.contains(','))
853             IncludeHeader = "<algorithm>";
854         }
855       }
856       // Otherwise find the approprate include header for the defining file.
857       if (IncludeHeader.empty())
858         IncludeHeader = HeaderFileURIs->getIncludeHeader(Entry.second);
859 
860       // Symbols in slabs aren't mutable, insert() has to walk all the strings
861       if (!IncludeHeader.empty()) {
862         Symbol NewSym = *S;
863         NewSym.IncludeHeaders.push_back({IncludeHeader, 1});
864         Symbols.insert(NewSym);
865       }
866     }
867   }
868 
869   ReferencedSymbols.clear();
870   IncludeFiles.clear();
871 }
872 
addDeclaration(const NamedDecl & ND,SymbolID ID,bool IsMainFileOnly)873 const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID,
874                                               bool IsMainFileOnly) {
875   auto &Ctx = ND.getASTContext();
876   auto &SM = Ctx.getSourceManager();
877 
878   Symbol S;
879   S.ID = std::move(ID);
880   std::string QName = printQualifiedName(ND);
881   // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
882   // for consistency with CodeCompletionString and a clean name/signature split.
883   std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
884   std::string TemplateSpecializationArgs = printTemplateSpecializationArgs(ND);
885   S.TemplateSpecializationArgs = TemplateSpecializationArgs;
886 
887   // We collect main-file symbols, but do not use them for code completion.
888   if (!IsMainFileOnly && isIndexedForCodeCompletion(ND, Ctx))
889     S.Flags |= Symbol::IndexedForCodeCompletion;
890   if (isImplementationDetail(&ND))
891     S.Flags |= Symbol::ImplementationDetail;
892   if (!IsMainFileOnly)
893     S.Flags |= Symbol::VisibleOutsideFile;
894   S.SymInfo = index::getSymbolInfo(&ND);
895   auto Loc = nameLocation(ND, SM);
896   assert(Loc.isValid() && "Invalid source location for NamedDecl");
897   // FIXME: use the result to filter out symbols.
898   shouldIndexFile(SM.getFileID(Loc));
899   if (auto DeclLoc = getTokenLocation(Loc))
900     S.CanonicalDeclaration = *DeclLoc;
901 
902   S.Origin = Opts.Origin;
903   if (ND.getAvailability() == AR_Deprecated)
904     S.Flags |= Symbol::Deprecated;
905 
906   // Add completion info.
907   // FIXME: we may want to choose a different redecl, or combine from several.
908   assert(ASTCtx && PP && "ASTContext and Preprocessor must be set.");
909   // We use the primary template, as clang does during code completion.
910   CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
911   const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
912       *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator,
913       *CompletionTUInfo,
914       /*IncludeBriefComments*/ false);
915   std::string Documentation =
916       formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
917                                               /*CommentsFromHeaders=*/true));
918   if (!(S.Flags & Symbol::IndexedForCodeCompletion)) {
919     if (Opts.StoreAllDocumentation)
920       S.Documentation = Documentation;
921     Symbols.insert(S);
922     return Symbols.find(S.ID);
923   }
924   S.Documentation = Documentation;
925   std::string Signature;
926   std::string SnippetSuffix;
927   getSignature(*CCS, &Signature, &SnippetSuffix);
928   S.Signature = Signature;
929   S.CompletionSnippetSuffix = SnippetSuffix;
930   std::string ReturnType = getReturnType(*CCS);
931   S.ReturnType = ReturnType;
932 
933   llvm::Optional<OpaqueType> TypeStorage;
934   if (S.Flags & Symbol::IndexedForCodeCompletion) {
935     TypeStorage = OpaqueType::fromCompletionResult(*ASTCtx, SymbolCompletion);
936     if (TypeStorage)
937       S.Type = TypeStorage->raw();
938   }
939 
940   Symbols.insert(S);
941   setIncludeLocation(S, ND.getLocation());
942   return Symbols.find(S.ID);
943 }
944 
addDefinition(const NamedDecl & ND,const Symbol & DeclSym)945 void SymbolCollector::addDefinition(const NamedDecl &ND,
946                                     const Symbol &DeclSym) {
947   if (DeclSym.Definition)
948     return;
949   const auto &SM = ND.getASTContext().getSourceManager();
950   auto Loc = nameLocation(ND, SM);
951   shouldIndexFile(SM.getFileID(Loc));
952   auto DefLoc = getTokenLocation(Loc);
953   // If we saw some forward declaration, we end up copying the symbol.
954   // This is not ideal, but avoids duplicating the "is this a definition" check
955   // in clang::index. We should only see one definition.
956   if (!DefLoc)
957     return;
958   Symbol S = DeclSym;
959   // FIXME: use the result to filter out symbols.
960   S.Definition = *DefLoc;
961   Symbols.insert(S);
962 }
963 
shouldIndexFile(FileID FID)964 bool SymbolCollector::shouldIndexFile(FileID FID) {
965   if (!Opts.FileFilter)
966     return true;
967   auto I = FilesToIndexCache.try_emplace(FID);
968   if (I.second)
969     I.first->second = Opts.FileFilter(ASTCtx->getSourceManager(), FID);
970   return I.first->second;
971 }
972 
addRef(SymbolID ID,const SymbolRef & SR)973 void SymbolCollector::addRef(SymbolID ID, const SymbolRef &SR) {
974   const auto &SM = ASTCtx->getSourceManager();
975   // FIXME: use the result to filter out references.
976   shouldIndexFile(SR.FID);
977   if (const auto *FE = SM.getFileEntryForID(SR.FID)) {
978     auto Range = getTokenRange(SR.Loc, SM, ASTCtx->getLangOpts());
979     Ref R;
980     R.Location.Start = Range.first;
981     R.Location.End = Range.second;
982     R.Location.FileURI = HeaderFileURIs->toURI(FE).c_str();
983     R.Kind = toRefKind(SR.Roles, SR.Spelled);
984     R.Container = getSymbolIDCached(SR.Container);
985     Refs.insert(ID, R);
986   }
987 }
988 
getSymbolIDCached(const Decl * D)989 SymbolID SymbolCollector::getSymbolIDCached(const Decl *D) {
990   auto It = DeclToIDCache.try_emplace(D, SymbolID{});
991   if (It.second)
992     It.first->second = getSymbolID(D);
993   return It.first->second;
994 }
995 
getSymbolIDCached(const llvm::StringRef MacroName,const MacroInfo * MI,const SourceManager & SM)996 SymbolID SymbolCollector::getSymbolIDCached(const llvm::StringRef MacroName,
997                                             const MacroInfo *MI,
998                                             const SourceManager &SM) {
999   auto It = MacroToIDCache.try_emplace(MI, SymbolID{});
1000   if (It.second)
1001     It.first->second = getSymbolID(MacroName, MI, SM);
1002   return It.first->second;
1003 }
1004 } // namespace clangd
1005 } // namespace clang
1006