aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/global_state.rs4
-rw-r--r--crates/rust-analyzer/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs85
-rw-r--r--crates/rust-analyzer/src/main_loop.rs68
-rw-r--r--crates/rust-analyzer/src/reload.rs24
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
190impl Drop for GlobalState { 186impl 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;
39use serde::de::DeserializeOwned; 39use serde::de::DeserializeOwned;
40 40
41pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>; 41pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>;
42pub use crate::{caps::server_capabilities, lsp_utils::show_message, main_loop::main_loop}; 42pub use crate::{caps::server_capabilities, main_loop::main_loop};
43use std::fmt; 43use std::fmt;
44 44
45pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { 45pub 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.
2use std::{error::Error, ops::Range}; 2use std::{error::Error, ops::Range};
3 3
4use crossbeam_channel::Sender; 4use lsp_server::Notification;
5use lsp_server::{Message, Notification}; 5use lsp_types::request::Request;
6use ra_db::Canceled; 6use ra_db::Canceled;
7use ra_ide::LineIndex; 7use ra_ide::LineIndex;
8use serde::Serialize; 8use serde::Serialize;
9 9
10use crate::from_proto; 10use crate::{from_proto, global_state::GlobalState};
11
12pub 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
23pub(crate) fn is_canceled(e: &(dyn Error + 'static)) -> bool { 12pub(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)]
31pub(crate) enum Progress {
32 Begin,
33 Report,
34 End,
35}
36
37impl 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
43impl 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
41pub(crate) fn apply_document_changes( 98pub(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)]
473enum Progress {
474 Begin,
475 Report,
476 End,
477}
478
479fn percentage(done: usize, total: usize) -> f64 {
480 (done as f64 / total.max(1) as f64) * 100.0
481}
482
483fn 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 {