From 8dad14b5cd63203d7ad9d86686b3c654ff353c83 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 12 Aug 2018 21:34:17 +0300 Subject: Convert Thunk to Task --- crates/server/src/dispatch.rs | 71 +++++++++++++++++++--------------------- crates/server/src/main.rs | 75 ++++++++++++++++++++++++++----------------- crates/server/src/util.rs | 10 ------ 3 files changed, 79 insertions(+), 77 deletions(-) (limited to 'crates/server/src') diff --git a/crates/server/src/dispatch.rs b/crates/server/src/dispatch.rs index eb23ab64f..369c56b64 100644 --- a/crates/server/src/dispatch.rs +++ b/crates/server/src/dispatch.rs @@ -19,38 +19,27 @@ pub struct Responder { ph: PhantomData, } -impl Responder -{ - pub fn response(self, io: &mut Io, resp: Result) -> Result<()> { - match resp { - Ok(res) => self.result(io, res)?, - Err(e) => { - self.error(io)?; - return Err(e); - } - } - Ok(()) - } - - pub fn result(mut self, io: &mut Io, result: R::Result) -> Result<()> { +impl Responder { + pub fn into_response(mut self, result: Result) -> Result { self.bomb.defuse(); - io.send(RawMsg::Response(RawResponse { - id: Some(self.id), - result: serde_json::to_value(result)?, - error: serde_json::Value::Null, - })); - Ok(()) - } - - pub fn error(mut self, io: &mut Io) -> Result<()> { - self.bomb.defuse(); - error(io, self.id, ErrorCode::InternalError, "internal error") + let res = match result { + Ok(result) => { + RawResponse { + id: Some(self.id), + result: serde_json::to_value(result)?, + error: serde_json::Value::Null, + } + } + Err(_) => { + error_response(self.id, ErrorCode::InternalError, "internal error")? + } + }; + Ok(res) } } - fn parse_request_as(raw: RawRequest) - -> Result<::std::result::Result<(R::Params, Responder), RawRequest>> + -> Result<::std::result::Result<(R::Params, Responder), RawRequest>> { if raw.method != R::METHOD { return Ok(Err(raw)); @@ -77,13 +66,13 @@ pub fn handle_request(req: &mut Option, f: F) -> Result<()> Err(r) => { *req = Some(r); Ok(()) - }, + } } } } pub fn expect_request(io: &mut Io, raw: RawRequest) - -> Result)>> + -> Result)>> { let ret = match parse_request_as::(raw)? { Ok(x) => Some(x), @@ -120,21 +109,21 @@ pub fn handle_notification(not: &mut Option, f: F) -> Res Err(n) => { *not = Some(n); Ok(()) - }, + } } } } -pub fn send_notification(io: &mut Io, params: N::Params) -> Result<()> +pub fn send_notification(params: N::Params) -> RawNotification where N: Notification, N::Params: Serialize { - io.send(RawMsg::Notification(RawNotification { + RawNotification { method: N::METHOD.to_string(), - params: serde_json::to_value(params)?, - })); - Ok(()) + params: serde_json::to_value(params) + .unwrap(), + } } @@ -142,20 +131,26 @@ pub fn unknown_method(io: &mut Io, raw: RawRequest) -> Result<()> { error(io, raw.id, ErrorCode::MethodNotFound, "unknown method") } -fn error(io: &mut Io, id: u64, code: ErrorCode, message: &'static str) -> Result<()> { +fn error_response(id: u64, code: ErrorCode, message: &'static str) -> Result { #[derive(Serialize)] struct Error { code: i32, message: &'static str, } - io.send(RawMsg::Response(RawResponse { + let resp = RawResponse { id: Some(id), result: serde_json::Value::Null, error: serde_json::to_value(Error { code: code as i32, message, })?, - })); + }; + Ok(resp) +} + +fn error(io: &mut Io, id: u64, code: ErrorCode, message: &'static str) -> Result<()> { + let resp = error_response(id, code, message)?; + io.send(RawMsg::Response(resp)); Ok(()) } diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 3ff300e3d..be63fea93 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -32,10 +32,10 @@ use languageserver_types::Url; use libanalysis::{WorldState, World}; use ::{ - io::{Io, RawMsg, RawRequest}, + io::{Io, RawMsg, RawRequest, RawResponse, RawNotification}, handlers::{handle_syntax_tree, handle_extend_selection, publish_diagnostics, publish_decorations, handle_document_symbol, handle_code_action}, - util::{FilePath, FnBox} + util::FilePath, }; pub type Result = ::std::result::Result; @@ -80,9 +80,9 @@ fn initialize(io: &mut Io) -> Result<()> { match io.recv()? { RawMsg::Request(req) => { if let Some((_params, resp)) = dispatch::expect_request::(io, req)? { - resp.result(io, req::InitializeResult { - capabilities: caps::SERVER_CAPABILITIES - })?; + let res = req::InitializeResult { capabilities: caps::SERVER_CAPABILITIES }; + let resp = resp.into_response(Ok(res))?; + io.send(RawMsg::Response(resp)); match io.recv()? { RawMsg::Notification(n) => { if n.method != "initialized" { @@ -106,13 +106,18 @@ fn initialize(io: &mut Io) -> Result<()> { } } -type Thunk = Box FnBox<&'a mut Io, Result<()>>>; + +enum Task { + Respond(RawResponse), + Notify(RawNotification), + Die(::failure::Error), +} fn initialized(io: &mut Io) -> Result<()> { { let mut world = WorldState::new(); let mut pool = ThreadPool::new(4); - let (sender, receiver) = bounded::(16); + let (sender, receiver) = bounded::(16); info!("lifecycle: handshake finished, server ready to serve requests"); let res = main_loop(io, &mut world, &mut pool, sender, receiver.clone()); info!("waiting for background jobs to finish..."); @@ -140,14 +145,14 @@ fn main_loop( io: &mut Io, world: &mut WorldState, pool: &mut ThreadPool, - sender: Sender, - receiver: Receiver, + sender: Sender, + receiver: Receiver, ) -> Result<()> { info!("server initialized, serving requests"); loop { enum Event { Msg(RawMsg), - Thunk(Thunk), + Task(Task), ReceiverDead, } @@ -156,7 +161,7 @@ fn main_loop( Some(msg) => Event::Msg(msg), None => Event::ReceiverDead, }, - recv(receiver, thunk) => Event::Thunk(thunk.unwrap()), + recv(receiver, task) => Event::Task(task.unwrap()), }; let msg = match event { @@ -164,8 +169,15 @@ fn main_loop( io.cleanup_receiver()?; unreachable!(); } - Event::Thunk(thunk) => { - thunk.call_box(io)?; + Event::Task(task) => { + match task { + Task::Respond(response) => + io.send(RawMsg::Response(response)), + Task::Notify(n) => + io.send(RawMsg::Notification(n)), + Task::Die(error) => + return Err(error), + } continue; } Event::Msg(msg) => msg, @@ -175,21 +187,22 @@ fn main_loop( RawMsg::Request(req) => { let mut req = Some(req); handle_request_on_threadpool::( - &mut req, pool, world, &sender, handle_syntax_tree + &mut req, pool, world, &sender, handle_syntax_tree, )?; handle_request_on_threadpool::( - &mut req, pool, world, &sender, handle_extend_selection + &mut req, pool, world, &sender, handle_extend_selection, )?; handle_request_on_threadpool::( - &mut req, pool, world, &sender, handle_document_symbol + &mut req, pool, world, &sender, handle_document_symbol, )?; handle_request_on_threadpool::( - &mut req, pool, world, &sender, handle_code_action + &mut req, pool, world, &sender, handle_code_action, )?; let mut shutdown = false; dispatch::handle_request::(&mut req, |(), resp| { - resp.result(io, ())?; + let resp = resp.into_response(Ok(()))?; + io.send(RawMsg::Response(resp)); shutdown = true; Ok(()) })?; @@ -227,10 +240,12 @@ fn main_loop( dispatch::handle_notification::(&mut not, |params| { let path = params.text_document.file_path()?; world.change_overlay(path, None); - dispatch::send_notification::(io, req::PublishDiagnosticsParams { + let not = req::PublishDiagnosticsParams { uri: params.text_document.uri, diagnostics: Vec::new(), - })?; + }; + let not = dispatch::send_notification::(not); + io.send(RawMsg::Notification(not)); Ok(()) })?; @@ -249,7 +264,7 @@ fn handle_request_on_threadpool( req: &mut Option, pool: &ThreadPool, world: &WorldState, - sender: &Sender, + sender: &Sender, f: fn(World, R::Params) -> Result, ) -> Result<()> { @@ -258,7 +273,11 @@ fn handle_request_on_threadpool( let sender = sender.clone(); pool.execute(move || { let res = f(world, params); - sender.send(Box::new(|io: &mut Io| resp.response(io, res))) + let task = match resp.into_response(res) { + Ok(resp) => Task::Respond(resp), + Err(e) => Task::Die(e), + }; + sender.send(task); }); Ok(()) }) @@ -267,7 +286,7 @@ fn handle_request_on_threadpool( fn update_file_notifications_on_threadpool( pool: &ThreadPool, world: World, - sender: Sender, + sender: Sender, uri: Url, ) { pool.execute(move || { @@ -276,9 +295,8 @@ fn update_file_notifications_on_threadpool( error!("failed to compute diagnostics: {:?}", e) } Ok(params) => { - sender.send(Box::new(|io: &mut Io| { - dispatch::send_notification::(io, params) - })) + let not = dispatch::send_notification::(params); + sender.send(Task::Notify(not)); } } match publish_decorations(world, uri) { @@ -286,9 +304,8 @@ fn update_file_notifications_on_threadpool( error!("failed to compute decortions: {:?}", e) } Ok(params) => { - sender.send(Box::new(|io: &mut Io| { - dispatch::send_notification::(io, params) - })) + let not = dispatch::send_notification::(params); + sender.send(Task::Notify(not)) } } }); diff --git a/crates/server/src/util.rs b/crates/server/src/util.rs index e4c226f93..6747c20a8 100644 --- a/crates/server/src/util.rs +++ b/crates/server/src/util.rs @@ -3,16 +3,6 @@ use languageserver_types::{TextDocumentItem, VersionedTextDocumentIdentifier, TextDocumentIdentifier, Url}; use ::{Result}; -pub trait FnBox: Send { - fn call_box(self: Box, a: A) -> R; -} - -impl R + Send> FnBox for F { - fn call_box(self: Box, a: A) -> R { - (*self)(a) - } -} - pub trait FilePath { fn file_path(&self) -> Result; } -- cgit v1.2.3