diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 0fcdc463f5..435f4ac79b 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1527,14 +1527,10 @@ impl Buffer { self.end_transaction(cx) } - fn changed_since_saved_version(&self) -> bool { - self.edits_since::(&self.saved_version) - .next() - .is_some() - } /// Checks if the buffer has unsaved changes. pub fn is_dirty(&self) -> bool { - (self.has_conflict || self.changed_since_saved_version()) + self.has_conflict + || self.has_edits_since(&self.saved_version) || self .file .as_ref() @@ -1544,11 +1540,10 @@ impl Buffer { /// Checks if the buffer and its file have both changed since the buffer /// was last saved or reloaded. pub fn has_conflict(&self) -> bool { - (self.has_conflict || self.changed_since_saved_version()) - && self - .file - .as_ref() - .map_or(false, |file| file.mtime() > self.saved_mtime) + self.has_conflict + || self.file.as_ref().map_or(false, |file| { + file.mtime() > self.saved_mtime && self.has_edits_since(&self.saved_version) + }) } /// Gets a [`Subscription`] that tracks all of the changes to the buffer's text. diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 489a160759..6f748fb588 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -139,6 +139,14 @@ fn test_random_edits(mut rng: StdRng) { assert_eq!(old_text, new_text); } + assert_eq!( + buffer.has_edits_since(&old_buffer.version), + buffer + .edits_since::(&old_buffer.version) + .next() + .is_some(), + ); + let subscription_edits = subscription.consume(); log::info!( "applying subscription edits since version {:?} to old text: {:?}: {:?}", diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index c02562ea57..75244f84a1 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -2165,6 +2165,24 @@ impl BufferSnapshot { buffer_id: self.remote_id, } } + + pub fn has_edits_since(&self, since: &clock::Global) -> bool { + if *since != self.version { + let mut cursor = self + .fragments + .filter::<_, usize>(move |summary| !since.observed_all(&summary.max_version)); + cursor.next(&None); + while let Some(fragment) = cursor.item() { + let was_visible = fragment.was_visible(since, &self.undo_map); + let is_visible = fragment.visible; + if was_visible != is_visible { + return true; + } + cursor.next(&None); + } + } + false + } } struct RopeBuilder<'a> {