aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs95
-rw-r--r--crates/ra_lsp_server/src/server_world.rs4
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;
2mod subscriptions; 2mod subscriptions;
3pub(crate) mod pending_requests; 3pub(crate) mod pending_requests;
4 4
5use std::{fmt, path::PathBuf, sync::Arc, time::Instant, any::TypeId}; 5use std::{fmt, path::PathBuf, sync::Arc, time::Instant};
6 6
7use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender}; 7use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender};
8use failure::{bail, format_err}; 8use 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
436impl<'a> PoolDispatcher<'a> { 430impl<'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),