From 1a28f30ba48254fae30a29c2f1053f653d5e687e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 17 Sep 2020 18:50:30 +0200 Subject: Spawn a flycheck instance per workspace --- crates/flycheck/src/lib.rs | 24 +++++++++++++++++------- crates/rust-analyzer/src/global_state.rs | 4 ++-- crates/rust-analyzer/src/main_loop.rs | 17 ++++++++++++----- crates/rust-analyzer/src/reload.rs | 22 +++++++++++++++------- 4 files changed, 46 insertions(+), 21 deletions(-) (limited to 'crates') diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 16078d104..d982c5f29 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -59,11 +59,12 @@ pub struct FlycheckHandle { impl FlycheckHandle { pub fn spawn( + id: usize, sender: Box, config: FlycheckConfig, workspace_root: PathBuf, ) -> FlycheckHandle { - let actor = FlycheckActor::new(sender, config, workspace_root); + let actor = FlycheckActor::new(id, sender, config, workspace_root); let (sender, receiver) = unbounded::(); let thread = jod_thread::spawn(move || actor.run(receiver)); FlycheckHandle { sender, thread } @@ -81,7 +82,11 @@ pub enum Message { AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic }, /// Request check progress notification to client - Progress(Progress), + Progress { + /// Flycheck instance ID + id: usize, + progress: Progress, + }, } #[derive(Debug)] @@ -95,6 +100,7 @@ pub enum Progress { struct Restart; struct FlycheckActor { + id: usize, sender: Box, config: FlycheckConfig, workspace_root: PathBuf, @@ -113,11 +119,15 @@ enum Event { impl FlycheckActor { fn new( + id: usize, sender: Box, config: FlycheckConfig, workspace_root: PathBuf, ) -> FlycheckActor { - FlycheckActor { sender, config, workspace_root, cargo_handle: None } + FlycheckActor { id, sender, config, workspace_root, cargo_handle: None } + } + fn progress(&self, progress: Progress) { + self.send(Message::Progress { id: self.id, progress }); } fn next_event(&self, inbox: &Receiver) -> Option { let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver); @@ -139,7 +149,7 @@ impl FlycheckActor { command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); if let Ok(child) = command.spawn().map(JodChild) { self.cargo_handle = Some(CargoHandle::spawn(child)); - self.send(Message::Progress(Progress::DidStart)); + self.progress(Progress::DidStart); } } Event::CheckEvent(None) => { @@ -153,11 +163,11 @@ impl FlycheckActor { self.check_command() ) } - self.send(Message::Progress(Progress::DidFinish(res))); + self.progress(Progress::DidFinish(res)); } Event::CheckEvent(Some(message)) => match message { cargo_metadata::Message::CompilerArtifact(msg) => { - self.send(Message::Progress(Progress::DidCheckCrate(msg.target.name))); + self.progress(Progress::DidCheckCrate(msg.target.name)); } cargo_metadata::Message::CompilerMessage(msg) => { @@ -179,7 +189,7 @@ impl FlycheckActor { } fn cancel_check_process(&mut self) { if self.cargo_handle.take().is_some() { - self.send(Message::Progress(Progress::DidCancel)); + self.progress(Progress::DidCancel); } } fn check_command(&self) -> Command { diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 212f98a30..96313aaec 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -63,7 +63,7 @@ pub(crate) struct GlobalState { req_queue: ReqQueue, pub(crate) task_pool: Handle, Receiver>, pub(crate) loader: Handle, Receiver>, - pub(crate) flycheck: Option, + pub(crate) flycheck: Vec, pub(crate) flycheck_sender: Sender, pub(crate) flycheck_receiver: Receiver, pub(crate) config: Config, @@ -115,7 +115,7 @@ impl GlobalState { req_queue: ReqQueue::default(), task_pool, loader, - flycheck: None, + flycheck: Vec::new(), flycheck_sender, flycheck_receiver, config, diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 8d3132581..06ab9d508 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -266,8 +266,8 @@ impl GlobalState { } } - flycheck::Message::Progress(status) => { - let (state, message) = match status { + flycheck::Message::Progress { id, progress } => { + let (state, message) = match progress { flycheck::Progress::DidStart => { self.diagnostics.clear_check(); (Progress::Begin, None) @@ -284,14 +284,21 @@ impl GlobalState { } }; - self.report_progress("cargo check", state, message, None); + // When we're running multiple flychecks, we have to include a disambiguator in + // the title, or the editor complains. Note that this is a user-facing string. + let title = if self.flycheck.len() == 1 { + "cargo check".to_string() + } else { + format!("cargo check (#{})", id + 1) + }; + self.report_progress(&title, state, message, None); } }, } let state_changed = self.process_changes(); if prev_status == Status::Loading && self.status == Status::Ready { - if let Some(flycheck) = &self.flycheck { + for flycheck in &self.flycheck { flycheck.update(); } } @@ -490,7 +497,7 @@ impl GlobalState { Ok(()) })? .on::(|this, params| { - if let Some(flycheck) = &this.flycheck { + for flycheck in &this.flycheck { flycheck.update(); } if let Ok(abs_path) = from_proto::abs_path(¶ms.text_document.uri) { diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index b070087a4..de0dbcad4 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -235,29 +235,37 @@ impl GlobalState { let config = match self.config.flycheck.clone() { Some(it) => it, None => { - self.flycheck = None; + self.flycheck = Vec::new(); return; } }; let sender = self.flycheck_sender.clone(); - let sender = Box::new(move |msg| sender.send(msg).unwrap()); self.flycheck = self .workspaces .iter() - // FIXME: Figure out the multi-workspace situation - .find_map(|w| match w { - ProjectWorkspace::Cargo { cargo, sysroot: _ } => Some(cargo.workspace_root()), + .enumerate() + .filter_map(|(id, w)| match w { + ProjectWorkspace::Cargo { cargo, sysroot: _ } => Some((id, cargo.workspace_root())), ProjectWorkspace::Json { project, .. } => { // Enable flychecks for json projects if a custom flycheck command was supplied // in the workspace configuration. match config { - FlycheckConfig::CustomCommand { .. } => Some(project.path()), + FlycheckConfig::CustomCommand { .. } => Some((id, project.path())), _ => None, } } }) - .map(move |root| FlycheckHandle::spawn(sender, config, root.to_path_buf().into())) + .map(|(id, root)| { + let sender = sender.clone(); + FlycheckHandle::spawn( + id, + Box::new(move |msg| sender.send(msg).unwrap()), + config.clone(), + root.to_path_buf().into(), + ) + }) + .collect(); } } -- cgit v1.2.3