From 8b943c6d7469b4fbfd5ab67257cecfee66da87e3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 7 Apr 2026 20:44:21 -0700 Subject: [PATCH] Restrict snapshot edits to a single-edit divergence from buffer --- crates/language/src/buffer.rs | 3 +-- crates/text/src/text.rs | 39 +++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 261991d751b3f07d78f45720d3c15539783c461e..90354c832eebdfbd688576b7141bea6756419ba2 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1245,7 +1245,7 @@ impl Buffer { let registry = self.language_registry(); let language = self.language().cloned(); let old_snapshot = self.text.snapshot().clone(); - let mut new_snapshot = old_snapshot.clone(); + let new_snapshot = self.text.snapshot_with_edits(edits.iter().cloned()); let mut syntax_snapshot = self.syntax_map.lock().snapshot(); cx.background_spawn(async move { if !edits.is_empty() { @@ -1253,7 +1253,6 @@ impl Buffer { syntax_snapshot.reparse(&old_snapshot, registry.clone(), language); } - new_snapshot.edit(edits.iter().cloned()); syntax_snapshot.interpolate(&new_snapshot); if let Some(language) = language { diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 2a435dd24e9de2f60c896e73a5140116aac3ec91..b6fb89d6f691fc57b64c43d3c2d5573e547d271d 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -838,6 +838,27 @@ impl Buffer { self.snapshot } + /// Returns a preview snapshot derived by applying one synthetic local-branch edit. + /// + /// This is intended for one-off preview workflows like syntax interpolation, not for + /// repeatedly mutating or composing synthetic snapshot histories. + pub fn snapshot_with_edits(&self, edits: I) -> BufferSnapshot + where + I: IntoIterator, T)>, + S: ToOffset, + T: Into>, + { + let mut snapshot = self.snapshot.clone(); + let timestamp = Lamport::new(ReplicaId::LOCAL_BRANCH).tick(); + let edits: Vec<_> = edits + .into_iter() + .map(|(range, new_text)| (range.to_offset(&snapshot), new_text.into())) + .collect(); + snapshot.apply_edit_internal(edits, timestamp); + snapshot.version.observe(timestamp); + snapshot + } + pub fn replica_id(&self) -> ReplicaId { self.lamport_clock.replica_id } @@ -1854,24 +1875,6 @@ impl Deref for Buffer { } impl BufferSnapshot { - /// Edits the snapshot in place, applying the given edits to the text content. - /// This is useful for creating a modified snapshot without needing a full Buffer. - pub fn edit(&mut self, edits: I) - where - I: IntoIterator, T)>, - S: ToOffset, - T: Into>, - { - let mut lamport_clock = clock::Lamport::new(ReplicaId::LOCAL_BRANCH); - let timestamp = lamport_clock.tick(); - let edits: Vec<_> = edits - .into_iter() - .map(|(range, new_text)| (range.to_offset(self), new_text.into())) - .collect(); - self.apply_edit_internal(edits, timestamp); - self.version.observe(timestamp); - } - fn apply_edit_internal( &mut self, edits: Vec<(Range, Arc)>,