Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | lib/lsp-server/src/lib.rs | 9 | ||||
| -rw-r--r-- | lib/lsp-server/src/msg.rs | 38 | ||||
| -rw-r--r-- | lib/lsp-server/src/stdio.rs | 17 |
3 files changed, 48 insertions, 16 deletions
diff --git a/lib/lsp-server/src/lib.rs b/lib/lsp-server/src/lib.rs index c8cdb86681..315cb2d5c3 100644 --- a/lib/lsp-server/src/lib.rs +++ b/lib/lsp-server/src/lib.rs @@ -14,7 +14,7 @@ mod socket; mod stdio; use std::{ - io, + io::{self, Stdin, Stdout}, net::{TcpListener, TcpStream, ToSocketAddrs}, }; @@ -37,8 +37,11 @@ impl Connection { /// Create connection over standard in/standard out. /// /// Use this to create a real language server. - pub fn stdio() -> (Connection, IoThreads) { - let (sender, receiver, io_threads) = stdio::stdio_transport(); + pub fn stdio( + stdout: impl io::Read + io::BufRead + Sync + Send + 'static, + stdin: impl io::Write + Sync + Send + 'static, + ) -> (Connection, IoThreads) { + let (sender, receiver, io_threads) = stdio::stdio_transport(stdout, stdin); (Connection { sender, receiver }, io_threads) } diff --git a/lib/lsp-server/src/msg.rs b/lib/lsp-server/src/msg.rs index 305008e69a..eb8b6bbf04 100644 --- a/lib/lsp-server/src/msg.rs +++ b/lib/lsp-server/src/msg.rs @@ -16,6 +16,27 @@ pub enum Message { Notification(Notification), } +impl Message { + pub fn request(self) -> Option<Request> { + match self { + Self::Request(x) => Some(x), + _ => None, + } + } + pub fn response(self) -> Option<Response> { + match self { + Self::Response(x) => Some(x), + _ => None, + } + } + pub fn notification(self) -> Option<Notification> { + match self { + Self::Notification(x) => Some(x), + _ => None, + } + } +} + impl From<Request> for Message { fn from(request: Request) -> Message { Message::Request(request) @@ -36,11 +57,20 @@ impl From<Notification> for Message { #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[serde(transparent)] -pub struct RequestId(IdRepr); +pub struct RequestId(pub IdRepr); + +impl RequestId { + pub fn i32(&self) -> i32 { + match self.0 { + IdRepr::I32(x) => x, + _ => panic!(), + } + } +} #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[serde(untagged)] -enum IdRepr { +pub enum IdRepr { I32(i32), String(String), } @@ -247,10 +277,10 @@ impl Notification { Err(error) => Err(ExtractError::JsonError { method: self.method, error }), } } - pub(crate) fn is_exit(&self) -> bool { + pub fn is_exit(&self) -> bool { self.method == "exit" } - pub(crate) fn is_initialized(&self) -> bool { + pub fn is_initialized(&self) -> bool { self.method == "initialized" } } diff --git a/lib/lsp-server/src/stdio.rs b/lib/lsp-server/src/stdio.rs index eccc89fd59..711c4e9907 100644 --- a/lib/lsp-server/src/stdio.rs +++ b/lib/lsp-server/src/stdio.rs @@ -1,5 +1,5 @@ use std::{ - io::{self, stdin, stdout}, + io::{self, Read, Stdin, Stdout, Write, stdin, stdout}, thread, }; @@ -10,16 +10,17 @@ use crossbeam_channel::{Receiver, Sender, bounded}; use crate::Message; /// Creates an LSP connection via stdio. -pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThreads) { +pub(crate) fn stdio_transport( + mut read_from: impl Read + std::io::BufRead + Sync + Send + 'static, + mut write_to: impl Write + Sync + Send + 'static, +) -> (Sender<Message>, Receiver<Message>, IoThreads) { let (drop_sender, drop_receiver) = bounded::<Message>(0); let (writer_sender, writer_receiver) = bounded::<Message>(0); let writer = thread::Builder::new() .name("LspServerWriter".to_owned()) .spawn(move || { - let stdout = stdout(); - let mut stdout = stdout.lock(); writer_receiver.into_iter().try_for_each(|it| { - let result = it.write(&mut stdout); + let result = it.write(&mut write_to); let _ = drop_sender.send(it); result }) @@ -30,12 +31,10 @@ pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThread .spawn(move || drop_receiver.into_iter().for_each(drop)) .unwrap(); let (reader_sender, reader_receiver) = bounded::<Message>(0); - let reader = thread::Builder::new() + let reader: thread::JoinHandle<Result<(), io::Error>> = thread::Builder::new() .name("LspServerReader".to_owned()) .spawn(move || { - let stdin = stdin(); - let mut stdin = stdin.lock(); - while let Some(msg) = Message::read(&mut stdin)? { + while let Some(msg) = Message::read(&mut read_from)? { let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit()); debug!("sending message {msg:#?}"); |