Implement proc-macro-api versioning

This commit is contained in:
Lukas Wirth 2023-02-01 11:04:20 +01:00
parent 41a46a78f2
commit c40b0895f0
4 changed files with 42 additions and 8 deletions

View File

@ -115,7 +115,7 @@ impl ProcMacroServer {
/// Spawns an external process as the proc macro server and returns a client connected to it.
pub fn spawn(
process_path: AbsPathBuf,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
) -> io::Result<ProcMacroServer> {
let process = ProcMacroProcessSrv::run(process_path, args)?;
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
@ -174,7 +174,7 @@ impl ProcMacro {
let response = self.process.lock().unwrap_or_else(|e| e.into_inner()).send_task(request)?;
match response {
msg::Response::ExpandMacro(it) => Ok(it.map(FlatTree::to_subtree)),
msg::Response::ListMacros { .. } => {
msg::Response::ListMacros(..) | msg::Response::ApiVersionCheck(..) => {
Err(ServerError { message: "unexpected response".to_string(), io: None })
}
}

View File

@ -12,16 +12,21 @@ use crate::ProcMacroKind;
pub use crate::msg::flat::FlatTree;
pub const NO_VERSION_CHECK_VERSION: u32 = 0;
pub const API_VERSION: u32 = 1;
#[derive(Debug, Serialize, Deserialize)]
pub enum Request {
ListMacros { dylib_path: PathBuf },
ExpandMacro(ExpandMacro),
ApiVersionCheck {},
}
#[derive(Debug, Serialize, Deserialize)]
pub enum Response {
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
ExpandMacro(Result<FlatTree, PanicMessage>),
ApiVersionCheck(u32),
}
#[derive(Debug, Serialize, Deserialize)]

View File

@ -19,19 +19,45 @@ pub(crate) struct ProcMacroProcessSrv {
_process: Process,
stdin: ChildStdin,
stdout: BufReader<ChildStdout>,
version: u32,
}
impl ProcMacroProcessSrv {
pub(crate) fn run(
process_path: AbsPathBuf,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
) -> io::Result<ProcMacroProcessSrv> {
let mut process = Process::run(process_path, args)?;
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
let create_srv = || {
let mut process = Process::run(process_path.clone(), args.clone())?;
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
let srv = ProcMacroProcessSrv { _process: process, stdin, stdout };
io::Result::Ok(ProcMacroProcessSrv { _process: process, stdin, stdout, version: 0 })
};
let mut srv = create_srv()?;
tracing::info!("sending version check");
match srv.version_check() {
Ok(v) => {
tracing::info!("got version {v}");
srv.version = v;
Ok(srv)
}
Err(e) => {
tracing::info!(%e, "proc-macro version check failed, restarting and assuming version 0");
create_srv()
}
}
}
Ok(srv)
pub(crate) fn version_check(&mut self) -> Result<u32, ServerError> {
let request = Request::ApiVersionCheck {};
let response = self.send_task(request)?;
match response {
Response::ApiVersionCheck(version) => Ok(version),
Response::ExpandMacro { .. } | Response::ListMacros { .. } => {
Err(ServerError { message: "unexpected response".to_string(), io: None })
}
}
}
pub(crate) fn find_proc_macros(
@ -44,7 +70,7 @@ impl ProcMacroProcessSrv {
match response {
Response::ListMacros(it) => Ok(it),
Response::ExpandMacro { .. } => {
Response::ExpandMacro { .. } | Response::ApiVersionCheck { .. } => {
Err(ServerError { message: "unexpected response".to_string(), io: None })
}
}

View File

@ -15,6 +15,9 @@ pub fn run() -> io::Result<()> {
msg::Response::ListMacros(srv.list_macros(&dylib_path))
}
msg::Request::ExpandMacro(task) => msg::Response::ExpandMacro(srv.expand(task)),
msg::Request::ApiVersionCheck {} => {
msg::Response::ApiVersionCheck(proc_macro_api::msg::API_VERSION)
}
};
write_response(res)?
}