aboutsummaryrefslogtreecommitdiff
path: root/crates/rust-analyzer
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-25 06:56:47 +0100
committerAleksey Kladov <[email protected]>2020-06-25 06:56:47 +0100
commit76a530242a12f75e2a8456f952cef07e2d564f67 (patch)
treec172661c9be87bea10b796bffd32f4c32c65ab7a /crates/rust-analyzer
parent78e94e4570f09c8cbe1f8c6802df9b112ca37f08 (diff)
parent6e81c9a921b975be7f2efb927dab4f3cfd505ebc (diff)
Merge branch 'Veetaha-feat/sync-branch'
Diffstat (limited to 'crates/rust-analyzer')
-rw-r--r--crates/rust-analyzer/Cargo.toml1
-rw-r--r--crates/rust-analyzer/src/global_state.rs23
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs52
-rw-r--r--crates/rust-analyzer/src/main_loop.rs36
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs4
5 files changed, 109 insertions, 7 deletions
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 68d04f3e3..2bbed395f 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -48,6 +48,7 @@ hir = { path = "../ra_hir", package = "ra_hir" }
48hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } 48hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
49hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } 49hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
50ra_proc_macro_srv = { path = "../ra_proc_macro_srv" } 50ra_proc_macro_srv = { path = "../ra_proc_macro_srv" }
51ra_progress = { path = "../ra_progress" }
51 52
52[target.'cfg(windows)'.dependencies] 53[target.'cfg(windows)'.dependencies]
53winapi = "0.3.8" 54winapi = "0.3.8"
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 87f3fe4db..7759c0ae3 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -27,9 +27,13 @@ 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 progress_src: &ProgressSource<(), String>,
34) -> Option<Flycheck> {
31 // FIXME: Figure out the multi-workspace situation 35 // FIXME: Figure out the multi-workspace situation
32 workspaces.iter().find_map(|w| match w { 36 workspaces.iter().find_map(move |w| match w {
33 ProjectWorkspace::Cargo { cargo, .. } => { 37 ProjectWorkspace::Cargo { cargo, .. } => {
34 let cargo_project_root = cargo.workspace_root().to_path_buf(); 38 let cargo_project_root = cargo.workspace_root().to_path_buf();
35 Some(Flycheck::new(config.clone(), cargo_project_root.into())) 39 Some(Flycheck::new(config.clone(), cargo_project_root.into()))
@@ -143,7 +147,12 @@ impl GlobalState {
143 } 147 }
144 change.set_crate_graph(crate_graph); 148 change.set_crate_graph(crate_graph);
145 149
146 let flycheck = config.check.as_ref().and_then(|c| create_flycheck(&workspaces, c)); 150 let (flycheck_progress_receiver, flycheck_progress_src) =
151 ProgressSource::real_if(config.client_caps.work_done_progress);
152 let flycheck = config
153 .check
154 .as_ref()
155 .and_then(|c| create_flycheck(&workspaces, c, &flycheck_progress_src));
147 156
148 let mut analysis_host = AnalysisHost::new(lru_capacity); 157 let mut analysis_host = AnalysisHost::new(lru_capacity);
149 analysis_host.apply_change(change); 158 analysis_host.apply_change(change);
@@ -153,6 +162,8 @@ impl GlobalState {
153 loader, 162 loader,
154 task_receiver, 163 task_receiver,
155 flycheck, 164 flycheck,
165 flycheck_progress_src,
166 flycheck_progress_receiver,
156 diagnostics: Default::default(), 167 diagnostics: Default::default(),
157 mem_docs: FxHashSet::default(), 168 mem_docs: FxHashSet::default(),
158 vfs: Arc::new(RwLock::new((vfs, FxHashMap::default()))), 169 vfs: Arc::new(RwLock::new((vfs, FxHashMap::default()))),
@@ -170,8 +181,10 @@ impl GlobalState {
170 pub(crate) fn update_configuration(&mut self, config: Config) { 181 pub(crate) fn update_configuration(&mut self, config: Config) {
171 self.analysis_host.update_lru_capacity(config.lru_capacity); 182 self.analysis_host.update_lru_capacity(config.lru_capacity);
172 if config.check != self.config.check { 183 if config.check != self.config.check {
173 self.flycheck = 184 self.flycheck = config
174 config.check.as_ref().and_then(|it| create_flycheck(&self.workspaces, it)); 185 .check
186 .as_ref()
187 .and_then(|it| create_flycheck(&self.workspaces, it, &self.flycheck_progress_src));
175 } 188 }
176 189
177 self.config = config; 190 self.config = config;
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
new file mode 100644
index 000000000..c79022797
--- /dev/null
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -0,0 +1,52 @@
1//! Utilities for LSP-related boilerplate code.
2
3use crossbeam_channel::Sender;
4use lsp_server::{Message, Notification, Request, RequestId};
5use ra_db::Canceled;
6use serde::{de::DeserializeOwned, Serialize};
7use std::error::Error;
8
9pub fn show_message(
10 typ: lsp_types::MessageType,
11 message: impl Into<String>,
12 sender: &Sender<Message>,
13) {
14 let message = message.into();
15 let params = lsp_types::ShowMessageParams { typ, message };
16 let not = notification_new::<lsp_types::notification::ShowMessage>(params);
17 sender.send(not.into()).unwrap();
18}
19
20pub(crate) fn is_canceled(e: &(dyn Error + 'static)) -> bool {
21 e.downcast_ref::<Canceled>().is_some()
22}
23
24pub(crate) fn notification_is<N: lsp_types::notification::Notification>(
25 notification: &Notification,
26) -> bool {
27 notification.method == N::METHOD
28}
29
30pub(crate) fn notification_cast<N>(notification: Notification) -> Result<N::Params, Notification>
31where
32 N: lsp_types::notification::Notification,
33 N::Params: DeserializeOwned,
34{
35 notification.extract(N::METHOD)
36}
37
38pub(crate) fn notification_new<N>(params: N::Params) -> Notification
39where
40 N: lsp_types::notification::Notification,
41 N::Params: Serialize,
42{
43 Notification::new(N::METHOD.to_string(), params)
44}
45
46pub(crate) fn request_new<R>(id: RequestId, params: R::Params) -> Request
47where
48 R: lsp_types::request::Request,
49 R::Params: Serialize,
50{
51 Request::new(id, R::METHOD.to_string(), params)
52}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index eb9e7f913..7ccdbd29c 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -28,6 +28,14 @@ use crate::{
28 request_metrics::RequestMetrics, 28 request_metrics::RequestMetrics,
29 LspError, Result, 29 LspError, Result,
30}; 30};
31pub use lsp_utils::show_message;
32use lsp_utils::{is_canceled, notification_cast, notification_is, notification_new, request_new};
33use ra_progress::{
34 IsDone, ProgressStatus, U32Progress, U32ProgressReport, U32ProgressSource, U32ProgressStatus,
35};
36
37const FLYCHECK_PROGRESS_TOKEN: &str = "rustAnalyzer/flycheck";
38const ROOTS_SCANNED_PROGRESS_TOKEN: &str = "rustAnalyzer/rootsScanned";
31 39
32pub fn main_loop(config: Config, connection: Connection) -> Result<()> { 40pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
33 log::info!("initial config: {:#?}", config); 41 log::info!("initial config: {:#?}", config);
@@ -138,6 +146,18 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
138 recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task { 146 recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task {
139 Ok(task) => Event::CheckWatcher(task), 147 Ok(task) => Event::CheckWatcher(task),
140 Err(RecvError) => return Err("check watcher died".into()), 148 Err(RecvError) => return Err("check watcher died".into()),
149 },
150 recv(global_state.flycheck_progress_receiver) -> status => match status {
151 Ok(status) => Event::ProgressReport(ProgressReport::Flycheck(status)),
152 Err(RecvError) => return Err("check watcher died".into()),
153 },
154 recv(roots_scanned_progress_receiver) -> status => match status {
155 Ok(status) => Event::ProgressReport(ProgressReport::RootsScanned(status)),
156 Err(RecvError) => {
157 // Roots analysis has finished, we no longer need this receiver
158 roots_scanned_progress_receiver = never();
159 continue;
160 }
141 } 161 }
142 }; 162 };
143 if let Event::Msg(Message::Request(req)) = &event { 163 if let Event::Msg(Message::Request(req)) = &event {
@@ -169,6 +189,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
169enum Task { 189enum Task {
170 Respond(Response), 190 Respond(Response),
171 Notify(Notification), 191 Notify(Notification),
192 SendRequest(Request),
172 Diagnostic(DiagnosticTask), 193 Diagnostic(DiagnosticTask),
173} 194}
174 195
@@ -177,6 +198,13 @@ enum Event {
177 Task(Task), 198 Task(Task),
178 Vfs(vfs::loader::Message), 199 Vfs(vfs::loader::Message),
179 CheckWatcher(CheckTask), 200 CheckWatcher(CheckTask),
201 ProgressReport(ProgressReport),
202}
203
204#[derive(Debug)]
205enum ProgressReport {
206 Flycheck(ProgressStatus<(), String>),
207 RootsScanned(U32ProgressStatus),
180} 208}
181 209
182impl fmt::Debug for Event { 210impl fmt::Debug for Event {
@@ -212,6 +240,7 @@ impl fmt::Debug for Event {
212 Event::Task(it) => fmt::Debug::fmt(it, f), 240 Event::Task(it) => fmt::Debug::fmt(it, f),
213 Event::Vfs(it) => fmt::Debug::fmt(it, f), 241 Event::Vfs(it) => fmt::Debug::fmt(it, f),
214 Event::CheckWatcher(it) => fmt::Debug::fmt(it, f), 242 Event::CheckWatcher(it) => fmt::Debug::fmt(it, f),
243 Event::ProgressReport(it) => fmt::Debug::fmt(it, f),
215 } 244 }
216 } 245 }
217} 246}
@@ -262,6 +291,9 @@ fn loop_turn(
262 } 291 }
263 }, 292 },
264 Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?, 293 Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?,
294 Event::ProgressReport(report) => {
295 on_progress_report(report, task_sender, loop_state, global_state)
296 }
265 Event::Msg(msg) => match msg { 297 Event::Msg(msg) => match msg {
266 Message::Request(req) => { 298 Message::Request(req) => {
267 on_request(global_state, pool, task_sender, &connection.sender, loop_start, req)? 299 on_request(global_state, pool, task_sender, &connection.sender, loop_start, req)?
@@ -826,7 +858,7 @@ where
826 Err(e) => match e.downcast::<LspError>() { 858 Err(e) => match e.downcast::<LspError>() {
827 Ok(lsp_error) => Response::new_err(id, lsp_error.code, lsp_error.message), 859 Ok(lsp_error) => Response::new_err(id, lsp_error.code, lsp_error.message),
828 Err(e) => { 860 Err(e) => {
829 if is_canceled(&e) { 861 if is_canceled(&*e) {
830 Response::new_err( 862 Response::new_err(
831 id, 863 id,
832 ErrorCode::ContentModified as i32, 864 ErrorCode::ContentModified as i32,
@@ -853,7 +885,7 @@ fn update_file_notifications_on_threadpool(
853 for file_id in subscriptions { 885 for file_id in subscriptions {
854 match handlers::publish_diagnostics(&world, file_id) { 886 match handlers::publish_diagnostics(&world, file_id) {
855 Err(e) => { 887 Err(e) => {
856 if !is_canceled(&e) { 888 if !is_canceled(&*e) {
857 log::error!("failed to compute diagnostics: {:?}", e); 889 log::error!("failed to compute diagnostics: {:?}", e);
858 } 890 }
859 } 891 }
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs
index 49f194f7e..15d2a05a4 100644
--- a/crates/rust-analyzer/tests/heavy_tests/support.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/support.rs
@@ -202,7 +202,11 @@ impl Server {
202 ProgressParams { 202 ProgressParams {
203 token: lsp_types::ProgressToken::String(ref token), 203 token: lsp_types::ProgressToken::String(ref token),
204 value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(_)), 204 value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(_)),
205<<<<<<< HEAD
205 } if token == "rustAnalyzer/roots scanned" => true, 206 } if token == "rustAnalyzer/roots scanned" => true,
207=======
208 } if token == "rustAnalyzer/rootsScanned" => true,
209>>>>>>> Veetaha-feat/sync-branch
206 _ => false, 210 _ => false,
207 } 211 }
208 } 212 }