From 3a576f0b654eb1ad19eed01de1fc7cfdc51bebcf Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 21 May 2021 12:25:24 +0200 Subject: [PATCH] Don't clone `visible_text` for splicing edits into the parse tree --- zed/src/editor/buffer/mod.rs | 28 +++++++++++++++++--------- zed/src/editor/display_map/fold_map.rs | 2 ++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/zed/src/editor/buffer/mod.rs b/zed/src/editor/buffer/mod.rs index 178f1844a4..fd1c263b30 100644 --- a/zed/src/editor/buffer/mod.rs +++ b/zed/src/editor/buffer/mod.rs @@ -76,7 +76,7 @@ pub struct Buffer { history: History, file: Option, language: Option>, - tree: Option<(Tree, time::Global, Rope)>, + tree: Option<(Tree, time::Global)>, is_parsing: bool, selections: HashMap>, pub selections_last_update: SelectionsVersion, @@ -248,16 +248,18 @@ impl UndoMap { } struct Edits<'a, F: Fn(&FragmentSummary) -> bool> { - cursor: FilterCursor<'a, F, Fragment, usize>, + deleted_text: &'a Rope, + cursor: FilterCursor<'a, F, Fragment, FragmentTextSummary>, undos: &'a UndoMap, since: time::Global, delta: isize, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Edit { pub old_range: Range, pub new_range: Range, + pub old_lines: Point, } impl Edit { @@ -549,7 +551,7 @@ impl Buffer { fn should_reparse(&self) -> bool { self.tree .as_ref() - .map_or(true, |(_, tree_version, _)| *tree_version != self.version) + .map_or(true, |(_, tree_version)| *tree_version != self.version) } fn reparse(&mut self, ctx: &mut ModelContext) { @@ -569,19 +571,18 @@ impl Buffer { .read_with(&ctx, |this, _| (this.version(), this.visible_text.clone())); let mut new_tree = None; handle.update(&mut ctx, |this, _| { - if let Some((mut tree, tree_version, old_text)) = this.tree.clone() { + if let Some((mut tree, tree_version)) = this.tree.clone() { let mut delta = 0_isize; for Edit { old_range, new_range, + old_lines, } in this.edits_since(tree_version) { let start_offset = (old_range.start as isize + delta) as usize; let start_point = new_text.to_point(start_offset); let old_bytes = old_range.end - old_range.start; let new_bytes = new_range.end - new_range.start; - let old_lines = old_text.to_point(old_range.end) - - old_text.to_point(old_range.start); tree.edit(&InputEdit { start_byte: start_offset, old_end_byte: start_offset + old_bytes, @@ -604,13 +605,12 @@ impl Buffer { .background_executor() .spawn({ let language = language.clone(); - let new_text = new_text.clone(); async move { Self::parse_text(&new_text, new_tree, &language) } }) .await; handle.update(&mut ctx, |this, ctx| { - this.tree = Some((new_tree, new_version, new_text)); + this.tree = Some((new_tree, new_version)); ctx.emit(Event::Reparsed); }); } @@ -767,6 +767,7 @@ impl Buffer { .filter(move |summary| summary.max_version.changed_since(&since_2)); Edits { + deleted_text: &self.deleted_text, cursor, undos: &self.undo_map, since, @@ -2083,7 +2084,7 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> { let mut change: Option = None; while let Some(fragment) = self.cursor.item() { - let new_offset = *self.cursor.start(); + let new_offset = self.cursor.start().visible; let old_offset = (new_offset as isize - self.delta) as usize; if !fragment.was_visible(&self.since, &self.undos) && fragment.visible { @@ -2098,13 +2099,18 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> { change = Some(Edit { old_range: old_offset..old_offset, new_range: new_offset..new_offset + fragment.len(), + old_lines: Point::zero(), }); self.delta += fragment.len() as isize; } } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible { + let deleted_start = self.cursor.start().deleted; + let old_lines = self.deleted_text.to_point(deleted_start + fragment.len()) + - self.deleted_text.to_point(deleted_start); if let Some(ref mut change) = change { if change.new_range.end == new_offset { change.old_range.end += fragment.len(); + change.old_lines += &old_lines; self.delta -= fragment.len() as isize; } else { break; @@ -2113,6 +2119,7 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> { change = Some(Edit { old_range: old_offset..old_offset + fragment.len(), new_range: new_offset..new_offset, + old_lines, }); self.delta -= fragment.len() as isize; } @@ -2594,6 +2601,7 @@ mod tests { for Edit { old_range, new_range, + .. } in buffer.edits_since(old_buffer.version.clone()) { let old_len = old_range.end - old_range.start; diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 243fabf0a6..5615105359 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -100,6 +100,7 @@ impl FoldMap { edits.push(Edit { old_range: range.clone(), new_range: range.clone(), + ..Default::default() }); } } @@ -144,6 +145,7 @@ impl FoldMap { edits.push(Edit { old_range: offset_range.clone(), new_range: offset_range, + ..Default::default() }); fold_ixs_to_delete.push(*folds_cursor.start()); folds_cursor.next();