]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
:arrow_up: rust-analyzer
[rust.git] / src / tools / rust-analyzer / crates / rust-analyzer / src / reload.rs
index 77125f88f473d1907e50d78966d574250f8f7461..eaab275bc68a41724f20d928d6081e2acbded763 100644 (file)
@@ -303,18 +303,56 @@ fn eq_ignore_build_data<'a>(
         let files_config = self.config.files();
         let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
 
-        if self.proc_macro_client.is_none() {
+        let standalone_server_name =
+            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() {
-                match ProcMacroServer::spawn(path.clone(), args) {
-                    Ok(it) => self.proc_macro_client = Some(it),
-                    Err(err) => {
-                        tracing::error!(
-                            "Failed to run proc_macro_srv from path {}, error: {:?}",
+                self.proc_macro_clients = self
+                    .workspaces
+                    .iter()
+                    .map(|ws| {
+                        let mut args = args.clone();
+                        let mut path = path.clone();
+
+                        if let ProjectWorkspace::Cargo { sysroot, .. } = ws {
+                            tracing::info!("Found a cargo workspace...");
+                            if let Some(sysroot) = sysroot.as_ref() {
+                                tracing::info!("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::info!(
+                                        "And the server exists at {}",
+                                        server_path.display()
+                                    );
+                                    path = server_path;
+                                    args = vec![];
+                                } else {
+                                    tracing::info!(
+                                        "And the server does not exist at {}",
+                                        server_path.display()
+                                    );
+                                }
+                            }
+                        }
+
+                        tracing::info!(
+                            "Using proc-macro server at {} with args {:?}",
                             path.display(),
-                            err
+                            args
                         );
-                    }
-                }
+                        ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
+                            let error = format!(
+                                "Failed to run proc_macro_srv from path {}, error: {:?}",
+                                path.display(),
+                                err
+                            );
+                            tracing::error!(error);
+                            error
+                        })
+                    })
+                    .collect();
             }
         }
 
@@ -331,15 +369,7 @@ fn eq_ignore_build_data<'a>(
 
         // Create crate graph from all the workspaces
         let crate_graph = {
-            let proc_macro_client = self.proc_macro_client.as_ref();
             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 loader = &mut self.loader;
@@ -359,7 +389,18 @@ fn eq_ignore_build_data<'a>(
             };
 
             let mut crate_graph = CrateGraph::default();
-            for ws in self.workspaces.iter() {
+            for (idx, ws) in self.workspaces.iter().enumerate() {
+                let proc_macro_client = match self.proc_macro_clients.get(idx) {
+                    Some(res) => res.as_ref().map_err(|e| &**e),
+                    None => Err("Proc macros are disabled"),
+                };
+                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
@@ -536,14 +577,14 @@ pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
 /// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
 /// with an identity dummy expander.
 pub(crate) fn load_proc_macro(
-    server: Option<&ProcMacroServer>,
+    server: Result<&ProcMacroServer, &str>,
     path: &AbsPath,
     dummy_replace: &[Box<str>],
 ) -> ProcMacroLoadResult {
     let res: Result<Vec<_>, String> = (|| {
         let dylib = MacroDylib::new(path.to_path_buf())
             .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}"))?;
         if vec.is_empty() {
             return Err("proc macro library returned no proc macros".to_string());