diff options
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_utils.rs | 85 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 68 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 24 |
5 files changed, 91 insertions, 92 deletions
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 4da094083..41659f99d 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -21,7 +21,6 @@ use crate::{ | |||
21 | main_loop::Task, | 21 | main_loop::Task, |
22 | reload::SourceRootConfig, | 22 | reload::SourceRootConfig, |
23 | request_metrics::{LatestRequests, RequestMetrics}, | 23 | request_metrics::{LatestRequests, RequestMetrics}, |
24 | show_message, | ||
25 | thread_pool::TaskPool, | 24 | thread_pool::TaskPool, |
26 | to_proto::url_from_abs_path, | 25 | to_proto::url_from_abs_path, |
27 | Result, | 26 | Result, |
@@ -182,9 +181,6 @@ impl GlobalState { | |||
182 | self.send(response.into()); | 181 | self.send(response.into()); |
183 | } | 182 | } |
184 | } | 183 | } |
185 | pub(crate) fn show_message(&self, typ: lsp_types::MessageType, message: String) { | ||
186 | show_message(typ, message, &self.sender) | ||
187 | } | ||
188 | } | 184 | } |
189 | 185 | ||
190 | impl Drop for GlobalState { | 186 | impl Drop for GlobalState { |
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index a24dfe58c..407944d85 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs | |||
@@ -39,7 +39,7 @@ pub mod config; | |||
39 | use serde::de::DeserializeOwned; | 39 | use serde::de::DeserializeOwned; |
40 | 40 | ||
41 | pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>; | 41 | pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>; |
42 | pub use crate::{caps::server_capabilities, lsp_utils::show_message, main_loop::main_loop}; | 42 | pub use crate::{caps::server_capabilities, main_loop::main_loop}; |
43 | use std::fmt; | 43 | use std::fmt; |
44 | 44 | ||
45 | pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { | 45 | pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { |
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index 35917030c..fd793a17c 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs | |||
@@ -1,24 +1,13 @@ | |||
1 | //! Utilities for LSP-related boilerplate code. | 1 | //! Utilities for LSP-related boilerplate code. |
2 | use std::{error::Error, ops::Range}; | 2 | use std::{error::Error, ops::Range}; |
3 | 3 | ||
4 | use crossbeam_channel::Sender; | 4 | use lsp_server::Notification; |
5 | use lsp_server::{Message, Notification}; | 5 | use lsp_types::request::Request; |
6 | use ra_db::Canceled; | 6 | use ra_db::Canceled; |
7 | use ra_ide::LineIndex; | 7 | use ra_ide::LineIndex; |
8 | use serde::Serialize; | 8 | use serde::Serialize; |
9 | 9 | ||
10 | use crate::from_proto; | 10 | use crate::{from_proto, global_state::GlobalState}; |
11 | |||
12 | pub fn show_message( | ||
13 | typ: lsp_types::MessageType, | ||
14 | message: impl Into<String>, | ||
15 | sender: &Sender<Message>, | ||
16 | ) { | ||
17 | let message = message.into(); | ||
18 | let params = lsp_types::ShowMessageParams { typ, message }; | ||
19 | let not = notification_new::<lsp_types::notification::ShowMessage>(params); | ||
20 | sender.send(not.into()).unwrap(); | ||
21 | } | ||
22 | 11 | ||
23 | pub(crate) fn is_canceled(e: &(dyn Error + 'static)) -> bool { | 12 | pub(crate) fn is_canceled(e: &(dyn Error + 'static)) -> bool { |
24 | e.downcast_ref::<Canceled>().is_some() | 13 | e.downcast_ref::<Canceled>().is_some() |
@@ -38,6 +27,74 @@ where | |||
38 | Notification::new(N::METHOD.to_string(), params) | 27 | Notification::new(N::METHOD.to_string(), params) |
39 | } | 28 | } |
40 | 29 | ||
30 | #[derive(Debug, Eq, PartialEq)] | ||
31 | pub(crate) enum Progress { | ||
32 | Begin, | ||
33 | Report, | ||
34 | End, | ||
35 | } | ||
36 | |||
37 | impl Progress { | ||
38 | pub(crate) fn percentage(done: usize, total: usize) -> f64 { | ||
39 | (done as f64 / total.max(1) as f64) * 100.0 | ||
40 | } | ||
41 | } | ||
42 | |||
43 | impl GlobalState { | ||
44 | pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) { | ||
45 | let message = message.into(); | ||
46 | let params = lsp_types::ShowMessageParams { typ, message }; | ||
47 | let not = notification_new::<lsp_types::notification::ShowMessage>(params); | ||
48 | self.send(not.into()); | ||
49 | } | ||
50 | |||
51 | pub(crate) fn report_progress( | ||
52 | &mut self, | ||
53 | title: &str, | ||
54 | state: Progress, | ||
55 | message: Option<String>, | ||
56 | percentage: Option<f64>, | ||
57 | ) { | ||
58 | if !self.config.client_caps.work_done_progress { | ||
59 | return; | ||
60 | } | ||
61 | let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title)); | ||
62 | let work_done_progress = match state { | ||
63 | Progress::Begin => { | ||
64 | let work_done_progress_create = self.req_queue.outgoing.register( | ||
65 | lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(), | ||
66 | lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, | ||
67 | |_, _| (), | ||
68 | ); | ||
69 | self.send(work_done_progress_create.into()); | ||
70 | |||
71 | lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { | ||
72 | title: title.into(), | ||
73 | cancellable: None, | ||
74 | message, | ||
75 | percentage, | ||
76 | }) | ||
77 | } | ||
78 | Progress::Report => { | ||
79 | lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport { | ||
80 | cancellable: None, | ||
81 | message, | ||
82 | percentage, | ||
83 | }) | ||
84 | } | ||
85 | Progress::End => { | ||
86 | lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message }) | ||
87 | } | ||
88 | }; | ||
89 | let notification = | ||
90 | notification_new::<lsp_types::notification::Progress>(lsp_types::ProgressParams { | ||
91 | token, | ||
92 | value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress), | ||
93 | }); | ||
94 | self.send(notification.into()); | ||
95 | } | ||
96 | } | ||
97 | |||
41 | pub(crate) fn apply_document_changes( | 98 | pub(crate) fn apply_document_changes( |
42 | old_text: &mut String, | 99 | old_text: &mut String, |
43 | content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>, | 100 | content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>, |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index ed3d27750..ae3c7e30e 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -18,7 +18,7 @@ use crate::{ | |||
18 | from_proto, | 18 | from_proto, |
19 | global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, | 19 | global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, |
20 | handlers, lsp_ext, | 20 | handlers, lsp_ext, |
21 | lsp_utils::{apply_document_changes, is_canceled, notification_is, notification_new}, | 21 | lsp_utils::{apply_document_changes, is_canceled, notification_is, notification_new, Progress}, |
22 | Result, | 22 | Result, |
23 | }; | 23 | }; |
24 | 24 | ||
@@ -181,12 +181,11 @@ impl GlobalState { | |||
181 | became_ready = true; | 181 | became_ready = true; |
182 | Progress::End | 182 | Progress::End |
183 | }; | 183 | }; |
184 | report_progress( | 184 | self.report_progress( |
185 | self, | ||
186 | "roots scanned", | 185 | "roots scanned", |
187 | state, | 186 | state, |
188 | Some(format!("{}/{}", n_done, n_total)), | 187 | Some(format!("{}/{}", n_done, n_total)), |
189 | Some(percentage(n_done, n_total)), | 188 | Some(Progress::percentage(n_done, n_total)), |
190 | ) | 189 | ) |
191 | } | 190 | } |
192 | }, | 191 | }, |
@@ -216,7 +215,7 @@ impl GlobalState { | |||
216 | flycheck::Progress::DidStart => { | 215 | flycheck::Progress::DidStart => { |
217 | self.diagnostics.clear_check(); | 216 | self.diagnostics.clear_check(); |
218 | (Progress::Begin, None) | 217 | (Progress::Begin, None) |
219 | }, | 218 | } |
220 | flycheck::Progress::DidCheckCrate(target) => { | 219 | flycheck::Progress::DidCheckCrate(target) => { |
221 | (Progress::Report, Some(target)) | 220 | (Progress::Report, Some(target)) |
222 | } | 221 | } |
@@ -225,7 +224,7 @@ impl GlobalState { | |||
225 | } | 224 | } |
226 | }; | 225 | }; |
227 | 226 | ||
228 | report_progress(self, "cargo check", state, message, None); | 227 | self.report_progress("cargo check", state, message, None); |
229 | } | 228 | } |
230 | }, | 229 | }, |
231 | } | 230 | } |
@@ -468,60 +467,3 @@ impl GlobalState { | |||
468 | }); | 467 | }); |
469 | } | 468 | } |
470 | } | 469 | } |
471 | |||
472 | #[derive(Debug, Eq, PartialEq)] | ||
473 | enum Progress { | ||
474 | Begin, | ||
475 | Report, | ||
476 | End, | ||
477 | } | ||
478 | |||
479 | fn percentage(done: usize, total: usize) -> f64 { | ||
480 | (done as f64 / total.max(1) as f64) * 100.0 | ||
481 | } | ||
482 | |||
483 | fn report_progress( | ||
484 | global_state: &mut GlobalState, | ||
485 | title: &str, | ||
486 | state: Progress, | ||
487 | message: Option<String>, | ||
488 | percentage: Option<f64>, | ||
489 | ) { | ||
490 | if !global_state.config.client_caps.work_done_progress { | ||
491 | return; | ||
492 | } | ||
493 | let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title)); | ||
494 | let work_done_progress = match state { | ||
495 | Progress::Begin => { | ||
496 | let work_done_progress_create = global_state.req_queue.outgoing.register( | ||
497 | lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(), | ||
498 | lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, | ||
499 | |_, _| (), | ||
500 | ); | ||
501 | global_state.send(work_done_progress_create.into()); | ||
502 | |||
503 | lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { | ||
504 | title: title.into(), | ||
505 | cancellable: None, | ||
506 | message, | ||
507 | percentage, | ||
508 | }) | ||
509 | } | ||
510 | Progress::Report => { | ||
511 | lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport { | ||
512 | cancellable: None, | ||
513 | message, | ||
514 | percentage, | ||
515 | }) | ||
516 | } | ||
517 | Progress::End => { | ||
518 | lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message }) | ||
519 | } | ||
520 | }; | ||
521 | let notification = | ||
522 | notification_new::<lsp_types::notification::Progress>(lsp_types::ProgressParams { | ||
523 | token, | ||
524 | value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress), | ||
525 | }); | ||
526 | global_state.send(notification.into()); | ||
527 | } | ||
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index a22d3e262..fece6176e 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -36,27 +36,31 @@ impl GlobalState { | |||
36 | self.config | 36 | self.config |
37 | .linked_projects | 37 | .linked_projects |
38 | .iter() | 38 | .iter() |
39 | .filter_map(|project| match project { | 39 | .map(|project| match project { |
40 | LinkedProject::ProjectManifest(manifest) => { | 40 | LinkedProject::ProjectManifest(manifest) => { |
41 | ra_project_model::ProjectWorkspace::load( | 41 | ra_project_model::ProjectWorkspace::load( |
42 | manifest.clone(), | 42 | manifest.clone(), |
43 | &self.config.cargo, | 43 | &self.config.cargo, |
44 | self.config.with_sysroot, | 44 | self.config.with_sysroot, |
45 | ) | 45 | ) |
46 | .map_err(|err| { | ||
47 | log::error!("failed to load workspace: {:#}", err); | ||
48 | self.show_message( | ||
49 | lsp_types::MessageType::Error, | ||
50 | format!("rust-analyzer failed to load workspace: {:#}", err), | ||
51 | ); | ||
52 | }) | ||
53 | .ok() | ||
54 | } | 46 | } |
55 | LinkedProject::InlineJsonProject(it) => { | 47 | LinkedProject::InlineJsonProject(it) => { |
56 | Some(ra_project_model::ProjectWorkspace::Json { project: it.clone() }) | 48 | Ok(ra_project_model::ProjectWorkspace::Json { project: it.clone() }) |
57 | } | 49 | } |
58 | }) | 50 | }) |
59 | .collect::<Vec<_>>() | 51 | .collect::<Vec<_>>() |
52 | .into_iter() | ||
53 | .filter_map(|res| { | ||
54 | res.map_err(|err| { | ||
55 | log::error!("failed to load workspace: {:#}", err); | ||
56 | self.show_message( | ||
57 | lsp_types::MessageType::Error, | ||
58 | format!("rust-analyzer failed to load workspace: {:#}", err), | ||
59 | ); | ||
60 | }) | ||
61 | .ok() | ||
62 | }) | ||
63 | .collect::<Vec<_>>() | ||
60 | }; | 64 | }; |
61 | 65 | ||
62 | if let FilesWatcher::Client = self.config.files.watcher { | 66 | if let FilesWatcher::Client = self.config.files.watcher { |