Get everything compiling again

Antonio Scandurra and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

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        | 112 ++--------------
crates/language/src/multi_buffer/anchor.rs |   5 
crates/server/src/rpc.rs                   |   8 
11 files changed, 207 insertions(+), 297 deletions(-)

Detailed changes

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<T: ToOffset>(
@@ -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<P>(
@@ -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<F>(&mut self, styles: HashMap<BlockId, F>)
@@ -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<Self>) {
@@ -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);
         });
 

crates/editor/src/display_map/block_map.rs 🔗

@@ -125,13 +125,8 @@ impl BlockMap {
         }
     }
 
-    pub fn read(
-        &self,
-        wrap_snapshot: WrapSnapshot,
-        edits: Vec<WrapEdit>,
-        cx: &AppContext,
-    ) -> BlockSnapshot {
-        self.sync(&wrap_snapshot, edits, cx);
+    pub fn read(&self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) -> 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<WrapEdit>,
-        cx: &AppContext,
-    ) -> BlockMapWriter {
-        self.sync(&wrap_snapshot, edits, cx);
+    pub fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) -> BlockMapWriter {
+        self.sync(&wrap_snapshot, edits);
         *self.wrap_snapshot.lock() = wrap_snapshot;
         BlockMapWriter(self)
     }
 
-    fn sync(&self, wrap_snapshot: &WrapSnapshot, edits: Vec<WrapEdit>, cx: &AppContext) {
+    fn sync(&self, wrap_snapshot: &WrapSnapshot, edits: Vec<WrapEdit>) {
         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<P>(
         &mut self,
         blocks: impl IntoIterator<Item = BlockProperties<P>>,
-        cx: &AppContext,
     ) -> Vec<BlockId>
     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::<Edit<u32>>::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<BlockId>, cx: &AppContext) {
-        let buffer = self.0.buffer.read(cx);
-        let buffer = buffer.as_snapshot();
+    pub fn remove(&mut self, block_ids: HashSet<BlockId>) {
         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();

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::<Vec<_>>();
         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::<String>();
         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));

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::<String>();
         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);

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<u32> {
         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()

crates/editor/src/editor.rs 🔗

@@ -559,7 +559,7 @@ impl Editor {
     }
 
     pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
-        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::<usize>(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::<Point>(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<Self>) {
         let selections = self.selections::<usize>(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::<SmallVec<[_; 32]>>();
 
                 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<Self>) -> bool {
-        let old_selections = self.selections::<usize>(cx).collect::<Vec<_>>();
+        let old_selections = self.selections::<usize>(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::<Point>(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::<Point>(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::<Point>(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<Self>) {
         let selections = self.selections::<Point>(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 mut len = 0;
-            for chunk in buffer.text_for_range(start..end) {
-                text.push_str(chunk);
-                len += chunk.len();
+        {
+            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,
+                });
             }
-            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<Self>) {
-        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<Self>) {
-        let mut selection = self.selections::<usize>(cx).last().unwrap().clone();
-        selection.set_head(self.buffer.read(cx).len());
+        let mut selection = self.selections::<usize>(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<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let mut selections = self.selections::<Point>(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<Self>,
     ) {
-        let selections = self.selections::<Point>(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::<Point>(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::<Point, _>(range, &buffer.as_snapshot())
+            .intersecting_selections::<Point, _>(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<Selection<D>> {
-        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::<D>(&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<Self>) {
         let selections = self.selections::<Point>(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",      //

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::<usize>(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()))

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::<u32>().ok());
                 let column = components.next().and_then(|row| row.parse::<u32>().ok());

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<MultiBufferSnapshot>,
+    snapshot: RefCell<MultiBufferSnapshot>,
     buffers: HashMap<usize, BufferState>,
     subscriptions: Topic,
     selection_sets: HashMap<SelectionSetId, SelectionSet>,
@@ -115,13 +116,18 @@ impl MultiBuffer {
         cx.add_model(|cx| Self::singleton(buffer, cx))
     }
 
+    pub fn replica_id(&self) -> clock::ReplicaId {
+        todo!()
+    }
+
     pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
         self.sync(cx);
-        self.snapshot.lock().clone()
+        self.snapshot.borrow().clone()
     }
 
-    pub fn as_snapshot(&self) -> MutexGuard<MultiBufferSnapshot> {
-        self.snapshot.lock()
+    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
+        self.sync(cx);
+        self.snapshot.borrow()
     }
 
     pub fn as_singleton(&self) -> Option<&ModelHandle<Buffer>> {
@@ -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<T>,
-    ) -> impl Iterator<Item = &'a str> {
-        todo!();
-        [].into_iter()
-    }
-
-    pub fn contains_str_at<T>(&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<T: ToOffset>(&self, position: T) -> Anchor {
-        self.snapshot.lock().anchor_before(position)
-    }
-
-    pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
-        self.snapshot.lock().anchor_after(position)
-    }
-
-    pub fn anchor_at<T: ToOffset>(&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<Language>> {
-        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<T>,
-    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
-    where
-        T: 'a + ToOffset,
-        O: 'a,
-    {
-        todo!();
-        None.into_iter()
-    }
-}
-
 #[cfg(any(test, feature = "test-support"))]
 impl MultiBuffer {
     pub fn randomly_edit<R: rand::Rng>(&mut self, _: &mut R, _: usize, _: &mut ModelContext<Self>) {
@@ -949,7 +865,7 @@ impl MultiBufferSnapshot {
     pub fn diagnostic_group<'a, O>(
         &'a self,
         group_id: usize,
-    ) -> impl Iterator<Item = (Range<O>, &Diagnostic)> + 'a
+    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
     where
         O: 'a,
     {
@@ -960,7 +876,7 @@ impl MultiBufferSnapshot {
     pub fn diagnostics_in_range<'a, T, O>(
         &'a self,
         search_range: Range<T>,
-    ) -> impl Iterator<Item = (Range<O>, &Diagnostic)> + 'a
+    ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
     where
         T: 'a + ToOffset,
         O: 'a,

crates/language/src/multi_buffer/anchor.rs 🔗

@@ -89,6 +89,7 @@ impl ToPoint for Anchor {
 pub trait AnchorRangeExt {
     fn cmp(&self, b: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Result<Ordering>;
     fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize>;
+    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point>;
 }
 
 impl AnchorRangeExt for Range<Anchor> {
@@ -102,4 +103,8 @@ impl AnchorRangeExt for Range<Anchor> {
     fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize> {
         self.start.to_offset(&content)..self.end.to_offset(&content)
     }
+
+    fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point> {
+        self.start.to_point(&content)..self.end.to_point(&content)
+    }
 }

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))