clang-tools  10.0.0
Background.cpp
Go to the documentation of this file.
1 //===-- Background.cpp - Build an index in a background thread ------------===//
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 "index/Background.h"
10 #include "Compiler.h"
11 #include "Context.h"
12 #include "FSProvider.h"
13 #include "Headers.h"
14 #include "Logger.h"
15 #include "ParsedAST.h"
16 #include "Path.h"
17 #include "SourceCode.h"
18 #include "Symbol.h"
19 #include "Threading.h"
20 #include "Trace.h"
21 #include "URI.h"
23 #include "index/FileIndex.h"
24 #include "index/IndexAction.h"
25 #include "index/MemIndex.h"
26 #include "index/Ref.h"
27 #include "index/Relation.h"
28 #include "index/Serialization.h"
29 #include "index/SymbolCollector.h"
30 #include "clang/Basic/SourceLocation.h"
31 #include "clang/Basic/SourceManager.h"
32 #include "clang/Driver/Types.h"
33 #include "llvm/ADT/ArrayRef.h"
34 #include "llvm/ADT/DenseSet.h"
35 #include "llvm/ADT/Hashing.h"
36 #include "llvm/ADT/STLExtras.h"
37 #include "llvm/ADT/ScopeExit.h"
38 #include "llvm/ADT/StringMap.h"
39 #include "llvm/ADT/StringRef.h"
40 #include "llvm/ADT/StringSet.h"
41 #include "llvm/Support/Error.h"
42 #include "llvm/Support/Path.h"
43 #include "llvm/Support/Threading.h"
44 
45 #include <algorithm>
46 #include <atomic>
47 #include <chrono>
48 #include <condition_variable>
49 #include <cstddef>
50 #include <memory>
51 #include <mutex>
52 #include <numeric>
53 #include <queue>
54 #include <random>
55 #include <string>
56 #include <thread>
57 #include <utility>
58 #include <vector>
59 
60 namespace clang {
61 namespace clangd {
62 namespace {
63 
64 // Resolves URI to file paths with cache.
65 class URIToFileCache {
66 public:
67  URIToFileCache(llvm::StringRef HintPath) : HintPath(HintPath) {}
68 
69  llvm::StringRef resolve(llvm::StringRef FileURI) {
70  auto I = URIToPathCache.try_emplace(FileURI);
71  if (I.second) {
72  auto Path = URI::resolve(FileURI, HintPath);
73  if (!Path) {
74  elog("Failed to resolve URI {0}: {1}", FileURI, Path.takeError());
75  assert(false && "Failed to resolve URI");
76  return "";
77  }
78  I.first->second = *Path;
79  }
80  return I.first->second;
81  }
82 
83 private:
84  std::string HintPath;
85  llvm::StringMap<std::string> URIToPathCache;
86 };
87 
88 // We keep only the node "U" and its edges. Any node other than "U" will be
89 // empty in the resultant graph.
90 IncludeGraph getSubGraph(const URI &U, const IncludeGraph &FullGraph) {
91  IncludeGraph IG;
92 
93  std::string FileURI = U.toString();
94  auto Entry = IG.try_emplace(FileURI).first;
95  auto &Node = Entry->getValue();
96  Node = FullGraph.lookup(Entry->getKey());
97  Node.URI = Entry->getKey();
98 
99  // URIs inside nodes must point into the keys of the same IncludeGraph.
100  for (auto &Include : Node.DirectIncludes) {
101  auto I = IG.try_emplace(Include).first;
102  I->getValue().URI = I->getKey();
103  Include = I->getKey();
104  }
105 
106  return IG;
107 }
108 
109 // We cannot use vfs->makeAbsolute because Cmd.FileName is either absolute or
110 // relative to Cmd.Directory, which might not be the same as current working
111 // directory.
112 llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) {
113  llvm::SmallString<128> AbsolutePath;
114  if (llvm::sys::path::is_absolute(Cmd.Filename)) {
115  AbsolutePath = Cmd.Filename;
116  } else {
117  AbsolutePath = Cmd.Directory;
118  llvm::sys::path::append(AbsolutePath, Cmd.Filename);
119  llvm::sys::path::remove_dots(AbsolutePath, true);
120  }
121  return AbsolutePath;
122 }
123 
124 bool shardIsStale(const LoadedShard &LS, llvm::vfs::FileSystem *FS) {
125  auto Buf = FS->getBufferForFile(LS.AbsolutePath);
126  if (!Buf) {
127  elog("Background-index: Couldn't read {0} to validate stored index: {1}",
128  LS.AbsolutePath, Buf.getError().message());
129  // There is no point in indexing an unreadable file.
130  return false;
131  }
132  return digest(Buf->get()->getBuffer()) != LS.Digest;
133 }
134 
135 } // namespace
136 
138  Context BackgroundContext, const FileSystemProvider &FSProvider,
139  const GlobalCompilationDatabase &CDB,
140  BackgroundIndexStorage::Factory IndexStorageFactory, size_t ThreadPoolSize)
141  : SwapIndex(std::make_unique<MemIndex>()), FSProvider(FSProvider),
142  CDB(CDB), BackgroundContext(std::move(BackgroundContext)),
143  Rebuilder(this, &IndexedSymbols, ThreadPoolSize),
144  IndexStorageFactory(std::move(IndexStorageFactory)),
145  CommandsChanged(
146  CDB.watch([&](const std::vector<std::string> &ChangedFiles) {
147  enqueue(ChangedFiles);
148  })) {
149  assert(ThreadPoolSize > 0 && "Thread pool size can't be zero.");
150  assert(this->IndexStorageFactory && "Storage factory can not be null!");
151  for (unsigned I = 0; I < ThreadPoolSize; ++I) {
152  ThreadPool.runAsync("background-worker-" + llvm::Twine(I + 1), [this] {
153  WithContext Ctx(this->BackgroundContext.clone());
154  Queue.work([&] { Rebuilder.idle(); });
155  });
156  }
157 }
158 
160  stop();
161  ThreadPool.wait();
162 }
163 
164 BackgroundQueue::Task BackgroundIndex::changedFilesTask(
165  const std::vector<std::string> &ChangedFiles) {
166  BackgroundQueue::Task T([this, ChangedFiles] {
167  trace::Span Tracer("BackgroundIndexEnqueue");
168  // We're doing this asynchronously, because we'll read shards here too.
169  log("Enqueueing {0} commands for indexing", ChangedFiles.size());
170  SPAN_ATTACH(Tracer, "files", int64_t(ChangedFiles.size()));
171 
172  auto NeedsReIndexing = loadProject(std::move(ChangedFiles));
173  // Run indexing for files that need to be updated.
174  std::shuffle(NeedsReIndexing.begin(), NeedsReIndexing.end(),
175  std::mt19937(std::random_device{}()));
176  std::vector<BackgroundQueue::Task> Tasks;
177  Tasks.reserve(NeedsReIndexing.size());
178  for (auto &Cmd : NeedsReIndexing)
179  Tasks.push_back(indexFileTask(std::move(Cmd)));
180  Queue.append(std::move(Tasks));
181  });
182 
183  T.QueuePri = LoadShards;
184  T.ThreadPri = llvm::ThreadPriority::Default;
185  return T;
186 }
187 
188 static llvm::StringRef filenameWithoutExtension(llvm::StringRef Path) {
189  Path = llvm::sys::path::filename(Path);
190  return Path.drop_back(llvm::sys::path::extension(Path).size());
191 }
192 
194 BackgroundIndex::indexFileTask(tooling::CompileCommand Cmd) {
195  BackgroundQueue::Task T([this, Cmd] {
196  // We can't use llvm::StringRef here since we are going to
197  // move from Cmd during the call below.
198  const std::string FileName = Cmd.Filename;
199  if (auto Error = index(std::move(Cmd)))
200  elog("Indexing {0} failed: {1}", FileName, std::move(Error));
201  });
202  T.QueuePri = IndexFile;
203  T.Tag = filenameWithoutExtension(Cmd.Filename);
204  return T;
205 }
206 
207 void BackgroundIndex::boostRelated(llvm::StringRef Path) {
208  if (isHeaderFile(Path))
209  Queue.boost(filenameWithoutExtension(Path), IndexBoostedFile);
210 }
211 
212 /// Given index results from a TU, only update symbols coming from files that
213 /// are different or missing from than \p ShardVersionsSnapshot. Also stores new
214 /// index information on IndexStorage.
215 void BackgroundIndex::update(
216  llvm::StringRef MainFile, IndexFileIn Index,
217  const llvm::StringMap<ShardVersion> &ShardVersionsSnapshot,
218  bool HadErrors) {
219  // Partition symbols/references into files.
220  struct File {
221  llvm::DenseSet<const Symbol *> Symbols;
222  llvm::DenseSet<const Ref *> Refs;
223  llvm::DenseSet<const Relation *> Relations;
224  FileDigest Digest;
225  };
226  llvm::StringMap<File> Files;
227  URIToFileCache URICache(MainFile);
228  for (const auto &IndexIt : *Index.Sources) {
229  const auto &IGN = IndexIt.getValue();
230  // Note that sources do not contain any information regarding missing
231  // headers, since we don't even know what absolute path they should fall in.
232  const auto AbsPath = URICache.resolve(IGN.URI);
233  const auto DigestIt = ShardVersionsSnapshot.find(AbsPath);
234  // File has different contents, or indexing was successfull this time.
235  if (DigestIt == ShardVersionsSnapshot.end() ||
236  DigestIt->getValue().Digest != IGN.Digest ||
237  (DigestIt->getValue().HadErrors && !HadErrors))
238  Files.try_emplace(AbsPath).first->getValue().Digest = IGN.Digest;
239  }
240  // This map is used to figure out where to store relations.
241  llvm::DenseMap<SymbolID, File *> SymbolIDToFile;
242  for (const auto &Sym : *Index.Symbols) {
243  if (Sym.CanonicalDeclaration) {
244  auto DeclPath = URICache.resolve(Sym.CanonicalDeclaration.FileURI);
245  const auto FileIt = Files.find(DeclPath);
246  if (FileIt != Files.end()) {
247  FileIt->second.Symbols.insert(&Sym);
248  SymbolIDToFile[Sym.ID] = &FileIt->second;
249  }
250  }
251  // For symbols with different declaration and definition locations, we store
252  // the full symbol in both the header file and the implementation file, so
253  // that merging can tell the preferred symbols (from canonical headers) from
254  // other symbols (e.g. forward declarations).
255  if (Sym.Definition &&
256  Sym.Definition.FileURI != Sym.CanonicalDeclaration.FileURI) {
257  auto DefPath = URICache.resolve(Sym.Definition.FileURI);
258  const auto FileIt = Files.find(DefPath);
259  if (FileIt != Files.end())
260  FileIt->second.Symbols.insert(&Sym);
261  }
262  }
263  llvm::DenseMap<const Ref *, SymbolID> RefToIDs;
264  for (const auto &SymRefs : *Index.Refs) {
265  for (const auto &R : SymRefs.second) {
266  auto Path = URICache.resolve(R.Location.FileURI);
267  const auto FileIt = Files.find(Path);
268  if (FileIt != Files.end()) {
269  auto &F = FileIt->getValue();
270  RefToIDs[&R] = SymRefs.first;
271  F.Refs.insert(&R);
272  }
273  }
274  }
275  for (const auto &Rel : *Index.Relations) {
276  const auto FileIt = SymbolIDToFile.find(Rel.Subject);
277  if (FileIt != SymbolIDToFile.end())
278  FileIt->second->Relations.insert(&Rel);
279  }
280 
281  // Build and store new slabs for each updated file.
282  for (const auto &FileIt : Files) {
283  llvm::StringRef Path = FileIt.getKey();
284  SymbolSlab::Builder Syms;
286  RelationSlab::Builder Relations;
287  for (const auto *S : FileIt.second.Symbols)
288  Syms.insert(*S);
289  for (const auto *R : FileIt.second.Refs)
290  Refs.insert(RefToIDs[R], *R);
291  for (const auto *Rel : FileIt.second.Relations)
292  Relations.insert(*Rel);
293  auto SS = std::make_unique<SymbolSlab>(std::move(Syms).build());
294  auto RS = std::make_unique<RefSlab>(std::move(Refs).build());
295  auto RelS = std::make_unique<RelationSlab>(std::move(Relations).build());
296  auto IG = std::make_unique<IncludeGraph>(
297  getSubGraph(URI::create(Path), Index.Sources.getValue()));
298 
299  // We need to store shards before updating the index, since the latter
300  // consumes slabs.
301  // FIXME: Also skip serializing the shard if it is already up-to-date.
302  BackgroundIndexStorage *IndexStorage = IndexStorageFactory(Path);
303  IndexFileOut Shard;
304  Shard.Symbols = SS.get();
305  Shard.Refs = RS.get();
306  Shard.Relations = RelS.get();
307  Shard.Sources = IG.get();
308 
309  // Only store command line hash for main files of the TU, since our
310  // current model keeps only one version of a header file.
311  if (Path == MainFile)
312  Shard.Cmd = Index.Cmd.getPointer();
313 
314  if (auto Error = IndexStorage->storeShard(Path, Shard))
315  elog("Failed to write background-index shard for file {0}: {1}", Path,
316  std::move(Error));
317 
318  {
319  std::lock_guard<std::mutex> Lock(ShardVersionsMu);
320  auto Hash = FileIt.second.Digest;
321  auto DigestIt = ShardVersions.try_emplace(Path);
322  ShardVersion &SV = DigestIt.first->second;
323  // Skip if file is already up to date, unless previous index was broken
324  // and this one is not.
325  if (!DigestIt.second && SV.Digest == Hash && SV.HadErrors && !HadErrors)
326  continue;
327  SV.Digest = Hash;
328  SV.HadErrors = HadErrors;
329 
330  // This can override a newer version that is added in another thread, if
331  // this thread sees the older version but finishes later. This should be
332  // rare in practice.
333  IndexedSymbols.update(Path, std::move(SS), std::move(RS), std::move(RelS),
334  Path == MainFile);
335  }
336  }
337 }
338 
339 llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
340  trace::Span Tracer("BackgroundIndex");
341  SPAN_ATTACH(Tracer, "file", Cmd.Filename);
342  auto AbsolutePath = getAbsolutePath(Cmd);
343 
344  auto FS = FSProvider.getFileSystem();
345  auto Buf = FS->getBufferForFile(AbsolutePath);
346  if (!Buf)
347  return llvm::errorCodeToError(Buf.getError());
348  auto Hash = digest(Buf->get()->getBuffer());
349 
350  // Take a snapshot of the versions to avoid locking for each file in the TU.
351  llvm::StringMap<ShardVersion> ShardVersionsSnapshot;
352  {
353  std::lock_guard<std::mutex> Lock(ShardVersionsMu);
354  ShardVersionsSnapshot = ShardVersions;
355  }
356 
357  vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
358  ParseInputs Inputs;
359  Inputs.FS = std::move(FS);
360  Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
361  Inputs.CompileCommand = std::move(Cmd);
363  auto CI = buildCompilerInvocation(Inputs, IgnoreDiags);
364  if (!CI)
365  return llvm::createStringError(llvm::inconvertibleErrorCode(),
366  "Couldn't build compiler invocation");
367  auto Clang = prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
368  std::move(*Buf), Inputs.FS, IgnoreDiags);
369  if (!Clang)
370  return llvm::createStringError(llvm::inconvertibleErrorCode(),
371  "Couldn't build compiler instance");
372 
373  SymbolCollector::Options IndexOpts;
374  // Creates a filter to not collect index results from files with unchanged
375  // digests.
376  IndexOpts.FileFilter = [&ShardVersionsSnapshot](const SourceManager &SM,
377  FileID FID) {
378  const auto *F = SM.getFileEntryForID(FID);
379  if (!F)
380  return false; // Skip invalid files.
381  auto AbsPath = getCanonicalPath(F, SM);
382  if (!AbsPath)
383  return false; // Skip files without absolute path.
384  auto Digest = digestFile(SM, FID);
385  if (!Digest)
386  return false;
387  auto D = ShardVersionsSnapshot.find(*AbsPath);
388  if (D != ShardVersionsSnapshot.end() && D->second.Digest == Digest &&
389  !D->second.HadErrors)
390  return false; // Skip files that haven't changed, without errors.
391  return true;
392  };
393 
394  IndexFileIn Index;
396  IndexOpts, [&](SymbolSlab S) { Index.Symbols = std::move(S); },
397  [&](RefSlab R) { Index.Refs = std::move(R); },
398  [&](RelationSlab R) { Index.Relations = std::move(R); },
399  [&](IncludeGraph IG) { Index.Sources = std::move(IG); });
400 
401  // We're going to run clang here, and it could potentially crash.
402  // We could use CrashRecoveryContext to try to make indexing crashes nonfatal,
403  // but the leaky "recovery" is pretty scary too in a long-running process.
404  // If crashes are a real problem, maybe we should fork a child process.
405 
406  const FrontendInputFile &Input = Clang->getFrontendOpts().Inputs.front();
407  if (!Action->BeginSourceFile(*Clang, Input))
408  return llvm::createStringError(llvm::inconvertibleErrorCode(),
409  "BeginSourceFile() failed");
410  if (llvm::Error Err = Action->Execute())
411  return Err;
412 
413  Action->EndSourceFile();
414 
415  Index.Cmd = Inputs.CompileCommand;
416  assert(Index.Symbols && Index.Refs && Index.Sources &&
417  "Symbols, Refs and Sources must be set.");
418 
419  log("Indexed {0} ({1} symbols, {2} refs, {3} files)",
420  Inputs.CompileCommand.Filename, Index.Symbols->size(),
421  Index.Refs->numRefs(), Index.Sources->size());
422  SPAN_ATTACH(Tracer, "symbols", int(Index.Symbols->size()));
423  SPAN_ATTACH(Tracer, "refs", int(Index.Refs->numRefs()));
424  SPAN_ATTACH(Tracer, "sources", int(Index.Sources->size()));
425 
426  bool HadErrors = Clang->hasDiagnostics() &&
427  Clang->getDiagnostics().hasUncompilableErrorOccurred();
428  if (HadErrors) {
429  log("Failed to compile {0}, index may be incomplete", AbsolutePath);
430  for (auto &It : *Index.Sources)
431  It.second.Flags |= IncludeGraphNode::SourceFlag::HadErrors;
432  }
433  update(AbsolutePath, std::move(Index), ShardVersionsSnapshot, HadErrors);
434 
435  Rebuilder.indexedTU();
436  return llvm::Error::success();
437 }
438 
439 // Restores shards for \p MainFiles from index storage. Then checks staleness of
440 // those shards and returns a list of TUs that needs to be indexed to update
441 // staleness.
442 std::vector<tooling::CompileCommand>
443 BackgroundIndex::loadProject(std::vector<std::string> MainFiles) {
444  std::vector<tooling::CompileCommand> NeedsReIndexing;
445 
446  Rebuilder.startLoading();
447  // Load shards for all of the mainfiles.
448  const std::vector<LoadedShard> Result =
449  loadIndexShards(MainFiles, IndexStorageFactory, CDB);
450  size_t LoadedShards = 0;
451  {
452  // Update in-memory state.
453  std::lock_guard<std::mutex> Lock(ShardVersionsMu);
454  for (auto &LS : Result) {
455  if (!LS.Shard)
456  continue;
457  auto SS =
458  LS.Shard->Symbols
459  ? std::make_unique<SymbolSlab>(std::move(*LS.Shard->Symbols))
460  : nullptr;
461  auto RS = LS.Shard->Refs
462  ? std::make_unique<RefSlab>(std::move(*LS.Shard->Refs))
463  : nullptr;
464  auto RelS =
465  LS.Shard->Relations
466  ? std::make_unique<RelationSlab>(std::move(*LS.Shard->Relations))
467  : nullptr;
468  ShardVersion &SV = ShardVersions[LS.AbsolutePath];
469  SV.Digest = LS.Digest;
470  SV.HadErrors = LS.HadErrors;
471  ++LoadedShards;
472 
473  IndexedSymbols.update(LS.AbsolutePath, std::move(SS), std::move(RS),
474  std::move(RelS), LS.CountReferences);
475  }
476  }
477  Rebuilder.loadedShard(LoadedShards);
478  Rebuilder.doneLoading();
479 
480  auto FS = FSProvider.getFileSystem();
481  llvm::DenseSet<PathRef> TUsToIndex;
482  // We'll accept data from stale shards, but ensure the files get reindexed
483  // soon.
484  for (auto &LS : Result) {
485  if (!shardIsStale(LS, FS.get()))
486  continue;
487  PathRef TUForFile = LS.DependentTU;
488  assert(!TUForFile.empty() && "File without a TU!");
489 
490  // FIXME: Currently, we simply schedule indexing on a TU whenever any of
491  // its dependencies needs re-indexing. We might do it smarter by figuring
492  // out a minimal set of TUs that will cover all the stale dependencies.
493  // FIXME: Try looking at other TUs if no compile commands are available
494  // for this TU, i.e TU was deleted after we performed indexing.
495  TUsToIndex.insert(TUForFile);
496  }
497 
498  for (PathRef TU : TUsToIndex) {
499  auto Cmd = CDB.getCompileCommand(TU);
500  if (!Cmd)
501  continue;
502  NeedsReIndexing.emplace_back(std::move(*Cmd));
503  }
504 
505  return NeedsReIndexing;
506 }
507 
508 } // namespace clangd
509 } // namespace clang
const tooling::CompileCommand * Cmd
Definition: Serialization.h:63
llvm::Optional< SymbolSlab > Symbols
Definition: Serialization.h:43
An immutable symbol container that stores a set of symbols.
Definition: Symbol.h:177
llvm::Optional< tooling::CompileCommand > Cmd
Definition: Serialization.h:49
llvm::unique_function< BackgroundIndexStorage *(PathRef)> Factory
Definition: Background.h:56
An efficient structure of storing large set of symbol references in memory.
Definition: Ref.h:69
void boostRelated(llvm::StringRef Path)
Boosts priority of indexing related to Path.
Definition: Background.cpp:207
std::array< uint8_t, 8 > FileDigest
Definition: SourceCode.h:38
static llvm::StringRef filenameWithoutExtension(llvm::StringRef Path)
Definition: Background.cpp:188
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
void insert(const Symbol &S)
Adds a symbol, overwriting any existing one with the same ID.
Definition: Symbol.cpp:50
MockFSProvider FS
std::unique_ptr< CompilerInstance > prepareCompilerInstance(std::unique_ptr< clang::CompilerInvocation > CI, const PrecompiledPreamble *Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, DiagnosticConsumer &DiagsClient)
Definition: Compiler.cpp:72
llvm::Optional< RelationSlab > Relations
Definition: Serialization.h:45
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:67
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
llvm::Optional< IncludeGraph > Sources
Definition: Serialization.h:47
const SymbolSlab * Symbols
Definition: Serialization.h:56
MockFSProvider FSProvider
SymbolSlab::Builder is a mutable container that can &#39;freeze&#39; to SymbolSlab.
Definition: Symbol.h:199
std::string MainFile
void boost(llvm::StringRef Tag, unsigned NewPriority)
Provides compilation arguments used for parsing C and C++ files.
Context Ctx
llvm::StringMap< IncludeGraphNode > IncludeGraph
Definition: Headers.h:82
Context clone() const
Clone this context object.
Definition: Context.cpp:20
void runAsync(const llvm::Twine &Name, llvm::unique_function< void()> Action)
Definition: Threading.cpp:70
IgnoringDiagConsumer IgnoreDiags
llvm::unique_function< void()> Action
MemIndex is a naive in-memory index suitable for a small set of symbols.
Definition: MemIndex.h:19
void log(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
std::string Path
A typedef to represent a file path.
Definition: Path.h:20
std::vector< LoadedShard > loadIndexShards(llvm::ArrayRef< Path > MainFiles, BackgroundIndexStorage::Factory &IndexStorageFactory, const GlobalCompilationDatabase &CDB)
Loads all shards for the TU MainFile from Storage.
tooling::CompileCommand CompileCommand
Definition: Compiler.h:45
void enqueue(const std::vector< std::string > &ChangedFiles)
Definition: Background.h:130
void insert(const Relation &R)
Adds a relation to the slab.
Definition: Relation.h:73
PathRef FileName
const IncludeGraph * Sources
Definition: Serialization.h:60
SymbolSlab Symbols
llvm::Optional< FileDigest > digestFile(const SourceManager &SM, FileID FID)
Definition: SourceCode.cpp:685
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
RelationSlab::Builder is a mutable container that can &#39;freeze&#39; to RelationSlab.
Definition: Relation.h:70
std::function< bool(const SourceManager &, FileID)> FileFilter
If this is set, only collect symbols/references from a file if FileFilter(SM, FID) is true...
RefSlab::Builder is a mutable container that can &#39;freeze&#39; to RefSlab.
Definition: Ref.h:93
WithContext replaces Context::current() with a provided scope.
Definition: Context.h:189
FileDigest digest(llvm::StringRef Content)
Definition: SourceCode.cpp:675
virtual llvm::Error storeShard(llvm::StringRef ShardIdentifier, IndexFileOut Shard) const =0
const RelationSlab * Relations
Definition: Serialization.h:58
llvm::Optional< RefSlab > Refs
Definition: Serialization.h:44
BackgroundIndex(Context BackgroundContext, const FileSystemProvider &, const GlobalCompilationDatabase &CDB, BackgroundIndexStorage::Factory IndexStorageFactory, size_t ThreadPoolSize=llvm::heavyweight_hardware_concurrency())
If BuildIndexPeriodMs is greater than 0, the symbol index will only be rebuilt periodically (one per ...
Definition: Background.cpp:137
Information required to run clang, e.g. to parse AST or do code completion.
Definition: Compiler.h:44
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Definition: URI.cpp:197
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< FrontendAction > createStaticIndexingAction(SymbolCollector::Options Opts, std::function< void(SymbolSlab)> SymbolsCallback, std::function< void(RefSlab)> RefsCallback, std::function< void(RelationSlab)> RelationsCallback, std::function< void(IncludeGraph)> IncludeGraphCallback)
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
Definition: SourceCode.cpp:622
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
Definition: Compiler.cpp:44
void insert(const SymbolID &ID, const Ref &S)
Adds a ref to the slab. Deep copy: Strings will be owned by the slab.
Definition: Ref.cpp:35
bool isHeaderFile(llvm::StringRef FileName, llvm::Optional< LangOptions > LangOpts)
Infers whether this is a header from the FileName and LangOpts (if presents).
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
Definition: URI.cpp:233
IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS
Definition: Compiler.h:46
void append(std::vector< Task >)
RefSlab Refs
A work item on the thread pool&#39;s queue.
Definition: Background.h:70
Records an event whose duration is the lifetime of the Span object.
Definition: Trace.h:81
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
Definition: Trace.h:97
llvm::StringMap< std::string > Files
void work(std::function< void()> OnIdle=nullptr)