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