Skip to content

Commit

Permalink
Add Proc macro server
Browse files Browse the repository at this point in the history
commit-id:2ceebe3f
  • Loading branch information
Draggu committed Nov 4, 2024
1 parent 4f3927c commit de2122f
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions scarb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ camino.workspace = true
clap.workspace = true
convert_case.workspace = true
create-output-dir = { path = "../utils/create-output-dir" }
crossbeam-channel = "0.5.13"
data-encoding.workspace = true
deno_task_shell.workspace = true
derive_builder.workspace = true
Expand All @@ -56,6 +57,7 @@ libloading.workspace = true
once_cell.workspace = true
pathdiff.workspace = true
petgraph.workspace = true
scarb-proc-macro-server-types = { path = "../utils/scarb-proc-macro-server-types" }
ra_ap_toolchain.workspace = true
redb.workspace = true
reqwest.workspace = true
Expand Down
101 changes: 101 additions & 0 deletions scarb/src/ops/proc_macro_server/connection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::io::{BufRead, Write};
use std::thread::JoinHandle;

use crossbeam_channel::{Receiver, Sender};
use scarb_proc_macro_server_types::jsonrpc::{RpcRequest, RpcResponse};
use tracing::error;

pub struct Connection {
pub sender: Sender<RpcResponse>,
pub receiver: Receiver<RpcRequest>,
io_threads: IoThreads,
}

impl Connection {
pub fn new() -> Self {
let (reader_sender, reader_receiver) = crossbeam_channel::bounded(0);
let (writer_sender, writer_receiver) = crossbeam_channel::bounded(0);

let reader = std::thread::spawn(move || {
let stdin = std::io::stdin();
let mut stdin = stdin.lock();
let mut line = String::new();

loop {
line.clear();

match stdin.read_line(&mut line) {
// End of stream.
Ok(0) => break,
Ok(_) => {}
Err(_) => {
// Report unexpected error.
error!("Reading from stdin failed");
break;
}
};

if line.is_empty() {
continue;
}

let Ok(request) = serde_json::from_str(&line) else {
error!("Deserializing request failed, used input:\n{line}");
break;
};

if reader_sender.send(request).is_err() {
break;
}
}
});

let writer = std::thread::spawn(move || {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();

for response in writer_receiver {
// This should not fail.
let mut res = serde_json::to_vec(&response).unwrap();

res.push(b'\n');

if stdout.write_all(&res).is_err() {
error!("Writing to stdout failed");
break;
}

if stdout.flush().is_err() {
error!("Flushing stdout failed");
break;
}
}
});

let io_threads = IoThreads { reader, writer };

Self {
sender: writer_sender,
receiver: reader_receiver,
io_threads,
}
}

pub fn join(self) {
// There are clones of these used by worker threads. Drop only our refs.
drop(self.sender);
drop(self.receiver);

if let Err(err) = self.io_threads.reader.join() {
std::panic::panic_any(err);
}
if let Err(err) = self.io_threads.writer.join() {
std::panic::panic_any(err);
}
}
}

struct IoThreads {
reader: JoinHandle<()>,
writer: JoinHandle<()>,
}
11 changes: 10 additions & 1 deletion scarb/src/ops/proc_macro_server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
use crate::compiler::plugin::proc_macro::ProcMacroHost;
use anyhow::Result;
use connection::Connection;

mod connection;

pub fn start_proc_macro_server(proc_macros: ProcMacroHost) -> Result<()> {
unimplemented!()
let connection = Connection::new();

//TODO

connection.join();

Ok(())
}

0 comments on commit de2122f

Please sign in to comment.