[clang-tools-extra] 6b85032 - [clangd] Update TUStatus api to accommodate preamble thread
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 6 12:20:54 PDT 2020
Author: Kadir Cetinkaya
Date: 2020-04-06T21:20:17+02:00
New Revision: 6b85032c95bee2e15ce7f239316de4d11e6ca08b
URL: https://github.com/llvm/llvm-project/commit/6b85032c95bee2e15ce7f239316de4d11e6ca08b
DIFF: https://github.com/llvm/llvm-project/commit/6b85032c95bee2e15ce7f239316de4d11e6ca08b.diff
LOG: [clangd] Update TUStatus api to accommodate preamble thread
Summary:
TUStatus api had a single thread in mind. This introudces a section
action to represent state of the preamble thread. In the file status extension,
we keep old behavior almost the same. We only prepend current task with a
`parsing includes` if preamble thread is working. We omit the idle thread in the
output unless both threads are idle.
Reviewers: sammccall
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76304
Added:
Modified:
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/TUScheduler.cpp
clang-tools-extra/clangd/TUScheduler.h
clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 19476d7fa052..eafe353bb70e 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -15,6 +15,7 @@
#include "Protocol.h"
#include "SemanticHighlighting.h"
#include "SourceCode.h"
+#include "TUScheduler.h"
#include "Trace.h"
#include "URI.h"
#include "refactor/Tweak.h"
@@ -1368,7 +1369,8 @@ ClangdLSPServer::ClangdLSPServer(
// clang-format on
}
-ClangdLSPServer::~ClangdLSPServer() { IsBeingDestroyed = true;
+ClangdLSPServer::~ClangdLSPServer() {
+ IsBeingDestroyed = true;
// Explicitly destroy ClangdServer first, blocking on threads it owns.
// This ensures they don't access any other members.
Server.reset();
@@ -1556,8 +1558,9 @@ void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
// two statuses are running faster in practice, which leads the UI constantly
// changing, and doesn't provide much value. We may want to emit status at a
// reasonable time interval (e.g. 0.5s).
- if (Status.Action.S == TUAction::BuildingFile ||
- Status.Action.S == TUAction::RunningAction)
+ if (Status.PreambleActivity == PreambleAction::Idle &&
+ (Status.ASTActivity.K == ASTAction::Building ||
+ Status.ASTActivity.K == ASTAction::RunningAction))
return;
notify("textDocument/clangd.fileStatus", Status.render(File));
}
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index 2341c340d7b9..2ca0ae855d56 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -57,15 +57,20 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Threading.h"
#include <algorithm>
#include <memory>
#include <mutex>
#include <queue>
+#include <string>
#include <thread>
namespace clang {
@@ -152,6 +157,39 @@ class TUScheduler::ASTCache {
};
namespace {
+/// Threadsafe manager for updating a TUStatus and emitting it after each
+/// update.
+class SynchronizedTUStatus {
+public:
+ SynchronizedTUStatus(PathRef FileName, ParsingCallbacks &Callbacks)
+ : FileName(FileName), Callbacks(Callbacks) {}
+
+ void update(llvm::function_ref<void(TUStatus &)> Mutator) {
+ std::lock_guard<std::mutex> Lock(StatusMu);
+ Mutator(Status);
+ emitStatusLocked();
+ }
+
+ /// Prevents emitting of further updates.
+ void stop() {
+ std::lock_guard<std::mutex> Lock(StatusMu);
+ CanPublish = false;
+ }
+
+private:
+ void emitStatusLocked() {
+ if (CanPublish)
+ Callbacks.onFileUpdated(FileName, Status);
+ }
+
+ const Path FileName;
+
+ std::mutex StatusMu;
+ TUStatus Status;
+ bool CanPublish = true;
+ ParsingCallbacks &Callbacks;
+};
+
/// Responsible for building and providing access to the preamble of a TU.
/// Whenever the thread is idle and the preamble is outdated, it starts to build
/// a fresh preamble from the latest inputs. If RunSync is true, preambles are
@@ -159,9 +197,11 @@ namespace {
class PreambleThread {
public:
PreambleThread(llvm::StringRef FileName, ParsingCallbacks &Callbacks,
- bool StorePreambleInMemory, bool RunSync)
+ bool StorePreambleInMemory, bool RunSync,
+ SynchronizedTUStatus &Status)
: FileName(FileName), Callbacks(Callbacks),
- StoreInMemory(StorePreambleInMemory), RunSync(RunSync) {}
+ StoreInMemory(StorePreambleInMemory), RunSync(RunSync), Status(Status) {
+ }
size_t getUsedBytes() const {
auto Preamble = latest();
@@ -174,10 +214,6 @@ class PreambleThread {
void update(CompilerInvocation *CI, ParseInputs PI) {
// If compiler invocation was broken, just fail out early.
if (!CI) {
- TUStatus::BuildDetails Details;
- Details.BuildFailed = true;
- std::string TaskName = llvm::formatv("Update ({0})", PI.Version);
- emitTUStatus({TUAction::BuildingPreamble, std::move(TaskName)}, &Details);
// Make sure anyone waiting for the preamble gets notified it could not be
// built.
BuiltFirst.notify();
@@ -187,6 +223,9 @@ class PreambleThread {
Request Req = {std::make_unique<CompilerInvocation>(*CI), std::move(PI)};
if (RunSync) {
build(std::move(Req));
+ Status.update([](TUStatus &Status) {
+ Status.PreambleActivity = PreambleAction::Idle;
+ });
return;
}
{
@@ -225,9 +264,19 @@ class PreambleThread {
}
// Build the preamble and let the waiters know about it.
build(std::move(*CurrentReq));
+ bool IsEmpty = false;
{
std::lock_guard<std::mutex> Lock(Mutex);
CurrentReq.reset();
+ IsEmpty = !NextReq.hasValue();
+ }
+ if (IsEmpty) {
+ // We don't perform this above, before waiting for a request to make
+ // tests more deterministic. As there can be a race between this thread
+ // and client thread(clangdserver).
+ Status.update([](TUStatus &Status) {
+ Status.PreambleActivity = PreambleAction::Idle;
+ });
}
ReqCV.notify_all();
}
@@ -265,18 +314,6 @@ class PreambleThread {
return Done;
}
- /// Updates the TUStatus and emits it. Only called in the worker thread.
- void emitTUStatus(TUAction Action,
- const TUStatus::BuildDetails *Details = nullptr) {
- // Do not emit TU statuses when the worker is shutting down.
- if (isDone())
- return;
- TUStatus Status({std::move(Action), {}});
- if (Details)
- Status.Details = *Details;
- Callbacks.onFileUpdated(FileName, Status);
- }
-
/// Builds a preamble for Req and caches it. Might re-use the latest built
/// preamble if it is valid for Req. Also signals waiters about the build.
/// FIXME: We shouldn't cache failed preambles, if we've got a successful
@@ -287,8 +324,9 @@ class PreambleThread {
std::shared_ptr<const PreambleData> OldPreamble =
Inputs.ForceRebuild ? nullptr : latest();
- std::string TaskName = llvm::formatv("Update ({0})", Inputs.Version);
- emitTUStatus({TUAction::BuildingPreamble, std::move(TaskName)});
+ Status.update([&](TUStatus &Status) {
+ Status.PreambleActivity = PreambleAction::Building;
+ });
auto Preamble = clang::clangd::buildPreamble(
FileName, std::move(*Req.CI), OldPreamble, Inputs, StoreInMemory,
@@ -321,6 +359,8 @@ class PreambleThread {
ParsingCallbacks &Callbacks;
const bool StoreInMemory;
const bool RunSync;
+
+ SynchronizedTUStatus &Status;
};
class ASTWorkerHandle;
@@ -391,9 +431,6 @@ class ASTWorker {
void startTask(llvm::StringRef Name, llvm::unique_function<void()> Task,
llvm::Optional<WantDiagnostics> UpdateType,
TUScheduler::ASTActionInvalidation);
- /// Updates the TUStatus and emits it. Only called in the worker thread.
- void emitTUStatus(TUAction FAction,
- const TUStatus::BuildDetails *Detail = nullptr);
/// Determines the next action to perform.
/// All actions that should never run are discarded.
@@ -427,8 +464,6 @@ class ASTWorker {
const GlobalCompilationDatabase &CDB;
/// Callback invoked when preamble or main file AST is built.
ParsingCallbacks &Callbacks;
- /// Only accessed by the worker thread.
- TUStatus Status;
Semaphore &Barrier;
/// Whether the 'onMainAST' callback ran for the current FileInputs.
@@ -458,6 +493,7 @@ class ASTWorker {
// any results to the user.
bool CanPublishResults = true; /* GUARDED_BY(PublishMu) */
+ SynchronizedTUStatus Status;
PreambleThread PW;
};
@@ -526,12 +562,11 @@ ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
bool RunSync, DebouncePolicy UpdateDebounce,
bool StorePreamblesInMemory, ParsingCallbacks &Callbacks)
: IdleASTs(LRUCache), RunSync(RunSync), UpdateDebounce(UpdateDebounce),
- FileName(FileName), CDB(CDB),
- Callbacks(Callbacks), Status{TUAction(TUAction::Idle, ""),
- TUStatus::BuildDetails()},
- Barrier(Barrier), Done(false),
+ FileName(FileName), CDB(CDB), Callbacks(Callbacks), Barrier(Barrier),
+ Done(false), Status(FileName, Callbacks),
// FIXME: Run preambleworker async.
- PW(FileName, Callbacks, StorePreamblesInMemory, /*RunSync=*/true) {
+ PW(FileName, Callbacks, StorePreamblesInMemory, /*RunSync=*/true,
+ Status) {
auto Inputs = std::make_shared<ParseInputs>();
// Set a fallback command because compile command can be accessed before
// `Inputs` is initialized. Other fields are only used after initialization
@@ -619,7 +654,10 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
// to the old preamble, so it can be freed if there are no other references
// to it.
OldPreamble.reset();
- emitTUStatus({TUAction::BuildingFile, TaskName});
+ Status.update([&](TUStatus &Status) {
+ Status.ASTActivity.K = ASTAction::Building;
+ Status.ASTActivity.Name = std::move(TaskName);
+ });
if (!CanReuseAST) {
IdleASTs.take(this); // Remove the old AST if it's still in cache.
} else {
@@ -635,9 +673,11 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
// current file at this point?
log("Skipping rebuild of the AST for {0}, inputs are the same.",
FileName);
- TUStatus::BuildDetails Details;
- Details.ReuseAST = true;
- emitTUStatus({TUAction::BuildingFile, TaskName}, &Details);
+
+ Status.update([](TUStatus &Status) {
+ Status.Details.ReuseAST = true;
+ Status.Details.BuildFailed = false;
+ });
return;
}
}
@@ -661,17 +701,18 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
llvm::Optional<ParsedAST> NewAST =
buildAST(FileName, std::move(Invocation), CompilerInvocationDiags,
Inputs, NewPreamble);
+ // buildAST fails.
+ Status.update([&](TUStatus &Status) {
+ Status.Details.ReuseAST = false;
+ Status.Details.BuildFailed = !NewAST.hasValue();
+ });
AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
- if (!(*AST)) { // buildAST fails.
- TUStatus::BuildDetails Details;
- Details.BuildFailed = true;
- emitTUStatus({TUAction::BuildingFile, TaskName}, &Details);
- }
} else {
// We are reusing the AST.
- TUStatus::BuildDetails Details;
- Details.ReuseAST = true;
- emitTUStatus({TUAction::BuildingFile, TaskName}, &Details);
+ Status.update([](TUStatus &Status) {
+ Status.Details.ReuseAST = true;
+ Status.Details.BuildFailed = false;
+ });
}
// We want to report the diagnostics even if this update was cancelled.
@@ -815,6 +856,7 @@ void ASTWorker::stop() {
assert(!Done && "stop() called twice");
Done = true;
}
+ Status.stop();
RequestsCV.notify_all();
}
@@ -856,18 +898,6 @@ void ASTWorker::startTask(llvm::StringRef Name,
RequestsCV.notify_all();
}
-void ASTWorker::emitTUStatus(TUAction Action,
- const TUStatus::BuildDetails *Details) {
- Status.Action = std::move(Action);
- if (Details)
- Status.Details = *Details;
- std::lock_guard<std::mutex> Lock(PublishMu);
- // Do not emit TU statuses when the ASTWorker is shutting down.
- if (CanPublishResults) {
- Callbacks.onFileUpdated(FileName, Status);
- }
-}
-
void ASTWorker::run() {
auto _ = llvm::make_scope_exit([this] { PW.stop(); });
while (true) {
@@ -891,7 +921,10 @@ void ASTWorker::run() {
Tracer.emplace("Debounce");
SPAN_ATTACH(*Tracer, "next_request", Requests.front().Name);
if (!(Wait == Deadline::infinity())) {
- emitTUStatus({TUAction::Queued, Requests.front().Name});
+ Status.update([&](TUStatus &Status) {
+ Status.ASTActivity.K = ASTAction::Queued;
+ Status.ASTActivity.Name = Requests.front().Name;
+ });
SPAN_ATTACH(*Tracer, "sleep_ms",
std::chrono::duration_cast<std::chrono::milliseconds>(
Wait.time() - steady_clock::now())
@@ -910,12 +943,18 @@ void ASTWorker::run() {
{
std::unique_lock<Semaphore> Lock(Barrier, std::try_to_lock);
if (!Lock.owns_lock()) {
- emitTUStatus({TUAction::Queued, CurrentRequest->Name});
+ Status.update([&](TUStatus &Status) {
+ Status.ASTActivity.K = ASTAction::Queued;
+ Status.ASTActivity.Name = CurrentRequest->Name;
+ });
Lock.lock();
}
WithContext Guard(std::move(CurrentRequest->Ctx));
trace::Span Tracer(CurrentRequest->Name);
- emitTUStatus({TUAction::RunningAction, CurrentRequest->Name});
+ Status.update([&](TUStatus &Status) {
+ Status.ASTActivity.K = ASTAction::RunningAction;
+ Status.ASTActivity.Name = CurrentRequest->Name;
+ });
CurrentRequest->Action();
}
@@ -925,8 +964,12 @@ void ASTWorker::run() {
CurrentRequest.reset();
IsEmpty = Requests.empty();
}
- if (IsEmpty)
- emitTUStatus({TUAction::Idle, /*Name*/ ""});
+ if (IsEmpty) {
+ Status.update([&](TUStatus &Status) {
+ Status.ASTActivity.K = ASTAction::Idle;
+ Status.ASTActivity.Name = "";
+ });
+ }
RequestsCV.notify_all();
}
}
@@ -1010,27 +1053,33 @@ bool ASTWorker::blockUntilIdle(Deadline Timeout) const {
// TUAction represents clangd-internal states, we don't intend to expose them
// to users (say C++ programmers) directly to avoid confusion, we use terms that
// are familiar by C++ programmers.
-std::string renderTUAction(const TUAction &Action) {
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- switch (Action.S) {
- case TUAction::Queued:
- OS << "file is queued";
+std::string renderTUAction(const PreambleAction PA, const ASTAction &AA) {
+ llvm::SmallVector<std::string, 2> Result;
+ switch (PA) {
+ case PreambleAction::Building:
+ Result.push_back("parsing includes");
break;
- case TUAction::RunningAction:
- OS << "running " << Action.Name;
+ case PreambleAction::Idle:
+ // We handle idle specially below.
+ break;
+ }
+ switch (AA.K) {
+ case ASTAction::Queued:
+ Result.push_back("file is queued");
break;
- case TUAction::BuildingPreamble:
- OS << "parsing includes";
+ case ASTAction::RunningAction:
+ Result.push_back("running " + AA.Name);
break;
- case TUAction::BuildingFile:
- OS << "parsing main file";
+ case ASTAction::Building:
+ Result.push_back("parsing main file");
break;
- case TUAction::Idle:
- OS << "idle";
+ case ASTAction::Idle:
+ // We handle idle specially below.
break;
}
- return OS.str();
+ if (Result.empty())
+ return "idle";
+ return llvm::join(Result, ",");
}
} // namespace
@@ -1042,7 +1091,7 @@ unsigned getDefaultAsyncThreadsCount() {
FileStatus TUStatus::render(PathRef File) const {
FileStatus FStatus;
FStatus.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
- FStatus.state = renderTUAction(Action);
+ FStatus.state = renderTUAction(PreambleActivity, ASTActivity);
return FStatus;
}
diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h
index 5cc7e029096c..b6b9e5ccae21 100644
--- a/clang-tools-extra/clangd/TUScheduler.h
+++ b/clang-tools-extra/clangd/TUScheduler.h
@@ -83,18 +83,22 @@ struct DebouncePolicy {
static DebouncePolicy fixed(clock::duration);
};
-struct TUAction {
- enum State {
- Queued, // The TU is pending in the thread task queue to be built.
- RunningAction, // Starting running actions on the TU.
- BuildingPreamble, // The preamble of the TU is being built.
- BuildingFile, // The TU is being built. It is only emitted when building
- // the AST for diagnostics in write action (update).
+enum class PreambleAction {
+ Idle,
+ Building,
+};
+
+struct ASTAction {
+ enum Kind {
+ Queued, // The action is pending in the thread task queue to be run.
+ RunningAction, // Started running actions on the TU.
+ Building, // The AST is being built.
Idle, // Indicates the worker thread is idle, and ready to run any upcoming
// actions.
};
- TUAction(State S, llvm::StringRef Name) : S(S), Name(Name) {}
- State S;
+ ASTAction() = default;
+ ASTAction(Kind K, llvm::StringRef Name) : K(K), Name(Name) {}
+ Kind K = ASTAction::Idle;
/// The name of the action currently running, e.g. Update, GoToDef, Hover.
/// Empty if we are in the idle state.
std::string Name;
@@ -111,7 +115,9 @@ struct TUStatus {
/// Serialize this to an LSP file status item.
FileStatus render(PathRef File) const;
- TUAction Action;
+ PreambleAction PreambleActivity = PreambleAction::Idle;
+ ASTAction ASTActivity;
+ /// Stores status of the last build for the translation unit.
BuildDetails Details;
};
diff --git a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
index 3d6812496f47..760e1c083353 100644
--- a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -24,6 +24,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <algorithm>
+#include <bits/stdint-uintn.h>
#include <chrono>
#include <utility>
@@ -40,13 +41,14 @@ using ::testing::IsEmpty;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
-MATCHER_P2(TUState, State, ActionName, "") {
- if (arg.Action.S != State) {
- *result_listener << "state is " << arg.Action.S;
+MATCHER_P2(TUState, PreambleActivity, ASTActivity, "") {
+ if (arg.PreambleActivity != PreambleActivity) {
+ *result_listener << "preamblestate is "
+ << static_cast<uint8_t>(arg.PreambleActivity);
return false;
}
- if (arg.Action.Name != ActionName) {
- *result_listener << "name is " << arg.Action.Name;
+ if (arg.ASTActivity.K != ASTActivity) {
+ *result_listener << "aststate is " << arg.ASTActivity.K;
return false;
}
return true;
@@ -732,14 +734,13 @@ TEST_F(TUSchedulerTests, ForceRebuild) {
// Update the source contents, which should trigger an initial build with
// the header file missing.
- updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
- [](std::vector<Diag> Diags) {
- EXPECT_THAT(
- Diags,
- ElementsAre(
- Field(&Diag::Message, "'foo.h' file not found"),
- Field(&Diag::Message, "use of undeclared identifier 'a'")));
- });
+ updateWithDiags(
+ S, Source, Inputs, WantDiagnostics::Yes, [](std::vector<Diag> Diags) {
+ EXPECT_THAT(Diags,
+ ElementsAre(Field(&Diag::Message, "'foo.h' file not found"),
+ Field(&Diag::Message,
+ "use of undeclared identifier 'a'")));
+ });
// Add the header file. We need to recreate the inputs since we changed a
// file from underneath the test FS.
@@ -749,18 +750,17 @@ TEST_F(TUSchedulerTests, ForceRebuild) {
// The addition of the missing header file shouldn't trigger a rebuild since
// we don't track missing files.
- updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
- [](std::vector<Diag> Diags) {
- ADD_FAILURE() << "Did not expect diagnostics for missing header update";
- });
+ updateWithDiags(
+ S, Source, Inputs, WantDiagnostics::Yes, [](std::vector<Diag> Diags) {
+ ADD_FAILURE() << "Did not expect diagnostics for missing header update";
+ });
// Forcing the reload should should cause a rebuild which no longer has any
// errors.
Inputs.ForceRebuild = true;
- updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
- [](std::vector<Diag> Diags) {
- EXPECT_THAT(Diags, IsEmpty());
- });
+ updateWithDiags(
+ S, Source, Inputs, WantDiagnostics::Yes,
+ [](std::vector<Diag> Diags) { EXPECT_THAT(Diags, IsEmpty()); });
ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
}
@@ -848,14 +848,21 @@ TEST_F(TUSchedulerTests, TUStatus) {
EXPECT_THAT(CaptureTUStatus.allStatus(),
ElementsAre(
- // Statuses of "Update" action.
- TUState(TUAction::RunningAction, "Update (1)"),
- TUState(TUAction::BuildingPreamble, "Update (1)"),
- TUState(TUAction::BuildingFile, "Update (1)"),
-
- // Statuses of "Definitions" action
- TUState(TUAction::RunningAction, "Definitions"),
- TUState(TUAction::Idle, /*No action*/ "")));
+ // Everything starts with ASTWorker starting to execute an
+ // update
+ TUState(PreambleAction::Idle, ASTAction::RunningAction),
+ // We build the preamble
+ TUState(PreambleAction::Building, ASTAction::RunningAction),
+ // Preamble worker goes idle
+ TUState(PreambleAction::Idle, ASTAction::RunningAction),
+ // We start building the ast
+ TUState(PreambleAction::Idle, ASTAction::Building),
+ // Built finished succesffully
+ TUState(PreambleAction::Idle, ASTAction::Building),
+ // Rnning go to def
+ TUState(PreambleAction::Idle, ASTAction::RunningAction),
+ // both workers go idle
+ TUState(PreambleAction::Idle, ASTAction::Idle)));
}
TEST_F(TUSchedulerTests, CommandLineErrors) {
@@ -868,8 +875,7 @@ TEST_F(TUSchedulerTests, CommandLineErrors) {
TUScheduler S(CDB, optsForTest(), captureDiags());
std::vector<Diag> Diagnostics;
updateWithDiags(S, testPath("foo.cpp"), "void test() {}",
- WantDiagnostics::Yes,
- [&](std::vector<Diag> D) {
+ WantDiagnostics::Yes, [&](std::vector<Diag> D) {
Diagnostics = std::move(D);
Ready.notify();
});
@@ -893,8 +899,7 @@ TEST_F(TUSchedulerTests, CommandLineWarnings) {
TUScheduler S(CDB, optsForTest(), captureDiags());
std::vector<Diag> Diagnostics;
updateWithDiags(S, testPath("foo.cpp"), "void test() {}",
- WantDiagnostics::Yes,
- [&](std::vector<Diag> D) {
+ WantDiagnostics::Yes, [&](std::vector<Diag> D) {
Diagnostics = std::move(D);
Ready.notify();
});
More information about the cfe-commits
mailing list