Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #16319 - Veykril:no-double-load, r=Veykril
fix: Differentiate between vfs config load and file changed events Kind of fixes https://github.com/rust-lang/rust-analyzer/issues/14730 in a pretty bad way. We need to rethink the vfs-notify layer entirely. For a decent fix.
bors 2024-01-09
parent e3575a8 · parent e1c6748 · commit 9e34e64
-rw-r--r--crates/load-cargo/src/lib.rs2
-rw-r--r--crates/project-model/src/workspace.rs2
-rw-r--r--crates/rust-analyzer/src/global_state.rs16
-rw-r--r--crates/rust-analyzer/src/handlers/notification.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop.rs7
-rw-r--r--crates/rust-analyzer/tests/slow-tests/main.rs2
-rw-r--r--crates/vfs-notify/src/lib.rs2
-rw-r--r--crates/vfs/src/loader.rs5
8 files changed, 26 insertions, 16 deletions
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::<Vec<_>>(),
};
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<Vec<u8>>)> },
+ /// The handle loaded the following files' content.
+ Changed { files: Vec<(AbsPathBuf, Option<Vec<u8>>)> },
}
/// 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)