[clang-tools-extra] Adopt FileManager's error-returning APIs
[lldb.git] / clang-tools-extra / clangd / index / SymbolCollector.cpp
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 "CanonicalIncludes.h"
12 #include "CodeComplete.h"
13 #include "CodeCompletionStrings.h"
14 #include "ExpectedTypes.h"
15 #include "Logger.h"
16 #include "SourceCode.h"
17 #include "SymbolLocation.h"
18 #include "URI.h"
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/DeclBase.h"
21 #include "clang/AST/DeclCXX.h"
22 #include "clang/AST/DeclTemplate.h"
23 #include "clang/Basic/SourceLocation.h"
24 #include "clang/Basic/SourceManager.h"
25 #include "clang/Basic/Specifiers.h"
26 #include "clang/Index/IndexSymbol.h"
27 #include "clang/Index/IndexingAction.h"
28 #include "clang/Index/USRGeneration.h"
29 #include "clang/Lex/Preprocessor.h"
30 #include "llvm/Support/Casting.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/Path.h"
34
35 namespace clang {
36 namespace clangd {
37 namespace {
38
39 /// If \p ND is a template specialization, returns the described template.
40 /// Otherwise, returns \p ND.
41 const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
42   if (auto T = ND.getDescribedTemplate())
43     return *T;
44   return ND;
45 }
46
47 // Returns a URI of \p Path. Firstly, this makes the \p Path absolute using the
48 // current working directory of the given SourceManager if the Path is not an
49 // absolute path. If failed, this resolves relative paths against \p FallbackDir
50 // to get an absolute path. Then, this tries creating an URI for the absolute
51 // path with schemes specified in \p Opts. This returns an URI with the first
52 // working scheme, if there is any; otherwise, this returns None.
53 //
54 // The Path can be a path relative to the build directory, or retrieved from
55 // the SourceManager.
56 std::string toURI(const SourceManager &SM, llvm::StringRef Path,
57                   const SymbolCollector::Options &Opts) {
58   llvm::SmallString<128> AbsolutePath(Path);
59   if (auto File = SM.getFileManager().getFile(Path)) {
60     if (auto CanonPath = getCanonicalPath(*File, SM)) {
61       AbsolutePath = *CanonPath;
62     }
63   }
64   // We don't perform is_absolute check in an else branch because makeAbsolute
65   // might return a relative path on some InMemoryFileSystems.
66   if (!llvm::sys::path::is_absolute(AbsolutePath) && !Opts.FallbackDir.empty())
67     llvm::sys::fs::make_absolute(Opts.FallbackDir, AbsolutePath);
68   llvm::sys::path::remove_dots(AbsolutePath, /*remove_dot_dot=*/true);
69   return URI::create(AbsolutePath).toString();
70 }
71
72 // All proto generated headers should start with this line.
73 static const char *PROTO_HEADER_COMMENT =
74     "// Generated by the protocol buffer compiler.  DO NOT EDIT!";
75
76 // Checks whether the decl is a private symbol in a header generated by
77 // protobuf compiler.
78 // To identify whether a proto header is actually generated by proto compiler,
79 // we check whether it starts with PROTO_HEADER_COMMENT.
80 // FIXME: make filtering extensible when there are more use cases for symbol
81 // filters.
82 bool isPrivateProtoDecl(const NamedDecl &ND) {
83   const auto &SM = ND.getASTContext().getSourceManager();
84   auto Loc = findNameLoc(&ND);
85   auto FileName = SM.getFilename(Loc);
86   if (!FileName.endswith(".proto.h") && !FileName.endswith(".pb.h"))
87     return false;
88   auto FID = SM.getFileID(Loc);
89   // Double check that this is an actual protobuf header.
90   if (!SM.getBufferData(FID).startswith(PROTO_HEADER_COMMENT))
91     return false;
92
93   // ND without identifier can be operators.
94   if (ND.getIdentifier() == nullptr)
95     return false;
96   auto Name = ND.getIdentifier()->getName();
97   if (!Name.contains('_'))
98     return false;
99   // Nested proto entities (e.g. Message::Nested) have top-level decls
100   // that shouldn't be used (Message_Nested). Ignore them completely.
101   // The nested entities are dangling type aliases, we may want to reconsider
102   // including them in the future.
103   // For enum constants, SOME_ENUM_CONSTANT is not private and should be
104   // indexed. Outer_INNER is private. This heuristic relies on naming style, it
105   // will include OUTER_INNER and exclude some_enum_constant.
106   // FIXME: the heuristic relies on naming style (i.e. no underscore in
107   // user-defined names) and can be improved.
108   return (ND.getKind() != Decl::EnumConstant) || llvm::any_of(Name, islower);
109 }
110
111 // We only collect #include paths for symbols that are suitable for global code
112 // completion, except for namespaces since #include path for a namespace is hard
113 // to define.
114 bool shouldCollectIncludePath(index::SymbolKind Kind) {
115   using SK = index::SymbolKind;
116   switch (Kind) {
117   case SK::Macro:
118   case SK::Enum:
119   case SK::Struct:
120   case SK::Class:
121   case SK::Union:
122   case SK::TypeAlias:
123   case SK::Using:
124   case SK::Function:
125   case SK::Variable:
126   case SK::EnumConstant:
127     return true;
128   default:
129     return false;
130   }
131 }
132
133 // Return the symbol range of the token at \p TokLoc.
134 std::pair<SymbolLocation::Position, SymbolLocation::Position>
135 getTokenRange(SourceLocation TokLoc, const SourceManager &SM,
136               const LangOptions &LangOpts) {
137   auto CreatePosition = [&SM](SourceLocation Loc) {
138     auto LSPLoc = sourceLocToPosition(SM, Loc);
139     SymbolLocation::Position Pos;
140     Pos.setLine(LSPLoc.line);
141     Pos.setColumn(LSPLoc.character);
142     return Pos;
143   };
144
145   auto TokenLength = clang::Lexer::MeasureTokenLength(TokLoc, SM, LangOpts);
146   return {CreatePosition(TokLoc),
147           CreatePosition(TokLoc.getLocWithOffset(TokenLength))};
148 }
149
150 bool shouldIndexFile(const SourceManager &SM, FileID FID,
151                      const SymbolCollector::Options &Opts,
152                      llvm::DenseMap<FileID, bool> *FilesToIndexCache) {
153   if (!Opts.FileFilter)
154     return true;
155   auto I = FilesToIndexCache->try_emplace(FID);
156   if (I.second)
157     I.first->second = Opts.FileFilter(SM, FID);
158   return I.first->second;
159 }
160
161 // Return the symbol location of the token at \p TokLoc.
162 llvm::Optional<SymbolLocation>
163 getTokenLocation(SourceLocation TokLoc, const SourceManager &SM,
164                  const SymbolCollector::Options &Opts,
165                  const clang::LangOptions &LangOpts,
166                  std::string &FileURIStorage) {
167   auto Path = SM.getFilename(TokLoc);
168   if (Path.empty())
169     return None;
170   FileURIStorage = toURI(SM, Path, Opts);
171   SymbolLocation Result;
172   Result.FileURI = FileURIStorage.c_str();
173   auto Range = getTokenRange(TokLoc, SM, LangOpts);
174   Result.Start = Range.first;
175   Result.End = Range.second;
176
177   return Result;
178 }
179
180 // Checks whether \p ND is a definition of a TagDecl (class/struct/enum/union)
181 // in a header file, in which case clangd would prefer to use ND as a canonical
182 // declaration.
183 // FIXME: handle symbol types that are not TagDecl (e.g. functions), if using
184 // the first seen declaration as canonical declaration is not a good enough
185 // heuristic.
186 bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) {
187   const auto &SM = ND.getASTContext().getSourceManager();
188   return (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) &&
189          isa<TagDecl>(&ND) && !isInsideMainFile(ND.getLocation(), SM);
190 }
191
192 RefKind toRefKind(index::SymbolRoleSet Roles) {
193   return static_cast<RefKind>(static_cast<unsigned>(RefKind::All) & Roles);
194 }
195
196 bool shouldIndexRelation(const index::SymbolRelation &R) {
197   // We currently only index BaseOf relations, for type hierarchy subtypes.
198   return R.Roles & static_cast<unsigned>(index::SymbolRole::RelationBaseOf);
199 }
200
201 } // namespace
202
203 SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
204
205 void SymbolCollector::initialize(ASTContext &Ctx) {
206   ASTCtx = &Ctx;
207   CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
208   CompletionTUInfo =
209       llvm::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
210 }
211
212 bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
213                                           const ASTContext &ASTCtx,
214                                           const Options &Opts,
215                                           bool IsMainFileOnly) {
216   // Skip anonymous declarations, e.g (anonymous enum/class/struct).
217   if (ND.getDeclName().isEmpty())
218     return false;
219
220   // Skip main-file symbols if we are not collecting them.
221   if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
222     return false;
223
224   // Skip symbols in anonymous namespaces in header files.
225   if (!IsMainFileOnly && ND.isInAnonymousNamespace())
226     return false;
227
228   // We want most things but not "local" symbols such as symbols inside
229   // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl.
230   // FIXME: Need a matcher for ExportDecl in order to include symbols declared
231   // within an export.
232   const auto *DeclCtx = ND.getDeclContext();
233   switch (DeclCtx->getDeclKind()) {
234   case Decl::TranslationUnit:
235   case Decl::Namespace:
236   case Decl::LinkageSpec:
237   case Decl::Enum:
238   case Decl::ObjCProtocol:
239   case Decl::ObjCInterface:
240   case Decl::ObjCCategory:
241   case Decl::ObjCCategoryImpl:
242   case Decl::ObjCImplementation:
243     break;
244   default:
245     // Record has a few derivations (e.g. CXXRecord, Class specialization), it's
246     // easier to cast.
247     if (!isa<RecordDecl>(DeclCtx))
248       return false;
249   }
250
251   // Avoid indexing internal symbols in protobuf generated headers.
252   if (isPrivateProtoDecl(ND))
253     return false;
254   return true;
255 }
256
257 // Always return true to continue indexing.
258 bool SymbolCollector::handleDeclOccurence(
259     const Decl *D, index::SymbolRoleSet Roles,
260     llvm::ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
261     index::IndexDataConsumer::ASTNodeInfo ASTNode) {
262   assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
263   assert(CompletionAllocator && CompletionTUInfo);
264   assert(ASTNode.OrigD);
265   // Indexing API puts cannonical decl into D, which might not have a valid
266   // source location for implicit/built-in decls. Fallback to original decl in
267   // such cases.
268   if (D->getLocation().isInvalid())
269     D = ASTNode.OrigD;
270   // If OrigD is an declaration associated with a friend declaration and it's
271   // not a definition, skip it. Note that OrigD is the occurrence that the
272   // collector is currently visiting.
273   if ((ASTNode.OrigD->getFriendObjectKind() !=
274        Decl::FriendObjectKind::FOK_None) &&
275       !(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
276     return true;
277   // Skip non-semantic references, we should start processing these when we
278   // decide to implement renaming with index support.
279   if ((Roles & static_cast<unsigned>(index::SymbolRole::NameReference)))
280     return true;
281   // A declaration created for a friend declaration should not be used as the
282   // canonical declaration in the index. Use OrigD instead, unless we've already
283   // picked a replacement for D
284   if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
285     D = CanonicalDecls.try_emplace(D, ASTNode.OrigD).first->second;
286   const NamedDecl *ND = dyn_cast<NamedDecl>(D);
287   if (!ND)
288     return true;
289
290   // Mark D as referenced if this is a reference coming from the main file.
291   // D may not be an interesting symbol, but it's cheaper to check at the end.
292   auto &SM = ASTCtx->getSourceManager();
293   auto SpellingLoc = SM.getSpellingLoc(Loc);
294   if (Opts.CountReferences &&
295       (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
296       SM.getFileID(SpellingLoc) == SM.getMainFileID())
297     ReferencedDecls.insert(ND);
298
299   auto ID = getSymbolID(ND);
300   if (!ID)
301     return true;
302
303   // Note: we need to process relations for all decl occurrences, including
304   // refs, because the indexing code only populates relations for specific
305   // occurrences. For example, RelationBaseOf is only populated for the
306   // occurrence inside the base-specifier.
307   processRelations(*ND, *ID, Relations);
308
309   bool CollectRef = static_cast<unsigned>(Opts.RefFilter) & Roles;
310   bool IsOnlyRef =
311       !(Roles & (static_cast<unsigned>(index::SymbolRole::Declaration) |
312                  static_cast<unsigned>(index::SymbolRole::Definition)));
313
314   if (IsOnlyRef && !CollectRef)
315     return true;
316
317   // ND is the canonical (i.e. first) declaration. If it's in the main file
318   // (which is not a header), then no public declaration was visible, so assume
319   // it's main-file only.
320   bool IsMainFileOnly =
321       SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc())) &&
322       !ASTCtx->getLangOpts().IsHeaderFile;
323   // In C, printf is a redecl of an implicit builtin! So check OrigD instead.
324   if (ASTNode.OrigD->isImplicit() ||
325       !shouldCollectSymbol(*ND, *ASTCtx, Opts, IsMainFileOnly))
326     return true;
327   // Do not store references to main-file symbols.
328   if (CollectRef && !IsMainFileOnly && !isa<NamespaceDecl>(ND) &&
329       (Opts.RefsInHeaders || SM.getFileID(SpellingLoc) == SM.getMainFileID()))
330     DeclRefs[ND].emplace_back(SpellingLoc, Roles);
331   // Don't continue indexing if this is a mere reference.
332   if (IsOnlyRef)
333     return true;
334
335   // FIXME: ObjCPropertyDecl are not properly indexed here:
336   // - ObjCPropertyDecl may have an OrigD of ObjCPropertyImplDecl, which is
337   // not a NamedDecl.
338   auto *OriginalDecl = dyn_cast<NamedDecl>(ASTNode.OrigD);
339   if (!OriginalDecl)
340     return true;
341
342   const Symbol *BasicSymbol = Symbols.find(*ID);
343   if (!BasicSymbol) // Regardless of role, ND is the canonical declaration.
344     BasicSymbol = addDeclaration(*ND, std::move(*ID), IsMainFileOnly);
345   else if (isPreferredDeclaration(*OriginalDecl, Roles))
346     // If OriginalDecl is preferred, replace the existing canonical
347     // declaration (e.g. a class forward declaration). There should be at most
348     // one duplicate as we expect to see only one preferred declaration per
349     // TU, because in practice they are definitions.
350     BasicSymbol = addDeclaration(*OriginalDecl, std::move(*ID), IsMainFileOnly);
351
352   if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
353     addDefinition(*OriginalDecl, *BasicSymbol);
354
355   return true;
356 }
357
358 bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
359                                            const MacroInfo *MI,
360                                            index::SymbolRoleSet Roles,
361                                            SourceLocation Loc) {
362   if (!Opts.CollectMacro)
363     return true;
364   assert(PP.get());
365
366   const auto &SM = PP->getSourceManager();
367   auto DefLoc = MI->getDefinitionLoc();
368
369   // Builtin macros don't have useful locations and aren't needed in completion.
370   if (MI->isBuiltinMacro())
371     return true;
372
373   // Skip main-file symbols if we are not collecting them.
374   bool IsMainFileSymbol = SM.isInMainFile(SM.getExpansionLoc(DefLoc));
375   if (IsMainFileSymbol && !Opts.CollectMainFileSymbols)
376     return false;
377
378   // Also avoid storing predefined macros like __DBL_MIN__.
379   if (SM.isWrittenInBuiltinFile(DefLoc))
380     return true;
381
382   // Mark the macro as referenced if this is a reference coming from the main
383   // file. The macro may not be an interesting symbol, but it's cheaper to check
384   // at the end.
385   if (Opts.CountReferences &&
386       (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
387       SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
388     ReferencedMacros.insert(Name);
389   // Don't continue indexing if this is a mere reference.
390   // FIXME: remove macro with ID if it is undefined.
391   if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
392         Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
393     return true;
394
395   auto ID = getSymbolID(*Name, MI, SM);
396   if (!ID)
397     return true;
398
399   // Only collect one instance in case there are multiple.
400   if (Symbols.find(*ID) != nullptr)
401     return true;
402
403   Symbol S;
404   S.ID = std::move(*ID);
405   S.Name = Name->getName();
406   if (!IsMainFileSymbol) {
407     S.Flags |= Symbol::IndexedForCodeCompletion;
408     S.Flags |= Symbol::VisibleOutsideFile;
409   }
410   S.SymInfo = index::getSymbolInfoForMacro(*MI);
411   std::string FileURI;
412   // FIXME: use the result to filter out symbols.
413   shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache);
414   if (auto DeclLoc =
415           getTokenLocation(DefLoc, SM, Opts, PP->getLangOpts(), FileURI))
416     S.CanonicalDeclaration = *DeclLoc;
417
418   CodeCompletionResult SymbolCompletion(Name);
419   const auto *CCS = SymbolCompletion.CreateCodeCompletionStringForMacro(
420       *PP, *CompletionAllocator, *CompletionTUInfo);
421   std::string Signature;
422   std::string SnippetSuffix;
423   getSignature(*CCS, &Signature, &SnippetSuffix);
424   S.Signature = Signature;
425   S.CompletionSnippetSuffix = SnippetSuffix;
426
427   IndexedMacros.insert(Name);
428   setIncludeLocation(S, DefLoc);
429   Symbols.insert(S);
430   return true;
431 }
432
433 void SymbolCollector::processRelations(
434     const NamedDecl &ND, const SymbolID &ID,
435     ArrayRef<index::SymbolRelation> Relations) {
436   // Store subtype relations.
437   if (!dyn_cast<TagDecl>(&ND))
438     return;
439
440   for (const auto &R : Relations) {
441     if (!shouldIndexRelation(R))
442       continue;
443
444     const Decl *Object = R.RelatedSymbol;
445
446     auto ObjectID = getSymbolID(Object);
447     if (!ObjectID)
448       continue;
449
450     // Record the relation.
451     // TODO: There may be cases where the object decl is not indexed for some
452     // reason. Those cases should probably be removed in due course, but for
453     // now there are two possible ways to handle it:
454     //   (A) Avoid storing the relation in such cases.
455     //   (B) Store it anyways. Clients will likely lookup() the SymbolID
456     //       in the index and find nothing, but that's a situation they
457     //       probably need to handle for other reasons anyways.
458     // We currently do (B) because it's simpler.
459     this->Relations.insert(
460         Relation{ID, index::SymbolRole::RelationBaseOf, *ObjectID});
461   }
462 }
463
464 void SymbolCollector::setIncludeLocation(const Symbol &S, SourceLocation Loc) {
465   if (Opts.CollectIncludePath)
466     if (shouldCollectIncludePath(S.SymInfo.Kind))
467       // Use the expansion location to get the #include header since this is
468       // where the symbol is exposed.
469       IncludeFiles[S.ID] =
470           PP->getSourceManager().getDecomposedExpansionLoc(Loc).first;
471 }
472
473 void SymbolCollector::finish() {
474   // At the end of the TU, add 1 to the refcount of all referenced symbols.
475   auto IncRef = [this](const SymbolID &ID) {
476     if (const auto *S = Symbols.find(ID)) {
477       Symbol Inc = *S;
478       ++Inc.References;
479       Symbols.insert(Inc);
480     }
481   };
482   for (const NamedDecl *ND : ReferencedDecls) {
483     if (auto ID = getSymbolID(ND)) {
484       IncRef(*ID);
485     }
486   }
487   if (Opts.CollectMacro) {
488     assert(PP);
489     // First, drop header guards. We can't identify these until EOF.
490     for (const IdentifierInfo *II : IndexedMacros) {
491       if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
492         if (auto ID = getSymbolID(*II, MI, PP->getSourceManager()))
493           if (MI->isUsedForHeaderGuard())
494             Symbols.erase(*ID);
495     }
496     // Now increment refcounts.
497     for (const IdentifierInfo *II : ReferencedMacros) {
498       if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
499         if (auto ID = getSymbolID(*II, MI, PP->getSourceManager()))
500           IncRef(*ID);
501     }
502   }
503
504   // Fill in IncludeHeaders.
505   // We delay this until end of TU so header guards are all resolved.
506   // Symbols in slabs aren' mutable, so insert() has to walk all the strings :-(
507   llvm::SmallString<256> QName;
508   for (const auto &Entry : IncludeFiles)
509     if (const Symbol *S = Symbols.find(Entry.first)) {
510       QName = S->Scope;
511       QName.append(S->Name);
512       if (auto Header = getIncludeHeader(QName, Entry.second)) {
513         Symbol NewSym = *S;
514         NewSym.IncludeHeaders.push_back({*Header, 1});
515         Symbols.insert(NewSym);
516       }
517     }
518
519   const auto &SM = ASTCtx->getSourceManager();
520   llvm::DenseMap<FileID, std::string> URICache;
521   auto GetURI = [&](FileID FID) -> llvm::Optional<std::string> {
522     auto Found = URICache.find(FID);
523     if (Found == URICache.end()) {
524       if (auto *FileEntry = SM.getFileEntryForID(FID)) {
525         auto FileURI = toURI(SM, FileEntry->getName(), Opts);
526         Found = URICache.insert({FID, FileURI}).first;
527       } else {
528         // Ignore cases where we can not find a corresponding file entry
529         // for the loc, thoses are not interesting, e.g. symbols formed
530         // via macro concatenation.
531         return None;
532       }
533     }
534     return Found->second;
535   };
536   // Populate Refs slab from DeclRefs.
537   if (auto MainFileURI = GetURI(SM.getMainFileID())) {
538     for (const auto &It : DeclRefs) {
539       if (auto ID = getSymbolID(It.first)) {
540         for (const auto &LocAndRole : It.second) {
541           auto FileID = SM.getFileID(LocAndRole.first);
542           // FIXME: use the result to filter out references.
543           shouldIndexFile(SM, FileID, Opts, &FilesToIndexCache);
544           if (auto FileURI = GetURI(FileID)) {
545             auto Range =
546                 getTokenRange(LocAndRole.first, SM, ASTCtx->getLangOpts());
547             Ref R;
548             R.Location.Start = Range.first;
549             R.Location.End = Range.second;
550             R.Location.FileURI = FileURI->c_str();
551             R.Kind = toRefKind(LocAndRole.second);
552             Refs.insert(*ID, R);
553           }
554         }
555       }
556     }
557   }
558
559   ReferencedDecls.clear();
560   ReferencedMacros.clear();
561   DeclRefs.clear();
562   FilesToIndexCache.clear();
563   HeaderIsSelfContainedCache.clear();
564   IncludeFiles.clear();
565 }
566
567 const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID,
568                                               bool IsMainFileOnly) {
569   auto &Ctx = ND.getASTContext();
570   auto &SM = Ctx.getSourceManager();
571
572   Symbol S;
573   S.ID = std::move(ID);
574   std::string QName = printQualifiedName(ND);
575   // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
576   // for consistency with CodeCompletionString and a clean name/signature split.
577   std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
578   std::string TemplateSpecializationArgs = printTemplateSpecializationArgs(ND);
579   S.TemplateSpecializationArgs = TemplateSpecializationArgs;
580
581   // We collect main-file symbols, but do not use them for code completion.
582   if (!IsMainFileOnly && isIndexedForCodeCompletion(ND, Ctx))
583     S.Flags |= Symbol::IndexedForCodeCompletion;
584   if (isImplementationDetail(&ND))
585     S.Flags |= Symbol::ImplementationDetail;
586   if (!IsMainFileOnly)
587     S.Flags |= Symbol::VisibleOutsideFile;
588   S.SymInfo = index::getSymbolInfo(&ND);
589   std::string FileURI;
590   auto Loc = findNameLoc(&ND);
591   assert(Loc.isValid() && "Invalid source location for NamedDecl");
592   // FIXME: use the result to filter out symbols.
593   shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache);
594   if (auto DeclLoc =
595           getTokenLocation(Loc, SM, Opts, ASTCtx->getLangOpts(), FileURI))
596     S.CanonicalDeclaration = *DeclLoc;
597
598   S.Origin = Opts.Origin;
599   if (ND.getAvailability() == AR_Deprecated)
600     S.Flags |= Symbol::Deprecated;
601
602   // Add completion info.
603   // FIXME: we may want to choose a different redecl, or combine from several.
604   assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
605   // We use the primary template, as clang does during code completion.
606   CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
607   const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
608       *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator,
609       *CompletionTUInfo,
610       /*IncludeBriefComments*/ false);
611   std::string Documentation =
612       formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
613                                               /*CommentsFromHeaders=*/true));
614   if (!(S.Flags & Symbol::IndexedForCodeCompletion)) {
615     if (Opts.StoreAllDocumentation)
616       S.Documentation = Documentation;
617     Symbols.insert(S);
618     return Symbols.find(S.ID);
619   }
620   S.Documentation = Documentation;
621   std::string Signature;
622   std::string SnippetSuffix;
623   getSignature(*CCS, &Signature, &SnippetSuffix);
624   S.Signature = Signature;
625   S.CompletionSnippetSuffix = SnippetSuffix;
626   std::string ReturnType = getReturnType(*CCS);
627   S.ReturnType = ReturnType;
628
629   llvm::Optional<OpaqueType> TypeStorage;
630   if (S.Flags & Symbol::IndexedForCodeCompletion) {
631     TypeStorage = OpaqueType::fromCompletionResult(*ASTCtx, SymbolCompletion);
632     if (TypeStorage)
633       S.Type = TypeStorage->raw();
634   }
635
636   Symbols.insert(S);
637   setIncludeLocation(S, ND.getLocation());
638   return Symbols.find(S.ID);
639 }
640
641 void SymbolCollector::addDefinition(const NamedDecl &ND,
642                                     const Symbol &DeclSym) {
643   if (DeclSym.Definition)
644     return;
645   // If we saw some forward declaration, we end up copying the symbol.
646   // This is not ideal, but avoids duplicating the "is this a definition" check
647   // in clang::index. We should only see one definition.
648   Symbol S = DeclSym;
649   std::string FileURI;
650   auto Loc = findNameLoc(&ND);
651   const auto &SM = ND.getASTContext().getSourceManager();
652   // FIXME: use the result to filter out symbols.
653   shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache);
654   if (auto DefLoc =
655           getTokenLocation(Loc, SM, Opts, ASTCtx->getLangOpts(), FileURI))
656     S.Definition = *DefLoc;
657   Symbols.insert(S);
658 }
659
660 /// Gets a canonical include (URI of the header or <header> or "header") for
661 /// header of \p FID (which should usually be the *expansion* file).
662 /// Returns None if includes should not be inserted for this file.
663 llvm::Optional<std::string>
664 SymbolCollector::getIncludeHeader(llvm::StringRef QName, FileID FID) {
665   const SourceManager &SM = ASTCtx->getSourceManager();
666   const FileEntry *FE = SM.getFileEntryForID(FID);
667   if (!FE || FE->getName().empty())
668     return llvm::None;
669   llvm::StringRef Filename = FE->getName();
670   // If a file is mapped by canonical headers, use that mapping, regardless
671   // of whether it's an otherwise-good header (header guards etc).
672   if (Opts.Includes) {
673     llvm::StringRef Canonical = Opts.Includes->mapHeader(Filename, QName);
674     // If we had a mapping, always use it.
675     if (Canonical.startswith("<") || Canonical.startswith("\""))
676       return Canonical.str();
677     if (Canonical != Filename)
678       return toURI(SM, Canonical, Opts);
679   }
680   if (!isSelfContainedHeader(FID)) {
681     // A .inc or .def file is often included into a real header to define
682     // symbols (e.g. LLVM tablegen files).
683     if (Filename.endswith(".inc") || Filename.endswith(".def"))
684       return getIncludeHeader(QName, SM.getFileID(SM.getIncludeLoc(FID)));
685     // Conservatively refuse to insert #includes to files without guards.
686     return llvm::None;
687   }
688   // Standard case: just insert the file itself.
689   return toURI(SM, Filename, Opts);
690 }
691
692 bool SymbolCollector::isSelfContainedHeader(FileID FID) {
693   // The real computation (which will be memoized).
694   auto Compute = [&] {
695     const SourceManager &SM = ASTCtx->getSourceManager();
696     const FileEntry *FE = SM.getFileEntryForID(FID);
697     if (!FE)
698       return false;
699     if (!PP->getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE))
700       return false;
701     // This pattern indicates that a header can't be used without
702     // particular preprocessor state, usually set up by another header.
703     if (isDontIncludeMeHeader(SM.getBufferData(FID)))
704       return false;
705     return true;
706   };
707
708   auto R = HeaderIsSelfContainedCache.try_emplace(FID, false);
709   if (R.second)
710     R.first->second = Compute();
711   return R.first->second;
712 }
713
714 // Is Line an #if or #ifdef directive?
715 static bool isIf(llvm::StringRef Line) {
716   Line = Line.ltrim();
717   if (!Line.consume_front("#"))
718     return false;
719   Line = Line.ltrim();
720   return Line.startswith("if");
721 }
722 // Is Line an #error directive mentioning includes?
723 static bool isErrorAboutInclude(llvm::StringRef Line) {
724   Line = Line.ltrim();
725   if (!Line.consume_front("#"))
726     return false;
727   Line = Line.ltrim();
728   if (!Line.startswith("error"))
729     return false;
730   return Line.contains_lower("includ"); // Matches "include" or "including".
731 }
732
733 bool SymbolCollector::isDontIncludeMeHeader(llvm::StringRef Content) {
734   llvm::StringRef Line;
735   // Only sniff up to 100 lines or 10KB.
736   Content = Content.take_front(100 * 100);
737   for (unsigned I = 0; I < 100 && !Content.empty(); ++I) {
738     std::tie(Line, Content) = Content.split('\n');
739     if (isIf(Line) && isErrorAboutInclude(Content.split('\n').first))
740       return true;
741   }
742   return false;
743 }
744
745 } // namespace clangd
746 } // namespace clang