Use Rope instead of String for buffer diff base (#11300)
As an attempt to do things better when showing diff hunks, store diff base as Rope, not String, to have cheaper clones when the diff base text is reused, e.g. creating another buffer with the diff base text for hunk diff expanding. Release Notes: - N/A
This commit is contained in:
@@ -4977,10 +4977,16 @@ impl Editor {
|
||||
if !revert_changes.is_empty() {
|
||||
self.transact(cx, |editor, cx| {
|
||||
editor.buffer().update(cx, |multi_buffer, cx| {
|
||||
for (buffer_id, buffer_revert_ranges) in revert_changes {
|
||||
for (buffer_id, changes) in revert_changes {
|
||||
if let Some(buffer) = multi_buffer.buffer(buffer_id) {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(buffer_revert_ranges, None, cx);
|
||||
buffer.edit(
|
||||
changes.into_iter().map(|(range, text)| {
|
||||
(range, text.to_string().map(Arc::<str>::from))
|
||||
}),
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5013,7 +5019,7 @@ impl Editor {
|
||||
&mut self,
|
||||
selections: &[Selection<Anchor>],
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> HashMap<BufferId, Vec<(Range<text::Anchor>, Arc<str>)>> {
|
||||
) -> HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>> {
|
||||
let mut revert_changes = HashMap::default();
|
||||
self.buffer.update(cx, |multi_buffer, cx| {
|
||||
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
|
||||
@@ -5025,14 +5031,14 @@ impl Editor {
|
||||
}
|
||||
|
||||
fn prepare_revert_change(
|
||||
revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Arc<str>)>>,
|
||||
revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
|
||||
multi_buffer: &MultiBuffer,
|
||||
hunk: &DiffHunk<u32>,
|
||||
cx: &mut AppContext,
|
||||
) -> Option<()> {
|
||||
let buffer = multi_buffer.buffer(hunk.buffer_id)?;
|
||||
let buffer = buffer.read(cx);
|
||||
let original_text = buffer.diff_base()?.get(hunk.diff_base_byte_range.clone())?;
|
||||
let original_text = buffer.diff_base()?.slice(hunk.diff_base_byte_range.clone());
|
||||
let buffer_snapshot = buffer.snapshot();
|
||||
let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
|
||||
if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
|
||||
@@ -5041,9 +5047,8 @@ impl Editor {
|
||||
.start
|
||||
.cmp(&hunk.buffer_range.start, &buffer_snapshot)
|
||||
.then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
|
||||
.then(probe.1.as_ref().cmp(original_text))
|
||||
}) {
|
||||
buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), Arc::from(original_text)));
|
||||
buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -9026,7 +9026,7 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
|
||||
.collect::<String>(),
|
||||
cx,
|
||||
);
|
||||
buffer.set_diff_base(Some(sample_text), cx);
|
||||
buffer.set_diff_base(Some(sample_text.into()), cx);
|
||||
});
|
||||
cx.executor().run_until_parked();
|
||||
}
|
||||
@@ -10041,17 +10041,17 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
|
||||
"vvvv\nwwww\nxxxx\nyyyy\nzzzz\n@@@@\n{{{{\n||||\n}}}}\n~~~~\n\u{7f}\u{7f}\u{7f}\u{7f}";
|
||||
let buffer_1 = cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local(modified_sample_text_1.to_string(), cx);
|
||||
buffer.set_diff_base(Some(sample_text_1.clone()), cx);
|
||||
buffer.set_diff_base(Some(sample_text_1.clone().into()), cx);
|
||||
buffer
|
||||
});
|
||||
let buffer_2 = cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local(modified_sample_text_2.to_string(), cx);
|
||||
buffer.set_diff_base(Some(sample_text_2.clone()), cx);
|
||||
buffer.set_diff_base(Some(sample_text_2.clone().into()), cx);
|
||||
buffer
|
||||
});
|
||||
let buffer_3 = cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local(modified_sample_text_3.to_string(), cx);
|
||||
buffer.set_diff_base(Some(sample_text_3.clone()), cx);
|
||||
buffer.set_diff_base(Some(sample_text_3.clone().into()), cx);
|
||||
buffer
|
||||
});
|
||||
|
||||
@@ -11351,7 +11351,7 @@ fn assert_hunk_revert(
|
||||
.as_singleton()
|
||||
.unwrap()
|
||||
.update(cx, |buffer, cx| {
|
||||
buffer.set_diff_base(Some(base_text.to_string()), cx);
|
||||
buffer.set_diff_base(Some(base_text.into()), cx);
|
||||
});
|
||||
});
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
@@ -145,7 +145,8 @@ mod tests {
|
||||
1.five
|
||||
1.six
|
||||
"
|
||||
.unindent(),
|
||||
.unindent()
|
||||
.into(),
|
||||
),
|
||||
cx,
|
||||
);
|
||||
@@ -181,7 +182,8 @@ mod tests {
|
||||
2.four
|
||||
2.six
|
||||
"
|
||||
.unindent(),
|
||||
.unindent()
|
||||
.into(),
|
||||
),
|
||||
cx,
|
||||
);
|
||||
|
||||
@@ -226,13 +226,14 @@ impl Editor {
|
||||
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
||||
.or_else(|| create_diff_base_buffer(&buffer, cx));
|
||||
let buffer = buffer.read(cx);
|
||||
let deleted_text_lines = buffer.diff_base().and_then(|diff_base| {
|
||||
Some(
|
||||
diff_base
|
||||
.get(hunk.diff_base_byte_range.clone())?
|
||||
.lines()
|
||||
.count(),
|
||||
)
|
||||
let deleted_text_lines = buffer.diff_base().map(|diff_base| {
|
||||
let diff_start_row = diff_base
|
||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||
.row;
|
||||
let diff_end_row =
|
||||
diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
||||
let line_count = diff_end_row - diff_start_row;
|
||||
line_count as usize
|
||||
});
|
||||
Some((
|
||||
diff_base_buffer?,
|
||||
@@ -542,12 +543,12 @@ fn create_diff_base_buffer(buffer: &Model<Buffer>, cx: &mut AppContext) -> Optio
|
||||
buffer
|
||||
.update(cx, |buffer, _| {
|
||||
let language = buffer.language().cloned();
|
||||
let diff_base = buffer.diff_base().map(|s| s.to_owned());
|
||||
Some((diff_base?, language))
|
||||
let diff_base = buffer.diff_base()?.clone();
|
||||
Some((buffer.line_ending(), diff_base, language))
|
||||
})
|
||||
.map(|(diff_base, language)| {
|
||||
.map(|(line_ending, diff_base, language)| {
|
||||
cx.new_model(|cx| {
|
||||
let buffer = Buffer::local(diff_base, cx);
|
||||
let buffer = Buffer::local_normalized(diff_base, line_ending, cx);
|
||||
match language {
|
||||
Some(language) => buffer.with_language(language, cx),
|
||||
None => buffer,
|
||||
|
||||
@@ -99,12 +99,13 @@ pub fn editor_hunks(
|
||||
.read(cx)
|
||||
.excerpt_containing(Point::new(hunk.associated_range.start, 0), cx)
|
||||
.expect("no excerpt for expanded buffer's hunk start");
|
||||
let diff_base = &buffer
|
||||
let diff_base = buffer
|
||||
.read(cx)
|
||||
.diff_base()
|
||||
.expect("should have a diff base for expanded hunk")
|
||||
[hunk.diff_base_byte_range.clone()];
|
||||
(diff_base.to_owned(), hunk.status(), display_range)
|
||||
.slice(hunk.diff_base_byte_range.clone())
|
||||
.to_string();
|
||||
(diff_base, hunk.status(), display_range)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -134,16 +135,13 @@ pub fn expanded_hunks(
|
||||
.read(cx)
|
||||
.excerpt_containing(expanded_hunk.hunk_range.start, cx)
|
||||
.expect("no excerpt for expanded buffer's hunk start");
|
||||
let diff_base = &buffer
|
||||
let diff_base = buffer
|
||||
.read(cx)
|
||||
.diff_base()
|
||||
.expect("should have a diff base for expanded hunk")
|
||||
[expanded_hunk.diff_base_byte_range.clone()];
|
||||
(
|
||||
diff_base.to_owned(),
|
||||
expanded_hunk.status,
|
||||
hunk_display_range,
|
||||
)
|
||||
.slice(expanded_hunk.diff_base_byte_range.clone())
|
||||
.to_string();
|
||||
(diff_base, expanded_hunk.status, hunk_display_range)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ use std::{
|
||||
Arc,
|
||||
},
|
||||
};
|
||||
use text::Rope;
|
||||
use ui::Context;
|
||||
use util::{
|
||||
assert_set_eq,
|
||||
@@ -271,7 +272,7 @@ impl EditorTestContext {
|
||||
}
|
||||
|
||||
pub fn set_diff_base(&mut self, diff_base: Option<&str>) {
|
||||
let diff_base = diff_base.map(String::from);
|
||||
let diff_base = diff_base.map(Rope::from);
|
||||
self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base, cx));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user