diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/rust-analyzer/src/dispatch.rs | 44 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 14 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 42 |
3 files changed, 43 insertions, 57 deletions
diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs index 5fdbed8ef..03b373dee 100644 --- a/crates/rust-analyzer/src/dispatch.rs +++ b/crates/rust-analyzer/src/dispatch.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! A visitor for downcasting arbitrary request (JSON) into a specific type. | 1 | //! A visitor for downcasting arbitrary request (JSON) into a specific type. |
2 | use std::{panic, time::Instant}; | 2 | use std::panic; |
3 | 3 | ||
4 | use serde::{de::DeserializeOwned, Serialize}; | 4 | use serde::{de::DeserializeOwned, Serialize}; |
5 | 5 | ||
@@ -13,7 +13,6 @@ use crate::{ | |||
13 | pub(crate) struct RequestDispatcher<'a> { | 13 | pub(crate) struct RequestDispatcher<'a> { |
14 | pub(crate) req: Option<lsp_server::Request>, | 14 | pub(crate) req: Option<lsp_server::Request>, |
15 | pub(crate) global_state: &'a mut GlobalState, | 15 | pub(crate) global_state: &'a mut GlobalState, |
16 | pub(crate) request_received: Instant, | ||
17 | } | 16 | } |
18 | 17 | ||
19 | impl<'a> RequestDispatcher<'a> { | 18 | impl<'a> RequestDispatcher<'a> { |
@@ -34,12 +33,12 @@ impl<'a> RequestDispatcher<'a> { | |||
34 | } | 33 | } |
35 | }; | 34 | }; |
36 | let world = panic::AssertUnwindSafe(&mut *self.global_state); | 35 | let world = panic::AssertUnwindSafe(&mut *self.global_state); |
37 | let task = panic::catch_unwind(move || { | 36 | let response = panic::catch_unwind(move || { |
38 | let result = f(world.0, params); | 37 | let result = f(world.0, params); |
39 | result_to_task::<R>(id, result) | 38 | result_to_response::<R>(id, result) |
40 | }) | 39 | }) |
41 | .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?; | 40 | .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?; |
42 | self.global_state.on_task(task); | 41 | self.global_state.respond(response); |
43 | Ok(self) | 42 | Ok(self) |
44 | } | 43 | } |
45 | 44 | ||
@@ -64,7 +63,7 @@ impl<'a> RequestDispatcher<'a> { | |||
64 | let world = self.global_state.snapshot(); | 63 | let world = self.global_state.snapshot(); |
65 | move || { | 64 | move || { |
66 | let result = f(world, params); | 65 | let result = f(world, params); |
67 | result_to_task::<R>(id, result) | 66 | Task::Response(result_to_response::<R>(id, result)) |
68 | } | 67 | } |
69 | }); | 68 | }); |
70 | 69 | ||
@@ -72,17 +71,14 @@ impl<'a> RequestDispatcher<'a> { | |||
72 | } | 71 | } |
73 | 72 | ||
74 | pub(crate) fn finish(&mut self) { | 73 | pub(crate) fn finish(&mut self) { |
75 | match self.req.take() { | 74 | if let Some(req) = self.req.take() { |
76 | None => (), | 75 | log::error!("unknown request: {:?}", req); |
77 | Some(req) => { | 76 | let response = lsp_server::Response::new_err( |
78 | log::error!("unknown request: {:?}", req); | 77 | req.id, |
79 | let resp = lsp_server::Response::new_err( | 78 | lsp_server::ErrorCode::MethodNotFound as i32, |
80 | req.id, | 79 | "unknown request".to_string(), |
81 | lsp_server::ErrorCode::MethodNotFound as i32, | 80 | ); |
82 | "unknown request".to_string(), | 81 | self.global_state.respond(response) |
83 | ); | ||
84 | self.global_state.send(resp.into()); | ||
85 | } | ||
86 | } | 82 | } |
87 | } | 83 | } |
88 | 84 | ||
@@ -99,21 +95,20 @@ impl<'a> RequestDispatcher<'a> { | |||
99 | return None; | 95 | return None; |
100 | } | 96 | } |
101 | }; | 97 | }; |
102 | self.global_state | ||
103 | .req_queue | ||
104 | .incoming | ||
105 | .register(id.clone(), (R::METHOD, self.request_received)); | ||
106 | Some((id, params)) | 98 | Some((id, params)) |
107 | } | 99 | } |
108 | } | 100 | } |
109 | 101 | ||
110 | fn result_to_task<R>(id: lsp_server::RequestId, result: Result<R::Result>) -> Task | 102 | fn result_to_response<R>( |
103 | id: lsp_server::RequestId, | ||
104 | result: Result<R::Result>, | ||
105 | ) -> lsp_server::Response | ||
111 | where | 106 | where |
112 | R: lsp_types::request::Request + 'static, | 107 | R: lsp_types::request::Request + 'static, |
113 | R::Params: DeserializeOwned + 'static, | 108 | R::Params: DeserializeOwned + 'static, |
114 | R::Result: Serialize + 'static, | 109 | R::Result: Serialize + 'static, |
115 | { | 110 | { |
116 | let response = match result { | 111 | match result { |
117 | Ok(resp) => lsp_server::Response::new_ok(id, &resp), | 112 | Ok(resp) => lsp_server::Response::new_ok(id, &resp), |
118 | Err(e) => match e.downcast::<LspError>() { | 113 | Err(e) => match e.downcast::<LspError>() { |
119 | Ok(lsp_error) => lsp_server::Response::new_err(id, lsp_error.code, lsp_error.message), | 114 | Ok(lsp_error) => lsp_server::Response::new_err(id, lsp_error.code, lsp_error.message), |
@@ -133,8 +128,7 @@ where | |||
133 | } | 128 | } |
134 | } | 129 | } |
135 | }, | 130 | }, |
136 | }; | 131 | } |
137 | Task::Respond(response) | ||
138 | } | 132 | } |
139 | 133 | ||
140 | pub(crate) struct NotificationDispatcher<'a> { | 134 | pub(crate) struct NotificationDispatcher<'a> { |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 56d50c789..149b1b5f9 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -253,13 +253,19 @@ impl GlobalState { | |||
253 | self.analysis_host.collect_garbage() | 253 | self.analysis_host.collect_garbage() |
254 | } | 254 | } |
255 | 255 | ||
256 | pub(crate) fn complete_request(&mut self, request: RequestMetrics) { | ||
257 | self.latest_requests.write().record(request) | ||
258 | } | ||
259 | |||
260 | pub(crate) fn send(&mut self, message: lsp_server::Message) { | 256 | pub(crate) fn send(&mut self, message: lsp_server::Message) { |
261 | self.sender.send(message).unwrap() | 257 | self.sender.send(message).unwrap() |
262 | } | 258 | } |
259 | pub(crate) fn respond(&mut self, response: lsp_server::Response) { | ||
260 | if let Some((method, start)) = self.req_queue.incoming.complete(response.id.clone()) { | ||
261 | let duration = start.elapsed(); | ||
262 | log::info!("handled req#{} in {:?}", response.id, duration); | ||
263 | let metrics = | ||
264 | RequestMetrics { id: response.id.clone(), method: method.to_string(), duration }; | ||
265 | self.latest_requests.write().record(metrics); | ||
266 | self.send(response.into()); | ||
267 | } | ||
268 | } | ||
263 | pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) { | 269 | pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) { |
264 | show_message(typ, message, &self.sender) | 270 | show_message(typ, message, &self.sender) |
265 | } | 271 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 94b9c0ca2..76dea3e22 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -23,7 +23,6 @@ use crate::{ | |||
23 | lsp_utils::{ | 23 | lsp_utils::{ |
24 | apply_document_changes, is_canceled, notification_is, notification_new, show_message, | 24 | apply_document_changes, is_canceled, notification_is, notification_new, show_message, |
25 | }, | 25 | }, |
26 | request_metrics::RequestMetrics, | ||
27 | Result, | 26 | Result, |
28 | }; | 27 | }; |
29 | 28 | ||
@@ -147,7 +146,7 @@ impl fmt::Debug for Event { | |||
147 | return debug_verbose_not(not, f); | 146 | return debug_verbose_not(not, f); |
148 | } | 147 | } |
149 | } | 148 | } |
150 | Event::Task(Task::Respond(resp)) => { | 149 | Event::Task(Task::Response(resp)) => { |
151 | return f | 150 | return f |
152 | .debug_struct("Response") | 151 | .debug_struct("Response") |
153 | .field("id", &resp.id) | 152 | .field("id", &resp.id) |
@@ -218,7 +217,13 @@ impl GlobalState { | |||
218 | } | 217 | } |
219 | }, | 218 | }, |
220 | Event::Task(task) => { | 219 | Event::Task(task) => { |
221 | self.on_task(task); | 220 | match task { |
221 | Task::Response(response) => self.respond(response), | ||
222 | Task::Diagnostics(tasks) => { | ||
223 | tasks.into_iter().for_each(|task| on_diagnostic_task(task, self)) | ||
224 | } | ||
225 | Task::Unit => (), | ||
226 | } | ||
222 | self.maybe_collect_garbage(); | 227 | self.maybe_collect_garbage(); |
223 | } | 228 | } |
224 | Event::Vfs(task) => match task { | 229 | Event::Vfs(task) => match task { |
@@ -331,7 +336,9 @@ impl GlobalState { | |||
331 | } | 336 | } |
332 | 337 | ||
333 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { | 338 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { |
334 | RequestDispatcher { req: Some(req), global_state: self, request_received } | 339 | self.req_queue.incoming.register(req.id.clone(), (req.method.clone(), request_received)); |
340 | |||
341 | RequestDispatcher { req: Some(req), global_state: self } | ||
335 | .on_sync::<lsp_ext::CollectGarbage>(|s, ()| Ok(s.collect_garbage()))? | 342 | .on_sync::<lsp_ext::CollectGarbage>(|s, ()| Ok(s.collect_garbage()))? |
336 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? | 343 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? |
337 | .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? | 344 | .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? |
@@ -492,27 +499,6 @@ impl GlobalState { | |||
492 | .finish(); | 499 | .finish(); |
493 | Ok(()) | 500 | Ok(()) |
494 | } | 501 | } |
495 | pub(crate) fn on_task(&mut self, task: Task) { | ||
496 | match task { | ||
497 | Task::Respond(response) => { | ||
498 | if let Some((method, start)) = self.req_queue.incoming.complete(response.id.clone()) | ||
499 | { | ||
500 | let duration = start.elapsed(); | ||
501 | log::info!("handled req#{} in {:?}", response.id, duration); | ||
502 | self.complete_request(RequestMetrics { | ||
503 | id: response.id.clone(), | ||
504 | method: method.to_string(), | ||
505 | duration, | ||
506 | }); | ||
507 | self.send(response.into()); | ||
508 | } | ||
509 | } | ||
510 | Task::Diagnostics(tasks) => { | ||
511 | tasks.into_iter().for_each(|task| on_diagnostic_task(task, self)) | ||
512 | } | ||
513 | Task::Unit => (), | ||
514 | } | ||
515 | } | ||
516 | fn update_file_notifications_on_threadpool(&mut self, subscriptions: Vec<FileId>) { | 502 | fn update_file_notifications_on_threadpool(&mut self, subscriptions: Vec<FileId>) { |
517 | log::trace!("updating notifications for {:?}", subscriptions); | 503 | log::trace!("updating notifications for {:?}", subscriptions); |
518 | if self.config.publish_diagnostics { | 504 | if self.config.publish_diagnostics { |
@@ -548,13 +534,13 @@ impl GlobalState { | |||
548 | 534 | ||
549 | #[derive(Debug)] | 535 | #[derive(Debug)] |
550 | pub(crate) enum Task { | 536 | pub(crate) enum Task { |
551 | Respond(Response), | 537 | Response(Response), |
552 | Diagnostics(Vec<DiagnosticTask>), | 538 | Diagnostics(()), |
553 | Unit, | 539 | Unit, |
554 | } | 540 | } |
555 | 541 | ||
556 | pub(crate) type ReqHandler = fn(&mut GlobalState, Response); | 542 | pub(crate) type ReqHandler = fn(&mut GlobalState, Response); |
557 | pub(crate) type ReqQueue = lsp_server::ReqQueue<(&'static str, Instant), ReqHandler>; | 543 | pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>; |
558 | const DO_NOTHING: ReqHandler = |_, _| (); | 544 | const DO_NOTHING: ReqHandler = |_, _| (); |
559 | 545 | ||
560 | fn on_diagnostic_task(task: DiagnosticTask, global_state: &mut GlobalState) { | 546 | fn on_diagnostic_task(task: DiagnosticTask, global_state: &mut GlobalState) { |