diff options
-rw-r--r-- | crates/ra_flycheck/src/lib.rs | 66 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 16 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 6 | ||||
-rw-r--r-- | crates/vfs-notify/src/lib.rs | 26 |
5 files changed, 66 insertions, 50 deletions
diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs index 0e2ee8698..af75adbe2 100644 --- a/crates/ra_flycheck/src/lib.rs +++ b/crates/ra_flycheck/src/lib.rs | |||
@@ -48,21 +48,23 @@ impl fmt::Display for FlycheckConfig { | |||
48 | /// diagnostics based on the output. | 48 | /// diagnostics based on the output. |
49 | /// The spawned thread is shut down when this struct is dropped. | 49 | /// The spawned thread is shut down when this struct is dropped. |
50 | #[derive(Debug)] | 50 | #[derive(Debug)] |
51 | pub struct Flycheck { | 51 | pub struct FlycheckHandle { |
52 | // XXX: drop order is significant | 52 | // XXX: drop order is significant |
53 | cmd_send: Sender<CheckCommand>, | 53 | cmd_send: Sender<CheckCommand>, |
54 | handle: jod_thread::JoinHandle<()>, | 54 | handle: jod_thread::JoinHandle<()>, |
55 | pub task_recv: Receiver<CheckTask>, | ||
56 | } | 55 | } |
57 | 56 | ||
58 | impl Flycheck { | 57 | impl FlycheckHandle { |
59 | pub fn new(config: FlycheckConfig, workspace_root: PathBuf) -> Flycheck { | 58 | pub fn spawn( |
60 | let (task_send, task_recv) = unbounded::<CheckTask>(); | 59 | sender: Box<dyn Fn(CheckTask) + Send>, |
60 | config: FlycheckConfig, | ||
61 | workspace_root: PathBuf, | ||
62 | ) -> FlycheckHandle { | ||
61 | let (cmd_send, cmd_recv) = unbounded::<CheckCommand>(); | 63 | let (cmd_send, cmd_recv) = unbounded::<CheckCommand>(); |
62 | let handle = jod_thread::spawn(move || { | 64 | let handle = jod_thread::spawn(move || { |
63 | FlycheckThread::new(config, workspace_root).run(&task_send, &cmd_recv); | 65 | FlycheckActor::new(sender, config, workspace_root).run(&cmd_recv); |
64 | }); | 66 | }); |
65 | Flycheck { task_recv, cmd_send, handle } | 67 | FlycheckHandle { cmd_send, handle } |
66 | } | 68 | } |
67 | 69 | ||
68 | /// Schedule a re-start of the cargo check worker. | 70 | /// Schedule a re-start of the cargo check worker. |
@@ -95,7 +97,8 @@ pub enum CheckCommand { | |||
95 | Update, | 97 | Update, |
96 | } | 98 | } |
97 | 99 | ||
98 | struct FlycheckThread { | 100 | struct FlycheckActor { |
101 | sender: Box<dyn Fn(CheckTask) + Send>, | ||
99 | config: FlycheckConfig, | 102 | config: FlycheckConfig, |
100 | workspace_root: PathBuf, | 103 | workspace_root: PathBuf, |
101 | last_update_req: Option<Instant>, | 104 | last_update_req: Option<Instant>, |
@@ -109,9 +112,14 @@ struct FlycheckThread { | |||
109 | check_process: Option<jod_thread::JoinHandle<()>>, | 112 | check_process: Option<jod_thread::JoinHandle<()>>, |
110 | } | 113 | } |
111 | 114 | ||
112 | impl FlycheckThread { | 115 | impl FlycheckActor { |
113 | fn new(config: FlycheckConfig, workspace_root: PathBuf) -> FlycheckThread { | 116 | fn new( |
114 | FlycheckThread { | 117 | sender: Box<dyn Fn(CheckTask) + Send>, |
118 | config: FlycheckConfig, | ||
119 | workspace_root: PathBuf, | ||
120 | ) -> FlycheckActor { | ||
121 | FlycheckActor { | ||
122 | sender, | ||
115 | config, | 123 | config, |
116 | workspace_root, | 124 | workspace_root, |
117 | last_update_req: None, | 125 | last_update_req: None, |
@@ -120,9 +128,9 @@ impl FlycheckThread { | |||
120 | } | 128 | } |
121 | } | 129 | } |
122 | 130 | ||
123 | fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) { | 131 | fn run(&mut self, cmd_recv: &Receiver<CheckCommand>) { |
124 | // If we rerun the thread, we need to discard the previous check results first | 132 | // If we rerun the thread, we need to discard the previous check results first |
125 | self.clean_previous_results(task_send); | 133 | self.clean_previous_results(); |
126 | 134 | ||
127 | loop { | 135 | loop { |
128 | select! { | 136 | select! { |
@@ -134,7 +142,7 @@ impl FlycheckThread { | |||
134 | }, | 142 | }, |
135 | }, | 143 | }, |
136 | recv(self.message_recv) -> msg => match msg { | 144 | recv(self.message_recv) -> msg => match msg { |
137 | Ok(msg) => self.handle_message(msg, task_send), | 145 | Ok(msg) => self.handle_message(msg), |
138 | Err(RecvError) => { | 146 | Err(RecvError) => { |
139 | // Watcher finished, replace it with a never channel to | 147 | // Watcher finished, replace it with a never channel to |
140 | // avoid busy-waiting. | 148 | // avoid busy-waiting. |
@@ -146,15 +154,15 @@ impl FlycheckThread { | |||
146 | 154 | ||
147 | if self.should_recheck() { | 155 | if self.should_recheck() { |
148 | self.last_update_req = None; | 156 | self.last_update_req = None; |
149 | task_send.send(CheckTask::ClearDiagnostics).unwrap(); | 157 | self.send(CheckTask::ClearDiagnostics); |
150 | self.restart_check_process(); | 158 | self.restart_check_process(); |
151 | } | 159 | } |
152 | } | 160 | } |
153 | } | 161 | } |
154 | 162 | ||
155 | fn clean_previous_results(&self, task_send: &Sender<CheckTask>) { | 163 | fn clean_previous_results(&self) { |
156 | task_send.send(CheckTask::ClearDiagnostics).unwrap(); | 164 | self.send(CheckTask::ClearDiagnostics); |
157 | task_send.send(CheckTask::Status(Status::End)).unwrap(); | 165 | self.send(CheckTask::Status(Status::End)); |
158 | } | 166 | } |
159 | 167 | ||
160 | fn should_recheck(&mut self) -> bool { | 168 | fn should_recheck(&mut self) -> bool { |
@@ -173,27 +181,25 @@ impl FlycheckThread { | |||
173 | } | 181 | } |
174 | } | 182 | } |
175 | 183 | ||
176 | fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) { | 184 | fn handle_message(&self, msg: CheckEvent) { |
177 | match msg { | 185 | match msg { |
178 | CheckEvent::Begin => { | 186 | CheckEvent::Begin => { |
179 | task_send.send(CheckTask::Status(Status::Being)).unwrap(); | 187 | self.send(CheckTask::Status(Status::Being)); |
180 | } | 188 | } |
181 | 189 | ||
182 | CheckEvent::End => { | 190 | CheckEvent::End => { |
183 | task_send.send(CheckTask::Status(Status::End)).unwrap(); | 191 | self.send(CheckTask::Status(Status::End)); |
184 | } | 192 | } |
185 | 193 | ||
186 | CheckEvent::Msg(Message::CompilerArtifact(msg)) => { | 194 | CheckEvent::Msg(Message::CompilerArtifact(msg)) => { |
187 | task_send.send(CheckTask::Status(Status::Progress(msg.target.name))).unwrap(); | 195 | self.send(CheckTask::Status(Status::Progress(msg.target.name))); |
188 | } | 196 | } |
189 | 197 | ||
190 | CheckEvent::Msg(Message::CompilerMessage(msg)) => { | 198 | CheckEvent::Msg(Message::CompilerMessage(msg)) => { |
191 | task_send | 199 | self.send(CheckTask::AddDiagnostic { |
192 | .send(CheckTask::AddDiagnostic { | 200 | workspace_root: self.workspace_root.clone(), |
193 | workspace_root: self.workspace_root.clone(), | 201 | diagnostic: msg.message, |
194 | diagnostic: msg.message, | 202 | }); |
195 | }) | ||
196 | .unwrap(); | ||
197 | } | 203 | } |
198 | 204 | ||
199 | CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} | 205 | CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} |
@@ -271,6 +277,10 @@ impl FlycheckThread { | |||
271 | let _ = message_send.send(CheckEvent::End); | 277 | let _ = message_send.send(CheckEvent::End); |
272 | })) | 278 | })) |
273 | } | 279 | } |
280 | |||
281 | fn send(&self, check_task: CheckTask) { | ||
282 | (self.sender)(check_task) | ||
283 | } | ||
274 | } | 284 | } |
275 | 285 | ||
276 | enum CheckEvent { | 286 | enum CheckEvent { |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 92e9b60fc..c5cf5ff27 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -28,7 +28,7 @@ pub fn load_cargo( | |||
28 | let mut vfs = vfs::Vfs::default(); | 28 | let mut vfs = vfs::Vfs::default(); |
29 | let mut loader = { | 29 | let mut loader = { |
30 | let loader = | 30 | let loader = |
31 | vfs_notify::LoaderHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap())); | 31 | vfs_notify::NotifyHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap())); |
32 | Box::new(loader) | 32 | Box::new(loader) |
33 | }; | 33 | }; |
34 | 34 | ||
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 64d4e2787..c022ff705 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -9,7 +9,7 @@ use crossbeam_channel::{unbounded, Receiver}; | |||
9 | use lsp_types::Url; | 9 | use lsp_types::Url; |
10 | use parking_lot::RwLock; | 10 | use parking_lot::RwLock; |
11 | use ra_db::{CrateId, SourceRoot, VfsPath}; | 11 | use ra_db::{CrateId, SourceRoot, VfsPath}; |
12 | use ra_flycheck::{Flycheck, FlycheckConfig}; | 12 | use ra_flycheck::{CheckTask, FlycheckConfig, FlycheckHandle}; |
13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId}; | 13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId}; |
14 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; | 14 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; |
15 | use stdx::format_to; | 15 | use stdx::format_to; |
@@ -27,12 +27,18 @@ use crate::{ | |||
27 | }; | 27 | }; |
28 | use rustc_hash::{FxHashMap, FxHashSet}; | 28 | use rustc_hash::{FxHashMap, FxHashSet}; |
29 | 29 | ||
30 | fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { | 30 | fn create_flycheck( |
31 | workspaces: &[ProjectWorkspace], | ||
32 | config: &FlycheckConfig, | ||
33 | ) -> Option<(FlycheckHandle, Receiver<CheckTask>)> { | ||
31 | // FIXME: Figure out the multi-workspace situation | 34 | // FIXME: Figure out the multi-workspace situation |
32 | workspaces.iter().find_map(move |w| match w { | 35 | workspaces.iter().find_map(move |w| match w { |
33 | ProjectWorkspace::Cargo { cargo, .. } => { | 36 | ProjectWorkspace::Cargo { cargo, .. } => { |
37 | let (sender, receiver) = unbounded(); | ||
38 | let sender = Box::new(move |msg| sender.send(msg).unwrap()); | ||
34 | let cargo_project_root = cargo.workspace_root().to_path_buf(); | 39 | let cargo_project_root = cargo.workspace_root().to_path_buf(); |
35 | Some(Flycheck::new(config.clone(), cargo_project_root.into())) | 40 | let flycheck = FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into()); |
41 | Some((flycheck, receiver)) | ||
36 | } | 42 | } |
37 | ProjectWorkspace::Json { .. } => { | 43 | ProjectWorkspace::Json { .. } => { |
38 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); | 44 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); |
@@ -63,7 +69,7 @@ pub(crate) struct GlobalState { | |||
63 | pub(crate) analysis_host: AnalysisHost, | 69 | pub(crate) analysis_host: AnalysisHost, |
64 | pub(crate) loader: Box<dyn vfs::loader::Handle>, | 70 | pub(crate) loader: Box<dyn vfs::loader::Handle>, |
65 | pub(crate) task_receiver: Receiver<vfs::loader::Message>, | 71 | pub(crate) task_receiver: Receiver<vfs::loader::Message>, |
66 | pub(crate) flycheck: Option<Flycheck>, | 72 | pub(crate) flycheck: Option<(FlycheckHandle, Receiver<CheckTask>)>, |
67 | pub(crate) diagnostics: DiagnosticCollection, | 73 | pub(crate) diagnostics: DiagnosticCollection, |
68 | pub(crate) mem_docs: FxHashSet<VfsPath>, | 74 | pub(crate) mem_docs: FxHashSet<VfsPath>, |
69 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 75 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
@@ -115,7 +121,7 @@ impl GlobalState { | |||
115 | }; | 121 | }; |
116 | 122 | ||
117 | let mut loader = { | 123 | let mut loader = { |
118 | let loader = vfs_notify::LoaderHandle::spawn(Box::new(move |msg| { | 124 | let loader = vfs_notify::NotifyHandle::spawn(Box::new(move |msg| { |
119 | task_sender.send(msg).unwrap() | 125 | task_sender.send(msg).unwrap() |
120 | })); | 126 | })); |
121 | Box::new(loader) | 127 | Box::new(loader) |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 03569086a..e5f82de5e 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -136,7 +136,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
136 | Ok(task) => Event::Vfs(task), | 136 | Ok(task) => Event::Vfs(task), |
137 | Err(RecvError) => return Err("vfs died".into()), | 137 | Err(RecvError) => return Err("vfs died".into()), |
138 | }, | 138 | }, |
139 | recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task { | 139 | recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.1)) -> task => match task { |
140 | Ok(task) => Event::CheckWatcher(task), | 140 | Ok(task) => Event::CheckWatcher(task), |
141 | Err(RecvError) => return Err("check watcher died".into()), | 141 | Err(RecvError) => return Err("check watcher died".into()), |
142 | }, | 142 | }, |
@@ -290,7 +290,7 @@ fn loop_turn( | |||
290 | 290 | ||
291 | if became_ready { | 291 | if became_ready { |
292 | if let Some(flycheck) = &global_state.flycheck { | 292 | if let Some(flycheck) = &global_state.flycheck { |
293 | flycheck.update(); | 293 | flycheck.0.update(); |
294 | } | 294 | } |
295 | } | 295 | } |
296 | 296 | ||
@@ -486,7 +486,7 @@ fn on_notification( | |||
486 | let not = match notification_cast::<lsp_types::notification::DidSaveTextDocument>(not) { | 486 | let not = match notification_cast::<lsp_types::notification::DidSaveTextDocument>(not) { |
487 | Ok(_params) => { | 487 | Ok(_params) => { |
488 | if let Some(flycheck) = &global_state.flycheck { | 488 | if let Some(flycheck) = &global_state.flycheck { |
489 | flycheck.update(); | 489 | flycheck.0.update(); |
490 | } | 490 | } |
491 | return Ok(()); | 491 | return Ok(()); |
492 | } | 492 | } |
diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index a2f4e0c5b..282cf0358 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs | |||
@@ -20,7 +20,7 @@ use walkdir::WalkDir; | |||
20 | use crate::include::Include; | 20 | use crate::include::Include; |
21 | 21 | ||
22 | #[derive(Debug)] | 22 | #[derive(Debug)] |
23 | pub struct LoaderHandle { | 23 | pub struct NotifyHandle { |
24 | // Relative order of fields below is significant. | 24 | // Relative order of fields below is significant. |
25 | sender: crossbeam_channel::Sender<Message>, | 25 | sender: crossbeam_channel::Sender<Message>, |
26 | _thread: jod_thread::JoinHandle, | 26 | _thread: jod_thread::JoinHandle, |
@@ -32,12 +32,12 @@ enum Message { | |||
32 | Invalidate(AbsPathBuf), | 32 | Invalidate(AbsPathBuf), |
33 | } | 33 | } |
34 | 34 | ||
35 | impl loader::Handle for LoaderHandle { | 35 | impl loader::Handle for NotifyHandle { |
36 | fn spawn(sender: loader::Sender) -> LoaderHandle { | 36 | fn spawn(sender: loader::Sender) -> NotifyHandle { |
37 | let actor = LoaderActor::new(sender); | 37 | let actor = NotifyActor::new(sender); |
38 | let (sender, receiver) = unbounded::<Message>(); | 38 | let (sender, receiver) = unbounded::<Message>(); |
39 | let thread = jod_thread::spawn(move || actor.run(receiver)); | 39 | let thread = jod_thread::spawn(move || actor.run(receiver)); |
40 | LoaderHandle { sender, _thread: thread } | 40 | NotifyHandle { sender, _thread: thread } |
41 | } | 41 | } |
42 | fn set_config(&mut self, config: loader::Config) { | 42 | fn set_config(&mut self, config: loader::Config) { |
43 | self.sender.send(Message::Config(config)).unwrap() | 43 | self.sender.send(Message::Config(config)).unwrap() |
@@ -52,10 +52,10 @@ impl loader::Handle for LoaderHandle { | |||
52 | 52 | ||
53 | type NotifyEvent = notify::Result<notify::Event>; | 53 | type NotifyEvent = notify::Result<notify::Event>; |
54 | 54 | ||
55 | struct LoaderActor { | 55 | struct NotifyActor { |
56 | sender: loader::Sender, | ||
56 | config: Vec<(AbsPathBuf, Include, bool)>, | 57 | config: Vec<(AbsPathBuf, Include, bool)>, |
57 | watched_paths: FxHashSet<AbsPathBuf>, | 58 | watched_paths: FxHashSet<AbsPathBuf>, |
58 | sender: loader::Sender, | ||
59 | // Drop order of fields bellow is significant, | 59 | // Drop order of fields bellow is significant, |
60 | watcher: Option<RecommendedWatcher>, | 60 | watcher: Option<RecommendedWatcher>, |
61 | watcher_receiver: Receiver<NotifyEvent>, | 61 | watcher_receiver: Receiver<NotifyEvent>, |
@@ -67,19 +67,19 @@ enum Event { | |||
67 | NotifyEvent(NotifyEvent), | 67 | NotifyEvent(NotifyEvent), |
68 | } | 68 | } |
69 | 69 | ||
70 | impl LoaderActor { | 70 | impl NotifyActor { |
71 | fn new(sender: loader::Sender) -> LoaderActor { | 71 | fn new(sender: loader::Sender) -> NotifyActor { |
72 | let (watcher_sender, watcher_receiver) = unbounded(); | 72 | let (watcher_sender, watcher_receiver) = unbounded(); |
73 | let watcher = log_notify_error(Watcher::new_immediate(move |event| { | 73 | let watcher = log_notify_error(Watcher::new_immediate(move |event| { |
74 | watcher_sender.send(event).unwrap() | 74 | watcher_sender.send(event).unwrap() |
75 | })); | 75 | })); |
76 | 76 | ||
77 | LoaderActor { | 77 | NotifyActor { |
78 | watcher, | ||
79 | watcher_receiver, | ||
80 | watched_paths: FxHashSet::default(), | ||
81 | sender, | 78 | sender, |
82 | config: Vec::new(), | 79 | config: Vec::new(), |
80 | watched_paths: FxHashSet::default(), | ||
81 | watcher, | ||
82 | watcher_receiver, | ||
83 | } | 83 | } |
84 | } | 84 | } |
85 | 85 | ||