multi_buffer: Optimize a bunch of things (#48519)

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
Lukas WirthandCole Miller authored and GitHub committed 2026-02-05 20:10:02 +00:00
1 parent 7dcff21dc9
commit 74746aa974
12 files changed
+256 -157

No files matched your search

@@ -320,7 +320,7 @@ mod tests {
);
let snapshot = buffer.snapshot();
let mut finder = StreamingFuzzyMatcher::new(snapshot);
let mut finder = StreamingFuzzyMatcher::new(snapshot.clone());
assert_eq!(push(&mut finder, ""), None);
assert_eq!(finish(finder), None);
}
@@ -334,7 +334,7 @@ mod tests {
);
let snapshot = buffer.snapshot();
let mut finder = StreamingFuzzyMatcher::new(snapshot);
let mut finder = StreamingFuzzyMatcher::new(snapshot.clone());
// Push partial query
assert_eq!(push(&mut finder, "This"), None);
@@ -366,7 +366,7 @@ mod tests {
);
let snapshot = buffer.snapshot();
let mut finder = StreamingFuzzyMatcher::new(snapshot);
let mut finder = StreamingFuzzyMatcher::new(snapshot.clone());
// Push a fuzzy query that should match the first function
assert_eq!(
@@ -392,7 +392,7 @@ mod tests {
);
let snapshot = buffer.snapshot();
let mut finder = StreamingFuzzyMatcher::new(snapshot);
let mut finder = StreamingFuzzyMatcher::new(snapshot.clone());
// No match initially
assert_eq!(push(&mut finder, "Lin"), None);
@@ -421,7 +421,7 @@ mod tests {
);
let snapshot = buffer.snapshot();
let mut finder = StreamingFuzzyMatcher::new(snapshot);
let mut finder = StreamingFuzzyMatcher::new(snapshot.clone());
// Push text in small chunks across line boundaries
assert_eq!(push(&mut finder, "jumps "), None); // No newline yet
@@ -459,7 +459,7 @@ mod tests {
);
let snapshot = buffer.snapshot();
let mut finder = StreamingFuzzyMatcher::new(snapshot);
let mut finder = StreamingFuzzyMatcher::new(snapshot.clone());
assert_eq!(
push(&mut finder, "impl Debug for User {\n"),
@@ -716,7 +716,7 @@ mod tests {
"Expected to match `second_function` based on the line hint"
);
let mut matcher = StreamingFuzzyMatcher::new(snapshot);
let mut matcher = StreamingFuzzyMatcher::new(snapshot.clone());
matcher.push(query, None);
matcher.finish();
let best_match = matcher.select_best_match();
@@ -732,7 +732,7 @@ mod tests {
let buffer = TextBuffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), text.clone());
let snapshot = buffer.snapshot();
let mut matcher = StreamingFuzzyMatcher::new(snapshot);
let mut matcher = StreamingFuzzyMatcher::new(snapshot.clone());
// Split query into random chunks
let chunks = to_random_chunks(rng, query);
+34 -35
View File
@@ -30,7 +30,7 @@ pub struct BufferDiff {
#[derive(Clone)]
pub struct BufferDiffSnapshot {
inner: BufferDiffInner<language::BufferSnapshot>,
secondary_diff: Option<Box<BufferDiffSnapshot>>,
secondary_diff: Option<Arc<BufferDiffSnapshot>>,
}
impl std::fmt::Debug for BufferDiffSnapshot {
@@ -222,11 +222,11 @@ impl std::fmt::Debug for BufferDiffInner<language::BufferSnapshot> {
impl BufferDiffSnapshot {
#[cfg(test)]
fn new_sync(
buffer: text::BufferSnapshot,
buffer: &text::BufferSnapshot,
diff_base: String,
cx: &mut gpui::TestAppContext,
) -> BufferDiffSnapshot {
let buffer_diff = cx.new(|cx| BufferDiff::new_with_base_text(&diff_base, &buffer, cx));
let buffer_diff = cx.new(|cx| BufferDiff::new_with_base_text(&diff_base, buffer, cx));
buffer_diff.update(cx, |buffer_diff, cx| buffer_diff.snapshot(cx))
}
@@ -950,10 +950,10 @@ fn build_diff_options(
fn compute_hunks(
diff_base: Option<(Arc<str>, Rope)>,
buffer: text::BufferSnapshot,
buffer: &text::BufferSnapshot,
diff_options: Option<DiffOptions>,
) -> SumTree<InternalDiffHunk> {
let mut tree = SumTree::new(&buffer);
let mut tree = SumTree::new(buffer);
if let Some((diff_base, diff_base_rope)) = diff_base {
let buffer_text = buffer.as_rope().to_string();
@@ -980,7 +980,7 @@ fn compute_hunks(
base_word_diffs: Vec::default(),
buffer_word_diffs: Vec::default(),
},
&buffer,
buffer,
);
return tree;
}
@@ -992,11 +992,11 @@ fn compute_hunks(
&patch,
hunk_index,
&diff_base_rope,
&buffer,
buffer,
&mut divergence,
diff_options.as_ref(),
);
tree.push(hunk, &buffer);
tree.push(hunk, buffer);
}
}
} else {
@@ -1007,7 +1007,7 @@ fn compute_hunks(
base_word_diffs: Vec::default(),
buffer_word_diffs: Vec::default(),
},
&buffer,
buffer,
);
}
@@ -1544,7 +1544,7 @@ impl BufferDiff {
base_text
.clone()
.map(|base_text| (base_text, base_text_rope.clone())),
buffer.clone(),
&buffer,
diff_options,
);
let base_text = base_text.unwrap_or_default();
@@ -1785,10 +1785,10 @@ impl BufferDiff {
base_text_exists: self.inner.base_text_exists,
buffer_snapshot: self.inner.buffer_snapshot.clone(),
},
secondary_diff: self
.secondary_diff
.as_ref()
.map(|diff| Box::new(diff.read(cx).snapshot(cx))),
secondary_diff: self.secondary_diff.as_ref().map(|diff| {
debug_assert!(diff.read(cx).secondary_diff.is_none());
Arc::new(diff.read(cx).snapshot(cx))
}),
}
}
@@ -2018,7 +2018,7 @@ mod tests {
.unindent();
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
let mut diff = BufferDiffSnapshot::new_sync(buffer.clone(), diff_base.clone(), cx);
let mut diff = BufferDiffSnapshot::new_sync(&buffer, diff_base.clone(), cx);
assert_hunks(
diff.hunks_intersecting_range(
Anchor::min_max_range_for_buffer(buffer.remote_id()),
@@ -2030,7 +2030,7 @@ mod tests {
);
buffer.edit([(0..0, "point five\n")]);
diff = BufferDiffSnapshot::new_sync(buffer.clone(), diff_base.clone(), cx);
diff = BufferDiffSnapshot::new_sync(&buffer, diff_base.clone(), cx);
assert_hunks(
diff.hunks_intersecting_range(
Anchor::min_max_range_for_buffer(buffer.remote_id()),
@@ -2101,10 +2101,9 @@ mod tests {
.unindent();
let buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
let unstaged_diff = BufferDiffSnapshot::new_sync(buffer.clone(), index_text, cx);
let mut uncommitted_diff =
BufferDiffSnapshot::new_sync(buffer.clone(), head_text.clone(), cx);
uncommitted_diff.secondary_diff = Some(Box::new(unstaged_diff));
let unstaged_diff = BufferDiffSnapshot::new_sync(&buffer, index_text, cx);
let mut uncommitted_diff = BufferDiffSnapshot::new_sync(&buffer, head_text.clone(), cx);
uncommitted_diff.secondary_diff = Some(Arc::new(unstaged_diff));
let expected_hunks = vec![
(2..3, "two\n", "TWO\n", DiffHunkStatus::modified_none()),
@@ -2631,7 +2630,7 @@ mod tests {
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text_1);
let empty_diff = cx.update(|cx| BufferDiff::new(&buffer, cx).snapshot(cx));
let diff_1 = BufferDiffSnapshot::new_sync(buffer.clone(), base_text.clone(), cx);
let diff_1 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx);
let DiffChanged {
changed_range,
base_text_changed_range,
@@ -2666,7 +2665,7 @@ mod tests {
"
.unindent(),
);
let diff_2 = BufferDiffSnapshot::new_sync(buffer.clone(), base_text.clone(), cx);
let diff_2 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx);
let DiffChanged {
changed_range,
base_text_changed_range,
@@ -2704,7 +2703,7 @@ mod tests {
"
.unindent(),
);
let diff_3 = BufferDiffSnapshot::new_sync(buffer.clone(), base_text.clone(), cx);
let diff_3 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx);
let DiffChanged {
changed_range,
base_text_changed_range,
@@ -2738,7 +2737,7 @@ mod tests {
"
.unindent(),
);
let diff_4 = BufferDiffSnapshot::new_sync(buffer.clone(), base_text.clone(), cx);
let diff_4 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx);
let DiffChanged {
changed_range,
base_text_changed_range,
@@ -3172,11 +3171,11 @@ mod tests {
.unindent();
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
let old_buffer = buffer.snapshot();
let diff_a = BufferDiffSnapshot::new_sync(buffer.clone(), base_text.clone(), cx);
let old_buffer = buffer.snapshot().clone();
let diff_a = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx);
buffer.edit([(Point::new(1, 3)..Point::new(1, 3), "\n")]);
let diff_b = BufferDiffSnapshot::new_sync(buffer.clone(), base_text, cx);
let diff_b = BufferDiffSnapshot::new_sync(&buffer, base_text, cx);
let DiffChanged {
changed_range,
@@ -3235,11 +3234,11 @@ mod tests {
.unindent();
let mut buffer_2 = Buffer::new(ReplicaId::LOCAL, BufferId::new(2).unwrap(), buffer_text_2);
let old_buffer_2 = buffer_2.snapshot();
let diff_2a = BufferDiffSnapshot::new_sync(buffer_2.clone(), base_text_2.clone(), cx);
let old_buffer_2 = buffer_2.snapshot().clone();
let diff_2a = BufferDiffSnapshot::new_sync(&buffer_2, base_text_2.clone(), cx);
buffer_2.edit([(Point::new(4, 0)..Point::new(4, 4), "FIVE_CHANGED")]);
let diff_2b = BufferDiffSnapshot::new_sync(buffer_2.clone(), base_text_2, cx);
let diff_2b = BufferDiffSnapshot::new_sync(&buffer_2, base_text_2, cx);
let DiffChanged {
changed_range,
@@ -3293,7 +3292,7 @@ mod tests {
buffer_text_1.to_string(),
);
let old_base_snapshot_1 = base_text_buffer.snapshot();
let old_base_snapshot_1 = base_text_buffer.snapshot().clone();
let old_hunks_1 = compute_hunks(
Some((Arc::from(initial_base), Rope::from(initial_base))),
buffer.snapshot(),
@@ -3352,7 +3351,7 @@ mod tests {
buffer_text_2.to_string(),
);
let old_base_snapshot_2 = base_buf_2.snapshot();
let old_base_snapshot_2 = base_buf_2.snapshot().clone();
let old_hunks_2 = compute_hunks(
Some((Arc::from(simple_base), Rope::from(simple_base))),
buffer_2.snapshot(),
@@ -3419,7 +3418,7 @@ mod tests {
buffer_text_3.to_string(),
);
let old_base_snapshot_3 = base_buf_3.snapshot();
let old_base_snapshot_3 = base_buf_3.snapshot().clone();
let old_hunks_3 = compute_hunks(
Some((Arc::from(base_3), Rope::from(base_3))),
buffer_3.snapshot(),
@@ -3485,8 +3484,8 @@ mod tests {
buffer_text_4.to_string(),
);
let old_base_snapshot_4 = base_buf_4.snapshot();
let old_buffer_snapshot_4 = buffer_4.snapshot();
let old_base_snapshot_4 = base_buf_4.snapshot().clone();
let old_buffer_snapshot_4 = buffer_4.snapshot().clone();
let old_hunks_4 = compute_hunks(
Some((Arc::from(base_4), Rope::from(base_4))),
buffer_4.snapshot(),
+9
View File
@@ -441,6 +441,15 @@ impl DisplayMap {
return;
};
// Second call to set_companion doesn't need to do anything
if companion_display_map
.update(cx, |companion_dm, _| companion_dm.companion.is_none())
.unwrap_or(true)
{
self.companion = Some((companion_display_map, companion));
return;
}
let rhs_display_map_id = companion.read(cx).rhs_display_map_id;
if self.entity_id != rhs_display_map_id {
let buffer_mapping = companion
+48 -20
View File
@@ -1110,20 +1110,32 @@ impl BlockMap {
let mut companion_tab_point_cursor = companion_snapshot.tab_point_cursor();
let mut companion_wrap_point_cursor = companion_snapshot.wrap_point_cursor();
let mut determine_spacer = |our_point: Point, their_point: Point, delta: i32| {
let our_wrap = our_wrap_point_cursor
let mut our_wrapper = |our_point: Point| {
our_wrap_point_cursor
.map(our_tab_point_cursor.map(
our_fold_point_cursor.map(our_inlay_point_cursor.map(our_point), Bias::Left),
))
.row();
let companion_wrap = companion_wrap_point_cursor
.row()
};
let mut companion_wrapper = |their_point: Point| {
companion_wrap_point_cursor
.map(
companion_tab_point_cursor.map(
companion_fold_point_cursor
.map(companion_inlay_point_cursor.map(their_point), Bias::Left),
),
)
.row();
.row()
};
fn determine_spacer(
our_wrapper: &mut impl FnMut(Point) -> WrapRow,
companion_wrapper: &mut impl FnMut(Point) -> WrapRow,
our_point: Point,
their_point: Point,
delta: i32,
) -> (i32, Option<(WrapRow, u32)>) {
let our_wrap = our_wrapper(our_point);
let companion_wrap = companion_wrapper(their_point);
let new_delta = companion_wrap.0 as i32 - our_wrap.0 as i32;
let spacer = if new_delta > delta {
@@ -1133,7 +1145,7 @@ impl BlockMap {
None
};
(new_delta, spacer)
};
}
let mut result = Vec::new();
@@ -1179,12 +1191,8 @@ impl BlockMap {
// Case 3: We are at the start of the excerpt--no previous row to use as the baseline.
(first_point, edit_for_first_point.new.start)
};
let our_baseline = wrap_snapshot
.make_wrap_point(our_baseline, Bias::Left)
.row();
let their_baseline = companion_snapshot
.make_wrap_point(their_baseline, Bias::Left)
.row();
let our_baseline = our_wrapper(our_baseline);
let their_baseline = companion_wrapper(their_baseline);
let mut delta = their_baseline.0 as i32 - our_baseline.0 as i32;
@@ -1201,8 +1209,13 @@ impl BlockMap {
current_boundary = next_point;
}
let (new_delta, spacer) =
determine_spacer(current_boundary, current_range.end, delta);
let (new_delta, spacer) = determine_spacer(
&mut our_wrapper,
&mut companion_wrapper,
current_boundary,
current_range.end,
delta,
);
delta = new_delta;
if let Some((wrap_row, height)) = spacer {
@@ -1229,8 +1242,13 @@ impl BlockMap {
}
// Align the two sides at the start of this group.
let (delta_at_start, mut spacer_at_start) =
determine_spacer(current_boundary, current_range.start, delta);
let (delta_at_start, mut spacer_at_start) = determine_spacer(
&mut our_wrapper,
&mut companion_wrapper,
current_boundary,
current_range.start,
delta,
);
delta = delta_at_start;
while let Some(next_point) = source_points.peek().copied() {
@@ -1260,8 +1278,13 @@ impl BlockMap {
break;
}
let (delta_at_end, spacer_at_end) =
determine_spacer(current_boundary, current_range.end, delta);
let (delta_at_end, spacer_at_end) = determine_spacer(
&mut our_wrapper,
&mut companion_wrapper,
current_boundary,
current_range.end,
delta,
);
delta = delta_at_end;
if let Some((wrap_row, mut height)) = spacer_at_start {
@@ -1289,8 +1312,13 @@ impl BlockMap {
}
if last_source_point == excerpt.source_excerpt_range.end {
let (_new_delta, spacer) =
determine_spacer(last_source_point, excerpt.target_excerpt_range.end, delta);
let (_new_delta, spacer) = determine_spacer(
&mut our_wrapper,
&mut companion_wrapper,
last_source_point,
excerpt.target_excerpt_range.end,
delta,
);
if let Some((wrap_row, height)) = spacer {
result.push((
BlockPlacement::Below(wrap_row),
+1
View File
@@ -523,6 +523,7 @@ impl SplittableEditor {
convert_lhs_rows_to_rhs,
);
// stream this
for (path, diff) in path_diffs {
for (lhs, rhs) in
lhs.update_path_excerpts_from_rhs(path, &self.rhs_multibuffer, diff.clone(), cx)
+36 -30
View File
@@ -151,16 +151,16 @@ pub struct TreeSitterData {
const MAX_ROWS_IN_A_CHUNK: u32 = 50;
impl TreeSitterData {
fn clear(&mut self, snapshot: text::BufferSnapshot) {
self.chunks = RowChunks::new(snapshot, MAX_ROWS_IN_A_CHUNK);
fn clear(&mut self, snapshot: &text::BufferSnapshot) {
self.chunks = RowChunks::new(&snapshot, MAX_ROWS_IN_A_CHUNK);
self.brackets_by_chunks.get_mut().clear();
self.brackets_by_chunks
.get_mut()
.resize(self.chunks.len(), None);
}
fn new(snapshot: text::BufferSnapshot) -> Self {
let chunks = RowChunks::new(snapshot, MAX_ROWS_IN_A_CHUNK);
fn new(snapshot: &text::BufferSnapshot) -> Self {
let chunks = RowChunks::new(&snapshot, MAX_ROWS_IN_A_CHUNK);
Self {
brackets_by_chunks: Mutex::new(vec![None; chunks.len()]),
chunks,
@@ -188,12 +188,12 @@ struct BufferBranchState {
pub struct BufferSnapshot {
pub text: text::BufferSnapshot,
pub syntax: SyntaxSnapshot,
file: Option<Arc<dyn File>>,
tree_sitter_data: Arc<TreeSitterData>,
diagnostics: TreeMap<LanguageServerId, DiagnosticSet>,
remote_selections: TreeMap<ReplicaId, SelectionSet>,
language: Option<Arc<Language>>,
file: Option<Arc<dyn File>>,
non_text_state_update_count: usize,
tree_sitter_data: Arc<TreeSitterData>,
pub capability: Capability,
}
@@ -1168,14 +1168,14 @@ impl Buffer {
let buffer_id = entity_id.as_non_zero_u64().into();
async move {
let text =
TextBuffer::new_normalized(ReplicaId::LOCAL, buffer_id, Default::default(), text)
.snapshot();
TextBuffer::new_normalized(ReplicaId::LOCAL, buffer_id, Default::default(), text);
let text = text.into_snapshot();
let mut syntax = SyntaxMap::new(&text).snapshot();
if let Some(language) = language.clone() {
let language_registry = language_registry.clone();
syntax.reparse(&text, language_registry, language);
}
let tree_sitter_data = TreeSitterData::new(text.clone());
let tree_sitter_data = TreeSitterData::new(&text);
BufferSnapshot {
text,
syntax,
@@ -1198,10 +1198,10 @@ impl Buffer {
buffer_id,
Default::default(),
Rope::new(),
)
.snapshot();
);
let text = text.into_snapshot();
let syntax = SyntaxMap::new(&text).snapshot();
let tree_sitter_data = TreeSitterData::new(text.clone());
let tree_sitter_data = TreeSitterData::new(&text);
BufferSnapshot {
text,
syntax,
@@ -1226,12 +1226,12 @@ impl Buffer {
let buffer_id = entity_id.as_non_zero_u64().into();
let text =
TextBuffer::new_normalized(ReplicaId::LOCAL, buffer_id, Default::default(), text)
.snapshot();
.into_snapshot();
let mut syntax = SyntaxMap::new(&text).snapshot();
if let Some(language) = language.clone() {
syntax.reparse(&text, language_registry, language);
}
let tree_sitter_data = TreeSitterData::new(text.clone());
let tree_sitter_data = TreeSitterData::new(&text);
BufferSnapshot {
text,
syntax,
@@ -1249,18 +1249,21 @@ impl Buffer {
/// cheap, and allows reading from the buffer on a background thread.
pub fn snapshot(&self) -> BufferSnapshot {
let text = self.text.snapshot();
let mut syntax_map = self.syntax_map.lock();
syntax_map.interpolate(&text);
let syntax = syntax_map.snapshot();
let syntax = {
let mut syntax_map = self.syntax_map.lock();
syntax_map.interpolate(text);
syntax_map.snapshot()
};
let tree_sitter_data = if self.text.version() != *self.tree_sitter_data.version() {
Arc::new(TreeSitterData::new(text.clone()))
Arc::new(TreeSitterData::new(text))
} else {
self.tree_sitter_data.clone()
};
BufferSnapshot {
text,
text: text.clone(),
syntax,
tree_sitter_data,
file: self.file.clone(),
@@ -1304,7 +1307,7 @@ impl Buffer {
) -> Task<EditPreview> {
let registry = self.language_registry();
let language = self.language().cloned();
let old_snapshot = self.text.snapshot();
let old_snapshot = self.text.snapshot().clone();
let mut branch_buffer = self.text.branch();
let mut syntax_snapshot = self.syntax_map.lock().snapshot();
cx.background_spawn(async move {
@@ -1323,7 +1326,7 @@ impl Buffer {
}
EditPreview {
old_snapshot,
applied_edits_snapshot: branch_buffer.snapshot(),
applied_edits_snapshot: branch_buffer.into_snapshot(),
syntax_snapshot,
}
})
@@ -1416,8 +1419,7 @@ impl Buffer {
}
}
#[cfg(test)]
pub(crate) fn as_text_snapshot(&self) -> &text::BufferSnapshot {
pub fn as_text_snapshot(&self) -> &text::BufferSnapshot {
&self.text
}
@@ -1425,7 +1427,8 @@ impl Buffer {
/// language-related state like the syntax tree or diagnostics.
#[ztracing::instrument(skip_all)]
pub fn text_snapshot(&self) -> text::BufferSnapshot {
self.text.snapshot()
// todo lw
self.text.snapshot().clone()
}
/// The file associated with the buffer, if any.
@@ -1781,12 +1784,15 @@ impl Buffer {
self.sync_parse_timeout = timeout;
}
fn invalidate_tree_sitter_data(&mut self, snapshot: text::BufferSnapshot) {
match Arc::get_mut(&mut self.tree_sitter_data) {
fn invalidate_tree_sitter_data(
tree_sitter_data: &mut Arc<TreeSitterData>,
snapshot: &text::BufferSnapshot,
) {
match Arc::get_mut(tree_sitter_data) {
Some(tree_sitter_data) => tree_sitter_data.clear(snapshot),
None => {
let tree_sitter_data = TreeSitterData::new(snapshot);
self.tree_sitter_data = Arc::new(tree_sitter_data)
let new_tree_sitter_data = TreeSitterData::new(snapshot);
*tree_sitter_data = Arc::new(new_tree_sitter_data)
}
}
}
@@ -1817,7 +1823,7 @@ impl Buffer {
#[ztracing::instrument(skip_all)]
pub fn reparse(&mut self, cx: &mut Context<Self>, may_block: bool) {
if self.text.version() != *self.tree_sitter_data.version() {
self.invalidate_tree_sitter_data(self.text.snapshot());
Self::invalidate_tree_sitter_data(&mut self.tree_sitter_data, self.text.snapshot());
}
if self.reparse.is_some() {
return;
@@ -1898,7 +1904,7 @@ impl Buffer {
self.was_changed();
self.request_autoindent(cx, block_budget);
self.parse_status.0.send(ParseStatus::Idle).unwrap();
self.invalidate_tree_sitter_data(self.text.snapshot());
Self::invalidate_tree_sitter_data(&mut self.tree_sitter_data, &self.text.snapshot());
cx.emit(BufferEvent::Reparsed);
cx.notify();
}
+1 -1
View File
@@ -31,7 +31,7 @@ impl std::fmt::Debug for RowChunks {
}
impl RowChunks {
pub fn new(snapshot: text::BufferSnapshot, max_rows_per_chunk: u32) -> Self {
pub fn new(snapshot: &text::BufferSnapshot, max_rows_per_chunk: u32) -> Self {
let buffer_point_range = (0..snapshot.len()).to_point(&snapshot);
let last_row = buffer_point_range.end.row;
let chunks = (buffer_point_range.start.row..=last_row)
@@ -1047,7 +1047,7 @@ fn test_random_edits(
log::info!("initial text:\n{}", buffer.text());
for _ in 0..operations {
let prev_buffer = buffer.snapshot();
let prev_buffer = buffer.snapshot().clone();
let prev_syntax_map = syntax_map.snapshot();
buffer.randomly_edit(&mut rng, 3);
+107 -52
View File
@@ -678,7 +678,7 @@ impl std::hash::Hash for DiffTransformHunkInfo {
#[derive(Clone)]
pub struct ExcerptInfo {
pub id: ExcerptId,
pub buffer: BufferSnapshot,
pub buffer: Arc<BufferSnapshot>,
pub buffer_id: BufferId,
pub range: ExcerptRange<text::Anchor>,
pub end_row: MultiBufferRow,
@@ -739,7 +739,7 @@ struct Excerpt {
/// The buffer being excerpted
buffer_id: BufferId,
/// A snapshot of the buffer being excerpted
buffer: BufferSnapshot,
buffer: Arc<BufferSnapshot>,
/// The range of the buffer to be shown in the excerpt
range: ExcerptRange<text::Anchor>,
/// The last row in the excerpted slice of the buffer
@@ -1849,6 +1849,7 @@ impl MultiBuffer {
};
let mut excerpts = Vec::new();
let buffer_snapshot = Arc::new(buffer_snapshot);
while let Some((id, range)) = ranges.next() {
let locator = Locator::between(&prev_locator, &next_locator);
if let Err(ix) = buffer_state.excerpts.binary_search(&locator) {
@@ -3013,6 +3014,21 @@ impl MultiBuffer {
*has_deleted_file = false;
*has_conflict = false;
if !diffs.is_empty() {
let mut diffs_to_add = Vec::new();
for (id, diff) in diffs {
if diff.is_inverted || buffer_diff.get(id).is_none() {
if diffs_to_add.capacity() == 0 {
// we'd rather overallocate than reallocate as buffer diffs are quite big
// meaning re-allocations will be fairly expensive
diffs_to_add.reserve(diffs.len());
}
diffs_to_add.push((*id, diff.snapshot(cx)));
}
}
buffer_diff.extend(diffs_to_add);
}
let mut excerpts_to_edit = Vec::new();
let mut non_text_state_updated = false;
let mut edited = false;
@@ -3052,19 +3068,7 @@ impl MultiBuffer {
*non_text_state_update_count += 1;
}
let diffs_to_add = diffs
.iter()
.filter_map(|(id, diff)| {
if diff.is_inverted || buffer_diff.get(id).is_none() {
Some((*id, diff.snapshot(cx)))
} else {
None
}
})
.collect::<Vec<_>>();
buffer_diff.extend(diffs_to_add);
excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
excerpts_to_edit.sort_unstable_by_key(|&(locator, _, _)| locator);
let mut edits = Vec::new();
let mut new_excerpts = SumTree::default();
@@ -3075,7 +3079,6 @@ impl MultiBuffer {
let old_excerpt = cursor.item().unwrap();
let buffer = buffer.read(cx);
let buffer_id = buffer.remote_id();
let mut new_excerpt;
if buffer_edited {
edits.extend(
@@ -3103,13 +3106,13 @@ impl MultiBuffer {
old_excerpt.id,
locator.clone(),
buffer_id,
buffer.snapshot(),
Arc::new(buffer.snapshot()),
old_excerpt.range.clone(),
old_excerpt.has_trailing_newline,
);
} else {
new_excerpt = old_excerpt.clone();
new_excerpt.buffer = buffer.snapshot();
new_excerpt.buffer = Arc::new(buffer.snapshot());
}
new_excerpts.push(new_excerpt, ());
@@ -3981,7 +3984,7 @@ impl MultiBufferSnapshot {
return None;
}
let excerpt = region.excerpt;
cursor.next_excerpt();
cursor.next_excerpt_forwards();
Some(excerpt)
})
}
@@ -4308,7 +4311,7 @@ impl MultiBufferSnapshot {
{
return None;
}
cursor.next_excerpt();
cursor.next_excerpt_forwards();
}
}
})
@@ -4477,7 +4480,7 @@ impl MultiBufferSnapshot {
self.excerpts
.iter()
.next()
.map(|e| (&e.id, e.buffer_id, &e.buffer))
.map(|e| (&e.id, e.buffer_id, &*e.buffer))
} else {
None
}
@@ -5699,7 +5702,7 @@ impl MultiBufferSnapshot {
) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, ExcerptRange<text::Anchor>)> {
self.excerpts
.iter()
.map(|excerpt| (excerpt.id, &excerpt.buffer, excerpt.range.clone()))
.map(|excerpt| (excerpt.id, &*excerpt.buffer, excerpt.range.clone()))
}
fn cursor<'a, MBD, BD>(&'a self) -> MultiBufferCursor<'a, MBD, BD>
@@ -5778,16 +5781,18 @@ impl MultiBufferSnapshot {
});
if cursor
.region()
.is_some_and(|region| bounds.contains(&region.range.start.key))
.fetch_excerpt_with_range()
.is_some_and(|(_, range)| bounds.contains(&range.start.key))
{
cursor.prev_excerpt();
} else {
cursor.seek_to_start_of_current_excerpt();
}
let mut prev_region = cursor.region().cloned();
let mut prev_region = cursor
.fetch_excerpt_with_range()
.map(|(excerpt, _)| excerpt);
cursor.next_excerpt();
cursor.next_excerpt_forwards();
iter::from_fn(move || {
loop {
@@ -5795,34 +5800,34 @@ impl MultiBufferSnapshot {
return None;
}
let next_region = cursor.region()?.clone();
cursor.next_excerpt();
if !bounds.contains(&next_region.range.start.key) {
prev_region = Some(next_region);
let (next_excerpt, next_range) = cursor.fetch_excerpt_with_range()?;
cursor.next_excerpt_forwards();
if !bounds.contains(&next_range.start.key) {
prev_region = Some(next_excerpt);
continue;
}
let next_region_start = next_region.range.start.value.unwrap();
let next_region_end = if let Some(region) = cursor.region() {
region.range.start.value.unwrap()
let next_region_start = next_range.start.value.unwrap();
let next_region_end = if let Some((_, range)) = cursor.fetch_excerpt_with_range() {
range.start.value.unwrap()
} else {
self.max_point()
};
let prev = prev_region.as_ref().map(|region| ExcerptInfo {
id: region.excerpt.id,
buffer: region.excerpt.buffer.clone(),
buffer_id: region.excerpt.buffer_id,
range: region.excerpt.range.clone(),
id: region.id,
buffer: region.buffer.clone(),
buffer_id: region.buffer_id,
range: region.range.clone(),
end_row: MultiBufferRow(next_region_start.row),
});
let next = ExcerptInfo {
id: next_region.excerpt.id,
buffer: next_region.excerpt.buffer.clone(),
buffer_id: next_region.excerpt.buffer_id,
range: next_region.excerpt.range.clone(),
end_row: if next_region.excerpt.has_trailing_newline {
id: next_excerpt.id,
buffer: next_excerpt.buffer.clone(),
buffer_id: next_excerpt.buffer_id,
range: next_excerpt.range.clone(),
end_row: if next_excerpt.has_trailing_newline {
MultiBufferRow(next_region_end.row - 1)
} else {
MultiBufferRow(next_region_end.row)
@@ -5831,7 +5836,7 @@ impl MultiBufferSnapshot {
let row = MultiBufferRow(next_region_start.row);
prev_region = Some(next_region);
prev_region = Some(next_excerpt);
return Some(ExcerptBoundary { row, prev, next });
}
@@ -6048,7 +6053,7 @@ impl MultiBufferSnapshot {
cursor.next();
Some(line_indents.map(move |(buffer_row, indent)| {
let row = region_row + (buffer_row - region_buffer_row);
(MultiBufferRow(row), indent, region_buffer)
(MultiBufferRow(row), indent, region_buffer.as_ref())
}))
})
.flatten()
@@ -6092,7 +6097,7 @@ impl MultiBufferSnapshot {
cursor.prev();
Some(line_indents.map(move |(buffer_row, indent)| {
let row = region_row + (buffer_row - region_buffer_row);
(MultiBufferRow(row), indent, region_buffer)
(MultiBufferRow(row), indent, region_buffer.as_ref())
}))
})
.flatten()
@@ -7029,8 +7034,26 @@ where
fn seek_to_start_of_current_excerpt(&mut self) {
self.cached_region.take();
self.diff_transforms.seek(self.excerpts.start(), Bias::Left);
if self.diff_transforms.end().excerpt_dimension == *self.excerpts.start()
if self.diff_transforms.seek(self.excerpts.start(), Bias::Left)
&& self.diff_transforms.start().excerpt_dimension < *self.excerpts.start()
&& self.diff_transforms.next_item().is_some()
{
self.diff_transforms.next();
}
}
fn next_excerpt_forwards(&mut self) {
self.excerpts.next();
self.seek_to_start_of_current_excerpt_forward();
}
fn seek_to_start_of_current_excerpt_forward(&mut self) {
self.cached_region.take();
if self
.diff_transforms
.seek_forward(self.excerpts.start(), Bias::Left)
&& self.diff_transforms.start().excerpt_dimension < *self.excerpts.start()
&& self.diff_transforms.next_item().is_some()
{
@@ -7191,10 +7214,10 @@ where
let mut end;
let mut buffer_end;
let has_trailing_newline;
if self.diff_transforms.end().excerpt_dimension < self.excerpts.end() {
let overshoot =
self.diff_transforms.end().excerpt_dimension - *self.excerpts.start();
end = self.diff_transforms.end().output_dimension.0;
let transform_end = self.diff_transforms.end();
if transform_end.excerpt_dimension < self.excerpts.end() {
let overshoot = transform_end.excerpt_dimension - *self.excerpts.start();
end = transform_end.output_dimension.0;
buffer_end = buffer_context_start;
buffer_end += overshoot;
has_trailing_newline = false;
@@ -7228,6 +7251,38 @@ where
}
}
fn fetch_excerpt_with_range(&self) -> Option<(&'a Excerpt, Range<MBD>)> {
let excerpt = self.excerpts.item()?;
match self.diff_transforms.item()? {
&DiffTransform::DeletedHunk { .. } => {
let start = self.diff_transforms.start().output_dimension.0;
let end = self.diff_transforms.end().output_dimension.0;
Some((excerpt, start..end))
}
DiffTransform::BufferContent { .. } => {
let mut start = self.diff_transforms.start().output_dimension.0;
if self.diff_transforms.start().excerpt_dimension < *self.excerpts.start() {
let overshoot =
*self.excerpts.start() - self.diff_transforms.start().excerpt_dimension;
start += overshoot;
}
let mut end;
let transform_end = self.diff_transforms.end();
if transform_end.excerpt_dimension < self.excerpts.end() {
end = transform_end.output_dimension.0;
} else {
let overshoot =
self.excerpts.end() - self.diff_transforms.start().excerpt_dimension;
end = self.diff_transforms.start().output_dimension.0;
end += overshoot;
};
Some((excerpt, start..end))
}
}
}
fn excerpt(&self) -> Option<&'a Excerpt> {
self.excerpts.item()
}
@@ -7238,7 +7293,7 @@ impl Excerpt {
id: ExcerptId,
locator: Locator,
buffer_id: BufferId,
buffer: BufferSnapshot,
buffer: Arc<BufferSnapshot>,
range: ExcerptRange<text::Anchor>,
has_trailing_newline: bool,
) -> Self {
@@ -78,7 +78,7 @@ const MAX_ROWS_IN_A_CHUNK: u32 = 50;
impl BufferInlayHints {
pub fn new(buffer: &Entity<Buffer>, cx: &mut App) -> Self {
let chunks = RowChunks::new(buffer.read(cx).text_snapshot(), MAX_ROWS_IN_A_CHUNK);
let chunks = RowChunks::new(buffer.read(cx).as_text_snapshot(), MAX_ROWS_IN_A_CHUNK);
Self {
hints_by_chunks: vec![None; chunks.len()],
-3
View File
@@ -83,9 +83,6 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
.into_iter()
.map(|(key, value)| Edit::Insert(MapEntry { key, value }))
.collect();
if edits.is_empty() {
return;
}
self.0.edit(edits, ());
}
+10 -6
View File
@@ -104,16 +104,16 @@ impl From<BufferId> for u64 {
#[derive(Clone)]
pub struct BufferSnapshot {
replica_id: ReplicaId,
remote_id: BufferId,
visible_text: Rope,
deleted_text: Rope,
line_ending: LineEnding,
undo_map: UndoMap,
fragments: SumTree<Fragment>,
insertions: SumTree<InsertionFragment>,
insertion_slices: TreeSet<InsertionSlice>,
undo_map: UndoMap,
pub version: clock::Global,
remote_id: BufferId,
replica_id: ReplicaId,
line_ending: LineEnding,
}
#[derive(Clone, Debug)]
@@ -780,8 +780,12 @@ impl Buffer {
self.version.clone()
}
pub fn snapshot(&self) -> BufferSnapshot {
self.snapshot.clone()
pub fn snapshot(&self) -> &BufferSnapshot {
&self.snapshot
}
pub fn into_snapshot(self) -> BufferSnapshot {
self.snapshot
}
pub fn branch(&self) -> Self {