Detailed changes
@@ -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);
@@ -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(),
@@ -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
@@ -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),
@@ -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)
@@ -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();
}
@@ -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);
@@ -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(®ion.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()],
@@ -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, ());
}
@@ -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 {