diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index ee0b9e6d50..e6ddfd580c 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -322,7 +322,7 @@ fn load_crate_graph( break; } } - vfs::loader::Message::Loaded { files } => { + vfs::loader::Message::Loaded { files } | vfs::loader::Message::Changed { files } => { for (path, contents) in files { vfs.set_file_contents(path.into(), contents); } diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 00cc7c30ee..c04eddc56f 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -1398,7 +1398,7 @@ fn sysroot_to_crate_graph( let public_deps = SysrootPublicDeps { deps: sysroot .public_deps() - .map(|(name, idx, prelude)| (name, sysroot_crates[&idx], prelude)) + .filter_map(|(name, idx, prelude)| Some((name, *sysroot_crates.get(&idx)?, prelude))) .collect::>(), }; diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index da132f9396..c4a29e0cbb 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -218,7 +218,7 @@ impl GlobalState { let _p = profile::span("GlobalState::process_changes"); let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); - let (change, modified_files, workspace_structure_change) = { + let (change, modified_rust_files, workspace_structure_change) = { let mut change = Change::new(); let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); @@ -254,8 +254,8 @@ impl GlobalState { *change = Create(new); *just_created = true; } - // shouldn't occur, but collapse into `Modify` - (Modify(prev), _, Create(new)) => *prev = new, + // shouldn't occur, but keep the Create + (prev @ Modify(_), _, new @ Create(_)) => *prev = new, } } Entry::Vacant(v) => { @@ -276,7 +276,7 @@ impl GlobalState { // A file was added or deleted let mut has_structure_changes = false; let mut bytes = vec![]; - let mut modified_files = vec![]; + let mut modified_rust_files = vec![]; for file in changed_files { let vfs_path = &vfs.file_path(file.file_id); if let Some(path) = vfs_path.as_path() { @@ -288,8 +288,8 @@ impl GlobalState { has_structure_changes = true; workspace_structure_change = Some((path, self.crate_graph_file_dependencies.contains(vfs_path))); - } else { - modified_files.push(file.file_id); + } else if path.extension() == Some("rs".as_ref()) { + modified_rust_files.push(file.file_id); } } @@ -324,7 +324,7 @@ impl GlobalState { let roots = self.source_root_config.partition(vfs); change.set_roots(roots); } - (change, modified_files, workspace_structure_change) + (change, modified_rust_files, workspace_structure_change) }; self.analysis_host.apply_change(change); @@ -339,7 +339,7 @@ impl GlobalState { force_crate_graph_reload, ); } - self.proc_macro_changed = modified_files.into_iter().any(|file_id| { + self.proc_macro_changed = modified_rust_files.into_iter().any(|file_id| { let crates = raw_database.relevant_crates(file_id); let crate_graph = raw_database.crate_graph(); diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index c0d35498c6..ce69d61225 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -101,8 +101,10 @@ pub(crate) fn handle_did_change_text_document( params.content_changes, ) .into_bytes(); - *data = new_contents.clone(); - state.vfs.write().0.set_file_contents(path, Some(new_contents)); + if *data != new_contents { + *data = new_contents.clone(); + state.vfs.write().0.set_file_contents(path, Some(new_contents)); + } } Ok(()) } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 356c332f90..ca7893faf5 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -571,15 +571,18 @@ impl GlobalState { } fn handle_vfs_msg(&mut self, message: vfs::loader::Message) { + let is_changed = matches!(message, vfs::loader::Message::Changed { .. }); match message { - vfs::loader::Message::Loaded { files } => { + vfs::loader::Message::Changed { files } | vfs::loader::Message::Loaded { files } => { let vfs = &mut self.vfs.write().0; for (path, contents) in files { let path = VfsPath::from(path); // if the file is in mem docs, it's managed by the client via notifications // so only set it if its not in there if !self.mem_docs.contains(&path) { - vfs.set_file_contents(path, contents); + if is_changed || vfs.file_id(&path).is_none() { + vfs.set_file_contents(path, contents); + } } } } diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index f76ff7db38..78411e2d58 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -835,7 +835,7 @@ fn main() { #[cfg(any(feature = "sysroot-abi", rust_analyzer))] fn resolve_proc_macro() { use expect_test::expect; - if skip_slow_tests() || true { + if skip_slow_tests() { return; } diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index 0306504371..19b34ffe6b 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs @@ -160,7 +160,7 @@ impl NotifyActor { Some((path, contents)) }) .collect(); - self.send(loader::Message::Loaded { files }); + self.send(loader::Message::Changed { files }); } } } diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs index e2d74782ae..89a544c81d 100644 --- a/crates/vfs/src/loader.rs +++ b/crates/vfs/src/loader.rs @@ -51,6 +51,8 @@ pub enum Message { Progress { n_total: usize, n_done: usize, config_version: u32 }, /// The handle loaded the following files' content. Loaded { files: Vec<(AbsPathBuf, Option>)> }, + /// The handle loaded the following files' content. + Changed { files: Vec<(AbsPathBuf, Option>)> }, } /// Type that will receive [`Messages`](Message) from a [`Handle`]. @@ -199,6 +201,9 @@ impl fmt::Debug for Message { Message::Loaded { files } => { f.debug_struct("Loaded").field("n_files", &files.len()).finish() } + Message::Changed { files } => { + f.debug_struct("Changed").field("n_files", &files.len()).finish() + } Message::Progress { n_total, n_done, config_version } => f .debug_struct("Progress") .field("n_total", n_total)