From aeb68867dabdc8e13086eaad6c949c797224f3a5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 25 May 2021 11:51:29 +0200 Subject: [PATCH] Move `highlighted_text_in_range` from `Buffer` to `buffer::Snapshot` --- zed/src/editor/buffer/mod.rs | 199 ++++++++++++++----------- zed/src/editor/buffer_view.rs | 4 +- zed/src/editor/display_map/fold_map.rs | 67 ++++----- zed/src/editor/display_map/mod.rs | 91 +++++------ zed/src/editor/movement.rs | 16 +- zed/src/worktree.rs | 5 +- 6 files changed, 182 insertions(+), 200 deletions(-) diff --git a/zed/src/editor/buffer/mod.rs b/zed/src/editor/buffer/mod.rs index 6c237212898e248d529b73d69c5ac516eda56d52..dd669a317ec7799a673dd12ce4315a01f31a86dc 100644 --- a/zed/src/editor/buffer/mod.rs +++ b/zed/src/editor/buffer/mod.rs @@ -62,7 +62,11 @@ type HashMap = std::collections::HashMap; type HashSet = std::collections::HashSet; thread_local! { - pub static PARSER: RefCell = RefCell::new(Parser::new()); + static PARSER: RefCell = RefCell::new(Parser::new()); +} + +lazy_static! { + static ref QUERY_CURSORS: Mutex> = Default::default(); } pub struct Buffer { @@ -78,8 +82,7 @@ pub struct Buffer { history: History, file: Option, language: Option>, - tree: Option<(Tree, time::Global)>, - query_cursor: Mutex>, + tree: Mutex>, is_parsing: bool, selections: HashMap>, pub selections_last_update: SelectionsVersion, @@ -489,10 +492,9 @@ impl Buffer { undo_map: Default::default(), history, file, - tree: None, + tree: Mutex::new(None), is_parsing: false, language, - query_cursor: Mutex::new(Some(QueryCursor::new())), saved_mtime, selections: HashMap::default(), selections_last_update: 0, @@ -506,8 +508,14 @@ impl Buffer { result } - pub fn snapshot(&self) -> Rope { - self.visible_text.clone() + pub fn snapshot(&self) -> Snapshot { + let mut cursors = QUERY_CURSORS.lock(); + Snapshot { + text: self.visible_text.clone(), + tree: self.syntax_tree(), + language: self.language.clone(), + query_cursor: Some(cursors.pop().unwrap_or_else(|| QueryCursor::new())), + } } pub fn file(&self) -> Option<&FileHandle> { @@ -519,13 +527,13 @@ impl Buffer { new_file: Option, ctx: &mut ModelContext, ) -> Task> { - let snapshot = self.snapshot(); + let text = self.visible_text.clone(); let version = self.version.clone(); let file = self.file.clone(); ctx.spawn(|handle, mut ctx| async move { if let Some(file) = new_file.as_ref().or(file.as_ref()) { - let result = ctx.read(|ctx| file.save(snapshot, ctx.as_ref())).await; + let result = ctx.read(|ctx| file.save(text, ctx.as_ref())).await; if result.is_ok() { handle.update(&mut ctx, |me, ctx| me.did_save(version, new_file, ctx)); } @@ -552,8 +560,8 @@ impl Buffer { ctx.emit(Event::Saved); } - pub fn syntax_tree(&mut self) -> Option { - if let Some((mut tree, tree_version)) = self.tree.take() { + pub fn syntax_tree(&self) -> Option { + if let Some((tree, tree_version)) = self.tree.lock().as_mut() { let mut delta = 0_isize; for Edit { old_range, @@ -575,9 +583,8 @@ impl Buffer { }); delta += new_bytes as isize - old_bytes as isize; } - let result = tree.clone(); - self.tree = Some((tree, self.version())); - Some(result) + *tree_version = self.version(); + Some(tree.clone()) } else { None } @@ -585,6 +592,7 @@ impl Buffer { fn should_reparse(&self) -> bool { self.tree + .lock() .as_ref() .map_or(true, |(_, tree_version)| *tree_version != self.version) } @@ -616,7 +624,7 @@ impl Buffer { .await; handle.update(&mut ctx, |this, ctx| { - this.tree = Some((new_tree, new_version)); + *this.tree.lock() = Some((new_tree, new_version)); ctx.emit(Event::Reparsed); ctx.notify(); }); @@ -754,47 +762,6 @@ impl Buffer { self.visible_text.chunks_in_range(start..end) } - pub fn highlighted_text_for_range(&self, range: Range) -> HighlightedChunks { - let start = range.start.to_offset(self); - let end = range.end.to_offset(self); - let chunks = self.visible_text.chunks_in_range(start..end); - - if let (Some(language), Some((tree, _))) = (&self.language, self.tree.as_ref()) { - let mut cursor = self - .query_cursor - .lock() - .take() - .unwrap_or_else(|| QueryCursor::new()); - - cursor.set_byte_range(start, end); - let cursor_ref = unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) }; - let captures = cursor_ref.captures( - &language.highlight_query, - tree.root_node(), - TextProvider(&self.visible_text), - ); - - HighlightedChunks { - range: start..end, - chunks, - highlights: Some(Highlights { - captures: captures.peekable(), - stack: Default::default(), - theme_mapping: language.theme_mapping(), - cursor, - }), - buffer: self, - } - } else { - HighlightedChunks { - range: start..end, - chunks, - highlights: None, - buffer: self, - } - } - } - pub fn chars(&self) -> impl Iterator + '_ { self.chars_at(0) } @@ -2049,9 +2016,8 @@ impl Clone for Buffer { deferred_ops: self.deferred_ops.clone(), file: self.file.clone(), language: self.language.clone(), - tree: self.tree.clone(), + tree: Mutex::new(self.tree.lock().clone()), is_parsing: false, - query_cursor: Mutex::new(Some(QueryCursor::new())), deferred_replicas: self.deferred_replicas.clone(), replica_id: self.replica_id, local_clock: self.local_clock.clone(), @@ -2060,6 +2026,79 @@ impl Clone for Buffer { } } +pub struct Snapshot { + text: Rope, + tree: Option, + language: Option>, + query_cursor: Option, +} + +impl Snapshot { + pub fn len(&self) -> usize { + self.text.len() + } + + pub fn text(&self) -> Rope { + self.text.clone() + } + + pub fn text_for_range(&self, range: Range) -> Chunks { + self.text.chunks_in_range(range) + } + + pub fn highlighted_text_for_range(&mut self, range: Range) -> HighlightedChunks { + let chunks = self.text.chunks_in_range(range.clone()); + if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) { + let query_cursor = self.query_cursor.as_mut().unwrap(); + query_cursor.set_byte_range(range.start, range.end); + let captures = query_cursor.captures( + &language.highlight_query, + tree.root_node(), + TextProvider(&self.text), + ); + + HighlightedChunks { + range, + chunks, + highlights: Some(Highlights { + captures, + next_capture: None, + stack: Default::default(), + theme_mapping: language.theme_mapping(), + }), + } + } else { + HighlightedChunks { + range, + chunks, + highlights: None, + } + } + } + + pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize { + self.text.clip_offset(offset, bias) + } + + pub fn clip_point(&self, point: Point, bias: Bias) -> Point { + self.text.clip_point(point, bias) + } + + pub fn to_offset(&self, point: Point) -> usize { + self.text.to_offset(point) + } + + pub fn to_point(&self, offset: usize) -> Point { + self.text.to_point(offset) + } +} + +impl Drop for Snapshot { + fn drop(&mut self) { + QUERY_CURSORS.lock().push(self.query_cursor.take().unwrap()); + } +} + struct RopeBuilder<'a> { old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>, @@ -2202,9 +2241,9 @@ impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> { } struct Highlights<'a> { - captures: iter::Peekable>>, + captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>, + next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>, stack: Vec<(usize, StyleId)>, - cursor: QueryCursor, theme_mapping: ThemeMap, } @@ -2212,7 +2251,6 @@ pub struct HighlightedChunks<'a> { range: Range, chunks: Chunks<'a>, highlights: Option>, - buffer: &'a Buffer, } impl<'a> HighlightedChunks<'a> { @@ -2220,21 +2258,9 @@ impl<'a> HighlightedChunks<'a> { self.range.start = offset; self.chunks.seek(self.range.start); if let Some(highlights) = self.highlights.as_mut() { - let language = self.buffer.language.as_ref().unwrap(); - let tree = &self.buffer.tree.as_ref().unwrap().0; - let cursor_ref = - unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut highlights.cursor) }; - highlights - .cursor - .set_byte_range(self.range.start, self.range.end); highlights.stack.clear(); - highlights.captures = cursor_ref - .captures( - &language.highlight_query, - tree.root_node(), - TextProvider(&self.buffer.visible_text), - ) - .peekable(); + highlights.next_capture.take(); + highlights.captures.advance_to_byte(self.range.start); } } @@ -2258,7 +2284,11 @@ impl<'a> Iterator for HighlightedChunks<'a> { } } - while let Some((mat, capture_ix)) = highlights.captures.peek() { + if highlights.next_capture.is_none() { + highlights.next_capture = highlights.captures.next(); + } + + while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() { let capture = mat.captures[*capture_ix as usize]; if self.range.start < capture.node.start_byte() { next_capture_start = capture.node.start_byte(); @@ -2266,7 +2296,7 @@ impl<'a> Iterator for HighlightedChunks<'a> { } else { let style_id = highlights.theme_mapping.get(capture.index); highlights.stack.push((capture.node.end_byte(), style_id)); - highlights.captures.next().unwrap(); + highlights.next_capture = highlights.captures.next(); } } } @@ -2296,17 +2326,6 @@ impl<'a> Iterator for HighlightedChunks<'a> { } } -impl<'a> Drop for HighlightedChunks<'a> { - fn drop(&mut self) { - if let Some(highlights) = self.highlights.take() { - let mut buffer_cursor = self.buffer.query_cursor.lock(); - if buffer_cursor.is_none() { - *buffer_cursor = Some(highlights.cursor); - } - } - } -} - #[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)] struct FragmentId(Arc<[u16]>); @@ -3448,7 +3467,7 @@ mod tests { let buffer = Buffer::from_history(0, History::new(text.into()), None, rust_lang, ctx); assert!(buffer.is_parsing); - assert!(buffer.tree.is_none()); + assert!(buffer.syntax_tree().is_none()); buffer }); @@ -3562,7 +3581,7 @@ mod tests { fn get_tree_sexp(buffer: &ModelHandle, ctx: &gpui::TestAppContext) -> String { buffer.read_with(ctx, |buffer, _| { - buffer.tree.as_ref().unwrap().0.root_node().to_sexp() + buffer.syntax_tree().unwrap().root_node().to_sexp() }) } } diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index 55ccfbc2c98879f495e160a6d538e3cf1592888d..b8f52e5073b8e95d1676dfb7390cf5105ca275c6 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -2148,8 +2148,8 @@ impl BufferView { let mut line = String::new(); let mut styles = Vec::new(); let mut row = rows.start; - let snapshot = self.display_map.snapshot(ctx); - let chunks = snapshot.highlighted_chunks_at(rows.start, ctx); + let mut snapshot = self.display_map.snapshot(ctx); + let chunks = snapshot.highlighted_chunks_at(rows.start); let theme = settings.theme.clone(); 'outer: for (chunk, style_ix) in chunks.chain(Some(("\n", StyleId::default()))) { diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 7a975003fdb75a553a91e00593996942c0708112..8a8471d6ee2f37a0b84d67eb04d5d02eb23f6b1a 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -46,7 +46,7 @@ impl FoldMap { pub fn snapshot(&self, ctx: &AppContext) -> FoldMapSnapshot { FoldMapSnapshot { transforms: self.sync(ctx).clone(), - buffer: self.buffer.clone(), + buffer: self.buffer.read(ctx).snapshot(), } } @@ -210,11 +210,11 @@ impl FoldMap { } pub fn to_buffer_offset(&self, point: DisplayPoint, ctx: &AppContext) -> usize { - self.snapshot(ctx).to_buffer_offset(point, ctx) + self.snapshot(ctx).to_buffer_offset(point) } pub fn to_display_offset(&self, point: DisplayPoint, ctx: &AppContext) -> DisplayOffset { - self.snapshot(ctx).to_display_offset(point, ctx) + self.snapshot(ctx).to_display_offset(point) } pub fn to_buffer_point(&self, display_point: DisplayPoint, ctx: &AppContext) -> Point { @@ -394,7 +394,7 @@ impl FoldMap { pub struct FoldMapSnapshot { transforms: SumTree, - buffer: ModelHandle, + buffer: buffer::Snapshot, } impl FoldMapSnapshot { @@ -413,13 +413,12 @@ impl FoldMapSnapshot { } } - pub fn chunks_at<'a>(&'a self, offset: DisplayOffset, ctx: &'a AppContext) -> Chunks<'a> { + pub fn chunks_at(&self, offset: DisplayOffset) -> Chunks { let mut transform_cursor = self.transforms.cursor::(); transform_cursor.seek(&offset, SeekBias::Right, &()); let overshoot = offset.0 - transform_cursor.start().display.bytes; let buffer_offset = transform_cursor.start().buffer.bytes + overshoot; - let buffer = self.buffer.read(ctx); - let rope_cursor = buffer.text_for_range(buffer_offset..buffer.len()); + let rope_cursor = self.buffer.text_for_range(buffer_offset..self.buffer.len()); Chunks { transform_cursor, buffer_offset, @@ -427,34 +426,27 @@ impl FoldMapSnapshot { } } - pub fn highlighted_chunks_at<'a>( - &'a self, - offset: DisplayOffset, - ctx: &'a AppContext, - ) -> HighlightedChunks<'a> { + pub fn highlighted_chunks_at(&mut self, offset: DisplayOffset) -> HighlightedChunks { let mut transform_cursor = self.transforms.cursor::(); transform_cursor.seek(&offset, SeekBias::Right, &()); let overshoot = offset.0 - transform_cursor.start().display.bytes; let buffer_offset = transform_cursor.start().buffer.bytes + overshoot; - let buffer = self.buffer.read(ctx); HighlightedChunks { transform_cursor, buffer_offset, - buffer_chunks: buffer.highlighted_text_for_range(buffer_offset..buffer.len()), + buffer_chunks: self + .buffer + .highlighted_text_for_range(buffer_offset..self.buffer.len()), buffer_chunk: None, } } - pub fn chars_at<'a>( - &'a self, - point: DisplayPoint, - ctx: &'a AppContext, - ) -> impl Iterator + 'a { - let offset = self.to_display_offset(point, ctx); - self.chunks_at(offset, ctx).flat_map(str::chars) + pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator + 'a { + let offset = self.to_display_offset(point); + self.chunks_at(offset).flat_map(str::chars) } - pub fn to_display_offset(&self, point: DisplayPoint, ctx: &AppContext) -> DisplayOffset { + pub fn to_display_offset(&self, point: DisplayPoint) -> DisplayOffset { let mut cursor = self.transforms.cursor::(); cursor.seek(&point, SeekBias::Right, &()); let overshoot = point.0 - cursor.start().display.lines; @@ -462,27 +454,24 @@ impl FoldMapSnapshot { if !overshoot.is_zero() { let transform = cursor.item().expect("display point out of range"); assert!(transform.display_text.is_none()); - let end_buffer_offset = - (cursor.start().buffer.lines + overshoot).to_offset(self.buffer.read(ctx)); + let end_buffer_offset = self + .buffer + .to_offset(cursor.start().buffer.lines + overshoot); offset += end_buffer_offset - cursor.start().buffer.bytes; } DisplayOffset(offset) } - pub fn to_buffer_offset(&self, point: DisplayPoint, ctx: &AppContext) -> usize { + pub fn to_buffer_offset(&self, point: DisplayPoint) -> usize { let mut cursor = self.transforms.cursor::(); cursor.seek(&point, SeekBias::Right, &()); let overshoot = point.0 - cursor.start().display.lines; - (cursor.start().buffer.lines + overshoot).to_offset(self.buffer.read(ctx)) + self.buffer + .to_offset(cursor.start().buffer.lines + overshoot) } #[cfg(test)] - pub fn clip_offset( - &self, - offset: DisplayOffset, - bias: Bias, - ctx: &AppContext, - ) -> DisplayOffset { + pub fn clip_offset(&self, offset: DisplayOffset, bias: Bias) -> DisplayOffset { let mut cursor = self.transforms.cursor::(); cursor.seek(&offset, SeekBias::Right, &()); if let Some(transform) = cursor.item() { @@ -496,7 +485,7 @@ impl FoldMapSnapshot { } else { let overshoot = offset.0 - transform_start; let buffer_offset = cursor.start().buffer.bytes + overshoot; - let clipped_buffer_offset = self.buffer.read(ctx).clip_offset(buffer_offset, bias); + let clipped_buffer_offset = self.buffer.clip_offset(buffer_offset, bias); DisplayOffset( (offset.0 as isize + (clipped_buffer_offset as isize - buffer_offset as isize)) as usize, @@ -507,7 +496,7 @@ impl FoldMapSnapshot { } } - pub fn clip_point(&self, point: DisplayPoint, bias: Bias, ctx: &AppContext) -> DisplayPoint { + pub fn clip_point(&self, point: DisplayPoint, bias: Bias) -> DisplayPoint { let mut cursor = self.transforms.cursor::(); cursor.seek(&point, SeekBias::Right, &()); if let Some(transform) = cursor.item() { @@ -521,8 +510,7 @@ impl FoldMapSnapshot { } else { let overshoot = point.0 - transform_start; let buffer_position = cursor.start().buffer.lines + overshoot; - let clipped_buffer_position = - self.buffer.read(ctx).clip_point(buffer_position, bias); + let clipped_buffer_position = self.buffer.clip_point(buffer_position, bias); DisplayPoint::new( point.row(), ((point.column() as i32) + clipped_buffer_position.column as i32 @@ -1131,11 +1119,10 @@ mod tests { let offset = map.snapshot(app.as_ref()).clip_offset( DisplayOffset(rng.gen_range(0..=map.len(app.as_ref()))), Bias::Right, - app.as_ref(), ); assert_eq!( map.snapshot(app.as_ref()) - .chunks_at(offset, app.as_ref()) + .chunks_at(offset) .collect::(), &expected_text[offset.0..], ); @@ -1218,9 +1205,7 @@ mod tests { impl FoldMap { fn text(&self, app: &AppContext) -> String { - self.snapshot(app) - .chunks_at(DisplayOffset(0), app) - .collect() + self.snapshot(app).chunks_at(DisplayOffset(0)).collect() } fn merged_fold_ranges(&self, app: &AppContext) -> Vec> { diff --git a/zed/src/editor/display_map/mod.rs b/zed/src/editor/display_map/mod.rs index 1dfe340a846921d06eb4f0ffe254eadc6fe26c34..2cf9de0b8c8deaf58030d4bc659e939636cc8989 100644 --- a/zed/src/editor/display_map/mod.rs +++ b/zed/src/editor/display_map/mod.rs @@ -62,16 +62,14 @@ impl DisplayMap { } pub fn text(&self, ctx: &AppContext) -> String { - self.snapshot(ctx) - .chunks_at(DisplayPoint::zero(), ctx) - .collect() + self.snapshot(ctx).chunks_at(DisplayPoint::zero()).collect() } pub fn line(&self, display_row: u32, ctx: &AppContext) -> String { let mut result = String::new(); for chunk in self .snapshot(ctx) - .chunks_at(DisplayPoint::new(display_row, 0), ctx) + .chunks_at(DisplayPoint::new(display_row, 0)) { if let Some(ix) = chunk.find('\n') { result.push_str(&chunk[0..ix]); @@ -88,7 +86,7 @@ impl DisplayMap { let mut is_blank = true; for c in self .snapshot(ctx) - .chars_at(DisplayPoint::new(display_row, 0), ctx) + .chars_at(DisplayPoint::new(display_row, 0)) { if c == ' ' { indent += 1; @@ -138,12 +136,11 @@ impl DisplayMapSnapshot { self.folds_snapshot.buffer_rows(start_row) } - pub fn chunks_at<'a>(&'a self, point: DisplayPoint, app: &'a AppContext) -> Chunks<'a> { - let (point, expanded_char_column, to_next_stop) = - self.collapse_tabs(point, Bias::Left, app); + pub fn chunks_at(&self, point: DisplayPoint) -> Chunks { + let (point, expanded_char_column, to_next_stop) = self.collapse_tabs(point, Bias::Left); let fold_chunks = self .folds_snapshot - .chunks_at(self.folds_snapshot.to_display_offset(point, app), app); + .chunks_at(self.folds_snapshot.to_display_offset(point)); Chunks { fold_chunks, column: expanded_char_column, @@ -153,15 +150,11 @@ impl DisplayMapSnapshot { } } - pub fn highlighted_chunks_at<'a>( - &'a self, - row: u32, - app: &'a AppContext, - ) -> HighlightedChunks<'a> { + pub fn highlighted_chunks_at(&mut self, row: u32) -> HighlightedChunks { let point = DisplayPoint::new(row, 0); - let offset = self.folds_snapshot.to_display_offset(point, app); + let offset = self.folds_snapshot.to_display_offset(point); HighlightedChunks { - fold_chunks: self.folds_snapshot.highlighted_chunks_at(offset, app), + fold_chunks: self.folds_snapshot.highlighted_chunks_at(offset), column: 0, tab_size: self.tab_size, chunk: "", @@ -169,18 +162,14 @@ impl DisplayMapSnapshot { } } - pub fn chars_at<'a>( - &'a self, - point: DisplayPoint, - app: &'a AppContext, - ) -> impl Iterator + 'a { - self.chunks_at(point, app).flat_map(str::chars) + pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator + 'a { + self.chunks_at(point).flat_map(str::chars) } - pub fn column_to_chars(&self, display_row: u32, target: u32, ctx: &AppContext) -> u32 { + pub fn column_to_chars(&self, display_row: u32, target: u32) -> u32 { let mut count = 0; let mut column = 0; - for c in self.chars_at(DisplayPoint::new(display_row, 0), ctx) { + for c in self.chars_at(DisplayPoint::new(display_row, 0)) { if column >= target { break; } @@ -190,10 +179,10 @@ impl DisplayMapSnapshot { count } - pub fn column_from_chars(&self, display_row: u32, char_count: u32, ctx: &AppContext) -> u32 { + pub fn column_from_chars(&self, display_row: u32, char_count: u32) -> u32 { let mut count = 0; let mut column = 0; - for c in self.chars_at(DisplayPoint::new(display_row, 0), ctx) { + for c in self.chars_at(DisplayPoint::new(display_row, 0)) { if c == '\n' || count >= char_count { break; } @@ -203,32 +192,26 @@ impl DisplayMapSnapshot { column } - pub fn clip_point(&self, point: DisplayPoint, bias: Bias, ctx: &AppContext) -> DisplayPoint { + pub fn clip_point(&self, point: DisplayPoint, bias: Bias) -> DisplayPoint { self.expand_tabs( self.folds_snapshot - .clip_point(self.collapse_tabs(point, bias, ctx).0, bias, ctx), - ctx, + .clip_point(self.collapse_tabs(point, bias).0, bias), ) } - fn expand_tabs(&self, mut point: DisplayPoint, ctx: &AppContext) -> DisplayPoint { + fn expand_tabs(&self, mut point: DisplayPoint) -> DisplayPoint { let chars = self .folds_snapshot - .chars_at(DisplayPoint(Point::new(point.row(), 0)), ctx); + .chars_at(DisplayPoint(Point::new(point.row(), 0))); let expanded = expand_tabs(chars, point.column() as usize, self.tab_size); *point.column_mut() = expanded as u32; point } - fn collapse_tabs( - &self, - mut point: DisplayPoint, - bias: Bias, - ctx: &AppContext, - ) -> (DisplayPoint, usize, usize) { + fn collapse_tabs(&self, mut point: DisplayPoint, bias: Bias) -> (DisplayPoint, usize, usize) { let chars = self .folds_snapshot - .chars_at(DisplayPoint(Point::new(point.row(), 0)), ctx); + .chars_at(DisplayPoint(Point::new(point.row(), 0))); let expanded = point.column() as usize; let (collapsed, expanded_char_column, to_next_stop) = collapse_tabs(chars, expanded, bias, self.tab_size); @@ -276,11 +259,11 @@ impl DisplayPoint { } fn expand_tabs(self, map: &DisplayMap, ctx: &AppContext) -> Self { - map.snapshot(ctx).expand_tabs(self, ctx) + map.snapshot(ctx).expand_tabs(self) } fn collapse_tabs(self, map: &DisplayMap, bias: Bias, ctx: &AppContext) -> Self { - map.snapshot(ctx).collapse_tabs(self, bias, ctx).0 + map.snapshot(ctx).collapse_tabs(self, bias).0 } } @@ -288,7 +271,7 @@ impl Point { pub fn to_display_point(self, map: &DisplayMap, ctx: &AppContext) -> DisplayPoint { let mut display_point = map.fold_map.to_display_point(self, ctx); let snapshot = map.fold_map.snapshot(ctx); - let chars = snapshot.chars_at(DisplayPoint::new(display_point.row(), 0), ctx); + let chars = snapshot.chars_at(DisplayPoint::new(display_point.row(), 0)); *display_point.column_mut() = expand_tabs(chars, display_point.column() as usize, map.tab_size) as u32; display_point @@ -487,19 +470,19 @@ mod tests { assert_eq!( &map.snapshot(app.as_ref()) - .chunks_at(DisplayPoint::new(1, 0), app.as_ref()) + .chunks_at(DisplayPoint::new(1, 0)) .collect::()[0..10], " b bb" ); assert_eq!( &map.snapshot(app.as_ref()) - .chunks_at(DisplayPoint::new(1, 2), app.as_ref()) + .chunks_at(DisplayPoint::new(1, 2)) .collect::()[0..10], " b bbbb" ); assert_eq!( &map.snapshot(app.as_ref()) - .chunks_at(DisplayPoint::new(1, 6), app.as_ref()) + .chunks_at(DisplayPoint::new(1, 6)) .collect::()[0..13], " bbbbb\nc c" ); @@ -534,7 +517,7 @@ mod tests { ), ] { assert_eq!( - map.clip_point(DisplayPoint::new(1, input_column as u32), bias, ctx), + map.clip_point(DisplayPoint::new(1, input_column as u32), bias), DisplayPoint::new(1, output_column as u32), "clip_point(({}, {}))", 1, @@ -584,7 +567,7 @@ mod tests { ); assert_eq!( map.snapshot(ctx) - .chunks_at(DisplayPoint::new(0, "āœ… ".len() as u32), ctx) + .chunks_at(DisplayPoint::new(0, "āœ… ".len() as u32)) .collect::(), " α\nβ \nšŸ€Ī² γ" ); @@ -598,26 +581,20 @@ mod tests { ); assert_eq!( map.snapshot(ctx) - .chunks_at(DisplayPoint::new(0, "āœ… ".len() as u32), ctx) + .chunks_at(DisplayPoint::new(0, "āœ… ".len() as u32)) .collect::(), " α\nβ \nšŸ€Ī² γ" ); // Clipping display points inside of multi-byte characters assert_eq!( - map.snapshot(ctx).clip_point( - DisplayPoint::new(0, "āœ…".len() as u32 - 1), - Bias::Left, - ctx - ), + map.snapshot(ctx) + .clip_point(DisplayPoint::new(0, "āœ…".len() as u32 - 1), Bias::Left), DisplayPoint::new(0, 0) ); assert_eq!( - map.snapshot(ctx).clip_point( - DisplayPoint::new(0, "āœ…".len() as u32 - 1), - Bias::Right, - ctx - ), + map.snapshot(ctx) + .clip_point(DisplayPoint::new(0, "āœ…".len() as u32 - 1), Bias::Right), DisplayPoint::new(0, "āœ…".len() as u32) ); } diff --git a/zed/src/editor/movement.rs b/zed/src/editor/movement.rs index b40573e5e8ea0d4f91112e77967154beedf0e4ee..f7e89776ecf1d3fd24dc90e03b689ea5f63de22f 100644 --- a/zed/src/editor/movement.rs +++ b/zed/src/editor/movement.rs @@ -9,7 +9,7 @@ pub fn left(map: &DisplayMap, mut point: DisplayPoint, app: &AppContext) -> Resu *point.row_mut() -= 1; *point.column_mut() = map.line_len(point.row(), app); } - Ok(map.snapshot(app).clip_point(point, Bias::Left, app)) + Ok(map.snapshot(app).clip_point(point, Bias::Left)) } pub fn right(map: &DisplayMap, mut point: DisplayPoint, app: &AppContext) -> Result { @@ -20,7 +20,7 @@ pub fn right(map: &DisplayMap, mut point: DisplayPoint, app: &AppContext) -> Res *point.row_mut() += 1; *point.column_mut() = 0; } - Ok(map.snapshot(app).clip_point(point, Bias::Right, app)) + Ok(map.snapshot(app).clip_point(point, Bias::Right)) } pub fn up( @@ -33,12 +33,12 @@ pub fn up( let goal_column = if let SelectionGoal::Column(column) = goal { column } else { - map.column_to_chars(point.row(), point.column(), app) + map.column_to_chars(point.row(), point.column()) }; if point.row() > 0 { *point.row_mut() -= 1; - *point.column_mut() = map.column_from_chars(point.row(), goal_column, app); + *point.column_mut() = map.column_from_chars(point.row(), goal_column); } else { point = DisplayPoint::new(0, 0); } @@ -57,12 +57,12 @@ pub fn down( let goal_column = if let SelectionGoal::Column(column) = goal { column } else { - map.column_to_chars(point.row(), point.column(), app) + map.column_to_chars(point.row(), point.column()) }; if point.row() < max_point.row() { *point.row_mut() += 1; - *point.column_mut() = map.column_from_chars(point.row(), goal_column, app); + *point.column_mut() = map.column_from_chars(point.row(), goal_column); } else { point = max_point; } @@ -107,7 +107,7 @@ pub fn prev_word_boundary( let mut boundary = DisplayPoint::new(point.row(), 0); let mut column = 0; let mut prev_c = None; - for c in map.snapshot(app).chars_at(boundary, app) { + for c in map.snapshot(app).chars_at(boundary) { if column >= point.column() { break; } @@ -129,7 +129,7 @@ pub fn next_word_boundary( app: &AppContext, ) -> Result { let mut prev_c = None; - for c in map.snapshot(app).chars_at(point, app) { + for c in map.snapshot(app).chars_at(point) { if prev_c.is_some() && (c == '\n' || char_kind(prev_c.unwrap()) != char_kind(c)) { break; } diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index 33b23c8d698102f699529183f187466b9fe92c47..a50dacc4683de41d7a8c02f627746ab229122f5c 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -1483,7 +1483,8 @@ mod tests { let path = tree.update(&mut app, |tree, ctx| { let path = tree.files(0).next().unwrap().path().clone(); assert_eq!(path.file_name().unwrap(), "file1"); - smol::block_on(tree.save(&path, buffer.read(ctx).snapshot(), ctx.as_ref())).unwrap(); + smol::block_on(tree.save(&path, buffer.read(ctx).snapshot().text(), ctx.as_ref())) + .unwrap(); path }); @@ -1512,7 +1513,7 @@ mod tests { let file = app.update(|ctx| tree.file("", ctx)).await; app.update(|ctx| { assert_eq!(file.path().file_name(), None); - smol::block_on(file.save(buffer.read(ctx).snapshot(), ctx.as_ref())).unwrap(); + smol::block_on(file.save(buffer.read(ctx).snapshot().text(), ctx.as_ref())).unwrap(); }); let history = app.read(|ctx| file.load_history(ctx)).await.unwrap();