lsp_server/
stdio.rs
1use std::{
2 io::{self, stdin, stdout},
3 thread,
4};
5
6use log::debug;
7
8use crossbeam_channel::{Receiver, Sender, bounded};
9
10use crate::Message;
11
12pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThreads) {
14 let (drop_sender, drop_receiver) = bounded::<Message>(0);
15 let (writer_sender, writer_receiver) = bounded::<Message>(0);
16 let writer = thread::Builder::new()
17 .name("LspServerWriter".to_owned())
18 .spawn(move || {
19 let stdout = stdout();
20 let mut stdout = stdout.lock();
21 writer_receiver.into_iter().try_for_each(|it| {
22 let result = it.write(&mut stdout);
23 let _ = drop_sender.send(it);
24 result
25 })
26 })
27 .unwrap();
28 let dropper = thread::Builder::new()
29 .name("LspMessageDropper".to_owned())
30 .spawn(move || drop_receiver.into_iter().for_each(drop))
31 .unwrap();
32 let (reader_sender, reader_receiver) = bounded::<Message>(0);
33 let reader = thread::Builder::new()
34 .name("LspServerReader".to_owned())
35 .spawn(move || {
36 let stdin = stdin();
37 let mut stdin = stdin.lock();
38 while let Some(msg) = Message::read(&mut stdin)? {
39 let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit());
40
41 debug!("sending message {:#?}", msg);
42 if let Err(e) = reader_sender.send(msg) {
43 return Err(io::Error::other(e));
44 }
45
46 if is_exit {
47 break;
48 }
49 }
50 Ok(())
51 })
52 .unwrap();
53 let threads = IoThreads { reader, writer, dropper };
54 (writer_sender, reader_receiver, threads)
55}
56
57pub(crate) fn make_io_threads(
59 reader: thread::JoinHandle<io::Result<()>>,
60 writer: thread::JoinHandle<io::Result<()>>,
61 dropper: thread::JoinHandle<()>,
62) -> IoThreads {
63 IoThreads { reader, writer, dropper }
64}
65
66pub struct IoThreads {
67 reader: thread::JoinHandle<io::Result<()>>,
68 writer: thread::JoinHandle<io::Result<()>>,
69 dropper: thread::JoinHandle<()>,
70}
71
72impl IoThreads {
73 pub fn join(self) -> io::Result<()> {
74 match self.reader.join() {
75 Ok(r) => r?,
76 Err(err) => std::panic::panic_any(err),
77 }
78 match self.dropper.join() {
79 Ok(_) => (),
80 Err(err) => {
81 std::panic::panic_any(err);
82 }
83 }
84 match self.writer.join() {
85 Ok(r) => r,
86 Err(err) => {
87 std::panic::panic_any(err);
88 }
89 }
90 }
91}