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