aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/rust-analyzer/src/dispatch.rs44
-rw-r--r--crates/rust-analyzer/src/global_state.rs14
-rw-r--r--crates/rust-analyzer/src/main_loop.rs42
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.
2use std::{panic, time::Instant}; 2use std::panic;
3 3
4use serde::{de::DeserializeOwned, Serialize}; 4use serde::{de::DeserializeOwned, Serialize};
5 5
@@ -13,7 +13,6 @@ use crate::{
13pub(crate) struct RequestDispatcher<'a> { 13pub(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
19impl<'a> RequestDispatcher<'a> { 18impl<'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
110fn result_to_task<R>(id: lsp_server::RequestId, result: Result<R::Result>) -> Task 102fn result_to_response<R>(
103 id: lsp_server::RequestId,
104 result: Result<R::Result>,
105) -> lsp_server::Response
111where 106where
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
140pub(crate) struct NotificationDispatcher<'a> { 134pub(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)]
550pub(crate) enum Task { 536pub(crate) enum Task {
551 Respond(Response), 537 Response(Response),
552 Diagnostics(Vec<DiagnosticTask>), 538 Diagnostics(()),
553 Unit, 539 Unit,
554} 540}
555 541
556pub(crate) type ReqHandler = fn(&mut GlobalState, Response); 542pub(crate) type ReqHandler = fn(&mut GlobalState, Response);
557pub(crate) type ReqQueue = lsp_server::ReqQueue<(&'static str, Instant), ReqHandler>; 543pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>;
558const DO_NOTHING: ReqHandler = |_, _| (); 544const DO_NOTHING: ReqHandler = |_, _| ();
559 545
560fn on_diagnostic_task(task: DiagnosticTask, global_state: &mut GlobalState) { 546fn on_diagnostic_task(task: DiagnosticTask, global_state: &mut GlobalState) {