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. /// Spawns an external process as the proc macro server and returns a client connected to it.
pub fn spawn( pub fn spawn(
process_path: AbsPathBuf, process_path: AbsPathBuf,
args: impl IntoIterator<Item = impl AsRef<OsStr>>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
) -> io::Result<ProcMacroServer> { ) -> io::Result<ProcMacroServer> {
let process = ProcMacroProcessSrv::run(process_path, args)?; let process = ProcMacroProcessSrv::run(process_path, args)?;
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) }) 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)?; let response = self.process.lock().unwrap_or_else(|e| e.into_inner()).send_task(request)?;
match response { match response {
msg::Response::ExpandMacro(it) => Ok(it.map(FlatTree::to_subtree)), 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 }) 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 use crate::msg::flat::FlatTree;
pub const NO_VERSION_CHECK_VERSION: u32 = 0;
pub const API_VERSION: u32 = 1;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum Request { pub enum Request {
ListMacros { dylib_path: PathBuf }, ListMacros { dylib_path: PathBuf },
ExpandMacro(ExpandMacro), ExpandMacro(ExpandMacro),
ApiVersionCheck {},
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum Response { pub enum Response {
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>), ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
ExpandMacro(Result<FlatTree, PanicMessage>), ExpandMacro(Result<FlatTree, PanicMessage>),
ApiVersionCheck(u32),
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]

View file

@ -19,19 +19,45 @@ pub(crate) struct ProcMacroProcessSrv {
_process: Process, _process: Process,
stdin: ChildStdin, stdin: ChildStdin,
stdout: BufReader<ChildStdout>, stdout: BufReader<ChildStdout>,
version: u32,
} }
impl ProcMacroProcessSrv { impl ProcMacroProcessSrv {
pub(crate) fn run( pub(crate) fn run(
process_path: AbsPathBuf, process_path: AbsPathBuf,
args: impl IntoIterator<Item = impl AsRef<OsStr>>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
) -> io::Result<ProcMacroProcessSrv> { ) -> io::Result<ProcMacroProcessSrv> {
let mut process = Process::run(process_path, args)?; let create_srv = || {
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio"); 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( pub(crate) fn find_proc_macros(
@ -44,7 +70,7 @@ impl ProcMacroProcessSrv {
match response { match response {
Response::ListMacros(it) => Ok(it), Response::ListMacros(it) => Ok(it),
Response::ExpandMacro { .. } => { Response::ExpandMacro { .. } | Response::ApiVersionCheck { .. } => {
Err(ServerError { message: "unexpected response".to_string(), io: None }) 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::Response::ListMacros(srv.list_macros(&dylib_path))
} }
msg::Request::ExpandMacro(task) => msg::Response::ExpandMacro(srv.expand(task)), 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)? write_response(res)?
} }