diff options
author | Aleksey Kladov <[email protected]> | 2019-05-31 18:50:16 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-05-31 18:50:16 +0100 |
commit | c6537c3280ba1c5df27c1ced9d4944a2acb02b6c (patch) | |
tree | 18ad74c5e59ddda7413a94c4acee97e79df9e2a8 | |
parent | 9697d8afadd96a8b18684e4967346f01a4343819 (diff) |
add sync requests
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 95 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 4 |
2 files changed, 56 insertions, 43 deletions
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 8f41937dc..8a7c53d2c 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -2,7 +2,7 @@ mod handlers; | |||
2 | mod subscriptions; | 2 | mod subscriptions; |
3 | pub(crate) mod pending_requests; | 3 | pub(crate) mod pending_requests; |
4 | 4 | ||
5 | use std::{fmt, path::PathBuf, sync::Arc, time::Instant, any::TypeId}; | 5 | use std::{fmt, path::PathBuf, sync::Arc, time::Instant}; |
6 | 6 | ||
7 | use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender}; | 7 | use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender}; |
8 | use failure::{bail, format_err}; | 8 | use failure::{bail, format_err}; |
@@ -219,22 +219,15 @@ fn main_loop_inner( | |||
219 | Some(req) => req, | 219 | Some(req) => req, |
220 | None => return Ok(()), | 220 | None => return Ok(()), |
221 | }; | 221 | }; |
222 | match req.cast::<req::CollectGarbage>() { | 222 | on_request( |
223 | Ok((id, ())) => { | 223 | state, |
224 | state.collect_garbage(); | 224 | pending_requests, |
225 | let resp = RawResponse::ok::<req::CollectGarbage>(id, &()); | 225 | pool, |
226 | msg_sender.send(resp.into()).unwrap() | 226 | &task_sender, |
227 | } | 227 | msg_sender, |
228 | Err(req) => on_request( | 228 | loop_start, |
229 | state, | 229 | req, |
230 | pending_requests, | 230 | )? |
231 | pool, | ||
232 | &task_sender, | ||
233 | msg_sender, | ||
234 | loop_start, | ||
235 | req, | ||
236 | )?, | ||
237 | } | ||
238 | } | 231 | } |
239 | RawMessage::Notification(not) => { | 232 | RawMessage::Notification(not) => { |
240 | on_notification(msg_sender, state, pending_requests, subs, not)?; | 233 | on_notification(msg_sender, state, pending_requests, subs, not)?; |
@@ -322,6 +315,7 @@ fn on_request( | |||
322 | request_received, | 315 | request_received, |
323 | }; | 316 | }; |
324 | pool_dispatcher | 317 | pool_dispatcher |
318 | .on_sync::<req::CollectGarbage>(|state, ()| Ok(state.collect_garbage()))? | ||
325 | .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)? | 319 | .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)? |
326 | .on::<req::SyntaxTree>(handlers::handle_syntax_tree)? | 320 | .on::<req::SyntaxTree>(handlers::handle_syntax_tree)? |
327 | .on::<req::ExtendSelection>(handlers::handle_extend_selection)? | 321 | .on::<req::ExtendSelection>(handlers::handle_extend_selection)? |
@@ -434,37 +428,39 @@ struct PoolDispatcher<'a> { | |||
434 | } | 428 | } |
435 | 429 | ||
436 | impl<'a> PoolDispatcher<'a> { | 430 | impl<'a> PoolDispatcher<'a> { |
437 | fn on<R>(&mut self, f: fn(ServerWorld, R::Params) -> Result<R::Result>) -> Result<&mut Self> | 431 | fn on_sync<R>( |
432 | &mut self, | ||
433 | f: fn(&mut ServerWorldState, R::Params) -> Result<R::Result>, | ||
434 | ) -> Result<&mut Self> | ||
438 | where | 435 | where |
439 | R: req::Request + 'static, | 436 | R: req::Request + 'static, |
440 | R::Params: DeserializeOwned + Send + 'static, | 437 | R::Params: DeserializeOwned + Send + 'static, |
441 | R::Result: Serialize + 'static, | 438 | R::Result: Serialize + 'static, |
442 | { | 439 | { |
443 | let req = match self.req.take() { | 440 | let (id, params) = match self.parse::<R>() { |
444 | None => return Ok(self), | 441 | Some(it) => it, |
445 | Some(req) => req, | 442 | None => { |
446 | }; | ||
447 | let (id, params) = match req.cast::<R>() { | ||
448 | Ok(it) => it, | ||
449 | Err(req) => { | ||
450 | self.req = Some(req); | ||
451 | return Ok(self); | 443 | return Ok(self); |
452 | } | 444 | } |
453 | }; | 445 | }; |
454 | self.pending_requests.start(PendingRequest { | 446 | let result = f(self.world, params); |
455 | id, | 447 | let task = result_to_task::<R>(id, result); |
456 | method: R::METHOD.to_string(), | 448 | on_task(task, self.msg_sender, self.pending_requests, self.world); |
457 | received: self.request_received, | 449 | Ok(self) |
458 | }); | 450 | } |
459 | 451 | ||
460 | // Real time requests block user typing, so we should react quickly to them. | 452 | fn on<R>(&mut self, f: fn(ServerWorld, R::Params) -> Result<R::Result>) -> Result<&mut Self> |
461 | // Currently this means that we try to cancel background jobs if we don't have | 453 | where |
462 | // a spare thread. | 454 | R: req::Request + 'static, |
463 | let is_real_time = TypeId::of::<R>() == TypeId::of::<req::JoinLines>() | 455 | R::Params: DeserializeOwned + Send + 'static, |
464 | || TypeId::of::<R>() == TypeId::of::<req::OnEnter>(); | 456 | R::Result: Serialize + 'static, |
465 | if self.pool.queued_count() > 0 && is_real_time { | 457 | { |
466 | self.world.cancel_requests(); | 458 | let (id, params) = match self.parse::<R>() { |
467 | } | 459 | Some(it) => it, |
460 | None => { | ||
461 | return Ok(self); | ||
462 | } | ||
463 | }; | ||
468 | 464 | ||
469 | self.pool.execute({ | 465 | self.pool.execute({ |
470 | let world = self.world.snapshot(); | 466 | let world = self.world.snapshot(); |
@@ -479,6 +475,27 @@ impl<'a> PoolDispatcher<'a> { | |||
479 | Ok(self) | 475 | Ok(self) |
480 | } | 476 | } |
481 | 477 | ||
478 | fn parse<R>(&mut self) -> Option<(u64, R::Params)> | ||
479 | where | ||
480 | R: req::Request + 'static, | ||
481 | R::Params: DeserializeOwned + Send + 'static, | ||
482 | { | ||
483 | let req = self.req.take()?; | ||
484 | let (id, params) = match req.cast::<R>() { | ||
485 | Ok(it) => it, | ||
486 | Err(req) => { | ||
487 | self.req = Some(req); | ||
488 | return None; | ||
489 | } | ||
490 | }; | ||
491 | self.pending_requests.start(PendingRequest { | ||
492 | id, | ||
493 | method: R::METHOD.to_string(), | ||
494 | received: self.request_received, | ||
495 | }); | ||
496 | Some((id, params)) | ||
497 | } | ||
498 | |||
482 | fn finish(&mut self) { | 499 | fn finish(&mut self) { |
483 | match self.req.take() { | 500 | match self.req.take() { |
484 | None => (), | 501 | None => (), |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 8c7951e13..6076a6cd6 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -136,10 +136,6 @@ impl ServerWorldState { | |||
136 | self.analysis_host.apply_change(change); | 136 | self.analysis_host.apply_change(change); |
137 | } | 137 | } |
138 | 138 | ||
139 | pub fn cancel_requests(&mut self) { | ||
140 | self.analysis_host.apply_change(AnalysisChange::new()); | ||
141 | } | ||
142 | |||
143 | pub fn snapshot(&self) -> ServerWorld { | 139 | pub fn snapshot(&self) -> ServerWorld { |
144 | ServerWorld { | 140 | ServerWorld { |
145 | workspaces: Arc::clone(&self.workspaces), | 141 | workspaces: Arc::clone(&self.workspaces), |