Tweak change collapsing
This commit is contained in:
parent
dd673eea33
commit
deff5f22f6
@ -3,7 +3,7 @@
|
||||
//!
|
||||
//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
|
||||
|
||||
use std::{mem, sync::Arc, time::Instant};
|
||||
use std::{sync::Arc, time::Instant};
|
||||
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use flycheck::FlycheckHandle;
|
||||
@ -179,10 +179,9 @@ impl GlobalState {
|
||||
|
||||
pub(crate) fn process_changes(&mut self) -> bool {
|
||||
let _p = profile::span("GlobalState::process_changes");
|
||||
// A file was added or deleted
|
||||
let mut has_structure_changes = false;
|
||||
let mut workspace_structure_change = None;
|
||||
|
||||
let mut file_changes = FxHashMap::default();
|
||||
let (change, changed_files) = {
|
||||
let mut change = Change::new();
|
||||
let (vfs, line_endings_map) = &mut *self.vfs.write();
|
||||
@ -191,57 +190,56 @@ impl GlobalState {
|
||||
return false;
|
||||
}
|
||||
|
||||
// important: this needs to be a stable sort, the order between changes is relevant
|
||||
// for the same file ids
|
||||
changed_files.sort_by_key(|file| file.file_id);
|
||||
// We need to fix up the changed events a bit, if we have a create or modify for a file
|
||||
// id that is followed by a delete we actually no longer observe the file text from the
|
||||
// create or modify which may cause problems later on
|
||||
let mut collapsed_create_delete = false;
|
||||
changed_files.dedup_by(|a, b| {
|
||||
// We need to fix up the changed events a bit. If we have a create or modify for a file
|
||||
// id that is followed by a delete we actually skip observing the file text from the
|
||||
// earlier event, to avoid problems later on.
|
||||
for changed_file in &changed_files {
|
||||
use vfs::ChangeKind::*;
|
||||
|
||||
let has_collapsed_create_delete = mem::replace(&mut collapsed_create_delete, false);
|
||||
|
||||
if a.file_id != b.file_id {
|
||||
return false;
|
||||
}
|
||||
|
||||
// true => delete the second element (a), we swap them here as they are inverted by dedup_by
|
||||
match (b.change_kind, a.change_kind) {
|
||||
// duplicate can be merged
|
||||
(Create, Create) | (Modify, Modify) | (Delete, Delete) => true,
|
||||
// just leave the create, modify is irrelevant
|
||||
(Create, Modify) => true,
|
||||
// modify becomes irrelevant if the file is deleted
|
||||
(Modify, Delete) => {
|
||||
mem::swap(a, b);
|
||||
true
|
||||
}
|
||||
// Remove the create message, and in the following loop, also remove the delete
|
||||
(Create, Delete) => {
|
||||
collapsed_create_delete = true;
|
||||
b.change_kind = Delete;
|
||||
true
|
||||
}
|
||||
// trailing delete from earlier
|
||||
(Delete, Create | Modify) if has_collapsed_create_delete => {
|
||||
b.change_kind = Create;
|
||||
true
|
||||
}
|
||||
// this is equivalent to a modify
|
||||
(Delete, Create) => {
|
||||
b.change_kind = Modify;
|
||||
true
|
||||
}
|
||||
// can't really occur
|
||||
(Modify, Create) => false,
|
||||
(Delete, Modify) => false,
|
||||
}
|
||||
});
|
||||
if collapsed_create_delete {
|
||||
changed_files.pop();
|
||||
file_changes
|
||||
.entry(changed_file.file_id)
|
||||
.and_modify(|(change, just_created)| {
|
||||
// None -> Delete => keep
|
||||
// Create -> Delete => collapse
|
||||
//
|
||||
match (change, just_created, changed_file.change_kind) {
|
||||
// latter `Delete` wins
|
||||
(change, _, Delete) => *change = Delete,
|
||||
// merge `Create` with `Create` or `Modify`
|
||||
(Create, _, Create | Modify) => {}
|
||||
// collapse identical `Modify`es
|
||||
(Modify, _, Modify) => {}
|
||||
// equivalent to `Modify`
|
||||
(change @ Delete, just_created, Create) => {
|
||||
*change = Modify;
|
||||
*just_created = true;
|
||||
}
|
||||
// shouldn't occur, but collapse into `Create`
|
||||
(change @ Delete, just_created, Modify) => {
|
||||
*change = Create;
|
||||
*just_created = true;
|
||||
}
|
||||
// shouldn't occur, but collapse into `Modify`
|
||||
(Modify, _, Create) => {}
|
||||
}
|
||||
})
|
||||
.or_insert((
|
||||
changed_file.change_kind,
|
||||
matches!(changed_file.change_kind, Create),
|
||||
));
|
||||
}
|
||||
|
||||
changed_files.extend(
|
||||
file_changes
|
||||
.into_iter()
|
||||
.filter(|(_, (change_kind, just_created))| {
|
||||
!matches!((change_kind, just_created), (vfs::ChangeKind::Delete, true))
|
||||
})
|
||||
.map(|(file_id, (change_kind, _))| vfs::ChangedFile { file_id, change_kind }),
|
||||
);
|
||||
|
||||
// A file was added or deleted
|
||||
let mut has_structure_changes = false;
|
||||
for file in &changed_files {
|
||||
if let Some(path) = vfs.file_path(file.file_id).as_path() {
|
||||
let path = path.to_path_buf();
|
||||
|
Loading…
x
Reference in New Issue
Block a user