From 25aebb5225da91d34a2cb946f93435f9f7e82a47 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 13 Aug 2018 00:09:30 +0300 Subject: Refctor --- crates/server/src/main.rs | 3 +- crates/server/src/main_loop/mod.rs | 196 ++++++++++++++++++++++--------------- 2 files changed, 119 insertions(+), 80 deletions(-) (limited to 'crates/server/src') diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 4b250acfa..7416de08a 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -31,7 +31,7 @@ use flexi_logger::Logger; use libanalysis::WorldState; use ::{ - io::{Io, RawMsg, RawResponse, RawNotification} + io::{Io, RawMsg, RawResponse, RawRequest, RawNotification} }; pub type Result = ::std::result::Result; @@ -104,6 +104,7 @@ fn initialize(io: &mut Io) -> Result<()> { enum Task { Respond(RawResponse), + Request(RawRequest), Notify(RawNotification), Die(::failure::Error), } diff --git a/crates/server/src/main_loop/mod.rs b/crates/server/src/main_loop/mod.rs index e80b9988d..3d367f5f6 100644 --- a/crates/server/src/main_loop/mod.rs +++ b/crates/server/src/main_loop/mod.rs @@ -1,13 +1,16 @@ mod handlers; +use std::collections::HashSet; + use threadpool::ThreadPool; use crossbeam_channel::{Sender, Receiver}; use languageserver_types::Url; use libanalysis::{World, WorldState}; + use { req, dispatch, Task, Result, - io::{Io, RawMsg, RawRequest}, + io::{Io, RawMsg, RawRequest, RawNotification}, util::FilePath, main_loop::handlers::{ handle_syntax_tree, @@ -27,6 +30,8 @@ pub(super) fn main_loop( receiver: Receiver, ) -> Result<()> { info!("server initialized, serving requests"); + let mut next_request_id = 0; + let mut pending_requests: HashSet = HashSet::new(); loop { enum Event { Msg(RawMsg), @@ -48,6 +53,12 @@ pub(super) fn main_loop( } Event::Task(task) => { match task { + Task::Request(mut request) => { + request.id = next_request_id; + pending_requests.insert(next_request_id); + next_request_id += 1; + io.send(RawMsg::Request(request)); + } Task::Respond(response) => io.send(RawMsg::Response(response)), Task::Notify(n) => @@ -58,97 +69,124 @@ pub(super) fn main_loop( continue; } Event::Msg(msg) => { - if !on_msg(io, world, pool, &sender, msg)? { - return Ok(()); + match msg { + RawMsg::Request(req) => { + if !on_request(io, world, pool, &sender, req)? { + return Ok(()); + } + } + RawMsg::Notification(not) => { + on_notification(io, world, pool, &sender, not)? + } + RawMsg::Response(resp) => { + error!("unexpected response: {:?}", resp) + } } } }; } } -fn on_msg( +fn on_request( io: &mut Io, - world: &mut WorldState, - pool: &mut ThreadPool, + world: &WorldState, + pool: &ThreadPool, sender: &Sender, - msg: RawMsg, + req: RawRequest, ) -> Result { - match msg { - RawMsg::Request(req) => { - let mut req = Some(req); - handle_request_on_threadpool::( - &mut req, pool, world, sender, handle_syntax_tree, - )?; - handle_request_on_threadpool::( - &mut req, pool, world, sender, handle_extend_selection, - )?; - handle_request_on_threadpool::( - &mut req, pool, world, sender, handle_document_symbol, - )?; - handle_request_on_threadpool::( - &mut req, pool, world, sender, handle_code_action, - )?; + let mut req = Some(req); + handle_request_on_threadpool::( + &mut req, pool, world, sender, handle_syntax_tree, + )?; + handle_request_on_threadpool::( + &mut req, pool, world, sender, handle_extend_selection, + )?; + handle_request_on_threadpool::( + &mut req, pool, world, sender, handle_document_symbol, + )?; + handle_request_on_threadpool::( + &mut req, pool, world, sender, handle_code_action, + )?; +// dispatch::handle_request::(&mut req, |(), resp| { +// let world = world.snapshot(); +// let sender = sender.clone(); +// pool.execute(move || { +// let task = match handle_execute_command(world, params) { +// Ok(req) => Task::Request(req), +// Err(e) => Task::Die(e), +// }; +// sender.send(task) +// }); +// +// let resp = resp.into_response(Ok(()))?; +// io.send(RawMsg::Response(resp)); +// shutdown = true; +// Ok(()) +// })?; - let mut shutdown = false; - dispatch::handle_request::(&mut req, |(), resp| { - let resp = resp.into_response(Ok(()))?; - io.send(RawMsg::Response(resp)); - shutdown = true; - Ok(()) - })?; - if shutdown { - info!("lifecycle: initiating shutdown"); - return Ok(false); - } - if let Some(req) = req { - error!("unknown method: {:?}", req); - io.send(RawMsg::Response(dispatch::unknown_method(req.id)?)); - } - } - RawMsg::Notification(not) => { - let mut not = Some(not); - dispatch::handle_notification::(&mut not, |params| { - let path = params.text_document.file_path()?; - world.change_overlay(path, Some(params.text_document.text)); - update_file_notifications_on_threadpool( - pool, world.snapshot(), sender.clone(), params.text_document.uri, - ); - Ok(()) - })?; - dispatch::handle_notification::(&mut not, |mut params| { - let path = params.text_document.file_path()?; - let text = params.content_changes.pop() - .ok_or_else(|| format_err!("empty changes"))? - .text; - world.change_overlay(path, Some(text)); - update_file_notifications_on_threadpool( - pool, world.snapshot(), sender.clone(), params.text_document.uri, - ); - Ok(()) - })?; - dispatch::handle_notification::(&mut not, |params| { - let path = params.text_document.file_path()?; - world.change_overlay(path, None); - let not = req::PublishDiagnosticsParams { - uri: params.text_document.uri, - diagnostics: Vec::new(), - }; - let not = dispatch::send_notification::(not); - io.send(RawMsg::Notification(not)); - Ok(()) - })?; - - if let Some(not) = not { - error!("unhandled notification: {:?}", not) - } - } - msg => { - eprintln!("msg = {:?}", msg); - } - }; + let mut shutdown = false; + dispatch::handle_request::(&mut req, |(), resp| { + let resp = resp.into_response(Ok(()))?; + io.send(RawMsg::Response(resp)); + shutdown = true; + Ok(()) + })?; + if shutdown { + info!("lifecycle: initiating shutdown"); + return Ok(false); + } + if let Some(req) = req { + error!("unknown method: {:?}", req); + io.send(RawMsg::Response(dispatch::unknown_method(req.id)?)); + } Ok(true) } +fn on_notification( + io: &mut Io, + world: &mut WorldState, + pool: &ThreadPool, + sender: &Sender, + not: RawNotification, +) -> Result<()> { + let mut not = Some(not); + dispatch::handle_notification::(&mut not, |params| { + let path = params.text_document.file_path()?; + world.change_overlay(path, Some(params.text_document.text)); + update_file_notifications_on_threadpool( + pool, world.snapshot(), sender.clone(), params.text_document.uri, + ); + Ok(()) + })?; + dispatch::handle_notification::(&mut not, |mut params| { + let path = params.text_document.file_path()?; + let text = params.content_changes.pop() + .ok_or_else(|| format_err!("empty changes"))? + .text; + world.change_overlay(path, Some(text)); + update_file_notifications_on_threadpool( + pool, world.snapshot(), sender.clone(), params.text_document.uri, + ); + Ok(()) + })?; + dispatch::handle_notification::(&mut not, |params| { + let path = params.text_document.file_path()?; + world.change_overlay(path, None); + let not = req::PublishDiagnosticsParams { + uri: params.text_document.uri, + diagnostics: Vec::new(), + }; + let not = dispatch::send_notification::(not); + io.send(RawMsg::Notification(not)); + Ok(()) + })?; + + if let Some(not) = not { + error!("unhandled notification: {:?}", not); + } + Ok(()) +} + fn handle_request_on_threadpool( req: &mut Option, pool: &ThreadPool, -- cgit v1.2.3