mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 13:23:25 +00:00
91 lines
2.7 KiB
Rust
91 lines
2.7 KiB
Rust
use std::{
|
|
io::{self, stdin, stdout},
|
|
thread,
|
|
};
|
|
|
|
use log::debug;
|
|
|
|
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) {
|
|
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 _ = drop_sender.send(it);
|
|
result
|
|
})
|
|
})
|
|
.unwrap();
|
|
let dropper = thread::Builder::new()
|
|
.name("LspMessageDropper".to_owned())
|
|
.spawn(move || drop_receiver.into_iter().for_each(drop))
|
|
.unwrap();
|
|
let (reader_sender, reader_receiver) = bounded::<Message>(0);
|
|
let reader = 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)? {
|
|
let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit());
|
|
|
|
debug!("sending message {msg:#?}");
|
|
if let Err(e) = reader_sender.send(msg) {
|
|
return Err(io::Error::other(e));
|
|
}
|
|
|
|
if is_exit {
|
|
break;
|
|
}
|
|
}
|
|
Ok(())
|
|
})
|
|
.unwrap();
|
|
let threads = IoThreads { reader, writer, dropper };
|
|
(writer_sender, reader_receiver, threads)
|
|
}
|
|
|
|
// Creates an IoThreads
|
|
pub(crate) fn make_io_threads(
|
|
reader: thread::JoinHandle<io::Result<()>>,
|
|
writer: thread::JoinHandle<io::Result<()>>,
|
|
dropper: thread::JoinHandle<()>,
|
|
) -> IoThreads {
|
|
IoThreads { reader, writer, dropper }
|
|
}
|
|
|
|
pub struct IoThreads {
|
|
reader: thread::JoinHandle<io::Result<()>>,
|
|
writer: thread::JoinHandle<io::Result<()>>,
|
|
dropper: thread::JoinHandle<()>,
|
|
}
|
|
|
|
impl IoThreads {
|
|
pub fn join(self) -> io::Result<()> {
|
|
match self.reader.join() {
|
|
Ok(r) => r?,
|
|
Err(err) => std::panic::panic_any(err),
|
|
}
|
|
match self.dropper.join() {
|
|
Ok(_) => (),
|
|
Err(err) => {
|
|
std::panic::panic_any(err);
|
|
}
|
|
}
|
|
match self.writer.join() {
|
|
Ok(r) => r,
|
|
Err(err) => {
|
|
std::panic::panic_any(err);
|
|
}
|
|
}
|
|
}
|
|
}
|