From 7524974f1976d98ebe85215951e100e1724dd822 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Dec 2021 17:15:16 +0100 Subject: [PATCH] Get everything compiling again Co-Authored-By: Nathan Sobo --- crates/editor/src/display_map.rs | 32 ++-- crates/editor/src/display_map/block_map.rs | 141 ++++++++---------- crates/editor/src/display_map/fold_map.rs | 14 +- crates/editor/src/display_map/tab_map.rs | 8 +- crates/editor/src/display_map/wrap_map.rs | 11 +- crates/editor/src/editor.rs | 164 ++++++++++----------- crates/editor/src/items.rs | 5 +- crates/go_to_line/src/go_to_line.rs | 4 +- crates/language/src/multi_buffer.rs | 116 ++------------- crates/language/src/multi_buffer/anchor.rs | 5 + crates/server/src/rpc.rs | 8 +- 11 files changed, 209 insertions(+), 299 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index e99df6b0a2..41683863e6 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -74,7 +74,7 @@ impl DisplayMap { let (wraps_snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(tabs_snapshot.clone(), edits, cx)); - let blocks_snapshot = self.block_map.read(wraps_snapshot.clone(), edits, cx); + let blocks_snapshot = self.block_map.read(wraps_snapshot.clone(), edits); DisplaySnapshot { buffer_snapshot: self.buffer.read(cx).snapshot(cx), @@ -97,13 +97,13 @@ impl DisplayMap { let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); - self.block_map.read(snapshot, edits, cx); + self.block_map.read(snapshot, edits); let (snapshot, edits) = fold_map.fold(ranges); let (snapshot, edits) = self.tab_map.sync(snapshot, edits); let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); - self.block_map.read(snapshot, edits, cx); + self.block_map.read(snapshot, edits); } pub fn unfold( @@ -118,13 +118,13 @@ impl DisplayMap { let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); - self.block_map.read(snapshot, edits, cx); + self.block_map.read(snapshot, edits); let (snapshot, edits) = fold_map.unfold(ranges); let (snapshot, edits) = self.tab_map.sync(snapshot, edits); let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); - self.block_map.read(snapshot, edits, cx); + self.block_map.read(snapshot, edits); } pub fn insert_blocks

