|
3 | 3 | //! |
4 | 4 | //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. |
5 | 5 |
|
6 | | -use std::{sync::Arc, time::Instant}; |
| 6 | +use std::{mem, sync::Arc, time::Instant}; |
7 | 7 |
|
8 | 8 | use crossbeam_channel::{unbounded, Receiver, Sender}; |
9 | 9 | use flycheck::FlycheckHandle; |
@@ -197,37 +197,51 @@ impl GlobalState { |
197 | 197 | // We need to fix up the changed events a bit, if we have a create or modify for a file |
198 | 198 | // id that is followed by a delete we actually no longer observe the file text from the |
199 | 199 | // create or modify which may cause problems later on |
| 200 | + let mut collapsed_create_delete = false; |
200 | 201 | changed_files.dedup_by(|a, b| { |
201 | 202 | use vfs::ChangeKind::*; |
202 | 203 |
|
| 204 | + let has_collapsed_create_delete = mem::replace(&mut collapsed_create_delete, false); |
| 205 | + |
203 | 206 | if a.file_id != b.file_id { |
204 | 207 | return false; |
205 | 208 | } |
206 | 209 |
|
207 | | - match (a.change_kind, b.change_kind) { |
| 210 | + // true => delete the second element (a), we swap them here as they are inverted by dedup_by |
| 211 | + match (b.change_kind, a.change_kind) { |
208 | 212 | // duplicate can be merged |
209 | 213 | (Create, Create) | (Modify, Modify) | (Delete, Delete) => true, |
210 | 214 | // just leave the create, modify is irrelevant |
211 | | - (Create, Modify) => { |
212 | | - std::mem::swap(a, b); |
| 215 | + (Create, Modify) => true, |
| 216 | + // modify becomes irrelevant if the file is deleted |
| 217 | + (Modify, Delete) => { |
| 218 | + mem::swap(a, b); |
| 219 | + true |
| 220 | + } |
| 221 | + // Remove the create message, and in the following loop, also remove the delete |
| 222 | + (Create, Delete) => { |
| 223 | + collapsed_create_delete = true; |
| 224 | + b.change_kind = Delete; |
| 225 | + true |
| 226 | + } |
| 227 | + // trailing delete from earlier |
| 228 | + (Delete, Create | Modify) if has_collapsed_create_delete => { |
| 229 | + b.change_kind = Create; |
213 | 230 | true |
214 | 231 | } |
215 | | - // modify becomes irrelevant if the file is deleted |
216 | | - (Modify, Delete) => true, |
217 | | - // we should fully remove this occurrence, |
218 | | - // but leaving just a delete works as well |
219 | | - (Create, Delete) => true, |
220 | 232 | // this is equivalent to a modify |
221 | 233 | (Delete, Create) => { |
222 | | - a.change_kind = Modify; |
| 234 | + b.change_kind = Modify; |
223 | 235 | true |
224 | 236 | } |
225 | 237 | // can't really occur |
226 | 238 | (Modify, Create) => false, |
227 | 239 | (Delete, Modify) => false, |
228 | 240 | } |
229 | 241 | }); |
230 | | - |
| 242 | + if collapsed_create_delete { |
| 243 | + changed_files.pop(); |
| 244 | + } |
231 | 245 | for file in &changed_files { |
232 | 246 | if let Some(path) = vfs.file_path(file.file_id).as_path() { |
233 | 247 | let path = path.to_path_buf(); |
|
0 commit comments