diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs index 04a4d7ca587..55754325f6f 100644 --- a/crates/proc_macro_api/src/lib.rs +++ b/crates/proc_macro_api/src/lib.rs @@ -26,58 +26,10 @@ pub use rpc::{ }; pub use version::{read_dylib_info, RustCInfo}; -#[derive(Debug, Clone)] -pub struct ProcMacroProcessExpander { - process: Arc>, - dylib_path: AbsPathBuf, - name: SmolStr, - kind: ProcMacroKind, -} - -impl Eq for ProcMacroProcessExpander {} -impl PartialEq for ProcMacroProcessExpander { - fn eq(&self, other: &Self) -> bool { - self.name == other.name - && self.kind == other.kind - && self.dylib_path == other.dylib_path - && Arc::ptr_eq(&self.process, &other.process) - } -} - -impl ProcMacroProcessExpander { - pub fn name(&self) -> &str { - &self.name - } - - pub fn kind(&self) -> ProcMacroKind { - self.kind - } - - pub fn expand( - &self, - subtree: &Subtree, - attr: Option<&Subtree>, - env: Vec<(String, String)>, - ) -> Result { - let task = ExpansionTask { - macro_body: FlatTree::new(subtree), - macro_name: self.name.to_string(), - attributes: attr.map(FlatTree::new), - lib: self.dylib_path.to_path_buf().into(), - env, - }; - - let result: ExpansionResult = self - .process - .lock() - .unwrap_or_else(|e| e.into_inner()) - .send_task(msg::Request::ExpansionMacro(task))?; - Ok(result.expansion.to_subtree()) - } -} - +/// A handle to an external process which load dylibs with macros (.so or .dll) +/// and runs actual macro expansion functions. #[derive(Debug)] -pub struct ProcMacroClient { +pub struct ProcMacroServer { /// Currently, the proc macro process expands all procedural macros sequentially. /// /// That means that concurrent salsa requests may block each other when expanding proc macros, @@ -87,17 +39,39 @@ pub struct ProcMacroClient { process: Arc>, } -impl ProcMacroClient { +/// A handle to a specific macro (a `#[proc_macro]` annotated function). +/// +/// It exists withing a context of a specific [`ProcMacroProcess`] -- currently +/// we share a single expander process for all macros. +#[derive(Debug, Clone)] +pub struct ProcMacro { + process: Arc>, + dylib_path: AbsPathBuf, + name: SmolStr, + kind: ProcMacroKind, +} + +impl Eq for ProcMacro {} +impl PartialEq for ProcMacro { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + && self.kind == other.kind + && self.dylib_path == other.dylib_path + && Arc::ptr_eq(&self.process, &other.process) + } +} + +impl ProcMacroServer { /// Spawns an external process as the proc macro server and returns a client connected to it. - pub fn extern_process( + pub fn spawn( process_path: AbsPathBuf, args: impl IntoIterator>, - ) -> io::Result { + ) -> io::Result { let process = ProcMacroProcessSrv::run(process_path, args)?; - Ok(ProcMacroClient { process: Arc::new(Mutex::new(process)) }) + Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) }) } - pub fn by_dylib_path(&self, dylib_path: &AbsPath) -> Vec { + pub fn load_dylib(&self, dylib_path: &AbsPath) -> Vec { let _p = profile::span("ProcMacroClient::by_dylib_path"); match version::read_dylib_info(dylib_path) { Ok(info) => { @@ -129,7 +103,7 @@ impl ProcMacroClient { macros .into_iter() - .map(|(name, kind)| ProcMacroProcessExpander { + .map(|(name, kind)| ProcMacro { process: self.process.clone(), name: name.into(), kind, @@ -138,3 +112,35 @@ impl ProcMacroClient { .collect() } } + +impl ProcMacro { + pub fn name(&self) -> &str { + &self.name + } + + pub fn kind(&self) -> ProcMacroKind { + self.kind + } + + pub fn expand( + &self, + subtree: &Subtree, + attr: Option<&Subtree>, + env: Vec<(String, String)>, + ) -> Result { + let task = ExpansionTask { + macro_body: FlatTree::new(subtree), + macro_name: self.name.to_string(), + attributes: attr.map(FlatTree::new), + lib: self.dylib_path.to_path_buf().into(), + env, + }; + + let result: ExpansionResult = self + .process + .lock() + .unwrap_or_else(|e| e.into_inner()) + .send_task(msg::Request::ExpansionMacro(task))?; + Ok(result.expansion.to_subtree()) + } +} diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 9559d352a7a..d60861a6274 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs @@ -7,7 +7,7 @@ use crossbeam_channel::{unbounded, Receiver}; use hir::db::DefDatabase; use ide::{AnalysisHost, Change}; use ide_db::base_db::CrateGraph; -use proc_macro_api::ProcMacroClient; +use proc_macro_api::ProcMacroServer; use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace}; use vfs::{loader::Handle, AbsPath, AbsPathBuf}; @@ -28,7 +28,7 @@ pub fn load_workspace_at( cargo_config: &CargoConfig, load_config: &LoadCargoConfig, progress: &dyn Fn(String), -) -> Result<(AnalysisHost, vfs::Vfs, Option)> { +) -> Result<(AnalysisHost, vfs::Vfs, Option)> { let root = AbsPathBuf::assert(std::env::current_dir()?.join(root)); let root = ProjectManifest::discover_single(&root)?; let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?; @@ -49,7 +49,7 @@ pub fn load_workspace_at( pub fn load_workspace( ws: ProjectWorkspace, load_config: &LoadCargoConfig, -) -> Result<(AnalysisHost, vfs::Vfs, Option)> { +) -> Result<(AnalysisHost, vfs::Vfs, Option)> { let (sender, receiver) = unbounded(); let mut vfs = vfs::Vfs::default(); let mut loader = { @@ -60,7 +60,7 @@ pub fn load_workspace( let proc_macro_client = if load_config.with_proc_macro { let path = AbsPathBuf::assert(std::env::current_exe()?); - Some(ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap()) + Some(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap()) } else { None }; diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index f2a40cb1992..19ddd7c717d 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -11,7 +11,7 @@ use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId}; use ide_db::base_db::CrateId; use lsp_types::{SemanticTokens, Url}; use parking_lot::{Mutex, RwLock}; -use proc_macro_api::ProcMacroClient; +use proc_macro_api::ProcMacroServer; use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts}; use rustc_hash::FxHashMap; use vfs::AnchoredPathBuf; @@ -60,7 +60,7 @@ pub(crate) struct GlobalState { pub(crate) shutdown_requested: bool, pub(crate) last_reported_status: Option, pub(crate) source_root_config: SourceRootConfig, - pub(crate) proc_macro_client: Option, + pub(crate) proc_macro_client: Option, pub(crate) flycheck: Vec, pub(crate) flycheck_sender: Sender, diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index ad4d81ada7a..7e419ba839d 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -7,7 +7,7 @@ use ide::Change; use ide_db::base_db::{ CrateGraph, Env, ProcMacro, ProcMacroExpander, ProcMacroKind, SourceRoot, VfsPath, }; -use proc_macro_api::ProcMacroClient; +use proc_macro_api::ProcMacroServer; use project_model::{ProjectWorkspace, WorkspaceBuildScripts}; use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; @@ -329,7 +329,7 @@ impl GlobalState { if self.proc_macro_client.is_none() { self.proc_macro_client = match self.config.proc_macro_srv() { None => None, - Some((path, args)) => match ProcMacroClient::extern_process(path.clone(), args) { + Some((path, args)) => match ProcMacroServer::spawn(path.clone(), args) { Ok(it) => Some(it), Err(err) => { tracing::error!( @@ -556,15 +556,15 @@ impl SourceRootConfig { } } -pub(crate) fn load_proc_macro(client: Option<&ProcMacroClient>, path: &AbsPath) -> Vec { +pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath) -> Vec { return client - .map(|it| it.by_dylib_path(path)) + .map(|it| it.load_dylib(path)) .unwrap_or_default() .into_iter() .map(expander_to_proc_macro) .collect(); - fn expander_to_proc_macro(expander: proc_macro_api::ProcMacroProcessExpander) -> ProcMacro { + fn expander_to_proc_macro(expander: proc_macro_api::ProcMacro) -> ProcMacro { let name = expander.name().into(); let kind = match expander.kind() { proc_macro_api::ProcMacroKind::CustomDerive => ProcMacroKind::CustomDerive, @@ -576,7 +576,7 @@ pub(crate) fn load_proc_macro(client: Option<&ProcMacroClient>, path: &AbsPath) } #[derive(Debug)] - struct Expander(proc_macro_api::ProcMacroProcessExpander); + struct Expander(proc_macro_api::ProcMacro); impl ProcMacroExpander for Expander { fn expand(