aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-09-27 18:43:28 +0100
committerGitHub <[email protected]>2020-09-27 18:43:28 +0100
commitca48c4534b61b7b51ff989409d9ad242753851be (patch)
tree66fb358443e69ad81bd9a5331b205891a7d5acfc
parent662ed41ebcb1cd221b32be95d08b5bf5f10ae525 (diff)
parent1a28f30ba48254fae30a29c2f1053f653d5e687e (diff)
Merge #6027
6027: Spawn a flycheck instance per workspace r=matklad a=jonas-schievink Limitations: - All instances are restarted on every file change - There's only one configuration used for all of them Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r--crates/flycheck/src/lib.rs24
-rw-r--r--crates/rust-analyzer/src/global_state.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs17
-rw-r--r--crates/rust-analyzer/src/reload.rs22
4 files changed, 46 insertions, 21 deletions
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 {
59 59
60impl FlycheckHandle { 60impl FlycheckHandle {
61 pub fn spawn( 61 pub fn spawn(
62 id: usize,
62 sender: Box<dyn Fn(Message) + Send>, 63 sender: Box<dyn Fn(Message) + Send>,
63 config: FlycheckConfig, 64 config: FlycheckConfig,
64 workspace_root: PathBuf, 65 workspace_root: PathBuf,
65 ) -> FlycheckHandle { 66 ) -> FlycheckHandle {
66 let actor = FlycheckActor::new(sender, config, workspace_root); 67 let actor = FlycheckActor::new(id, sender, config, workspace_root);
67 let (sender, receiver) = unbounded::<Restart>(); 68 let (sender, receiver) = unbounded::<Restart>();
68 let thread = jod_thread::spawn(move || actor.run(receiver)); 69 let thread = jod_thread::spawn(move || actor.run(receiver));
69 FlycheckHandle { sender, thread } 70 FlycheckHandle { sender, thread }
@@ -81,7 +82,11 @@ pub enum Message {
81 AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic }, 82 AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },
82 83
83 /// Request check progress notification to client 84 /// Request check progress notification to client
84 Progress(Progress), 85 Progress {
86 /// Flycheck instance ID
87 id: usize,
88 progress: Progress,
89 },
85} 90}
86 91
87#[derive(Debug)] 92#[derive(Debug)]
@@ -95,6 +100,7 @@ pub enum Progress {
95struct Restart; 100struct Restart;
96 101
97struct FlycheckActor { 102struct FlycheckActor {
103 id: usize,
98 sender: Box<dyn Fn(Message) + Send>, 104 sender: Box<dyn Fn(Message) + Send>,
99 config: FlycheckConfig, 105 config: FlycheckConfig,
100 workspace_root: PathBuf, 106 workspace_root: PathBuf,
@@ -113,11 +119,15 @@ enum Event {
113 119
114impl FlycheckActor { 120impl FlycheckActor {
115 fn new( 121 fn new(
122 id: usize,
116 sender: Box<dyn Fn(Message) + Send>, 123 sender: Box<dyn Fn(Message) + Send>,
117 config: FlycheckConfig, 124 config: FlycheckConfig,
118 workspace_root: PathBuf, 125 workspace_root: PathBuf,
119 ) -> FlycheckActor { 126 ) -> FlycheckActor {
120 FlycheckActor { sender, config, workspace_root, cargo_handle: None } 127 FlycheckActor { id, sender, config, workspace_root, cargo_handle: None }
128 }
129 fn progress(&self, progress: Progress) {
130 self.send(Message::Progress { id: self.id, progress });
121 } 131 }
122 fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> { 132 fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> {
123 let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver); 133 let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver);
@@ -139,7 +149,7 @@ impl FlycheckActor {
139 command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); 149 command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null());
140 if let Ok(child) = command.spawn().map(JodChild) { 150 if let Ok(child) = command.spawn().map(JodChild) {
141 self.cargo_handle = Some(CargoHandle::spawn(child)); 151 self.cargo_handle = Some(CargoHandle::spawn(child));
142 self.send(Message::Progress(Progress::DidStart)); 152 self.progress(Progress::DidStart);
143 } 153 }
144 } 154 }
145 Event::CheckEvent(None) => { 155 Event::CheckEvent(None) => {
@@ -153,11 +163,11 @@ impl FlycheckActor {
153 self.check_command() 163 self.check_command()
154 ) 164 )
155 } 165 }
156 self.send(Message::Progress(Progress::DidFinish(res))); 166 self.progress(Progress::DidFinish(res));
157 } 167 }
158 Event::CheckEvent(Some(message)) => match message { 168 Event::CheckEvent(Some(message)) => match message {
159 cargo_metadata::Message::CompilerArtifact(msg) => { 169 cargo_metadata::Message::CompilerArtifact(msg) => {
160 self.send(Message::Progress(Progress::DidCheckCrate(msg.target.name))); 170 self.progress(Progress::DidCheckCrate(msg.target.name));
161 } 171 }
162 172
163 cargo_metadata::Message::CompilerMessage(msg) => { 173 cargo_metadata::Message::CompilerMessage(msg) => {
@@ -179,7 +189,7 @@ impl FlycheckActor {
179 } 189 }
180 fn cancel_check_process(&mut self) { 190 fn cancel_check_process(&mut self) {
181 if self.cargo_handle.take().is_some() { 191 if self.cargo_handle.take().is_some() {
182 self.send(Message::Progress(Progress::DidCancel)); 192 self.progress(Progress::DidCancel);
183 } 193 }
184 } 194 }
185 fn check_command(&self) -> Command { 195 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 {
63 req_queue: ReqQueue, 63 req_queue: ReqQueue,
64 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>, 64 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
65 pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>, 65 pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
66 pub(crate) flycheck: Option<FlycheckHandle>, 66 pub(crate) flycheck: Vec<FlycheckHandle>,
67 pub(crate) flycheck_sender: Sender<flycheck::Message>, 67 pub(crate) flycheck_sender: Sender<flycheck::Message>,
68 pub(crate) flycheck_receiver: Receiver<flycheck::Message>, 68 pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
69 pub(crate) config: Config, 69 pub(crate) config: Config,
@@ -115,7 +115,7 @@ impl GlobalState {
115 req_queue: ReqQueue::default(), 115 req_queue: ReqQueue::default(),
116 task_pool, 116 task_pool,
117 loader, 117 loader,
118 flycheck: None, 118 flycheck: Vec::new(),
119 flycheck_sender, 119 flycheck_sender,
120 flycheck_receiver, 120 flycheck_receiver,
121 config, 121 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 {
266 } 266 }
267 } 267 }
268 268
269 flycheck::Message::Progress(status) => { 269 flycheck::Message::Progress { id, progress } => {
270 let (state, message) = match status { 270 let (state, message) = match progress {
271 flycheck::Progress::DidStart => { 271 flycheck::Progress::DidStart => {
272 self.diagnostics.clear_check(); 272 self.diagnostics.clear_check();
273 (Progress::Begin, None) 273 (Progress::Begin, None)
@@ -284,14 +284,21 @@ impl GlobalState {
284 } 284 }
285 }; 285 };
286 286
287 self.report_progress("cargo check", state, message, None); 287 // When we're running multiple flychecks, we have to include a disambiguator in
288 // the title, or the editor complains. Note that this is a user-facing string.
289 let title = if self.flycheck.len() == 1 {
290 "cargo check".to_string()
291 } else {
292 format!("cargo check (#{})", id + 1)
293 };
294 self.report_progress(&title, state, message, None);
288 } 295 }
289 }, 296 },
290 } 297 }
291 298
292 let state_changed = self.process_changes(); 299 let state_changed = self.process_changes();
293 if prev_status == Status::Loading && self.status == Status::Ready { 300 if prev_status == Status::Loading && self.status == Status::Ready {
294 if let Some(flycheck) = &self.flycheck { 301 for flycheck in &self.flycheck {
295 flycheck.update(); 302 flycheck.update();
296 } 303 }
297 } 304 }
@@ -490,7 +497,7 @@ impl GlobalState {
490 Ok(()) 497 Ok(())
491 })? 498 })?
492 .on::<lsp_types::notification::DidSaveTextDocument>(|this, params| { 499 .on::<lsp_types::notification::DidSaveTextDocument>(|this, params| {
493 if let Some(flycheck) = &this.flycheck { 500 for flycheck in &this.flycheck {
494 flycheck.update(); 501 flycheck.update();
495 } 502 }
496 if let Ok(abs_path) = from_proto::abs_path(&params.text_document.uri) { 503 if let Ok(abs_path) = from_proto::abs_path(&params.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 {
235 let config = match self.config.flycheck.clone() { 235 let config = match self.config.flycheck.clone() {
236 Some(it) => it, 236 Some(it) => it,
237 None => { 237 None => {
238 self.flycheck = None; 238 self.flycheck = Vec::new();
239 return; 239 return;
240 } 240 }
241 }; 241 };
242 242
243 let sender = self.flycheck_sender.clone(); 243 let sender = self.flycheck_sender.clone();
244 let sender = Box::new(move |msg| sender.send(msg).unwrap());
245 self.flycheck = self 244 self.flycheck = self
246 .workspaces 245 .workspaces
247 .iter() 246 .iter()
248 // FIXME: Figure out the multi-workspace situation 247 .enumerate()
249 .find_map(|w| match w { 248 .filter_map(|(id, w)| match w {
250 ProjectWorkspace::Cargo { cargo, sysroot: _ } => Some(cargo.workspace_root()), 249 ProjectWorkspace::Cargo { cargo, sysroot: _ } => Some((id, cargo.workspace_root())),
251 ProjectWorkspace::Json { project, .. } => { 250 ProjectWorkspace::Json { project, .. } => {
252 // Enable flychecks for json projects if a custom flycheck command was supplied 251 // Enable flychecks for json projects if a custom flycheck command was supplied
253 // in the workspace configuration. 252 // in the workspace configuration.
254 match config { 253 match config {
255 FlycheckConfig::CustomCommand { .. } => Some(project.path()), 254 FlycheckConfig::CustomCommand { .. } => Some((id, project.path())),
256 _ => None, 255 _ => None,
257 } 256 }
258 } 257 }
259 }) 258 })
260 .map(move |root| FlycheckHandle::spawn(sender, config, root.to_path_buf().into())) 259 .map(|(id, root)| {
260 let sender = sender.clone();
261 FlycheckHandle::spawn(
262 id,
263 Box::new(move |msg| sender.send(msg).unwrap()),
264 config.clone(),
265 root.to_path_buf().into(),
266 )
267 })
268 .collect();
261 } 269 }
262} 270}
263 271