From 3588d6b2da6e63730cc560c9986ba7fda5de816e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 1 Sep 2018 16:18:02 +0300 Subject: add gen_lsp_server --- crates/gen_lsp_server/src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 crates/gen_lsp_server/src/lib.rs (limited to 'crates/gen_lsp_server/src/lib.rs') diff --git a/crates/gen_lsp_server/src/lib.rs b/crates/gen_lsp_server/src/lib.rs new file mode 100644 index 000000000..a31e90f35 --- /dev/null +++ b/crates/gen_lsp_server/src/lib.rs @@ -0,0 +1,77 @@ +#[macro_use] +extern crate failure; +#[macro_use] +extern crate log; +extern crate serde; +extern crate serde_json; +#[macro_use] +extern crate serde_derive; +extern crate crossbeam_channel; +extern crate languageserver_types; + +mod msg; +mod stdio; + +use crossbeam_channel::{Sender, Receiver}; +use languageserver_types::{ + ServerCapabilities, InitializeResult, + request::{Initialize}, + notification::{Initialized, Exit}, +}; + +pub type Result = ::std::result::Result; +pub use { + msg::{RawMessage, RawRequest, RawResponse, RawResponseError, RawNotification}, + stdio::{stdio_transport, Threads}, +}; + +pub type LspServer = fn(&mut Receiver, &mut Sender) -> Result<()>; + +pub fn run_server( + caps: ServerCapabilities, + server: LspServer, + mut receiver: Receiver, + mut sender: Sender, +) -> Result<()> { + info!("lsp server initializes"); + initialize(&mut receiver, &mut sender, caps)?; + info!("lsp server initialized, serving requests"); + server(&mut receiver, &mut sender)?; + info!("lsp server waiting for exit notification"); + match receiver.recv() { + Some(RawMessage::Notification(n)) => { + n.cast::().map_err(|n| format_err!( + "unexpected notification during shutdown: {:?}", n + ))? + } + m => bail!("unexpected message during shutdown: {:?}", m) + } + info!("lsp server shutdown complete"); + Ok(()) +} + +fn initialize( + receiver: &mut Receiver, + sender: &mut Sender, + caps: ServerCapabilities, +) -> Result<()> { + let id = match receiver.recv() { + Some(RawMessage::Request(req)) => match req.cast::() { + Err(req) => bail!("expected initialize request, got {:?}", req), + Ok(req) => req.0, + } + msg => + bail!("expected initialize request, got {:?}", msg), + }; + let resp = RawResponse::ok(id, InitializeResult { capabilities: caps }); + sender.send(RawMessage::Response(resp)); + match receiver.recv() { + Some(RawMessage::Notification(n)) => { + n.cast::().map_err(|_| format_err!( + "expected initialized notification" + ))?; + } + _ => bail!("expected initialized notification"), + } + Ok(()) +} -- cgit v1.2.3