diff --git a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp --- a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp +++ b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp @@ -8,6 +8,7 @@ #include "Annotations.h" #include "Cancellation.h" +#include "ClangdServer.h" #include "Context.h" #include "Diagnostics.h" #include "Matchers.h" @@ -829,18 +830,35 @@ class CaptureTUStatus : public ClangdServer::Callbacks { public: void onFileUpdated(PathRef File, const TUStatus &Status) override { + auto ASTAction = Status.ASTActivity.K; + auto PreambleAction = Status.PreambleActivity; std::lock_guard Lock(Mutex); - AllStatus.push_back(Status); + // Only push the action if it has changed. Since TUStatus can be published + // from either Preamble or AST thread and when one changes the other stays + // the same. + // Note that this can result in missing some updates when something other + // than action kind changes, e.g. when AST is built/reused the action kind + // stays as Building. + if (ASTActions.empty() || ASTActions.back() != ASTAction) + ASTActions.push_back(ASTAction); + if (PreambleActions.empty() || PreambleActions.back() != PreambleAction) + PreambleActions.push_back(PreambleAction); } - std::vector allStatus() { + std::vector preambleStatuses() { std::lock_guard Lock(Mutex); - return AllStatus; + return PreambleActions; + } + + std::vector astStatuses() { + std::lock_guard Lock(Mutex); + return ASTActions; } private: std::mutex Mutex; - std::vector AllStatus; + std::vector ASTActions; + std::vector PreambleActions; } CaptureTUStatus; MockFSProvider FS; MockCompilationDatabase CDB; @@ -850,35 +868,39 @@ // We schedule the following tasks in the queue: // [Update] [GoToDefinition] Server.addDocument(testPath("foo.cpp"), Code.code(), "1", - WantDiagnostics::Yes); + WantDiagnostics::Auto); + ASSERT_TRUE(Server.blockUntilIdleForTest()); Server.locateSymbolAt(testPath("foo.cpp"), Code.point(), [](Expected> Result) { ASSERT_TRUE((bool)Result); }); - ASSERT_TRUE(Server.blockUntilIdleForTest()); - EXPECT_THAT(CaptureTUStatus.allStatus(), + EXPECT_THAT(CaptureTUStatus.preambleStatuses(), + ElementsAre( + // PreambleThread starts idle, as the update is first handled + // by ASTWorker. + PreambleAction::Idle, + // Then it starts building first preamble and releases that to + // ASTWorker. + PreambleAction::Building, + // Then goes idle and stays that way as we don't receive any + // more update requests. + PreambleAction::Idle)); + EXPECT_THAT(CaptureTUStatus.astStatuses(), ElementsAre( - // Everything starts with ASTWorker starting to execute an - // update - TUState(PreambleAction::Idle, ASTAction::RunningAction), - // We build the preamble - TUState(PreambleAction::Building, ASTAction::RunningAction), - // We built the preamble, and issued ast built on ASTWorker - // thread. Preambleworker goes idle afterwards. - TUState(PreambleAction::Idle, ASTAction::RunningAction), - // Start task for building the ast, as a result of building - // preamble, on astworker thread. - TUState(PreambleAction::Idle, ASTAction::RunningAction), - // AST build starts. - TUState(PreambleAction::Idle, ASTAction::Building), - // AST built finished successfully - TUState(PreambleAction::Idle, ASTAction::Building), - // Running go to def - TUState(PreambleAction::Idle, ASTAction::RunningAction), - // ASTWorker goes idle. - TUState(PreambleAction::Idle, ASTAction::Idle))); + // Starts handling the update action and blocks until the + // first preamble is built. + ASTAction::RunningAction, + // Afterwqards it builds an AST for that preamble to publish + // diagnostics. + ASTAction::Building, + // Then goes idle. + ASTAction::Idle, + // Afterwards we start executing go-to-def. + ASTAction::RunningAction, + // Then go idle. + ASTAction::Idle)); } TEST_F(TUSchedulerTests, CommandLineErrors) {