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