From 5d961afffbd3528e194787e908c9a4f8e0c2aca6 Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Mon, 17 Apr 2023 14:34:51 +1000 Subject: [PATCH] Add a clear diagnostics command to flycheck. This will allow for watcher-style flychecks. Currently, we can only run flychecks on every save. This allows for a long-running flycheck that can update diagnostics between file saves (eg. update on every build). Rationale: I'm trying to improve the experience developing using bazel + rust (see [issue](https://github.com/bazelbuild/rules_rust/pull/1657)). The developer experience I'm looking at is: 1. Dev invokes "ibazel build //:my_crate //:my_crate_test". This ensures that whenever the source code changes, it rebuilds. both the crate and the test for the crate. 2. The discover project command is automatically invoked when you open main.rs, which generates a file listing the `.rustc-output` files mentioned below. 3. Dev modifies `my_crate/src/main.rs` and saves in vscode. 4. bazel is automatically invoked on save, and under the hood invokes rustc, which generates `bazel-out/k8-fastbuild/bin/my_crate/my_crate.rustc-output` and `bazel-out/k8-fastbuild/bin/my_crate_test/my_crate_test.rustc_output` for the original crate and the test crate respectively. 5. The non-test crate finishes building 6. A watcher script would see that `my_crate.rustc-output` has been updated, and update the rust-analyzer result for the file. 7. The test crate finishes building 8. The watcher script would see that `my_crate_test.rustc-output` has been updated, and update the rust-analyzer result for the file. --- crates/flycheck/src/lib.rs | 13 +++++++++++++ crates/rust-analyzer/src/main_loop.rs | 1 + 2 files changed, 14 insertions(+) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index accb14a51deb..c0a3272bd095 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -113,6 +113,8 @@ impl FlycheckHandle { } pub enum Message { + /// Request clearing diagnostics for a file. + ClearDiagnostics{ id: usize }, /// Request adding a diagnostic with fixes included to a file AddDiagnostic { id: usize, workspace_root: AbsPathBuf, diagnostic: Diagnostic }, @@ -136,6 +138,9 @@ impl fmt::Debug for Message { Message::Progress { id, progress } => { f.debug_struct("Progress").field("id", id).field("progress", progress).finish() } + Message::ClearDiagnostics {id} => { + f.debug_struct("Clear").field("id", id).finish() + } } } } @@ -264,6 +269,10 @@ impl FlycheckActor { self.report_progress(Progress::DidCheckCrate(msg.target.name)); } + CargoMessage::ClearDiagnostics => { + self.send(Message::ClearDiagnostics{id: self.id}); + } + CargoMessage::Diagnostic(msg) => { tracing::trace!( flycheck_id = self.id, @@ -461,6 +470,9 @@ impl CargoActor { let mut read_at_least_one_stdout_message = false; let mut read_at_least_one_stderr_message = false; let process_line = |line: &str, error: &mut String| { + if line == "CLEAR" { + self.sender.send(CargoMessage::ClearDiagnostics).unwrap(); + } // Try to deserialize a message from Cargo or Rustc. let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); @@ -516,6 +528,7 @@ impl CargoActor { enum CargoMessage { CompilerArtifact(cargo_metadata::Artifact), Diagnostic(Diagnostic), + ClearDiagnostics, } #[derive(Deserialize)] diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index f9930fb25990..a843f79f6613 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -556,6 +556,7 @@ impl GlobalState { fn handle_flycheck_msg(&mut self, message: flycheck::Message) { match message { + flycheck::Message::ClearDiagnostics{id} => self.diagnostics.clear_check(id), flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => { let snap = self.snapshot(); let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(