aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_flycheck/src/lib.rs66
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs2
-rw-r--r--crates/rust-analyzer/src/global_state.rs16
-rw-r--r--crates/rust-analyzer/src/main_loop.rs6
-rw-r--r--crates/vfs-notify/src/lib.rs26
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)]
51pub struct Flycheck { 51pub 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
58impl Flycheck { 57impl 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
98struct FlycheckThread { 100struct 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
112impl FlycheckThread { 115impl 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
276enum CheckEvent { 286enum 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};
9use lsp_types::Url; 9use lsp_types::Url;
10use parking_lot::RwLock; 10use parking_lot::RwLock;
11use ra_db::{CrateId, SourceRoot, VfsPath}; 11use ra_db::{CrateId, SourceRoot, VfsPath};
12use ra_flycheck::{Flycheck, FlycheckConfig}; 12use ra_flycheck::{CheckTask, FlycheckConfig, FlycheckHandle};
13use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId}; 13use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId};
14use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; 14use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
15use stdx::format_to; 15use stdx::format_to;
@@ -27,12 +27,18 @@ use crate::{
27}; 27};
28use rustc_hash::{FxHashMap, FxHashSet}; 28use rustc_hash::{FxHashMap, FxHashSet};
29 29
30fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { 30fn 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;
20use crate::include::Include; 20use crate::include::Include;
21 21
22#[derive(Debug)] 22#[derive(Debug)]
23pub struct LoaderHandle { 23pub 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
35impl loader::Handle for LoaderHandle { 35impl 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
53type NotifyEvent = notify::Result<notify::Event>; 53type NotifyEvent = notify::Result<notify::Event>;
54 54
55struct LoaderActor { 55struct 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
70impl LoaderActor { 70impl 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