From 038eb8754b0d5bd6b1683ceefa7064ee17fffb08 Mon Sep 17 00:00:00 2001 From: "warp-agent-staging[bot]" <240773466+warp-agent-staging[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:52:09 +0000 Subject: [PATCH] [APP-5810] Share precise deltas across edit clones Store EditDelta precise deltas behind Arc so delayed-rendering clones retain one allocation while preserving existing read-only behavior. ticket_source=linear ticket_id=APP-5810 Co-Authored-By: Warp Agent --- crates/editor/src/content/buffer.rs | 26 ++++++++++----------- crates/editor/src/content/buffer_tests.rs | 12 +++++----- crates/editor/src/content/core.rs | 2 +- crates/editor/src/content/edit.rs | 5 +++- crates/editor/src/content/edit_tests.rs | 28 ++++++++++++++++++++--- 5 files changed, 49 insertions(+), 24 deletions(-) diff --git a/crates/editor/src/content/buffer.rs b/crates/editor/src/content/buffer.rs index 39e6ec5b2b7..453b7e782fd 100644 --- a/crates/editor/src/content/buffer.rs +++ b/crates/editor/src/content/buffer.rs @@ -990,14 +990,14 @@ impl Buffer { EditResult { undo_item: None, delta: Some(EditDelta { - precise_deltas: vec![PreciseDelta { + precise_deltas: Arc::new(vec![PreciseDelta { replaced_range: CharOffset::from(1)..old_offset.end, replaced_points, resolved_range: CharOffset::from(1)..self.max_charoffset(), replaced_byte_range: old_byte_start..old_byte_end, new_byte_length, new_end_point, - }], + }]), old_offset, new_lines: Arc::new(self.styled_blocks_in_range( CharOffset::from(1)..self.max_charoffset(), @@ -2593,7 +2593,7 @@ impl Buffer { let old_byte_start = range.start.to_buffer_byte_offset(self); let old_byte_end = range.end.to_buffer_byte_offset(self); EditDelta { - precise_deltas: vec![PreciseDelta { + precise_deltas: Arc::new(vec![PreciseDelta { replaced_range: range.clone(), replaced_points: full_points.clone(), resolved_range: range.clone(), @@ -2602,7 +2602,7 @@ impl Buffer { .as_usize() .saturating_sub(old_byte_start.as_usize()), new_end_point: full_points.end, - }], + }]), old_offset: range.clone(), new_lines: Arc::new( self.styled_blocks_in_range(range, StyledBlockBoundaryBehavior::Exclusive), @@ -4859,14 +4859,14 @@ impl Buffer { EditResult { undo_item: None, delta: Some(EditDelta { - precise_deltas: vec![PreciseDelta { + precise_deltas: Arc::new(vec![PreciseDelta { replaced_range: old_range.clone(), replaced_points, resolved_range: old_range.clone(), replaced_byte_range: old_byte_start..old_byte_end, new_byte_length, new_end_point, - }], + }]), // Note that we need to shift the range to the right by one here since // the offset we take as the parameter is right before the block item // marker. @@ -5001,14 +5001,14 @@ impl Buffer { EditResult { undo_item: None, delta: Some(EditDelta { - precise_deltas: vec![PreciseDelta { + precise_deltas: Arc::new(vec![PreciseDelta { replaced_range: old_range.clone(), replaced_points, resolved_range: old_range.clone(), replaced_byte_range: old_byte_start..old_byte_end, new_byte_length, new_end_point, - }], + }]), old_offset: old_range.clone(), new_lines: Arc::new( self.styled_blocks_in_range(old_range, StyledBlockBoundaryBehavior::Exclusive), @@ -5084,14 +5084,14 @@ impl Buffer { EditResult { undo_item: None, delta: Some(EditDelta { - precise_deltas: vec![PreciseDelta { + precise_deltas: Arc::new(vec![PreciseDelta { replaced_range: at..at, replaced_points, resolved_range: at..at + 1, replaced_byte_range: byte_at..byte_at, new_byte_length, new_end_point, - }], + }]), old_offset: old_range, new_lines: Arc::new( self.styled_blocks_in_range(new_range, StyledBlockBoundaryBehavior::Exclusive), @@ -5211,7 +5211,7 @@ impl Buffer { EditResult { undo_item: None, delta: Some(EditDelta { - precise_deltas, + precise_deltas: Arc::new(precise_deltas), old_offset: undo_item.replacement_range.old_range, new_lines: Arc::new(self.styled_blocks_in_range( undo_item.replacement_range.new_range, @@ -5240,7 +5240,7 @@ impl Buffer { anchor_updates.extend(result.anchor_updates); if let Some(delta) = result.delta { - precise_deltas.extend(delta.precise_deltas); + precise_deltas.extend(Arc::unwrap_or_clone(delta.precise_deltas)); } } @@ -5260,7 +5260,7 @@ impl Buffer { EditResult { undo_item: None, delta: Some(EditDelta { - precise_deltas, + precise_deltas: Arc::new(precise_deltas), old_offset: undo_item.replacement_range.old_range, new_lines: Arc::new(self.styled_blocks_in_range( undo_item.replacement_range.new_range, diff --git a/crates/editor/src/content/buffer_tests.rs b/crates/editor/src/content/buffer_tests.rs index 0142a5c1a5c..11b977c6447 100644 --- a/crates/editor/src/content/buffer_tests.rs +++ b/crates/editor/src/content/buffer_tests.rs @@ -1037,7 +1037,7 @@ fn test_edit_delta() { .expect("Should exist"); assert_eq!(buffer.content.debug(), "te\\nst"); assert_eq!( - delta.precise_deltas, + (*delta.precise_deltas), vec![PreciseDelta { replaced_range: CharOffset::from(1)..CharOffset::from(1), replaced_points: Point::new(1, 0)..Point::new(1, 0), @@ -1084,7 +1084,7 @@ fn test_edit_delta() { .expect("Should exist"); assert_eq!(buffer.content.debug(), "tnst"); assert_eq!( - delta.precise_deltas, + (*delta.precise_deltas), vec![PreciseDelta { replaced_range: CharOffset::from(2)..CharOffset::from(4), replaced_points: Point::new(1, 1)..Point::new(2, 0), @@ -1119,7 +1119,7 @@ fn test_edit_delta() { .expect("Should exist"); assert_eq!(buffer.content.debug(), "tn\\n\\nt"); assert_eq!( - delta.precise_deltas, + (*delta.precise_deltas), vec![PreciseDelta { replaced_range: CharOffset::from(2)..CharOffset::from(4), replaced_points: Point::new(1, 1)..Point::new(1, 3), @@ -1174,7 +1174,7 @@ fn test_edit_delta() { .expect("Should exist"); assert_eq!(buffer.content.debug(), "ts\\n\\nt"); assert_eq!( - delta.precise_deltas, + (*delta.precise_deltas), vec![PreciseDelta { replaced_range: CharOffset::from(2)..CharOffset::from(3), replaced_points: Point::new(1, 1)..Point::new(1, 2), @@ -1209,7 +1209,7 @@ fn test_edit_delta() { .expect("Should exist"); assert_eq!(buffer.content.debug(), "ts\\nhi\\nt"); assert_eq!( - delta.precise_deltas, + (*delta.precise_deltas), vec![PreciseDelta { replaced_range: CharOffset::from(4)..CharOffset::from(4), replaced_points: Point::new(2, 0)..Point::new(2, 0), @@ -1243,7 +1243,7 @@ fn test_edit_delta() { .delta .expect("Should exist"); assert_eq!( - delta.precise_deltas, + (*delta.precise_deltas), vec![PreciseDelta { replaced_range: CharOffset::from(2)..CharOffset::from(3), replaced_points: Point::new(1, 1)..Point::new(1, 2), diff --git a/crates/editor/src/content/core.rs b/crates/editor/src/content/core.rs index 2ab461737fe..7f7ad58fc55 100644 --- a/crates/editor/src/content/core.rs +++ b/crates/editor/src/content/core.rs @@ -373,7 +373,7 @@ impl Buffer { EditResult { undo_item: Some(undo_arg), delta: Some(EditDelta { - precise_deltas, + precise_deltas: Arc::new(precise_deltas), old_offset: replacement_range.old_range, new_lines, }), diff --git a/crates/editor/src/content/edit.rs b/crates/editor/src/content/edit.rs index a23ec064041..317a6ce7517 100644 --- a/crates/editor/src/content/edit.rs +++ b/crates/editor/src/content/edit.rs @@ -187,7 +187,10 @@ impl PreciseDelta { #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct EditDelta { /// The exact replacement charoffset range where content was changed. - pub precise_deltas: Vec, + /// + /// Wrapped in `Arc` so cloning an `EditDelta` does not copy every entry in a large + /// multi-delta edit. + pub precise_deltas: Arc>, /// Offset of the old blocks that are being replaced. The start is the first /// character of the first block, and the end is the end of the last block - /// the first character after it. diff --git a/crates/editor/src/content/edit_tests.rs b/crates/editor/src/content/edit_tests.rs index 552d4791bcd..57825908300 100644 --- a/crates/editor/src/content/edit_tests.rs +++ b/crates/editor/src/content/edit_tests.rs @@ -6,11 +6,12 @@ use std::sync::Arc; use std::time::{SystemTime, UNIX_EPOCH}; use rangemap::RangeSet; -use string_offset::CharOffset; +use string_offset::{ByteOffset, CharOffset}; use warp_core::features::FeatureFlag; use warpui_core::assets::asset_cache::{AssetCache, AssetSource, AssetState}; use warpui_core::fonts::{Properties, Style, Weight}; use warpui_core::image_cache::ImageType; +use warpui_core::text::point::Point; use warpui_core::text_layout::{LayoutCache, StyleAndFont, TextStyle}; use warpui_core::{App, SingletonEntity}; @@ -21,8 +22,9 @@ use super::{ }; use crate::content::buffer::{StyledBufferBlock, StyledBufferRun, StyledTextBlock}; use crate::content::edit::{ - EditDelta, ParsedUrl, TemporaryBlock, highlight_urls, layout_mermaid_block_for_test, - resolve_asset_source, resolve_asset_source_relative_to_directory, + EditDelta, ParsedUrl, PreciseDelta, TemporaryBlock, highlight_urls, + layout_mermaid_block_for_test, resolve_asset_source, + resolve_asset_source_relative_to_directory, }; use crate::content::mermaid_diagram::{mermaid_asset_source, mermaid_diagram_layout}; use crate::content::text::{BufferBlockStyle, CodeBlockType, TextStylesWithMetadata}; @@ -306,6 +308,26 @@ fn test_layout_delta_never_takes_ownership_of_new_lines_with_multiple_owners() { }) } +#[test] +fn test_edit_delta_clone_shares_precise_delta_allocation() { + let delta = EditDelta { + precise_deltas: Arc::new(vec![PreciseDelta { + replaced_range: CharOffset::from(1)..CharOffset::from(2), + replaced_points: Point::new(1, 0)..Point::new(1, 1), + replaced_byte_range: ByteOffset::from(1)..ByteOffset::from(2), + new_byte_length: 1, + new_end_point: Point::new(1, 1), + resolved_range: CharOffset::from(1)..CharOffset::from(2), + }]), + ..Default::default() + }; + + let cloned = delta.clone(); + + assert_eq!(delta.precise_deltas, cloned.precise_deltas); + assert!(Arc::ptr_eq(&delta.precise_deltas, &cloned.precise_deltas)); +} + #[test] fn test_layout_partial_url() { // Regression test for laying out a partially-styled autodetected URL (CLD-871).