#include "Annotations.h"
#include "Cancellation.h"
+#include "ClangdServer.h"
#include "Context.h"
#include "Diagnostics.h"
#include "Matchers.h"
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<std::mutex> 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<TUStatus> allStatus() {
+ std::vector<PreambleAction> preambleStatuses() {
std::lock_guard<std::mutex> Lock(Mutex);
- return AllStatus;
+ return PreambleActions;
+ }
+
+ std::vector<ASTAction::Kind> astStatuses() {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ return ASTActions;
}
private:
std::mutex Mutex;
- std::vector<TUStatus> AllStatus;
+ std::vector<ASTAction::Kind> ASTActions;
+ std::vector<PreambleAction> PreambleActions;
} CaptureTUStatus;
MockFSProvider FS;
MockCompilationDatabase CDB;
// 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<std::vector<LocatedSymbol>> 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) {