aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/flycheck/src/lib.rs76
-rw-r--r--crates/rust-analyzer/src/global_state.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop.rs35
3 files changed, 54 insertions, 63 deletions
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index af75adbe2..3e73cf6ff 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -10,7 +10,6 @@ use std::{
10 time::Instant, 10 time::Instant,
11}; 11};
12 12
13use cargo_metadata::Message;
14use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; 13use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender};
15 14
16pub use cargo_metadata::diagnostic::{ 15pub use cargo_metadata::diagnostic::{
@@ -50,17 +49,17 @@ impl fmt::Display for FlycheckConfig {
50#[derive(Debug)] 49#[derive(Debug)]
51pub struct FlycheckHandle { 50pub struct FlycheckHandle {
52 // XXX: drop order is significant 51 // XXX: drop order is significant
53 cmd_send: Sender<CheckCommand>, 52 cmd_send: Sender<Restart>,
54 handle: jod_thread::JoinHandle<()>, 53 handle: jod_thread::JoinHandle,
55} 54}
56 55
57impl FlycheckHandle { 56impl FlycheckHandle {
58 pub fn spawn( 57 pub fn spawn(
59 sender: Box<dyn Fn(CheckTask) + Send>, 58 sender: Box<dyn Fn(Message) + Send>,
60 config: FlycheckConfig, 59 config: FlycheckConfig,
61 workspace_root: PathBuf, 60 workspace_root: PathBuf,
62 ) -> FlycheckHandle { 61 ) -> FlycheckHandle {
63 let (cmd_send, cmd_recv) = unbounded::<CheckCommand>(); 62 let (cmd_send, cmd_recv) = unbounded::<Restart>();
64 let handle = jod_thread::spawn(move || { 63 let handle = jod_thread::spawn(move || {
65 FlycheckActor::new(sender, config, workspace_root).run(&cmd_recv); 64 FlycheckActor::new(sender, config, workspace_root).run(&cmd_recv);
66 }); 65 });
@@ -69,12 +68,12 @@ impl FlycheckHandle {
69 68
70 /// Schedule a re-start of the cargo check worker. 69 /// Schedule a re-start of the cargo check worker.
71 pub fn update(&self) { 70 pub fn update(&self) {
72 self.cmd_send.send(CheckCommand::Update).unwrap(); 71 self.cmd_send.send(Restart).unwrap();
73 } 72 }
74} 73}
75 74
76#[derive(Debug)] 75#[derive(Debug)]
77pub enum CheckTask { 76pub enum Message {
78 /// Request a clearing of all cached diagnostics from the check watcher 77 /// Request a clearing of all cached diagnostics from the check watcher
79 ClearDiagnostics, 78 ClearDiagnostics,
80 79
@@ -82,23 +81,20 @@ pub enum CheckTask {
82 AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic }, 81 AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },
83 82
84 /// Request check progress notification to client 83 /// Request check progress notification to client
85 Status(Status), 84 Progress(Progress),
86} 85}
87 86
88#[derive(Debug)] 87#[derive(Debug)]
89pub enum Status { 88pub enum Progress {
90 Being, 89 Being,
91 Progress(String), 90 DidCheckCrate(String),
92 End, 91 End,
93} 92}
94 93
95pub enum CheckCommand { 94struct Restart;
96 /// Request re-start of check thread
97 Update,
98}
99 95
100struct FlycheckActor { 96struct FlycheckActor {
101 sender: Box<dyn Fn(CheckTask) + Send>, 97 sender: Box<dyn Fn(Message) + Send>,
102 config: FlycheckConfig, 98 config: FlycheckConfig,
103 workspace_root: PathBuf, 99 workspace_root: PathBuf,
104 last_update_req: Option<Instant>, 100 last_update_req: Option<Instant>,
@@ -109,12 +105,12 @@ struct FlycheckActor {
109 /// doesn't provide a way to read sub-process output without blocking, so we 105 /// doesn't provide a way to read sub-process output without blocking, so we
110 /// have to wrap sub-processes output handling in a thread and pass messages 106 /// have to wrap sub-processes output handling in a thread and pass messages
111 /// back over a channel. 107 /// back over a channel.
112 check_process: Option<jod_thread::JoinHandle<()>>, 108 check_process: Option<jod_thread::JoinHandle>,
113} 109}
114 110
115impl FlycheckActor { 111impl FlycheckActor {
116 fn new( 112 fn new(
117 sender: Box<dyn Fn(CheckTask) + Send>, 113 sender: Box<dyn Fn(Message) + Send>,
118 config: FlycheckConfig, 114 config: FlycheckConfig,
119 workspace_root: PathBuf, 115 workspace_root: PathBuf,
120 ) -> FlycheckActor { 116 ) -> FlycheckActor {
@@ -128,14 +124,14 @@ impl FlycheckActor {
128 } 124 }
129 } 125 }
130 126
131 fn run(&mut self, cmd_recv: &Receiver<CheckCommand>) { 127 fn run(&mut self, cmd_recv: &Receiver<Restart>) {
132 // If we rerun the thread, we need to discard the previous check results first 128 // If we rerun the thread, we need to discard the previous check results first
133 self.clean_previous_results(); 129 self.clean_previous_results();
134 130
135 loop { 131 loop {
136 select! { 132 select! {
137 recv(&cmd_recv) -> cmd => match cmd { 133 recv(&cmd_recv) -> cmd => match cmd {
138 Ok(cmd) => self.handle_command(cmd), 134 Ok(Restart) => self.last_update_req = Some(Instant::now()),
139 Err(RecvError) => { 135 Err(RecvError) => {
140 // Command channel has closed, so shut down 136 // Command channel has closed, so shut down
141 break; 137 break;
@@ -154,15 +150,15 @@ impl FlycheckActor {
154 150
155 if self.should_recheck() { 151 if self.should_recheck() {
156 self.last_update_req = None; 152 self.last_update_req = None;
157 self.send(CheckTask::ClearDiagnostics); 153 self.send(Message::ClearDiagnostics);
158 self.restart_check_process(); 154 self.restart_check_process();
159 } 155 }
160 } 156 }
161 } 157 }
162 158
163 fn clean_previous_results(&self) { 159 fn clean_previous_results(&self) {
164 self.send(CheckTask::ClearDiagnostics); 160 self.send(Message::ClearDiagnostics);
165 self.send(CheckTask::Status(Status::End)); 161 self.send(Message::Progress(Progress::End));
166 } 162 }
167 163
168 fn should_recheck(&mut self) -> bool { 164 fn should_recheck(&mut self) -> bool {
@@ -175,37 +171,31 @@ impl FlycheckActor {
175 false 171 false
176 } 172 }
177 173
178 fn handle_command(&mut self, cmd: CheckCommand) {
179 match cmd {
180 CheckCommand::Update => self.last_update_req = Some(Instant::now()),
181 }
182 }
183
184 fn handle_message(&self, msg: CheckEvent) { 174 fn handle_message(&self, msg: CheckEvent) {
185 match msg { 175 match msg {
186 CheckEvent::Begin => { 176 CheckEvent::Begin => {
187 self.send(CheckTask::Status(Status::Being)); 177 self.send(Message::Progress(Progress::Being));
188 } 178 }
189 179
190 CheckEvent::End => { 180 CheckEvent::End => {
191 self.send(CheckTask::Status(Status::End)); 181 self.send(Message::Progress(Progress::End));
192 } 182 }
193 183
194 CheckEvent::Msg(Message::CompilerArtifact(msg)) => { 184 CheckEvent::Msg(cargo_metadata::Message::CompilerArtifact(msg)) => {
195 self.send(CheckTask::Status(Status::Progress(msg.target.name))); 185 self.send(Message::Progress(Progress::DidCheckCrate(msg.target.name)));
196 } 186 }
197 187
198 CheckEvent::Msg(Message::CompilerMessage(msg)) => { 188 CheckEvent::Msg(cargo_metadata::Message::CompilerMessage(msg)) => {
199 self.send(CheckTask::AddDiagnostic { 189 self.send(Message::AddDiagnostic {
200 workspace_root: self.workspace_root.clone(), 190 workspace_root: self.workspace_root.clone(),
201 diagnostic: msg.message, 191 diagnostic: msg.message,
202 }); 192 });
203 } 193 }
204 194
205 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} 195 CheckEvent::Msg(cargo_metadata::Message::BuildScriptExecuted(_))
206 CheckEvent::Msg(Message::BuildFinished(_)) => {} 196 | CheckEvent::Msg(cargo_metadata::Message::BuildFinished(_))
207 CheckEvent::Msg(Message::TextLine(_)) => {} 197 | CheckEvent::Msg(cargo_metadata::Message::TextLine(_))
208 CheckEvent::Msg(Message::Unknown) => {} 198 | CheckEvent::Msg(cargo_metadata::Message::Unknown) => {}
209 } 199 }
210 } 200 }
211 201
@@ -256,9 +246,11 @@ impl FlycheckActor {
256 let res = run_cargo(cmd, &mut |message| { 246 let res = run_cargo(cmd, &mut |message| {
257 // Skip certain kinds of messages to only spend time on what's useful 247 // Skip certain kinds of messages to only spend time on what's useful
258 match &message { 248 match &message {
259 Message::CompilerArtifact(artifact) if artifact.fresh => return true, 249 cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => {
260 Message::BuildScriptExecuted(_) => return true, 250 return true
261 Message::Unknown => return true, 251 }
252 cargo_metadata::Message::BuildScriptExecuted(_)
253 | cargo_metadata::Message::Unknown => return true,
262 _ => {} 254 _ => {}
263 } 255 }
264 256
@@ -278,7 +270,7 @@ impl FlycheckActor {
278 })) 270 }))
279 } 271 }
280 272
281 fn send(&self, check_task: CheckTask) { 273 fn send(&self, check_task: Message) {
282 (self.sender)(check_task) 274 (self.sender)(check_task)
283 } 275 }
284} 276}
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 6038bf664..446207e9e 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -6,7 +6,7 @@
6use std::{convert::TryFrom, sync::Arc}; 6use std::{convert::TryFrom, sync::Arc};
7 7
8use crossbeam_channel::{unbounded, Receiver}; 8use crossbeam_channel::{unbounded, Receiver};
9use flycheck::{CheckTask, FlycheckConfig, FlycheckHandle}; 9use flycheck::{FlycheckConfig, FlycheckHandle};
10use lsp_types::Url; 10use lsp_types::Url;
11use parking_lot::RwLock; 11use parking_lot::RwLock;
12use ra_db::{CrateId, SourceRoot, VfsPath}; 12use ra_db::{CrateId, SourceRoot, VfsPath};
@@ -30,7 +30,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
30fn create_flycheck( 30fn create_flycheck(
31 workspaces: &[ProjectWorkspace], 31 workspaces: &[ProjectWorkspace],
32 config: &FlycheckConfig, 32 config: &FlycheckConfig,
33) -> Option<(FlycheckHandle, Receiver<CheckTask>)> { 33) -> Option<(FlycheckHandle, Receiver<flycheck::Message>)> {
34 // FIXME: Figure out the multi-workspace situation 34 // FIXME: Figure out the multi-workspace situation
35 workspaces.iter().find_map(move |w| match w { 35 workspaces.iter().find_map(move |w| match w {
36 ProjectWorkspace::Cargo { cargo, .. } => { 36 ProjectWorkspace::Cargo { cargo, .. } => {
@@ -69,7 +69,7 @@ pub(crate) struct GlobalState {
69 pub(crate) analysis_host: AnalysisHost, 69 pub(crate) analysis_host: AnalysisHost,
70 pub(crate) loader: Box<dyn vfs::loader::Handle>, 70 pub(crate) loader: Box<dyn vfs::loader::Handle>,
71 pub(crate) task_receiver: Receiver<vfs::loader::Message>, 71 pub(crate) task_receiver: Receiver<vfs::loader::Message>,
72 pub(crate) flycheck: Option<(FlycheckHandle, Receiver<CheckTask>)>, 72 pub(crate) flycheck: Option<(FlycheckHandle, Receiver<flycheck::Message>)>,
73 pub(crate) diagnostics: DiagnosticCollection, 73 pub(crate) diagnostics: DiagnosticCollection,
74 pub(crate) mem_docs: FxHashSet<VfsPath>, 74 pub(crate) mem_docs: FxHashSet<VfsPath>,
75 pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, 75 pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 0664e4a5a..200641cd5 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -9,7 +9,6 @@ use std::{
9}; 9};
10 10
11use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; 11use crossbeam_channel::{never, select, unbounded, RecvError, Sender};
12use flycheck::CheckTask;
13use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; 12use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
14use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent}; 13use lsp_types::{request::Request as _, NumberOrString, TextDocumentContentChangeEvent};
15use ra_db::VfsPath; 14use ra_db::VfsPath;
@@ -176,7 +175,7 @@ enum Event {
176 Msg(Message), 175 Msg(Message),
177 Task(Task), 176 Task(Task),
178 Vfs(vfs::loader::Message), 177 Vfs(vfs::loader::Message),
179 CheckWatcher(CheckTask), 178 CheckWatcher(flycheck::Message),
180} 179}
181 180
182impl fmt::Debug for Event { 181impl fmt::Debug for Event {
@@ -250,14 +249,14 @@ fn loop_turn(
250 } 249 }
251 vfs::loader::Message::Progress { n_total, n_done } => { 250 vfs::loader::Message::Progress { n_total, n_done } => {
252 let state = if n_done == 0 { 251 let state = if n_done == 0 {
253 ProgressState::Start 252 Progress::Begin
254 } else if n_done < n_total { 253 } else if n_done < n_total {
255 ProgressState::Report 254 Progress::Report
256 } else { 255 } else {
257 assert_eq!(n_done, n_total); 256 assert_eq!(n_done, n_total);
258 global_state.status = Status::Ready; 257 global_state.status = Status::Ready;
259 became_ready = true; 258 became_ready = true;
260 ProgressState::End 259 Progress::End
261 }; 260 };
262 report_progress( 261 report_progress(
263 global_state, 262 global_state,
@@ -593,17 +592,17 @@ fn apply_document_changes(
593} 592}
594 593
595fn on_check_task( 594fn on_check_task(
596 task: CheckTask, 595 task: flycheck::Message,
597 global_state: &mut GlobalState, 596 global_state: &mut GlobalState,
598 task_sender: &Sender<Task>, 597 task_sender: &Sender<Task>,
599 msg_sender: &Sender<Message>, 598 msg_sender: &Sender<Message>,
600) -> Result<()> { 599) -> Result<()> {
601 match task { 600 match task {
602 CheckTask::ClearDiagnostics => { 601 flycheck::Message::ClearDiagnostics => {
603 task_sender.send(Task::Diagnostic(DiagnosticTask::ClearCheck))?; 602 task_sender.send(Task::Diagnostic(DiagnosticTask::ClearCheck))?;
604 } 603 }
605 604
606 CheckTask::AddDiagnostic { workspace_root, diagnostic } => { 605 flycheck::Message::AddDiagnostic { workspace_root, diagnostic } => {
607 let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( 606 let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
608 &global_state.config.diagnostics, 607 &global_state.config.diagnostics,
609 &diagnostic, 608 &diagnostic,
@@ -627,11 +626,11 @@ fn on_check_task(
627 } 626 }
628 } 627 }
629 628
630 CheckTask::Status(status) => { 629 flycheck::Message::Progress(status) => {
631 let (state, message) = match status { 630 let (state, message) = match status {
632 flycheck::Status::Being => (ProgressState::Start, None), 631 flycheck::Progress::Being => (Progress::Begin, None),
633 flycheck::Status::Progress(target) => (ProgressState::Report, Some(target)), 632 flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
634 flycheck::Status::End => (ProgressState::End, None), 633 flycheck::Progress::End => (Progress::End, None),
635 }; 634 };
636 635
637 report_progress(global_state, msg_sender, "cargo check", state, message, None); 636 report_progress(global_state, msg_sender, "cargo check", state, message, None);
@@ -654,8 +653,8 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state:
654} 653}
655 654
656#[derive(Eq, PartialEq)] 655#[derive(Eq, PartialEq)]
657enum ProgressState { 656enum Progress {
658 Start, 657 Begin,
659 Report, 658 Report,
660 End, 659 End,
661} 660}
@@ -668,7 +667,7 @@ fn report_progress(
668 global_state: &mut GlobalState, 667 global_state: &mut GlobalState,
669 sender: &Sender<Message>, 668 sender: &Sender<Message>,
670 title: &str, 669 title: &str,
671 state: ProgressState, 670 state: Progress,
672 message: Option<String>, 671 message: Option<String>,
673 percentage: Option<f64>, 672 percentage: Option<f64>,
674) { 673) {
@@ -677,7 +676,7 @@ fn report_progress(
677 } 676 }
678 let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title)); 677 let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title));
679 let work_done_progress = match state { 678 let work_done_progress = match state {
680 ProgressState::Start => { 679 Progress::Begin => {
681 let work_done_progress_create = global_state.req_queue.outgoing.register( 680 let work_done_progress_create = global_state.req_queue.outgoing.register(
682 lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(), 681 lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(),
683 lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, 682 lsp_types::WorkDoneProgressCreateParams { token: token.clone() },
@@ -692,14 +691,14 @@ fn report_progress(
692 percentage, 691 percentage,
693 }) 692 })
694 } 693 }
695 ProgressState::Report => { 694 Progress::Report => {
696 lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport { 695 lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport {
697 cancellable: None, 696 cancellable: None,
698 message, 697 message,
699 percentage, 698 percentage,
700 }) 699 })
701 } 700 }
702 ProgressState::End => { 701 Progress::End => {
703 lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message }) 702 lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message })
704 } 703 }
705 }; 704 };