mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Auto merge of #12856 - Veykril:multi-proc-srv, r=Veykril
feat: Spawn a proc-macro-srv instance per workspace cc https://github.com/rust-lang/rust-analyzer/issues/12855 The idea is to have each server be spawned with the appropriate toolchain, that way workspaces with differing toolchains shouldn't suffer from proc-macro abi mismatches.
This commit is contained in:
commit
ac86b8edff
4 changed files with 31 additions and 28 deletions
|
@ -60,9 +60,9 @@ pub fn load_workspace(
|
||||||
|
|
||||||
let proc_macro_client = if load_config.with_proc_macro {
|
let proc_macro_client = if load_config.with_proc_macro {
|
||||||
let path = AbsPathBuf::assert(std::env::current_exe()?);
|
let path = AbsPathBuf::assert(std::env::current_exe()?);
|
||||||
Some(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
|
Ok(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
Err("proc macro server not started".to_owned())
|
||||||
};
|
};
|
||||||
|
|
||||||
let crate_graph = ws.to_crate_graph(
|
let crate_graph = ws.to_crate_graph(
|
||||||
|
@ -89,7 +89,7 @@ pub fn load_workspace(
|
||||||
if load_config.prefill_caches {
|
if load_config.prefill_caches {
|
||||||
host.analysis().parallel_prime_caches(1, |_| {})?;
|
host.analysis().parallel_prime_caches(1, |_| {})?;
|
||||||
}
|
}
|
||||||
Ok((host, vfs, proc_macro_client))
|
Ok((host, vfs, proc_macro_client.ok()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_crate_graph(
|
fn load_crate_graph(
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub(crate) struct GlobalState {
|
||||||
pub(crate) proc_macro_changed: bool,
|
pub(crate) proc_macro_changed: bool,
|
||||||
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
|
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
|
||||||
pub(crate) source_root_config: SourceRootConfig,
|
pub(crate) source_root_config: SourceRootConfig,
|
||||||
pub(crate) proc_macro_client: Option<ProcMacroServer>,
|
pub(crate) proc_macro_clients: Vec<Result<ProcMacroServer, String>>,
|
||||||
|
|
||||||
pub(crate) flycheck: Vec<FlycheckHandle>,
|
pub(crate) flycheck: Vec<FlycheckHandle>,
|
||||||
pub(crate) flycheck_sender: Sender<flycheck::Message>,
|
pub(crate) flycheck_sender: Sender<flycheck::Message>,
|
||||||
|
@ -151,7 +151,7 @@ impl GlobalState {
|
||||||
proc_macro_changed: false,
|
proc_macro_changed: false,
|
||||||
last_reported_status: None,
|
last_reported_status: None,
|
||||||
source_root_config: SourceRootConfig::default(),
|
source_root_config: SourceRootConfig::default(),
|
||||||
proc_macro_client: None,
|
proc_macro_clients: vec![],
|
||||||
|
|
||||||
flycheck: Vec::new(),
|
flycheck: Vec::new(),
|
||||||
flycheck_sender,
|
flycheck_sender,
|
||||||
|
|
|
@ -44,7 +44,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<()> {
|
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<()> {
|
||||||
state.proc_macro_client = None;
|
state.proc_macro_clients.clear();
|
||||||
state.proc_macro_changed = false;
|
state.proc_macro_changed = false;
|
||||||
state.fetch_workspaces_queue.request_op("reload workspace request".to_string());
|
state.fetch_workspaces_queue.request_op("reload workspace request".to_string());
|
||||||
state.fetch_build_data_queue.request_op("reload workspace request".to_string());
|
state.fetch_build_data_queue.request_op("reload workspace request".to_string());
|
||||||
|
|
|
@ -303,18 +303,21 @@ impl GlobalState {
|
||||||
let files_config = self.config.files();
|
let files_config = self.config.files();
|
||||||
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
|
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
|
||||||
|
|
||||||
if self.proc_macro_client.is_none() {
|
if self.proc_macro_clients.is_empty() {
|
||||||
if let Some((path, args)) = self.config.proc_macro_srv() {
|
if let Some((path, args)) = self.config.proc_macro_srv() {
|
||||||
match ProcMacroServer::spawn(path.clone(), args) {
|
self.proc_macro_clients = (0..self.workspaces.len())
|
||||||
Ok(it) => self.proc_macro_client = Some(it),
|
.map(|_| {
|
||||||
Err(err) => {
|
ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
|
||||||
tracing::error!(
|
let error = format!(
|
||||||
"Failed to run proc_macro_srv from path {}, error: {:?}",
|
"Failed to run proc_macro_srv from path {}, error: {:?}",
|
||||||
path.display(),
|
path.display(),
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
}
|
tracing::error!(error);
|
||||||
}
|
error
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,15 +334,7 @@ impl GlobalState {
|
||||||
|
|
||||||
// Create crate graph from all the workspaces
|
// Create crate graph from all the workspaces
|
||||||
let crate_graph = {
|
let crate_graph = {
|
||||||
let proc_macro_client = self.proc_macro_client.as_ref();
|
|
||||||
let dummy_replacements = self.config.dummy_replacements();
|
let dummy_replacements = self.config.dummy_replacements();
|
||||||
let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
|
|
||||||
load_proc_macro(
|
|
||||||
proc_macro_client,
|
|
||||||
path,
|
|
||||||
dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let vfs = &mut self.vfs.write().0;
|
let vfs = &mut self.vfs.write().0;
|
||||||
let loader = &mut self.loader;
|
let loader = &mut self.loader;
|
||||||
|
@ -359,7 +354,15 @@ impl GlobalState {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut crate_graph = CrateGraph::default();
|
let mut crate_graph = CrateGraph::default();
|
||||||
for ws in self.workspaces.iter() {
|
for (idx, ws) in self.workspaces.iter().enumerate() {
|
||||||
|
let proc_macro_client = self.proc_macro_clients[idx].as_ref();
|
||||||
|
let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
|
||||||
|
load_proc_macro(
|
||||||
|
proc_macro_client,
|
||||||
|
path,
|
||||||
|
dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
|
||||||
|
)
|
||||||
|
};
|
||||||
crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
|
crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
|
||||||
}
|
}
|
||||||
crate_graph
|
crate_graph
|
||||||
|
@ -536,14 +539,14 @@ impl SourceRootConfig {
|
||||||
/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
|
/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
|
||||||
/// with an identity dummy expander.
|
/// with an identity dummy expander.
|
||||||
pub(crate) fn load_proc_macro(
|
pub(crate) fn load_proc_macro(
|
||||||
server: Option<&ProcMacroServer>,
|
server: Result<&ProcMacroServer, &String>,
|
||||||
path: &AbsPath,
|
path: &AbsPath,
|
||||||
dummy_replace: &[Box<str>],
|
dummy_replace: &[Box<str>],
|
||||||
) -> ProcMacroLoadResult {
|
) -> ProcMacroLoadResult {
|
||||||
let res: Result<Vec<_>, String> = (|| {
|
let res: Result<Vec<_>, String> = (|| {
|
||||||
let dylib = MacroDylib::new(path.to_path_buf())
|
let dylib = MacroDylib::new(path.to_path_buf())
|
||||||
.map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
|
.map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
|
||||||
let server = server.ok_or_else(|| format!("Proc-macro server not started"))?;
|
let server = server.map_err(ToOwned::to_owned)?;
|
||||||
let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
|
let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
|
||||||
if vec.is_empty() {
|
if vec.is_empty() {
|
||||||
return Err("proc macro library returned no proc macros".to_string());
|
return Err("proc macro library returned no proc macros".to_string());
|
||||||
|
|
Loading…
Reference in a new issue