( @@ -142,8 +142,8 @@ impl DisplayMap { let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); - let mut block_map = self.block_map.write(snapshot, edits, cx); - block_map.insert(blocks, cx) + let mut block_map = self.block_map.write(snapshot, edits); + block_map.insert(blocks) } pub fn replace_blocks(&mut self, styles: HashMap) @@ -161,8 +161,8 @@ impl DisplayMap { let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); - let mut block_map = self.block_map.write(snapshot, edits, cx); - block_map.remove(ids, cx); + let mut block_map = self.block_map.write(snapshot, edits); + block_map.remove(ids); } pub fn set_font(&self, font_id: FontId, font_size: f32, cx: &mut ModelContext) { @@ -518,7 +518,8 @@ mod tests { 20..=80 => { let mut ranges = Vec::new(); for _ in 0..rng.gen_range(1..=3) { - buffer.read_with(&cx, |buffer, _| { + buffer.read_with(&cx, |buffer, cx| { + let buffer = buffer.read(cx); let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right); let start = buffer.clip_offset(rng.gen_range(0..=end), Left); ranges.push(start..end); @@ -548,7 +549,7 @@ mod tests { let snapshot = map.update(&mut cx, |map, cx| map.snapshot(cx)); fold_count = snapshot.fold_count(); - log::info!("buffer text: {:?}", buffer.read_with(&cx, |b, _| b.text())); + log::info!("buffer text: {:?}", snapshot.buffer_snapshot.text()); log::info!("display text: {:?}", snapshot.text()); // Line boundaries @@ -566,12 +567,9 @@ mod tests { assert_eq!(prev_display_bound.column(), 0); if next_display_bound < snapshot.max_point() { assert_eq!( - buffer.read_with(&cx, |buffer, _| buffer - .as_snapshot() - .chars_at(next_buffer_bound) - .next()), + snapshot.buffer_snapshot.chars_at(next_buffer_bound).next(), Some('\n') - ) + ); } assert_eq!( @@ -705,8 +703,8 @@ mod tests { (DisplayPoint::new(2, 4), SelectionGoal::Column(10)) ); + let ix = snapshot.buffer_snapshot.text().find("seven").unwrap(); buffer.update(cx, |buffer, cx| { - let ix = buffer.text().find("seven").unwrap(); buffer.edit(vec![ix..ix], "and ", cx); }); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 00c70c361f..1b6c8a162e 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -125,13 +125,8 @@ impl BlockMap { } } - pub fn read( - &self, - wrap_snapshot: WrapSnapshot, - edits: Vec, - cx: &AppContext, - ) -> BlockSnapshot { - self.sync(&wrap_snapshot, edits, cx); + pub fn read(&self, wrap_snapshot: WrapSnapshot, edits: Vec) -> BlockSnapshot { + self.sync(&wrap_snapshot, edits); *self.wrap_snapshot.lock() = wrap_snapshot.clone(); BlockSnapshot { wrap_snapshot, @@ -139,24 +134,18 @@ impl BlockMap { } } - pub fn write( - &mut self, - wrap_snapshot: WrapSnapshot, - edits: Vec, - cx: &AppContext, - ) -> BlockMapWriter { - self.sync(&wrap_snapshot, edits, cx); + pub fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: Vec) -> BlockMapWriter { + self.sync(&wrap_snapshot, edits); *self.wrap_snapshot.lock() = wrap_snapshot; BlockMapWriter(self) } - fn sync(&self, wrap_snapshot: &WrapSnapshot, edits: Vec, cx: &AppContext) { + fn sync(&self, wrap_snapshot: &WrapSnapshot, edits: Vec) { if edits.is_empty() { return; } - let buffer = self.buffer.read(cx); - let buffer = buffer.as_snapshot(); + let buffer = wrap_snapshot.buffer_snapshot(); let mut transforms = self.transforms.lock(); let mut new_transforms = SumTree::new(); let old_row_count = transforms.summary().input_rows; @@ -378,16 +367,14 @@ impl<'a> BlockMapWriter<'a> { pub fn insert

( &mut self, blocks: impl IntoIterator>, - cx: &AppContext, ) -> Vec where P: ToOffset + Clone, { - let buffer = self.0.buffer.read(cx); - let buffer = buffer.as_snapshot(); let mut ids = Vec::new(); let mut edits = Vec::>::new(); let wrap_snapshot = &*self.0.wrap_snapshot.lock(); + let buffer = wrap_snapshot.buffer_snapshot(); for block in blocks { let id = BlockId(self.0.next_block_id.fetch_add(1, SeqCst)); @@ -435,14 +422,13 @@ impl<'a> BlockMapWriter<'a> { } } - self.0.sync(wrap_snapshot, edits, cx); + self.0.sync(wrap_snapshot, edits); ids } - pub fn remove(&mut self, block_ids: HashSet, cx: &AppContext) { - let buffer = self.0.buffer.read(cx); - let buffer = buffer.as_snapshot(); + pub fn remove(&mut self, block_ids: HashSet) { let wrap_snapshot = &*self.0.wrap_snapshot.lock(); + let buffer = wrap_snapshot.buffer_snapshot(); let mut edits = Vec::new(); let mut last_block_buffer_row = None; self.0.blocks.retain(|block| { @@ -470,7 +456,7 @@ impl<'a> BlockMapWriter<'a> { true } }); - self.0.sync(wrap_snapshot, edits, cx); + self.0.sync(wrap_snapshot, edits); } } @@ -918,32 +904,29 @@ mod tests { let (wrap_map, wraps_snapshot) = WrapMap::new(tabs_snapshot, font_id, 14.0, None, cx); let mut block_map = BlockMap::new(buffer.clone(), wraps_snapshot.clone()); - let mut writer = block_map.write(wraps_snapshot.clone(), vec![], cx); - writer.insert( - vec![ - BlockProperties { - position: Point::new(1, 0), - height: 1, - disposition: BlockDisposition::Above, - render: Arc::new(|_| Empty::new().named("block 1")), - }, - BlockProperties { - position: Point::new(1, 2), - height: 2, - disposition: BlockDisposition::Above, - render: Arc::new(|_| Empty::new().named("block 2")), - }, - BlockProperties { - position: Point::new(3, 3), - height: 3, - disposition: BlockDisposition::Below, - render: Arc::new(|_| Empty::new().named("block 3")), - }, - ], - cx, - ); + let mut writer = block_map.write(wraps_snapshot.clone(), vec![]); + writer.insert(vec![ + BlockProperties { + position: Point::new(1, 0), + height: 1, + disposition: BlockDisposition::Above, + render: Arc::new(|_| Empty::new().named("block 1")), + }, + BlockProperties { + position: Point::new(1, 2), + height: 2, + disposition: BlockDisposition::Above, + render: Arc::new(|_| Empty::new().named("block 2")), + }, + BlockProperties { + position: Point::new(3, 3), + height: 3, + disposition: BlockDisposition::Below, + render: Arc::new(|_| Empty::new().named("block 3")), + }, + ]); - let mut snapshot = block_map.read(wraps_snapshot, vec![], cx); + let mut snapshot = block_map.read(wraps_snapshot, vec![]); assert_eq!(snapshot.text(), "aaa\n\n\n\nbbb\nccc\nddd\n\n\n"); let blocks = snapshot @@ -1068,7 +1051,7 @@ mod tests { let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| { wrap_map.sync(tabs_snapshot, tab_edits, cx) }); - let mut snapshot = block_map.read(wraps_snapshot, wrap_edits, cx); + let mut snapshot = block_map.read(wraps_snapshot, wrap_edits); assert_eq!(snapshot.text(), "aaa\n\nb!!!\n\n\nbb\nccc\nddd\n\n\n"); } @@ -1088,28 +1071,25 @@ mod tests { let (_, wraps_snapshot) = WrapMap::new(tabs_snapshot, font_id, 14.0, Some(60.), cx); let mut block_map = BlockMap::new(buffer.clone(), wraps_snapshot.clone()); - let mut writer = block_map.write(wraps_snapshot.clone(), vec![], cx); - writer.insert( - vec![ - BlockProperties { - position: Point::new(1, 12), - disposition: BlockDisposition::Above, - render: Arc::new(|_| Empty::new().named("block 1")), - height: 1, - }, - BlockProperties { - position: Point::new(1, 1), - disposition: BlockDisposition::Below, - render: Arc::new(|_| Empty::new().named("block 2")), - height: 1, - }, - ], - cx, - ); + let mut writer = block_map.write(wraps_snapshot.clone(), vec![]); + writer.insert(vec![ + BlockProperties { + position: Point::new(1, 12), + disposition: BlockDisposition::Above, + render: Arc::new(|_| Empty::new().named("block 1")), + height: 1, + }, + BlockProperties { + position: Point::new(1, 1), + disposition: BlockDisposition::Below, + render: Arc::new(|_| Empty::new().named("block 2")), + height: 1, + }, + ]); // Blocks with an 'above' disposition go above their corresponding buffer line. // Blocks with a 'below' disposition go below their corresponding buffer line. - let mut snapshot = block_map.read(wraps_snapshot, vec![], cx); + let mut snapshot = block_map.read(wraps_snapshot, vec![]); assert_eq!( snapshot.text(), "one two \nthree\n\nfour five \nsix\n\nseven \neight" @@ -1166,7 +1146,7 @@ mod tests { let block_count = rng.gen_range(1..=1); let block_properties = (0..block_count) .map(|_| { - let buffer = buffer.read(cx); + let buffer = buffer.read(cx).read(cx); let position = buffer.anchor_after( buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Left), ); @@ -1180,7 +1160,7 @@ mod tests { log::info!( "inserting block {:?} {:?} with height {}", disposition, - position.to_point(&buffer.as_snapshot()), + position.to_point(&buffer), height ); BlockProperties { @@ -1198,8 +1178,8 @@ mod tests { let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| { wrap_map.sync(tabs_snapshot, tab_edits, cx) }); - let mut block_map = block_map.write(wraps_snapshot, wrap_edits, cx); - let block_ids = block_map.insert(block_properties.clone(), cx); + let mut block_map = block_map.write(wraps_snapshot, wrap_edits); + let block_ids = block_map.insert(block_properties.clone()); for (block_id, props) in block_ids.into_iter().zip(block_properties) { expected_blocks.push((block_id, props)); } @@ -1220,17 +1200,17 @@ mod tests { let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| { wrap_map.sync(tabs_snapshot, tab_edits, cx) }); - let mut block_map = block_map.write(wraps_snapshot, wrap_edits, cx); - block_map.remove(block_ids_to_remove, cx); + let mut block_map = block_map.write(wraps_snapshot, wrap_edits); + block_map.remove(block_ids_to_remove); } _ => { buffer.update(cx, |buffer, cx| { let edit_count = rng.gen_range(1..=5); let subscription = buffer.subscribe(); buffer.randomly_edit(&mut rng, edit_count, cx); - log::info!("buffer text: {:?}", buffer.text()); buffer_edits.extend(subscription.consume()); buffer_snapshot = buffer.snapshot(cx); + log::info!("buffer text: {:?}", buffer_snapshot.text()); }); } } @@ -1240,26 +1220,25 @@ mod tests { let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| { wrap_map.sync(tabs_snapshot, tab_edits, cx) }); - let mut blocks_snapshot = block_map.read(wraps_snapshot.clone(), wrap_edits, cx); + let mut blocks_snapshot = block_map.read(wraps_snapshot.clone(), wrap_edits); assert_eq!( blocks_snapshot.transforms.summary().input_rows, wraps_snapshot.max_point().row() + 1 ); log::info!("blocks text: {:?}", blocks_snapshot.text()); - let buffer = buffer.read(cx); let mut sorted_blocks = expected_blocks .iter() .cloned() .map(|(id, block)| { - let mut position = block.position.to_point(&buffer.as_snapshot()); + let mut position = block.position.to_point(&buffer_snapshot); let column = wraps_snapshot.from_point(position, Bias::Left).column(); match block.disposition { BlockDisposition::Above => { position.column = 0; } BlockDisposition::Below => { - position.column = buffer.line_len(position.row); + position.column = buffer_snapshot.line_len(position.row); } }; let row = wraps_snapshot.from_point(position, Bias::Left).row(); diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index 1b9402bcc5..1290fe33fa 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -482,6 +482,10 @@ pub struct FoldSnapshot { } impl FoldSnapshot { + pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot { + &self.buffer_snapshot + } + #[cfg(test)] pub fn text(&self) -> String { self.chunks(FoldOffset(0)..self.len(), None) @@ -1232,9 +1236,7 @@ mod tests { let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]); let fold_ranges = snapshot .folds_in_range(Point::new(1, 0)..Point::new(1, 3)) - .map(|fold| { - fold.start.to_point(&buffer.as_snapshot())..fold.end.to_point(&buffer.as_snapshot()) - }) + .map(|fold| fold.start.to_point(&buffer_snapshot)..fold.end.to_point(&buffer_snapshot)) .collect::>(); assert_eq!( fold_ranges, @@ -1254,14 +1256,14 @@ mod tests { let len = rng.gen_range(0..10); let text = RandomCharIter::new(&mut rng).take(len).collect::(); let buffer = MultiBuffer::build_simple(&text, cx); - let buffer_snapshot = buffer.read(cx).snapshot(cx); + let mut buffer_snapshot = buffer.read(cx).snapshot(cx); let mut map = FoldMap::new(buffer_snapshot.clone()).0; let (mut initial_snapshot, _) = map.read(buffer_snapshot.clone(), vec![]); let mut snapshot_edits = Vec::new(); for _ in 0..operations { - log::info!("text: {:?}", buffer.read(cx).text()); + log::info!("text: {:?}", buffer_snapshot.text()); let mut buffer_edits = Vec::new(); match rng.gen_range(0..=100) { 0..=59 => { @@ -1276,7 +1278,7 @@ mod tests { buffer_edits.extend(edits); }), }; - let buffer_snapshot = buffer.read(cx).snapshot(cx); + buffer_snapshot = buffer.read(cx).snapshot(cx); let (snapshot, edits) = map.read(buffer_snapshot.clone(), buffer_edits); snapshot_edits.push((snapshot.clone(), edits)); diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 52b4c3e6a2..2786c594b6 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -1,5 +1,5 @@ use super::fold_map::{self, FoldEdit, FoldPoint, FoldSnapshot, ToFoldPoint}; -use language::{rope, Chunk}; +use language::{multi_buffer::MultiBufferSnapshot, rope, Chunk}; use parking_lot::Mutex; use std::{cmp, mem, ops::Range}; use sum_tree::Bias; @@ -87,6 +87,10 @@ pub struct TabSnapshot { } impl TabSnapshot { + pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot { + self.fold_snapshot.buffer_snapshot() + } + pub fn text_summary(&self) -> TextSummary { self.text_summary_for_range(TabPoint::zero()..self.max_point()) } @@ -453,7 +457,7 @@ mod tests { let text = RandomCharIter::new(&mut rng).take(len).collect::(); let buffer = MultiBuffer::build_simple(&text, cx); let buffer_snapshot = buffer.read(cx).snapshot(cx); - log::info!("Buffer text: {:?}", buffer.read(cx).text()); + log::info!("Buffer text: {:?}", buffer_snapshot.text()); let (mut fold_map, _) = FoldMap::new(buffer_snapshot.clone()); fold_map.randomly_mutate(&mut rng); diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index c346ab03c3..d5c11f61dc 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -6,7 +6,7 @@ use gpui::{ fonts::FontId, text_layout::LineWrapper, Entity, ModelContext, ModelHandle, MutableAppContext, Task, }; -use language::{Chunk, Point}; +use language::{multi_buffer::MultiBufferSnapshot, Chunk, Point}; use lazy_static::lazy_static; use smol::future::yield_now; use std::{collections::VecDeque, mem, ops::Range, time::Duration}; @@ -305,6 +305,10 @@ impl WrapSnapshot { } } + pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot { + self.tab_snapshot.buffer_snapshot() + } + fn interpolate(&mut self, new_tab_snapshot: TabSnapshot, tab_edits: &[TabEdit]) -> Patch { let mut new_transforms; if tab_edits.is_empty() { @@ -1012,10 +1016,7 @@ mod tests { let buffer_snapshot = buffer.read_with(&cx, |buffer, cx| buffer.snapshot(cx)); let (mut fold_map, folds_snapshot) = FoldMap::new(buffer_snapshot.clone()); let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), tab_size); - log::info!( - "Unwrapped text (no folds): {:?}", - buffer.read_with(&cx, |buf, _| buf.text()) - ); + log::info!("Unwrapped text (no folds): {:?}", buffer_snapshot.text()); log::info!( "Unwrapped text (unexpanded tabs): {:?}", folds_snapshot.text() diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 56948bfd6e..f9e6951f8a 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -559,7 +559,7 @@ impl Editor { } pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc> { - self.buffer.read(cx).language() + self.buffer.read(cx).read(cx).language() } pub fn set_placeholder_text( @@ -575,9 +575,8 @@ impl Editor { let map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let scroll_top_buffer_offset = DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right); - self.scroll_top_anchor = self - .buffer - .read(cx) + self.scroll_top_anchor = map + .buffer_snapshot .anchor_at(scroll_top_buffer_offset, Bias::Right); self.scroll_position = vec2f( scroll_position.x(), @@ -771,9 +770,8 @@ impl Editor { let tail = self.newest_selection::(cx).tail(); self.begin_selection(position, false, click_count, cx); - let buffer = self.buffer.read(cx); let position = position.to_offset(&display_map, Bias::Left); - let tail_anchor = buffer.anchor_before(tail); + let tail_anchor = display_map.buffer_snapshot.anchor_before(tail); let pending = self.pending_selection.as_mut().unwrap(); if position >= tail { @@ -804,7 +802,7 @@ impl Editor { } let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let buffer = self.buffer.read(cx); + let buffer = &display_map.buffer_snapshot; let start; let end; let mode; @@ -874,10 +872,8 @@ impl Editor { } let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let buffer = self.buffer.read(cx); - let tail = self.newest_selection::(cx).tail(); - self.columnar_selection_tail = Some(buffer.anchor_before(tail)); + self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail)); self.select_columns( tail.to_display_point(&display_map), @@ -1293,17 +1289,18 @@ impl Editor { fn autoclose_pairs(&mut self, cx: &mut ViewContext) { let selections = self.selections::(cx); let new_autoclose_pair = self.buffer.update(cx, |buffer, cx| { - let autoclose_pair = buffer.language().and_then(|language| { + let snapshot = buffer.snapshot(cx); + let autoclose_pair = snapshot.language().and_then(|language| { let first_selection_start = selections.first().unwrap().start; let pair = language.brackets().iter().find(|pair| { - buffer.contains_str_at( + snapshot.contains_str_at( first_selection_start.saturating_sub(pair.start.len()), &pair.start, ) }); pair.and_then(|pair| { let should_autoclose = selections[1..].iter().all(|selection| { - buffer.contains_str_at( + snapshot.contains_str_at( selection.start.saturating_sub(pair.start.len()), &pair.start, ) @@ -1321,12 +1318,13 @@ impl Editor { let selection_ranges = selections .iter() .map(|selection| { - let start = selection.start.to_offset(buffer); + let start = selection.start.to_offset(&snapshot); start..start }) .collect::>(); buffer.edit(selection_ranges, &pair.end, cx); + let snapshot = buffer.snapshot(cx); if pair.end.len() == 1 { let mut delta = 0; @@ -1336,7 +1334,7 @@ impl Editor { .map(move |selection| { let offset = selection.start + delta; delta += 1; - buffer.anchor_before(offset)..buffer.anchor_after(offset) + snapshot.anchor_before(offset)..snapshot.anchor_after(offset) }) .collect(), pair, @@ -1350,7 +1348,7 @@ impl Editor { } fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext) -> bool { - let old_selections = self.selections::(cx).collect::>(); + let old_selections = self.selections::(cx); let autoclose_pair = if let Some(autoclose_pair) = self.autoclose_stack.last() { autoclose_pair } else { @@ -1446,7 +1444,7 @@ impl Editor { for selection in &mut selections { if selection.is_empty() { let char_column = buffer - .as_snapshot() + .read(cx) .text_for_range(Point::new(selection.start.row, 0)..selection.start) .flat_map(str::chars) .count(); @@ -1482,7 +1480,7 @@ impl Editor { } for row in start_row..end_row { - let indent_column = buffer.indent_column_for_line(row) as usize; + let indent_column = buffer.read(cx).indent_column_for_line(row) as usize; let columns_to_next_tab_stop = tab_size - (indent_column % tab_size); let row_start = Point::new(row, 0); buffer.edit( @@ -1515,7 +1513,8 @@ impl Editor { let selections = self.selections::(cx); let mut deletion_ranges = Vec::new(); let mut last_outdent = None; - self.buffer.update(cx, |buffer, cx| { + { + let buffer = self.buffer.read(cx).read(cx); for selection in &selections { let mut start_row = selection.start.row; let mut end_row = selection.end.row + 1; @@ -1546,6 +1545,8 @@ impl Editor { } } } + } + self.buffer.update(cx, |buffer, cx| { buffer.edit(deletion_ranges, "", cx); }); @@ -1627,7 +1628,7 @@ impl Editor { let mut selections = self.selections::(cx); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let buffer = self.buffer.read(cx); + let buffer = &display_map.buffer_snapshot; let mut edits = Vec::new(); let mut selections_iter = selections.iter().peekable(); @@ -1863,7 +1864,7 @@ impl Editor { let mut selections = self.selections::(cx); let mut clipboard_selections = Vec::with_capacity(selections.len()); { - let buffer = self.buffer.read(cx); + let buffer = self.buffer.read(cx).read(cx); let max_point = buffer.max_point(); for selection in &mut selections { let is_entire_line = selection.is_empty(); @@ -1892,27 +1893,29 @@ impl Editor { pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext) { let selections = self.selections::(cx); - let buffer = self.buffer.read(cx); - let max_point = buffer.max_point(); let mut text = String::new(); let mut clipboard_selections = Vec::with_capacity(selections.len()); - for selection in selections.iter() { - let mut start = selection.start; - let mut end = selection.end; - let is_entire_line = selection.is_empty(); - if is_entire_line { - start = Point::new(start.row, 0); - end = cmp::min(max_point, Point::new(start.row + 1, 0)); + { + let buffer = self.buffer.read(cx).read(cx); + let max_point = buffer.max_point(); + for selection in selections.iter() { + let mut start = selection.start; + let mut end = selection.end; + let is_entire_line = selection.is_empty(); + if is_entire_line { + start = Point::new(start.row, 0); + end = cmp::min(max_point, Point::new(start.row + 1, 0)); + } + let mut len = 0; + for chunk in buffer.text_for_range(start..end) { + text.push_str(chunk); + len += chunk.len(); + } + clipboard_selections.push(ClipboardSelection { + len, + is_entire_line, + }); } - let mut len = 0; - for chunk in buffer.text_for_range(start..end) { - text.push_str(chunk); - len += chunk.len(); - } - clipboard_selections.push(ClipboardSelection { - len, - is_entire_line, - }); } cx.as_mut() @@ -1954,8 +1957,7 @@ impl Editor { // selection was copied. If this selection is also currently empty, // then paste the line before the current line of the buffer. let range = if selection.is_empty() && entire_line { - let column = - selection.start.to_point(&*buffer.as_snapshot()).column as usize; + let column = selection.start.to_point(&buffer.read(cx)).column as usize; let line_start = selection.start - column; line_start..line_start } else { @@ -2352,8 +2354,7 @@ impl Editor { } pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext) { - let buffer = self.buffer.read(cx); - let cursor = buffer.len(); + let cursor = self.buffer.read(cx).read(cx).len(); let selection = Selection { id: post_inc(&mut self.next_selection_id), start: cursor, @@ -2365,8 +2366,8 @@ impl Editor { } pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext) { - let mut selection = self.selections::(cx).last().unwrap().clone(); - selection.set_head(self.buffer.read(cx).len()); + let mut selection = self.selections::(cx).first().unwrap().clone(); + selection.set_head(self.buffer.read(cx).read(cx).len()); self.update_selections(vec![selection], Some(Autoscroll::Fit), cx); } @@ -2374,7 +2375,7 @@ impl Editor { let selection = Selection { id: post_inc(&mut self.next_selection_id), start: 0, - end: self.buffer.read(cx).len(), + end: self.buffer.read(cx).read(cx).len(), reversed: false, goal: SelectionGoal::None, }; @@ -2384,8 +2385,7 @@ impl Editor { pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let mut selections = self.selections::(cx); - let buffer = self.buffer.read(cx); - let max_point = buffer.max_point(); + let max_point = display_map.buffer_snapshot.max_point(); for selection in &mut selections { let rows = selection.spanned_rows(true, &display_map).buffer_rows; selection.start = Point::new(rows.start, 0); @@ -2400,30 +2400,30 @@ impl Editor { _: &SplitSelectionIntoLines, cx: &mut ViewContext, ) { - let selections = self.selections::(cx); - let buffer = self.buffer.read(cx); - let mut to_unfold = Vec::new(); let mut new_selections = Vec::new(); - for selection in selections.iter() { - for row in selection.start.row..selection.end.row { - let cursor = Point::new(row, buffer.line_len(row)); + { + let buffer = self.buffer.read(cx).read(cx); + for selection in self.selections::(cx) { + for row in selection.start.row..selection.end.row { + let cursor = Point::new(row, buffer.line_len(row)); + new_selections.push(Selection { + id: post_inc(&mut self.next_selection_id), + start: cursor, + end: cursor, + reversed: false, + goal: SelectionGoal::None, + }); + } new_selections.push(Selection { - id: post_inc(&mut self.next_selection_id), - start: cursor, - end: cursor, + id: selection.id, + start: selection.end, + end: selection.end, reversed: false, goal: SelectionGoal::None, }); + to_unfold.push(selection.start..selection.end); } - new_selections.push(Selection { - id: selection.id, - start: selection.end, - end: selection.end, - reversed: false, - goal: SelectionGoal::None, - }); - to_unfold.push(selection.start..selection.end); } self.unfold_ranges(to_unfold, cx); self.update_selections(new_selections, Some(Autoscroll::Fit), cx); @@ -2646,9 +2646,9 @@ impl Editor { let mut edit_ranges = Vec::new(); let mut last_toggled_row = None; self.buffer.update(cx, |buffer, cx| { - let buffer_snapshot = buffer.snapshot(cx); for selection in &mut selections { edit_ranges.clear(); + let snapshot = buffer.snapshot(cx); let end_row = if selection.end.row > selection.start.row && selection.end.column == 0 { @@ -2666,13 +2666,13 @@ impl Editor { last_toggled_row = Some(row); } - if buffer_snapshot.is_line_blank(row) { + if snapshot.is_line_blank(row) { continue; } - let start = Point::new(row, buffer_snapshot.indent_column_for_line(row)); - let mut line_bytes = buffer_snapshot - .bytes_in_range(start..buffer.max_point()) + let start = Point::new(row, snapshot.indent_column_for_line(row)); + let mut line_bytes = snapshot + .bytes_in_range(start..snapshot.max_point()) .flatten() .copied(); @@ -3037,7 +3037,7 @@ impl Editor { buffer .selection_set(set_id) .unwrap() - .intersecting_selections::(range, &buffer.as_snapshot()) + .intersecting_selections::(range, &buffer.read(cx)) .map(move |s| Selection { id: s.id, start: s.start.to_display_point(&display_map), @@ -3087,7 +3087,7 @@ impl Editor { &self, cx: &AppContext, ) -> Option> { - let buffer = self.buffer.read(cx).as_snapshot(); + let buffer = self.buffer.read(cx).read(cx); self.pending_selection.as_ref().map(|pending| Selection { id: pending.selection.id, start: pending.selection.start.summary::(&buffer), @@ -3123,7 +3123,7 @@ impl Editor { self.pending_selection(cx) .or_else(|| { self.selection_set(cx) - .newest_selection(&self.buffer.read(cx).as_snapshot()) + .newest_selection(&self.buffer.read(cx).read(cx)) }) .unwrap() } @@ -3169,7 +3169,7 @@ impl Editor { if selections.len() == autoclose_pair.ranges.len() { selections .iter() - .zip(autoclose_pair.ranges.iter().map(|r| r.to_point(buffer))) + .zip(autoclose_pair.ranges.iter().map(|r| r.to_point(&buffer))) .all(|(selection, autoclose_range)| { let head = selection.head().to_point(&buffer); autoclose_range.start <= head && autoclose_range.end >= head @@ -3253,7 +3253,7 @@ impl Editor { pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext) { let selections = self.selections::(cx); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let buffer = self.buffer.read(cx); + let buffer = &display_map.buffer_snapshot; let ranges = selections .iter() .map(|s| { @@ -3351,7 +3351,7 @@ impl Editor { } pub fn text(&self, cx: &AppContext) -> String { - self.buffer.read(cx).text() + self.buffer.read(cx).read(cx).text() } pub fn display_text(&self, cx: &mut MutableAppContext) -> String { @@ -3938,7 +3938,7 @@ mod tests { ); view.unfold(&Unfold, cx); - assert_eq!(view.display_text(cx), buffer.read(cx).text()); + assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text()); }); } @@ -4465,7 +4465,7 @@ mod tests { view.delete_to_previous_word_boundary(&DeleteToPreviousWordBoundary, cx); }); - assert_eq!(buffer.read(cx).text(), "e two te four"); + assert_eq!(buffer.read(cx).read(cx).text(), "e two te four"); view.update(cx, |view, cx| { view.select_display_ranges( @@ -4481,7 +4481,7 @@ mod tests { view.delete_to_next_word_boundary(&DeleteToNextWordBoundary, cx); }); - assert_eq!(buffer.read(cx).text(), "e t te our"); + assert_eq!(buffer.read(cx).read(cx).text(), "e t te our"); } #[gpui::test] @@ -4595,7 +4595,7 @@ mod tests { }); assert_eq!( - buffer.read(cx).text(), + buffer.read(cx).read(cx).text(), "oe two three\nfou five six\nseven ten\n" ); } @@ -4626,7 +4626,7 @@ mod tests { }); assert_eq!( - buffer.read(cx).text(), + buffer.read(cx).read(cx).text(), "on two three\nfou five six\nseven ten\n" ); } @@ -5650,7 +5650,7 @@ mod tests { view.newline(&Newline, cx); assert_eq!( - view.buffer().read(cx).text(), + view.buffer().read(cx).read(cx).text(), concat!( "{ \n", // Suppress rustfmt "\n", // diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index fe4336126a..aeef3f71b9 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -76,7 +76,9 @@ impl ItemHandle for BufferItemHandle { font_properties, underline: None, }; - let language = buffer.upgrade(cx).and_then(|buf| buf.read(cx).language()); + let language = buffer + .upgrade(cx) + .and_then(|buf| buf.read(cx).read(cx).language()); let soft_wrap = match settings.soft_wrap(language) { settings::SoftWrap::None => crate::SoftWrap::None, settings::SoftWrap::EditorWidth => crate::SoftWrap::EditorWidth, @@ -327,6 +329,7 @@ impl DiagnosticMessage { let cursor_position = editor.newest_selection::(cx).head(); let buffer = editor.buffer().read(cx); let new_diagnostic = buffer + .read(cx) .diagnostics_in_range::<_, usize>(cursor_position..cursor_position) .filter(|entry| !entry.range.is_empty()) .min_by_key(|entry| (entry.diagnostic.severity, entry.range.len())) diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index b35a6fe002..4c021ac1a4 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -73,7 +73,7 @@ impl GoToLine { ( restore_state, editor.newest_selection(cx).head(), - editor.buffer().read(cx).max_point(), + editor.buffer().read(cx).read(cx).max_point(), ) }); @@ -127,7 +127,7 @@ impl GoToLine { match event { editor::Event::Blurred => cx.emit(Event::Dismissed), editor::Event::Edited => { - let line_editor = self.line_editor.read(cx).buffer().read(cx).text(); + let line_editor = self.line_editor.read(cx).buffer().read(cx).read(cx).text(); let mut components = line_editor.trim().split(&[',', ':'][..]); let row = components.next().and_then(|row| row.parse::().ok()); let column = components.next().and_then(|row| row.parse::().ok()); diff --git a/crates/language/src/multi_buffer.rs b/crates/language/src/multi_buffer.rs index 8f8274a744..35aef1aecb 100644 --- a/crates/language/src/multi_buffer.rs +++ b/crates/language/src/multi_buffer.rs @@ -13,6 +13,7 @@ use gpui::{AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Tas use parking_lot::{Mutex, MutexGuard}; pub use selection::SelectionSet; use std::{ + cell::{Ref, RefCell}, cmp, io, ops::{Range, Sub}, sync::Arc, @@ -33,7 +34,7 @@ pub type ExcerptId = Locator; #[derive(Default)] pub struct MultiBuffer { - snapshot: Mutex, + snapshot: RefCell, buffers: HashMap, subscriptions: Topic, selection_sets: HashMap, @@ -115,13 +116,18 @@ impl MultiBuffer { cx.add_model(|cx| Self::singleton(buffer, cx)) } - pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot { - self.sync(cx); - self.snapshot.lock().clone() + pub fn replica_id(&self) -> clock::ReplicaId { + todo!() } - pub fn as_snapshot(&self) -> MutexGuard { - self.snapshot.lock() + pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot { + self.sync(cx); + self.snapshot.borrow().clone() + } + + pub fn read(&self, cx: &AppContext) -> Ref { + self.sync(cx); + self.snapshot.borrow() } pub fn as_singleton(&self) -> Option<&ModelHandle> { @@ -246,7 +252,7 @@ impl MultiBuffer { let buffer = props.buffer.read(cx); let range = buffer.anchor_before(props.range.start)..buffer.anchor_after(props.range.end); - let mut snapshot = self.snapshot.lock(); + let mut snapshot = self.snapshot.borrow_mut(); let prev_id = snapshot.excerpts.last().map(|e| &e.id); let id = ExcerptId::between(prev_id.unwrap_or(&ExcerptId::min()), &ExcerptId::max()); @@ -297,7 +303,7 @@ impl MultiBuffer { } fn sync(&self, cx: &AppContext) { - let mut snapshot = self.snapshot.lock(); + let mut snapshot = self.snapshot.borrow_mut(); let mut excerpts_to_edit = Vec::new(); for buffer_state in self.buffers.values() { if buffer_state @@ -365,96 +371,6 @@ impl MultiBuffer { } } -// Methods delegating to the snapshot -impl MultiBuffer { - pub fn replica_id(&self) -> ReplicaId { - self.snapshot.lock().replica_id() - } - - pub fn text(&self) -> String { - self.snapshot.lock().text() - } - - pub fn text_for_range<'a, T: ToOffset>( - &'a self, - range: Range, - ) -> impl Iterator { - todo!(); - [].into_iter() - } - - pub fn contains_str_at(&self, _: T, _: &str) -> bool - where - T: ToOffset, - { - todo!() - } - - pub fn max_point(&self) -> Point { - self.snapshot.lock().max_point() - } - - pub fn len(&self) -> usize { - self.snapshot.lock().len() - } - - pub fn line_len(&self, row: u32) -> u32 { - self.snapshot.lock().line_len(row) - } - - pub fn is_line_blank(&self, row: u32) -> bool { - self.snapshot.lock().is_line_blank(row) - } - - pub fn indent_column_for_line(&self, row: u32) -> u32 { - self.snapshot.lock().indent_column_for_line(row) - } - - pub fn anchor_before(&self, position: T) -> Anchor { - self.snapshot.lock().anchor_before(position) - } - - pub fn anchor_after(&self, position: T) -> Anchor { - self.snapshot.lock().anchor_after(position) - } - - pub fn anchor_at(&self, position: T, bias: Bias) -> Anchor { - self.snapshot.lock().anchor_at(position, bias) - } - - pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize { - self.snapshot.lock().clip_offset(offset, bias) - } - - pub fn clip_point(&self, point: Point, bias: Bias) -> Point { - self.snapshot.lock().clip_point(point, bias) - } - - pub fn language<'a>(&self) -> Option<&'a Arc> { - todo!() - } - - pub fn parse_count(&self) -> usize { - self.snapshot.lock().parse_count() - } - - pub fn diagnostics_update_count(&self) -> usize { - self.snapshot.lock().diagnostics_update_count() - } - - pub fn diagnostics_in_range<'a, T, O>( - &'a self, - search_range: Range, - ) -> impl Iterator> + 'a - where - T: 'a + ToOffset, - O: 'a, - { - todo!(); - None.into_iter() - } -} - #[cfg(any(test, feature = "test-support"))] impl MultiBuffer { pub fn randomly_edit(&mut self, _: &mut R, _: usize, _: &mut ModelContext) { @@ -949,7 +865,7 @@ impl MultiBufferSnapshot { pub fn diagnostic_group<'a, O>( &'a self, group_id: usize, - ) -> impl Iterator, &Diagnostic)> + 'a + ) -> impl Iterator> + 'a where O: 'a, { @@ -960,7 +876,7 @@ impl MultiBufferSnapshot { pub fn diagnostics_in_range<'a, T, O>( &'a self, search_range: Range, - ) -> impl Iterator, &Diagnostic)> + 'a + ) -> impl Iterator> + 'a where T: 'a + ToOffset, O: 'a, diff --git a/crates/language/src/multi_buffer/anchor.rs b/crates/language/src/multi_buffer/anchor.rs index 033ed009b0..7bc8c85848 100644 --- a/crates/language/src/multi_buffer/anchor.rs +++ b/crates/language/src/multi_buffer/anchor.rs @@ -89,6 +89,7 @@ impl ToPoint for Anchor { pub trait AnchorRangeExt { fn cmp(&self, b: &Range, buffer: &MultiBufferSnapshot) -> Result; fn to_offset(&self, content: &MultiBufferSnapshot) -> Range; + fn to_point(&self, content: &MultiBufferSnapshot) -> Range; } impl AnchorRangeExt for Range { @@ -102,4 +103,8 @@ impl AnchorRangeExt for Range { fn to_offset(&self, content: &MultiBufferSnapshot) -> Range { self.start.to_offset(&content)..self.end.to_offset(&content) } + + fn to_point(&self, content: &MultiBufferSnapshot) -> Range { + self.start.to_point(&content)..self.end.to_point(&content) + } } diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index f3fd04ff74..144d7b93fa 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -947,8 +947,8 @@ mod tests { editor::{Editor, EditorSettings, Input}, fs::{FakeFs, Fs as _}, language::{ - tree_sitter_rust, Diagnostic, Language, LanguageConfig, LanguageRegistry, - LanguageServerConfig, MultiBuffer, Point, + tree_sitter_rust, Diagnostic, DiagnosticEntry, Language, LanguageConfig, + LanguageRegistry, LanguageServerConfig, MultiBuffer, Point, }, lsp, project::{ProjectPath, Worktree}, @@ -1036,7 +1036,9 @@ mod tests { .await .unwrap(); let buffer_b = cx_b.add_model(|cx| MultiBuffer::singleton(buffer_b, cx)); - buffer_b.read_with(&cx_b, |buf, _| assert_eq!(buf.text(), "b-contents")); + buffer_b.read_with(&cx_b, |buf, cx| { + assert_eq!(buf.read(cx).text(), "b-contents") + }); worktree_a.read_with(&cx_a, |tree, cx| assert!(tree.has_open_buffer("b.txt", cx))); let buffer_a = worktree_a .update(&mut cx_a, |tree, cx| tree.open_buffer("b.txt", cx))