51 #include "clang/Frontend/CompilerInvocation.h" 52 #include "clang/Tooling/CompilationDatabase.h" 53 #include "llvm/ADT/Optional.h" 54 #include "llvm/ADT/ScopeExit.h" 55 #include "llvm/Support/Errc.h" 56 #include "llvm/Support/Path.h" 64 using std::chrono::steady_clock;
74 return llvm::StringRef(*
File);
84 using Key =
const ASTWorker *;
86 ASTCache(
unsigned MaxRetainedASTs) : MaxRetainedASTs(MaxRetainedASTs) {}
91 std::lock_guard<std::mutex> Lock(Mut);
92 auto It = findByKey(K);
93 if (It == LRU.end() || !It->second)
95 return It->second->getUsedBytes();
100 void put(
Key K, std::unique_ptr<ParsedAST> V) {
101 std::unique_lock<std::mutex> Lock(Mut);
102 assert(findByKey(K) == LRU.end());
104 LRU.insert(LRU.begin(), {K, std::move(V)});
105 if (LRU.size() <= MaxRetainedASTs)
108 std::unique_ptr<ParsedAST> ForCleanup = std::move(LRU.back().second);
118 llvm::Optional<std::unique_ptr<ParsedAST>>
take(
Key K) {
119 std::unique_lock<std::mutex> Lock(Mut);
120 auto Existing = findByKey(K);
121 if (Existing == LRU.end())
123 std::unique_ptr<ParsedAST> V = std::move(Existing->second);
128 return llvm::Optional<std::unique_ptr<ParsedAST>>(std::move(V));
132 using KVPair = std::pair<Key, std::unique_ptr<ParsedAST>>;
134 std::vector<KVPair>::iterator findByKey(
Key K) {
135 return llvm::find_if(LRU, [K](
const KVPair &P) {
return P.first == K; });
139 unsigned MaxRetainedASTs;
142 std::vector<KVPair> LRU;
146 class ASTWorkerHandle;
159 friend class ASTWorkerHandle;
162 steady_clock::duration UpdateDebounce,
bool StorePreamblesInMemory,
171 static ASTWorkerHandle
174 Semaphore &Barrier, steady_clock::duration UpdateDebounce,
181 llvm::unique_function<
void(llvm::Expected<InputsAndAST>)>
Action);
184 std::shared_ptr<const PreambleData> getPossiblyStalePreamble()
const;
188 void getCurrentPreamble(
189 llvm::unique_function<
void(std::shared_ptr<const PreambleData>)>);
191 tooling::CompileCommand getCurrentCompileCommand()
const;
197 void waitForFirstPreamble()
const;
199 std::size_t getUsedBytes()
const;
200 bool isASTCached()
const;
210 void startTask(llvm::StringRef Name, llvm::unique_function<
void()> Task,
222 bool shouldSkipHeadLocked()
const;
226 std::shared_ptr<const ParseInputs> getCurrentFileInputs()
const;
237 TUScheduler::ASTCache &IdleASTs;
240 const steady_clock::duration UpdateDebounce;
243 const GlobalCompilationDatabase &CDB;
245 const bool StorePreambleInMemory;
247 ParsingCallbacks &Callbacks;
254 bool DiagsWereReported =
false;
256 mutable std::mutex Mutex;
260 std::shared_ptr<const ParseInputs> FileInputs;
261 std::shared_ptr<const PreambleData> LastBuiltPreamble;
263 Notification PreambleWasBuilt;
266 std::deque<Request> Requests;
267 mutable std::condition_variable RequestsCV;
276 bool ReportDiagnostics =
true;
283 class ASTWorkerHandle {
284 friend class ASTWorker;
285 ASTWorkerHandle(std::shared_ptr<ASTWorker> Worker)
286 : Worker(std::move(Worker)) {
287 assert(this->Worker);
291 ASTWorkerHandle(
const ASTWorkerHandle &) =
delete;
292 ASTWorkerHandle &operator=(
const ASTWorkerHandle &) =
delete;
293 ASTWorkerHandle(ASTWorkerHandle &&) =
default;
294 ASTWorkerHandle &operator=(ASTWorkerHandle &&) =
default;
301 ASTWorker &operator*() {
302 assert(Worker &&
"Handle was moved from");
306 ASTWorker *operator->() {
307 assert(Worker &&
"Handle was moved from");
315 std::shared_ptr<const ASTWorker> lock() {
return Worker; }
318 std::shared_ptr<ASTWorker> Worker;
322 ASTWorker::create(
PathRef FileName,
const GlobalCompilationDatabase &CDB,
323 TUScheduler::ASTCache &IdleASTs, AsyncTaskRunner *Tasks,
324 Semaphore &Barrier, steady_clock::duration UpdateDebounce,
325 bool StorePreamblesInMemory, ParsingCallbacks &Callbacks) {
326 std::shared_ptr<ASTWorker> Worker(
327 new ASTWorker(FileName, CDB, IdleASTs, Barrier, !Tasks,
328 UpdateDebounce, StorePreamblesInMemory, Callbacks));
330 Tasks->runAsync(
"worker:" + llvm::sys::path::filename(FileName),
331 [Worker]() { Worker->run(); });
333 return ASTWorkerHandle(std::move(Worker));
336 ASTWorker::ASTWorker(
PathRef FileName,
const GlobalCompilationDatabase &CDB,
337 TUScheduler::ASTCache &LRUCache, Semaphore &Barrier,
338 bool RunSync, steady_clock::duration UpdateDebounce,
339 bool StorePreamblesInMemory, ParsingCallbacks &Callbacks)
340 : IdleASTs(LRUCache), RunSync(RunSync), UpdateDebounce(UpdateDebounce),
341 FileName(FileName), CDB(CDB),
342 StorePreambleInMemory(StorePreamblesInMemory),
344 TUStatus::BuildDetails()},
345 Barrier(Barrier), Done(
false) {
346 auto Inputs = std::make_shared<ParseInputs>();
350 Inputs->CompileCommand = CDB.getFallbackCommand(FileName);
351 FileInputs = std::move(Inputs);
354 ASTWorker::~ASTWorker() {
358 std::lock_guard<std::mutex> Lock(Mutex);
359 assert(Done &&
"handle was not destroyed");
360 assert(Requests.empty() &&
"unprocessed requests when destroying ASTWorker");
364 void ASTWorker::update(ParseInputs Inputs,
WantDiagnostics WantDiags) {
365 llvm::StringRef TaskName =
"Update";
366 auto Task = [=]()
mutable {
372 if (
auto Cmd = CDB.getCompileCommand(FileName))
373 Inputs.CompileCommand = *Cmd;
376 Inputs.CompileCommand = CDB.getFallbackCommand(FileName);
377 auto PrevInputs = getCurrentFileInputs();
379 bool InputsAreTheSame =
380 std::tie(PrevInputs->CompileCommand, PrevInputs->Contents) ==
381 std::tie(Inputs.CompileCommand, Inputs.Contents);
383 tooling::CompileCommand OldCommand = PrevInputs->CompileCommand;
384 bool PrevDiagsWereReported = DiagsWereReported;
386 std::lock_guard<std::mutex> Lock(Mutex);
387 FileInputs = std::make_shared<ParseInputs>(Inputs);
389 DiagsWereReported =
false;
391 log(
"Updating file {0} with command {1}\n[{2}]\n{3}", FileName,
392 Inputs.CompileCommand.Heuristic,
393 Inputs.CompileCommand.Directory,
394 llvm::join(Inputs.CompileCommand.CommandLine,
" "));
396 std::unique_ptr<CompilerInvocation> Invocation =
399 elog(
"Could not build CompilerInvocation for file {0}", FileName);
402 TUStatus::BuildDetails Details;
403 Details.BuildFailed =
true;
407 PreambleWasBuilt.notify();
411 std::shared_ptr<const PreambleData> OldPreamble =
412 getPossiblyStalePreamble();
413 std::shared_ptr<const PreambleData> NewPreamble =
buildPreamble(
414 FileName, *Invocation, OldPreamble, OldCommand, Inputs,
415 StorePreambleInMemory,
416 [
this](ASTContext &
Ctx, std::shared_ptr<clang::Preprocessor> PP,
417 const CanonicalIncludes &CanonIncludes) {
418 Callbacks.onPreambleAST(FileName, Ctx, std::move(PP), CanonIncludes);
421 bool CanReuseAST = InputsAreTheSame && (OldPreamble == NewPreamble);
423 std::lock_guard<std::mutex> Lock(Mutex);
424 LastBuiltPreamble = NewPreamble;
430 PreambleWasBuilt.notify();
437 if (PrevDiagsWereReported) {
438 DiagsWereReported =
true;
446 log(
"Skipping rebuild of the AST for {0}, inputs are the same.",
448 TUStatus::BuildDetails Details;
449 Details.ReuseAST =
true;
460 std::lock_guard<std::mutex> Lock(DiagsMu);
463 if (!ReportDiagnostics)
468 llvm::Optional<std::unique_ptr<ParsedAST>>
AST = IdleASTs.take(
this);
470 llvm::Optional<ParsedAST> NewAST =
471 buildAST(FileName, std::move(Invocation), Inputs, NewPreamble);
472 AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) :
nullptr;
474 TUStatus::BuildDetails Details;
475 Details.BuildFailed =
true;
480 TUStatus::BuildDetails Details;
481 Details.ReuseAST =
true;
490 std::lock_guard<std::mutex> Lock(DiagsMu);
491 if (ReportDiagnostics)
492 Callbacks.onDiagnostics(FileName, (*AST)->getDiagnostics());
494 trace::Span Span(
"Running main AST callback");
495 Callbacks.onMainAST(FileName, **AST);
496 DiagsWereReported =
true;
499 IdleASTs.put(
this, std::move(*AST));
501 startTask(TaskName, std::move(Task), WantDiags);
504 void ASTWorker::runWithAST(
505 llvm::StringRef
Name,
506 llvm::unique_function<
void(llvm::Expected<InputsAndAST>)>
Action) {
509 return Action(llvm::make_error<CancelledError>());
510 llvm::Optional<std::unique_ptr<ParsedAST>>
AST = IdleASTs.take(
this);
511 auto CurrentInputs = getCurrentFileInputs();
513 std::unique_ptr<CompilerInvocation> Invocation =
516 llvm::Optional<ParsedAST> NewAST =
519 llvm::make_unique<CompilerInvocation>(*Invocation),
520 *CurrentInputs, getPossiblyStalePreamble())
522 AST = NewAST ? llvm::make_unique<ParsedAST>(std::move(*NewAST)) :
nullptr;
525 auto _ = llvm::make_scope_exit(
526 [&AST,
this]() { IdleASTs.put(
this, std::move(*AST)); });
529 return Action(llvm::make_error<llvm::StringError>(
530 "invalid AST", llvm::errc::invalid_argument));
531 Action(InputsAndAST{*CurrentInputs, **AST});
533 startTask(Name,
Bind(Task, std::move(
Action)),
537 std::shared_ptr<const PreambleData>
538 ASTWorker::getPossiblyStalePreamble()
const {
539 std::lock_guard<std::mutex> Lock(Mutex);
540 return LastBuiltPreamble;
543 void ASTWorker::getCurrentPreamble(
544 llvm::unique_function<
void(std::shared_ptr<const PreambleData>)>
Callback) {
548 std::unique_lock<std::mutex> Lock(Mutex);
550 std::find_if(Requests.rbegin(), Requests.rend(),
551 [](
const Request &R) {
return R.UpdateType.hasValue(); });
553 if (LastUpdate == Requests.rend()) {
555 return Callback(getPossiblyStalePreamble());
557 assert(!RunSync &&
"Running synchronously, but queue is non-empty!");
558 Requests.insert(LastUpdate.base(),
561 Callback(getPossiblyStalePreamble());
563 std::move(Callback)),
564 "GetPreamble", steady_clock::now(),
568 RequestsCV.notify_all();
571 void ASTWorker::waitForFirstPreamble()
const { PreambleWasBuilt.wait(); }
573 std::shared_ptr<const ParseInputs> ASTWorker::getCurrentFileInputs()
const {
574 std::unique_lock<std::mutex> Lock(Mutex);
578 tooling::CompileCommand ASTWorker::getCurrentCompileCommand()
const {
579 std::unique_lock<std::mutex> Lock(Mutex);
580 return FileInputs->CompileCommand;
583 std::size_t ASTWorker::getUsedBytes()
const {
587 std::size_t
Result = IdleASTs.getUsedBytes(
this);
588 if (
auto Preamble = getPossiblyStalePreamble())
589 Result +=
Preamble->Preamble.getSize();
593 bool ASTWorker::isASTCached()
const {
return IdleASTs.getUsedBytes(
this) != 0; }
595 void ASTWorker::stop() {
597 std::lock_guard<std::mutex> Lock(DiagsMu);
598 ReportDiagnostics =
false;
601 std::lock_guard<std::mutex> Lock(Mutex);
602 assert(!Done &&
"stop() called twice");
605 RequestsCV.notify_all();
608 void ASTWorker::startTask(llvm::StringRef Name,
609 llvm::unique_function<
void()> Task,
612 assert(!Done &&
"running a task after stop()");
613 trace::Span Tracer(Name +
":" + llvm::sys::path::filename(FileName));
619 std::lock_guard<std::mutex> Lock(Mutex);
620 assert(!Done &&
"running a task after stop()");
622 {std::move(Task),
Name, steady_clock::now(),
625 RequestsCV.notify_all();
628 void ASTWorker::emitTUStatus(TUAction
Action,
629 const TUStatus::BuildDetails *Details) {
630 Status.Action = std::move(Action);
632 Status.Details = *Details;
633 std::lock_guard<std::mutex> Lock(DiagsMu);
635 if (ReportDiagnostics) {
636 Callbacks.onFileUpdated(FileName, Status);
640 void ASTWorker::run() {
644 std::unique_lock<std::mutex> Lock(Mutex);
645 for (
auto Wait = scheduleLocked(); !Wait.expired();
646 Wait = scheduleLocked()) {
648 if (Requests.empty())
655 llvm::Optional<WithContext>
Ctx;
656 llvm::Optional<trace::Span> Tracer;
657 if (!Requests.empty()) {
658 Ctx.emplace(Requests.front().Ctx.clone());
659 Tracer.emplace(
"Debounce");
660 SPAN_ATTACH(*Tracer,
"next_request", Requests.front().Name);
664 std::chrono::duration_cast<std::chrono::milliseconds>(
665 Wait.time() - steady_clock::now())
670 wait(Lock, RequestsCV, Wait);
672 Req = std::move(Requests.front());
677 std::unique_lock<Semaphore> Lock(Barrier, std::try_to_lock);
678 if (!Lock.owns_lock()) {
682 WithContext Guard(std::move(Req.Ctx));
683 trace::Span Tracer(Req.Name);
688 bool IsEmpty =
false;
690 std::lock_guard<std::mutex> Lock(Mutex);
691 Requests.pop_front();
692 IsEmpty = Requests.empty();
696 RequestsCV.notify_all();
700 Deadline ASTWorker::scheduleLocked() {
701 if (Requests.empty())
704 for (
auto I = Requests.begin(), E = Requests.end(); I != E; ++I) {
707 if (I->UpdateType ==
None)
712 if (I->UpdateType ==
None) {
713 Request R = std::move(*I);
715 Requests.push_front(std::move(R));
723 while (shouldSkipHeadLocked())
724 Requests.pop_front();
725 assert(!Requests.empty() &&
"skipped the whole queue");
730 for (
const auto &R : Requests)
734 Deadline
D(Requests.front().AddTime + UpdateDebounce);
739 bool ASTWorker::shouldSkipHeadLocked()
const {
740 assert(!Requests.empty());
741 auto Next = Requests.begin();
742 auto UpdateType = Next->UpdateType;
748 if (Next == Requests.end() || !Next->UpdateType)
751 switch (*UpdateType) {
758 for (; Next != Requests.end(); ++Next)
764 llvm_unreachable(
"Unknown WantDiagnostics");
767 bool ASTWorker::blockUntilIdle(Deadline Timeout)
const {
768 std::unique_lock<std::mutex> Lock(Mutex);
769 return wait(Lock, RequestsCV, Timeout, [&] {
return Requests.empty(); });
776 std::string renderTUAction(
const TUAction &Action) {
778 llvm::raw_string_ostream OS(Result);
781 OS <<
"file is queued";
784 OS <<
"running " << Action.Name;
787 OS <<
"parsing includes";
790 OS <<
"parsing main file";
802 unsigned HardwareConcurrency = std::thread::hardware_concurrency();
806 if (HardwareConcurrency == 0)
808 return HardwareConcurrency;
825 unsigned AsyncThreadsCount,
826 bool StorePreamblesInMemory,
827 std::unique_ptr<ParsingCallbacks> Callbacks,
828 std::chrono::steady_clock::duration UpdateDebounce,
830 : CDB(CDB), StorePreamblesInMemory(StorePreamblesInMemory),
831 Callbacks(Callbacks ? move(Callbacks)
833 Barrier(AsyncThreadsCount),
834 IdleASTs(
llvm::make_unique<
ASTCache>(RetentionPolicy.MaxRetainedASTs)),
835 UpdateDebounce(UpdateDebounce) {
836 if (0 < AsyncThreadsCount) {
837 PreambleTasks.emplace();
838 WorkerThreads.emplace();
848 PreambleTasks->wait();
850 WorkerThreads->wait();
854 for (
auto &
File : Files)
855 if (!
File.getValue()->Worker->blockUntilIdle(D))
858 if (!PreambleTasks->wait(D))
865 std::unique_ptr<FileData> &FD = Files[
File];
866 bool NewFile = FD ==
nullptr;
869 ASTWorkerHandle Worker = ASTWorker::create(
870 File, CDB, *IdleASTs,
871 WorkerThreads ? WorkerThreads.getPointer() :
nullptr, Barrier,
872 UpdateDebounce, StorePreamblesInMemory, *Callbacks);
873 FD = std::unique_ptr<FileData>(
878 FD->Worker->update(std::move(Inputs), WantDiags);
883 bool Removed = Files.erase(File);
885 elog(
"Trying to remove file from TUScheduler that is not tracked: {0}",
890 auto It = Files.find(File);
891 if (It == Files.end()) {
892 elog(
"getContents() for untracked file: {0}", File);
895 return It->second->Contents;
899 llvm::unique_function<
void()>
Action) {
902 PreambleTasks->runAsync(Name, std::move(
Action));
907 llvm::unique_function<
void(llvm::Expected<InputsAndAST>)>
Action) {
908 auto It = Files.find(File);
909 if (It == Files.end()) {
910 Action(llvm::make_error<LSPError>(
915 It->second->Worker->runWithAST(Name, std::move(
Action));
921 auto It = Files.find(File);
922 if (It == Files.end()) {
923 Action(llvm::make_error<LSPError>(
924 "trying to get preamble for non-added document",
929 if (!PreambleTasks) {
932 std::shared_ptr<const PreambleData>
Preamble =
933 It->second->Worker->getPossiblyStalePreamble();
935 It->second->Worker->getCurrentCompileCommand(),
941 std::future<std::shared_ptr<const PreambleData>> ConsistentPreamble;
943 std::promise<std::shared_ptr<const PreambleData>> Promise;
944 ConsistentPreamble = Promise.get_future();
945 It->second->Worker->getCurrentPreamble(
Bind(
946 [](decltype(Promise) Promise,
947 std::shared_ptr<const PreambleData>
Preamble) {
948 Promise.set_value(std::move(Preamble));
950 std::move(Promise)));
953 std::shared_ptr<const ASTWorker> Worker = It->second->Worker.lock();
954 auto Task = [Worker, Consistency,
957 decltype(ConsistentPreamble) ConsistentPreamble,
958 decltype(Action)
Action)
mutable {
959 std::shared_ptr<const PreambleData>
Preamble;
960 if (ConsistentPreamble.valid()) {
961 Preamble = ConsistentPreamble.get();
963 if (Consistency != PreambleConsistency::StaleOrAbsent) {
967 Worker->waitForFirstPreamble();
969 Preamble = Worker->getPossiblyStalePreamble();
972 std::lock_guard<Semaphore> BarrierLock(Barrier);
979 PreambleTasks->runAsync(
980 "task:" + llvm::sys::path::filename(File),
981 Bind(Task, std::string(Name), std::string(File), It->second->Contents,
982 Worker->getCurrentCompileCommand(),
984 std::move(ConsistentPreamble), std::move(Action)));
987 std::vector<std::pair<Path, std::size_t>>
989 std::vector<std::pair<Path, std::size_t>>
Result;
990 Result.reserve(Files.size());
991 for (
auto &&PathAndFile : Files)
993 {PathAndFile.first(), PathAndFile.second->Worker->getUsedBytes()});
999 for (
auto &&PathAndFile : Files) {
1000 if (!PathAndFile.second->Worker->isASTCached())
1002 Result.push_back(PathAndFile.first());
PreambleConsistency
Controls whether preamble reads wait for the preamble to be up-to-date.
const tooling::CompileCommand & Command
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Some operations such as code completion produce a set of candidates.
Diagnostics must be generated for this snapshot.
FileStatus render(PathRef File) const
Serialize this to an LSP file status item.
static llvm::Optional< llvm::StringRef > getFileBeingProcessedInContext()
bool blockUntilIdle(Deadline D) const
Wait until there are no scheduled or running tasks.
void remove(PathRef File)
Remove File from the list of tracked files and schedule removal of its resources. ...
TUScheduler(const GlobalCompilationDatabase &CDB, unsigned AsyncThreadsCount, bool StorePreamblesInMemory, std::unique_ptr< ParsingCallbacks > ASTCallbacks, std::chrono::steady_clock::duration UpdateDebounce, ASTRetentionPolicy RetentionPolicy)
std::string state
The human-readable string presents the current state of the file, can be shown in the UI (e...
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Values in a Context are indexed by typed keys.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Documents should not be synced at all.
Limits the number of threads that can acquire the lock at the same time.
URIForFile uri
The text document's URI.
bool update(PathRef File, ParseInputs Inputs, WantDiagnostics WD)
Schedule an update for File.
void elog(const char *Fmt, Ts &&... Vals)
Configuration of the AST retention policy.
bool isCancelled(const Context &Ctx)
True if the current context is within a cancelable task which was cancelled.
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation &CI, std::shared_ptr< const PreambleData > OldPreamble, const tooling::CompileCommand &OldCompileCommand, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback)
Rebuild the preamble for the new inputs unless the old one can be reused.
Provides compilation arguments used for parsing C and C++ files.
Context clone() const
Clone this context object.
ForwardBinder< Func, Args... > Bind(Func F, Args &&... As)
Creates an object that stores a callable (F) and first arguments to the callable (As) and allows to c...
llvm::Optional< WantDiagnostics > UpdateType
static Deadline infinity()
llvm::unique_function< void()> Action
void log(const char *Fmt, Ts &&... Vals)
void put(Key K, std::unique_ptr< ParsedAST > V)
Store the value in the pool, possibly removing the last used AST.
llvm::Optional< ParsedAST > buildAST(PathRef FileName, std::unique_ptr< CompilerInvocation > Invocation, const ParseInputs &Inputs, std::shared_ptr< const PreambleData > Preamble)
Build an AST from provided user inputs.
std::string Path
A typedef to represent a file path.
static const Context & current()
Returns the context for the current thread, creating it if needed.
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs)
Builds compiler invocation that could be used to build AST or preamble.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
std::vector< std::pair< Path, std::size_t > > getUsedBytesPerFile() const
Returns estimated memory usage for each of the currently open files.
void runWithPreamble(llvm::StringRef Name, PathRef File, PreambleConsistency Consistency, Callback< InputsAndPreamble > Action)
Schedule an async read of the preamble.
std::vector< Path > getFilesWithCachedAST() const
Returns a list of files with ASTs currently stored in memory.
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
Runs tasks on separate (detached) threads and wait for all tasks to finish.
A context is an immutable container for per-request data that must be propagated through layers that ...
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
WithContext replaces Context::current() with a provided scope.
std::string Contents
Latest inputs, passed to TUScheduler::update().
ASTCache(unsigned MaxRetainedASTs)
const PreambleData * Preamble
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Context derive(const Key< Type > &Key, typename std::decay< Type >::type Value) const &
Derives a child context It is safe to move or destroy a parent context after calling derive()...
llvm::Optional< std::unique_ptr< ParsedAST > > take(Key K)
Returns the cached value for K, or llvm::None if the value is not in the cache anymore.
steady_clock::time_point AddTime
static clang::clangd::Key< std::string > kFileBeingProcessed
void runWithAST(llvm::StringRef Name, PathRef File, Callback< InputsAndAST > Action)
Schedule an async read of the AST.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
A point in time we can wait for.
Clangd extension: indicates the current state of the file in clangd, sent from server via the textDoc...
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
An LRU cache of idle ASTs.
llvm::StringRef getContents(PathRef File) const
Returns the current contents of the buffer for File, per last update().
Records an event whose duration is the lifetime of the Span object.
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
Diagnostics must not be generated for this snapshot.
The preamble is generated from the current version of the file.
std::size_t getUsedBytes(Key K)
Returns result of getUsedBytes() for the AST cached by K.
void run(llvm::StringRef Name, llvm::unique_function< void()> Action)
Schedule an async task with no dependencies.