diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 5d99d2fb1193d..dfef6f014ca5c 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -7,7 +7,7 @@ //! configure the server itself, feature flags are passed into analysis, and //! tweak things like automatic insertion of `()` in completions. -use std::{ffi::OsString, fmt, iter, path::PathBuf}; +use std::{fmt, iter, path::PathBuf}; use flycheck::FlycheckConfig; use ide::{ @@ -977,15 +977,17 @@ impl Config { self.data.lru_capacity } - pub fn proc_macro_srv(&self) -> Option<(AbsPathBuf, Vec)> { + pub fn proc_macro_srv(&self) -> Option<(AbsPathBuf, /* is path explicitly set */ bool)> { if !self.data.procMacro_enable { return None; } - let path = match &self.data.procMacro_server { - Some(it) => self.root_path.join(it), - None => AbsPathBuf::assert(std::env::current_exe().ok()?), - }; - Some((path, vec!["proc-macro".into()])) + Some(match &self.data.procMacro_server { + Some(it) => ( + AbsPathBuf::try_from(it.clone()).unwrap_or_else(|path| self.root_path.join(path)), + true, + ), + None => (AbsPathBuf::assert(std::env::current_exe().ok()?), false), + }) } pub fn dummy_replacements(&self) -> &FxHashMap, Box<[Box]>> { diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index e7f7972e9abb1..f873489394462 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -306,41 +306,50 @@ impl GlobalState { format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX); if self.proc_macro_clients.is_empty() { - if let Some((path, args)) = self.config.proc_macro_srv() { + if let Some((path, path_manually_set)) = self.config.proc_macro_srv() { tracing::info!("Spawning proc-macro servers"); self.proc_macro_clients = self .workspaces .iter() .map(|ws| { - let mut args = args.clone(); - let mut path = path.clone(); - - if let ProjectWorkspace::Cargo { sysroot, .. } - | ProjectWorkspace::Json { sysroot, .. } = ws - { - tracing::debug!("Found a cargo workspace..."); - if let Some(sysroot) = sysroot.as_ref() { - tracing::debug!("Found a cargo workspace with a sysroot..."); - let server_path = - sysroot.root().join("libexec").join(&standalone_server_name); - if std::fs::metadata(&server_path).is_ok() { - tracing::debug!( - "And the server exists at {}", - server_path.display() - ); - path = server_path; - args = vec![]; - } else { - tracing::debug!( - "And the server does not exist at {}", - server_path.display() - ); + let (path, args) = if path_manually_set { + tracing::debug!( + "Pro-macro server path explicitly set: {}", + path.display() + ); + (path.clone(), vec![]) + } else { + let mut sysroot_server = None; + if let ProjectWorkspace::Cargo { sysroot, .. } + | ProjectWorkspace::Json { sysroot, .. } = ws + { + if let Some(sysroot) = sysroot.as_ref() { + let server_path = sysroot + .root() + .join("libexec") + .join(&standalone_server_name); + if std::fs::metadata(&server_path).is_ok() { + tracing::debug!( + "Sysroot proc-macro server exists at {}", + server_path.display() + ); + sysroot_server = Some(server_path); + } else { + tracing::debug!( + "Sysroot proc-macro server does not exist at {}", + server_path.display() + ); + } } } - } + sysroot_server.map_or_else( + || (path.clone(), vec!["proc-macro".to_owned()]), + |path| (path, vec![]), + ) + }; tracing::info!(?args, "Using proc-macro server at {}", path.display(),); - ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| { + ProcMacroServer::spawn(path.clone(), args).map_err(|err| { let error = format!( "Failed to run proc-macro server from path {}, error: {:?}", path.display(),