Unnamed repository; edit this file 'description' to name the repository.
bendn 6 weeks ago
parent 3e832f3 · commit a51108e
-rw-r--r--lib/lsp-server/src/lib.rs9
-rw-r--r--lib/lsp-server/src/msg.rs38
-rw-r--r--lib/lsp-server/src/stdio.rs17
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:#?}");