-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix: Fix process-changes not deduplicating changes correctly #14025
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
//! | ||
//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. | ||
|
||
use std::{sync::Arc, time::Instant}; | ||
use std::{mem, sync::Arc, time::Instant}; | ||
|
||
use crossbeam_channel::{unbounded, Receiver, Sender}; | ||
use flycheck::FlycheckHandle; | ||
|
@@ -197,37 +197,51 @@ impl GlobalState { | |
// 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| { | ||
use vfs::ChangeKind::*; | ||
|
||
let has_collapsed_create_delete = mem::replace(&mut collapsed_create_delete, false); | ||
|
||
if a.file_id != b.file_id { | ||
return false; | ||
} | ||
|
||
match (a.change_kind, b.change_kind) { | ||
// 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) => { | ||
std::mem::swap(a, b); | ||
(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 | ||
} | ||
// modify becomes irrelevant if the file is deleted | ||
(Modify, Delete) => true, | ||
// we should fully remove this occurrence, | ||
// but leaving just a delete works as well | ||
(Create, Delete) => true, | ||
// this is equivalent to a modify | ||
(Delete, Create) => { | ||
a.change_kind = Modify; | ||
b.change_kind = Modify; | ||
true | ||
} | ||
// can't really occur | ||
(Modify, Create) => false, | ||
(Delete, Modify) => false, | ||
} | ||
}); | ||
|
||
if collapsed_create_delete { | ||
changed_files.pop(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've only skimmed the changes, but does this work for And generally, I don't think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should work, because the flag is only I agree that the code is hard to follow though, and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But on my example, this results in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A simple map might be a better choice here indeed |
||
} | ||
for file in &changed_files { | ||
if let Some(path) = vfs.file_path(file.file_id).as_path() { | ||
let path = path.to_path_buf(); | ||
|
Uh oh!
There was an error while loading. Please reload this page.