Skip to content

Commit 8297e78

Browse files
authored
Add Proc macro server (#1681)
**Stack**: - #1686 - #1685 - #1684 - #1683 - #1718 - #1682 - #1681⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do not merge manually using the UI - doing so may have unexpected results.*
1 parent ccdf19a commit 8297e78

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scarb/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ camino.workspace = true
3737
clap.workspace = true
3838
convert_case.workspace = true
3939
create-output-dir = { path = "../utils/create-output-dir" }
40+
crossbeam-channel = "0.5.13"
4041
data-encoding.workspace = true
4142
deno_task_shell.workspace = true
4243
derive_builder.workspace = true
@@ -56,6 +57,7 @@ libloading.workspace = true
5657
once_cell.workspace = true
5758
pathdiff.workspace = true
5859
petgraph.workspace = true
60+
scarb-proc-macro-server-types = { path = "../utils/scarb-proc-macro-server-types" }
5961
ra_ap_toolchain.workspace = true
6062
redb.workspace = true
6163
reqwest.workspace = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use std::io::{BufRead, Write};
2+
use std::thread::JoinHandle;
3+
4+
use crossbeam_channel::{Receiver, Sender};
5+
use scarb_proc_macro_server_types::jsonrpc::{RpcRequest, RpcResponse};
6+
use tracing::error;
7+
8+
pub struct Connection {
9+
pub sender: Sender<RpcResponse>,
10+
pub receiver: Receiver<RpcRequest>,
11+
io_threads: IoThreads,
12+
}
13+
14+
impl Connection {
15+
pub fn new() -> Self {
16+
let (reader_sender, reader_receiver) = crossbeam_channel::bounded(0);
17+
let (writer_sender, writer_receiver) = crossbeam_channel::bounded(0);
18+
19+
let reader = std::thread::spawn(move || {
20+
let stdin = std::io::stdin();
21+
let mut stdin = stdin.lock();
22+
let mut line = String::new();
23+
24+
loop {
25+
line.clear();
26+
27+
match stdin.read_line(&mut line) {
28+
// End of stream.
29+
Ok(0) => break,
30+
Ok(_) => {}
31+
Err(_) => {
32+
// Report unexpected error.
33+
error!("Reading from stdin failed");
34+
break;
35+
}
36+
};
37+
38+
if line.is_empty() {
39+
continue;
40+
}
41+
42+
let Ok(request) = serde_json::from_str(&line) else {
43+
error!("Deserializing request failed, used input:\n{line}");
44+
break;
45+
};
46+
47+
if reader_sender.send(request).is_err() {
48+
break;
49+
}
50+
}
51+
});
52+
53+
let writer = std::thread::spawn(move || {
54+
let stdout = std::io::stdout();
55+
let mut stdout = stdout.lock();
56+
57+
for response in writer_receiver {
58+
// This should not fail.
59+
let mut res = serde_json::to_vec(&response).unwrap();
60+
61+
res.push(b'\n');
62+
63+
if stdout.write_all(&res).is_err() {
64+
error!("Writing to stdout failed");
65+
break;
66+
}
67+
68+
if stdout.flush().is_err() {
69+
error!("Flushing stdout failed");
70+
break;
71+
}
72+
}
73+
});
74+
75+
let io_threads = IoThreads { reader, writer };
76+
77+
Self {
78+
sender: writer_sender,
79+
receiver: reader_receiver,
80+
io_threads,
81+
}
82+
}
83+
84+
pub fn join(self) {
85+
// There are clones of these used by worker threads. Drop only our refs.
86+
drop(self.sender);
87+
drop(self.receiver);
88+
89+
if let Err(err) = self.io_threads.reader.join() {
90+
std::panic::panic_any(err);
91+
}
92+
if let Err(err) = self.io_threads.writer.join() {
93+
std::panic::panic_any(err);
94+
}
95+
}
96+
}
97+
98+
struct IoThreads {
99+
reader: JoinHandle<()>,
100+
writer: JoinHandle<()>,
101+
}
+10-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
use crate::compiler::plugin::proc_macro::ProcMacroHost;
22
use anyhow::Result;
3+
use connection::Connection;
4+
5+
mod connection;
36

47
pub fn start_proc_macro_server(_proc_macros: ProcMacroHost) -> Result<()> {
5-
unimplemented!()
8+
let connection = Connection::new();
9+
10+
//TODO
11+
12+
connection.join();
13+
14+
Ok(())
615
}

0 commit comments

Comments
 (0)