]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/reload.rs
Replaced fold with for loop
[rust.git] / crates / rust-analyzer / src / reload.rs
index f7ec3707c0aecb152e8bc304ac5bd7be3c04a6da..eecc83e02ac499d4b0e40156c4d1db06e3f73002 100644 (file)
@@ -10,6 +10,7 @@
 };
 use proc_macro_api::{MacroDylib, ProcMacroServer};
 use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
+use syntax::SmolStr;
 use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
 
 use crate::{
@@ -66,6 +67,11 @@ pub(crate) fn current_status(&self) -> lsp_ext::ServerStatusParams {
             message: None,
         };
 
+        if self.proc_macro_changed {
+            status.health = lsp_ext::Health::Warning;
+            status.message =
+                Some("Reload required due to source changes of a procedural macro.".into())
+        }
         if let Some(error) = self.fetch_build_data_error() {
             status.health = lsp_ext::Health::Warning;
             status.message = Some(error)
@@ -211,7 +217,7 @@ fn eq_ignore_build_data<'a>(
 
         if same_workspaces {
             let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
-            if Arc::ptr_eq(&workspaces, &self.workspaces) {
+            if Arc::ptr_eq(workspaces, &self.workspaces) {
                 let workspaces = workspaces
                     .iter()
                     .cloned()
@@ -236,38 +242,33 @@ fn eq_ignore_build_data<'a>(
         }
 
         if let FilesWatcher::Client = self.config.files().watcher {
-            if self.config.did_change_watched_files_dynamic_registration() {
-                let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
-                    watchers: self
-                        .workspaces
-                        .iter()
-                        .flat_map(|ws| ws.to_roots())
-                        .filter(|it| it.is_local)
-                        .flat_map(|root| {
-                            root.include.into_iter().flat_map(|it| {
-                                [
-                                    format!("{}/**/*.rs", it.display()),
-                                    format!("{}/**/Cargo.toml", it.display()),
-                                    format!("{}/**/Cargo.lock", it.display()),
-                                ]
-                            })
-                        })
-                        .map(|glob_pattern| lsp_types::FileSystemWatcher {
-                            glob_pattern,
-                            kind: None,
+            let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
+                watchers: self
+                    .workspaces
+                    .iter()
+                    .flat_map(|ws| ws.to_roots())
+                    .filter(|it| it.is_local)
+                    .flat_map(|root| {
+                        root.include.into_iter().flat_map(|it| {
+                            [
+                                format!("{}/**/*.rs", it.display()),
+                                format!("{}/**/Cargo.toml", it.display()),
+                                format!("{}/**/Cargo.lock", it.display()),
+                            ]
                         })
-                        .collect(),
-                };
-                let registration = lsp_types::Registration {
-                    id: "workspace/didChangeWatchedFiles".to_string(),
-                    method: "workspace/didChangeWatchedFiles".to_string(),
-                    register_options: Some(serde_json::to_value(registration_options).unwrap()),
-                };
-                self.send_request::<lsp_types::request::RegisterCapability>(
-                    lsp_types::RegistrationParams { registrations: vec![registration] },
-                    |_, _| (),
-                );
-            }
+                    })
+                    .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
+                    .collect(),
+            };
+            let registration = lsp_types::Registration {
+                id: "workspace/didChangeWatchedFiles".to_string(),
+                method: "workspace/didChangeWatchedFiles".to_string(),
+                register_options: Some(serde_json::to_value(registration_options).unwrap()),
+            };
+            self.send_request::<lsp_types::request::RegisterCapability>(
+                lsp_types::RegistrationParams { registrations: vec![registration] },
+                |_, _| (),
+            );
         }
 
         let mut change = Change::new();
@@ -306,8 +307,9 @@ 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 mut load_proc_macro =
-                move |path: &AbsPath| load_proc_macro(proc_macro_client, path);
+            let mut load_proc_macro = move |path: &AbsPath, dummy_replace: &_| {
+                load_proc_macro(proc_macro_client, path, dummy_replace)
+            };
 
             let vfs = &mut self.vfs.write().0;
             let loader = &mut self.loader;
@@ -328,7 +330,11 @@ fn eq_ignore_build_data<'a>(
 
             let mut crate_graph = CrateGraph::default();
             for ws in self.workspaces.iter() {
-                crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
+                crate_graph.extend(ws.to_crate_graph(
+                    self.config.dummy_replacements(),
+                    &mut load_proc_macro,
+                    &mut load,
+                ));
             }
             crate_graph
         };
@@ -417,7 +423,7 @@ fn reload_flycheck(&mut self) {
                     id,
                     Box::new(move |msg| sender.send(msg).unwrap()),
                     config.clone(),
-                    root.to_path_buf().into(),
+                    root.to_path_buf(),
                 )
             })
             .collect();
@@ -505,7 +511,13 @@ pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
     }
 }
 
-pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath) -> Vec<ProcMacro> {
+/// 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(
+    client: Option<&ProcMacroServer>,
+    path: &AbsPath,
+    dummy_replace: &[Box<str>],
+) -> Vec<ProcMacro> {
     let dylib = match MacroDylib::new(path.to_path_buf()) {
         Ok(it) => it,
         Err(err) => {
@@ -532,17 +544,25 @@ pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath)
                 Vec::new()
             }
         })
-        .map(expander_to_proc_macro)
+        .map(|expander| expander_to_proc_macro(expander, dummy_replace))
         .collect();
 
-    fn expander_to_proc_macro(expander: proc_macro_api::ProcMacro) -> ProcMacro {
-        let name = expander.name().into();
+    fn expander_to_proc_macro(
+        expander: proc_macro_api::ProcMacro,
+        dummy_replace: &[Box<str>],
+    ) -> ProcMacro {
+        let name = SmolStr::from(expander.name());
         let kind = match expander.kind() {
             proc_macro_api::ProcMacroKind::CustomDerive => ProcMacroKind::CustomDerive,
             proc_macro_api::ProcMacroKind::FuncLike => ProcMacroKind::FuncLike,
             proc_macro_api::ProcMacroKind::Attr => ProcMacroKind::Attr,
         };
-        let expander = Arc::new(Expander(expander));
+        let expander: Arc<dyn ProcMacroExpander> =
+            if dummy_replace.iter().any(|replace| &**replace == name) {
+                Arc::new(DummyExpander)
+            } else {
+                Arc::new(Expander(expander))
+            };
         ProcMacro { name, kind, expander }
     }
 
@@ -564,6 +584,21 @@ fn expand(
             }
         }
     }
+
+    /// Dummy identity expander, used for proc-macros that are deliberately ignored by the user.
+    #[derive(Debug)]
+    struct DummyExpander;
+
+    impl ProcMacroExpander for DummyExpander {
+        fn expand(
+            &self,
+            subtree: &tt::Subtree,
+            _: Option<&tt::Subtree>,
+            _: &Env,
+        ) -> Result<tt::Subtree, ProcMacroExpansionError> {
+            Ok(subtree.clone())
+        }
+    }
 }
 
 pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {