clang-tools  10.0.0svn
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  namespace types = clang::driver::types;
209  auto Type =
210  types::lookupTypeForExtension(llvm::sys::path::extension(Path).substr(1));
211  // is this a header?
212  if (Type != types::TY_INVALID && types::onlyPrecompileType(Type))
213  Queue.boost(filenameWithoutExtension(Path), IndexBoostedFile);
214 }
215 
216 /// Given index results from a TU, only update symbols coming from files that
217 /// are different or missing from than \p ShardVersionsSnapshot. Also stores new
218 /// index information on IndexStorage.
219 void BackgroundIndex::update(
220  llvm::StringRef MainFile, IndexFileIn Index,
221  const llvm::StringMap<ShardVersion> &ShardVersionsSnapshot,
222  bool HadErrors) {
223  // Partition symbols/references into files.
224  struct File {
225  llvm::DenseSet<const Symbol *> Symbols;
226  llvm::DenseSet<const Ref *> Refs;
227  llvm::DenseSet<const Relation *> Relations;
228  FileDigest Digest;
229  };
230  llvm::StringMap<File> Files;
231  URIToFileCache URICache(MainFile);
232  for (const auto &IndexIt : *Index.Sources) {
233  const auto &IGN = IndexIt.getValue();
234  // Note that sources do not contain any information regarding missing
235  // headers, since we don't even know what absolute path they should fall in.
236  const auto AbsPath = URICache.resolve(IGN.URI);
237  const auto DigestIt = ShardVersionsSnapshot.find(AbsPath);
238  // File has different contents, or indexing was successfull this time.
239  if (DigestIt == ShardVersionsSnapshot.end() ||
240  DigestIt->getValue().Digest != IGN.Digest ||
241  (DigestIt->getValue().HadErrors && !HadErrors))
242  Files.try_emplace(AbsPath).first->getValue().Digest = IGN.Digest;
243  }
244  // This map is used to figure out where to store relations.
245  llvm::DenseMap<SymbolID, File *> SymbolIDToFile;
246  for (const auto &Sym : *Index.Symbols) {
247  if (Sym.CanonicalDeclaration) {
248  auto DeclPath = URICache.resolve(Sym.CanonicalDeclaration.FileURI);
249  const auto FileIt = Files.find(DeclPath);
250  if (FileIt != Files.end()) {
251  FileIt->second.Symbols.insert(&Sym);
252  SymbolIDToFile[Sym.ID] = &FileIt->second;
253  }
254  }
255  // For symbols with different declaration and definition locations, we store
256  // the full symbol in both the header file and the implementation file, so
257  // that merging can tell the preferred symbols (from canonical headers) from
258  // other symbols (e.g. forward declarations).
259  if (Sym.Definition &&
260  Sym.Definition.FileURI != Sym.CanonicalDeclaration.FileURI) {
261  auto DefPath = URICache.resolve(Sym.Definition.FileURI);
262  const auto FileIt = Files.find(DefPath);
263  if (FileIt != Files.end())
264  FileIt->second.Symbols.insert(&Sym);
265  }
266  }
267  llvm::DenseMap<const Ref *, SymbolID> RefToIDs;
268  for (const auto &SymRefs : *Index.Refs) {
269  for (const auto &R : SymRefs.second) {
270  auto Path = URICache.resolve(R.Location.FileURI);
271  const auto FileIt = Files.find(Path);
272  if (FileIt != Files.end()) {
273  auto &F = FileIt->getValue();
274  RefToIDs[&R] = SymRefs.first;
275  F.Refs.insert(&R);
276  }
277  }
278  }
279  for (const auto &Rel : *Index.Relations) {
280  const auto FileIt = SymbolIDToFile.find(Rel.Subject);
281  if (FileIt != SymbolIDToFile.end())
282  FileIt->second->Relations.insert(&Rel);
283  }
284 
285  // Build and store new slabs for each updated file.
286  for (const auto &FileIt : Files) {
287  llvm::StringRef Path = FileIt.getKey();
288  SymbolSlab::Builder Syms;
290  RelationSlab::Builder Relations;
291  for (const auto *S : FileIt.second.Symbols)
292  Syms.insert(*S);
293  for (const auto *R : FileIt.second.Refs)
294  Refs.insert(RefToIDs[R], *R);
295  for (const auto *Rel : FileIt.second.Relations)
296  Relations.insert(*Rel);
297  auto SS = std::make_unique<SymbolSlab>(std::move(Syms).build());
298  auto RS = std::make_unique<RefSlab>(std::move(Refs).build());
299  auto RelS = std::make_unique<RelationSlab>(std::move(Relations).build());
300  auto IG = std::make_unique<IncludeGraph>(
301  getSubGraph(URI::create(Path), Index.Sources.getValue()));
302 
303  // We need to store shards before updating the index, since the latter
304  // consumes slabs.
305  // FIXME: Also skip serializing the shard if it is already up-to-date.
306  BackgroundIndexStorage *IndexStorage = IndexStorageFactory(Path);
307  IndexFileOut Shard;
308  Shard.Symbols = SS.get();
309  Shard.Refs = RS.get();
310  Shard.Relations = RelS.get();
311  Shard.Sources = IG.get();
312 
313  // Only store command line hash for main files of the TU, since our
314  // current model keeps only one version of a header file.
315  if (Path == MainFile)
316  Shard.Cmd = Index.Cmd.getPointer();
317 
318  if (auto Error = IndexStorage->storeShard(Path, Shard))
319  elog("Failed to write background-index shard for file {0}: {1}", Path,
320  std::move(Error));
321 
322  {
323  std::lock_guard<std::mutex> Lock(ShardVersionsMu);
324  auto Hash = FileIt.second.Digest;
325  auto DigestIt = ShardVersions.try_emplace(Path);
326  ShardVersion &SV = DigestIt.first->second;
327  // Skip if file is already up to date, unless previous index was broken
328  // and this one is not.
329  if (!DigestIt.second && SV.Digest == Hash && SV.HadErrors && !HadErrors)
330  continue;
331  SV.Digest = Hash;
332  SV.HadErrors = HadErrors;
333 
334  // This can override a newer version that is added in another thread, if
335  // this thread sees the older version but finishes later. This should be
336  // rare in practice.
337  IndexedSymbols.update(Path, std::move(SS), std::move(RS), std::move(RelS),
338  Path == MainFile);
339  }
340  }
341 }
342 
343 llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
344  trace::Span Tracer("BackgroundIndex");
345  SPAN_ATTACH(Tracer, "file", Cmd.Filename);
346  auto AbsolutePath = getAbsolutePath(Cmd);
347 
348  auto FS = FSProvider.getFileSystem();
349  auto Buf = FS->getBufferForFile(AbsolutePath);
350  if (!Buf)
351  return llvm::errorCodeToError(Buf.getError());
352  auto Hash = digest(Buf->get()->getBuffer());
353 
354  // Take a snapshot of the versions to avoid locking for each file in the TU.
355  llvm::StringMap<ShardVersion> ShardVersionsSnapshot;
356  {
357  std::lock_guard<std::mutex> Lock(ShardVersionsMu);
358  ShardVersionsSnapshot = ShardVersions;
359  }
360 
361  vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
362  ParseInputs Inputs;
363  Inputs.FS = std::move(FS);
364  Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
365  Inputs.CompileCommand = std::move(Cmd);
367  auto CI = buildCompilerInvocation(Inputs, IgnoreDiags);
368  if (!CI)
369  return llvm::createStringError(llvm::inconvertibleErrorCode(),
370  "Couldn't build compiler invocation");
371  auto Clang = prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
372  std::move(*Buf), Inputs.FS, IgnoreDiags);
373  if (!Clang)
374  return llvm::createStringError(llvm::inconvertibleErrorCode(),
375  "Couldn't build compiler instance");
376 
377  SymbolCollector::Options IndexOpts;
378  // Creates a filter to not collect index results from files with unchanged
379  // digests.
380  IndexOpts.FileFilter = [&ShardVersionsSnapshot](const SourceManager &SM,
381  FileID FID) {
382  const auto *F = SM.getFileEntryForID(FID);
383  if (!F)
384  return false; // Skip invalid files.
385  auto AbsPath = getCanonicalPath(F, SM);
386  if (!AbsPath)
387  return false; // Skip files without absolute path.
388  auto Digest = digestFile(SM, FID);
389  if (!Digest)
390  return false;
391  auto D = ShardVersionsSnapshot.find(*AbsPath);
392  if (D != ShardVersionsSnapshot.end() && D->second.Digest == Digest &&
393  !D->second.HadErrors)
394  return false; // Skip files that haven't changed, without errors.
395  return true;
396  };
397 
398  IndexFileIn Index;
400  IndexOpts, [&](SymbolSlab S) { Index.Symbols = std::move(S); },
401  [&](RefSlab R) { Index.Refs = std::move(R); },
402  [&](RelationSlab R) { Index.Relations = std::move(R); },
403  [&](IncludeGraph IG) { Index.Sources = std::move(IG); });
404 
405  // We're going to run clang here, and it could potentially crash.
406  // We could use CrashRecoveryContext to try to make indexing crashes nonfatal,
407  // but the leaky "recovery" is pretty scary too in a long-running process.
408  // If crashes are a real problem, maybe we should fork a child process.
409 
410  const FrontendInputFile &Input = Clang->getFrontendOpts().Inputs.front();
411  if (!Action->BeginSourceFile(*Clang, Input))
412  return llvm::createStringError(llvm::inconvertibleErrorCode(),
413  "BeginSourceFile() failed");
414  if (llvm::Error Err = Action->Execute())
415  return Err;
416 
417  Action->EndSourceFile();
418 
419  Index.Cmd = Inputs.CompileCommand;
420  assert(Index.Symbols && Index.Refs && Index.Sources &&
421  "Symbols, Refs and Sources must be set.");
422 
423  log("Indexed {0} ({1} symbols, {2} refs, {3} files)",
424  Inputs.CompileCommand.Filename, Index.Symbols->size(),
425  Index.Refs->numRefs(), Index.Sources->size());
426  SPAN_ATTACH(Tracer, "symbols", int(Index.Symbols->size()));
427  SPAN_ATTACH(Tracer, "refs", int(Index.Refs->numRefs()));
428  SPAN_ATTACH(Tracer, "sources", int(Index.Sources->size()));
429 
430  bool HadErrors = Clang->hasDiagnostics() &&
431  Clang->getDiagnostics().hasUncompilableErrorOccurred();
432  if (HadErrors) {
433  log("Failed to compile {0}, index may be incomplete", AbsolutePath);
434  for (auto &It : *Index.Sources)
435  It.second.Flags |= IncludeGraphNode::SourceFlag::HadErrors;
436  }
437  update(AbsolutePath, std::move(Index), ShardVersionsSnapshot, HadErrors);
438 
439  Rebuilder.indexedTU();
440  return llvm::Error::success();
441 }
442 
443 // Restores shards for \p MainFiles from index storage. Then checks staleness of
444 // those shards and returns a list of TUs that needs to be indexed to update
445 // staleness.
446 std::vector<tooling::CompileCommand>
447 BackgroundIndex::loadProject(std::vector<std::string> MainFiles) {
448  std::vector<tooling::CompileCommand> NeedsReIndexing;
449 
450  Rebuilder.startLoading();
451  // Load shards for all of the mainfiles.
452  const std::vector<LoadedShard> Result =
453  loadIndexShards(MainFiles, IndexStorageFactory, CDB);
454  size_t LoadedShards = 0;
455  {
456  // Update in-memory state.
457  std::lock_guard<std::mutex> Lock(ShardVersionsMu);
458  for (auto &LS : Result) {
459  if (!LS.Shard)
460  continue;
461  auto SS =
462  LS.Shard->Symbols
463  ? std::make_unique<SymbolSlab>(std::move(*LS.Shard->Symbols))
464  : nullptr;
465  auto RS = LS.Shard->Refs
466  ? std::make_unique<RefSlab>(std::move(*LS.Shard->Refs))
467  : nullptr;
468  auto RelS =
469  LS.Shard->Relations
470  ? std::make_unique<RelationSlab>(std::move(*LS.Shard->Relations))
471  : nullptr;
472  ShardVersion &SV = ShardVersions[LS.AbsolutePath];
473  SV.Digest = LS.Digest;
474  SV.HadErrors = LS.HadErrors;
475  ++LoadedShards;
476 
477  IndexedSymbols.update(LS.AbsolutePath, std::move(SS), std::move(RS),
478  std::move(RelS), LS.CountReferences);
479  }
480  }
481  Rebuilder.loadedShard(LoadedShards);
482  Rebuilder.doneLoading();
483 
484  auto FS = FSProvider.getFileSystem();
485  llvm::DenseSet<PathRef> TUsToIndex;
486  // We'll accept data from stale shards, but ensure the files get reindexed
487  // soon.
488  for (auto &LS : Result) {
489  if (!shardIsStale(LS, FS.get()))
490  continue;
491  PathRef TUForFile = LS.DependentTU;
492  assert(!TUForFile.empty() && "File without a TU!");
493 
494  // FIXME: Currently, we simply schedule indexing on a TU whenever any of
495  // its dependencies needs re-indexing. We might do it smarter by figuring
496  // out a minimal set of TUs that will cover all the stale dependencies.
497  // FIXME: Try looking at other TUs if no compile commands are available
498  // for this TU, i.e TU was deleted after we performed indexing.
499  TUsToIndex.insert(TUForFile);
500  }
501 
502  for (PathRef TU : TUsToIndex) {
503  auto Cmd = CDB.getCompileCommand(TU);
504  if (!Cmd)
505  continue;
506  NeedsReIndexing.emplace_back(std::move(*Cmd));
507  }
508 
509  return NeedsReIndexing;
510 }
511 
512 } // namespace clangd
513 } // 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:70
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
const Decl * D
Definition: XRefs.cpp:849
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
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D)
Builds compiler invocation that could be used to build AST or preamble.
Definition: Compiler.cpp:44
llvm::Optional< FileDigest > digestFile(const SourceManager &SM, FileID FID)
Definition: SourceCode.cpp:688
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:678
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:625
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
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
NodeType Type
void work(std::function< void()> OnIdle=nullptr)
const SymbolIndex * Index
Definition: Dexp.cpp:84