From 97a8a8ed43f975536d60d617fe7974cb833f62be Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 10 Apr 2021 00:05:09 -0600 Subject: [PATCH] Remove unsafe code from App::test_async I don't actually think it was correct to allow the future to borrow a mutable app reference. I went back to passing a wrapper around the refcell to async tests. They'll be a bit more annoying to write but also totally safe. --- gpui/src/app.rs | 210 +++++++++++-------------- zed/src/editor/buffer_element.rs | 20 +-- zed/src/editor/buffer_view.rs | 110 ++++++------- zed/src/editor/display_map/fold_map.rs | 18 +-- zed/src/editor/display_map/mod.rs | 10 +- zed/src/file_finder.rs | 40 ++--- zed/src/workspace/mod.rs | 4 +- zed/src/workspace/workspace.rs | 22 +-- zed/src/workspace/workspace_view.rs | 138 ++++++++-------- zed/src/worktree/worktree.rs | 60 ++++--- 10 files changed, 317 insertions(+), 315 deletions(-) diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 48720eabcb..702fc952a7 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -45,8 +45,8 @@ pub trait View: Entity { } } -pub trait ModelAsRef { - fn model(&self, handle: &ModelHandle) -> &T; +pub trait ReadModel { + fn read_model(&self, handle: &ModelHandle) -> &T; } pub trait UpdateModel { @@ -56,8 +56,8 @@ pub trait UpdateModel { F: FnOnce(&mut T, &mut ModelContext) -> S; } -pub trait ViewAsRef { - fn view(&self, handle: &ViewHandle) -> &T; +pub trait ReadView { + fn read_view(&self, handle: &ViewHandle) -> &T; } pub trait UpdateView { @@ -84,6 +84,9 @@ pub enum MenuItem<'a> { #[derive(Clone)] pub struct App(Rc>); +#[derive(Clone)] +pub struct TestAppContext(Rc>); + impl App { pub fn test T>( asset_source: A, @@ -101,27 +104,21 @@ impl App { f(&mut *ctx) } - pub fn test_async<'a, T, F, A: AssetSource, Fn>(asset_source: A, f: Fn) -> T + pub fn test_async(asset_source: A, f: Fn) -> T where - Fn: FnOnce(&'a mut MutableAppContext) -> F, - F: Future + 'a, + Fn: FnOnce(TestAppContext) -> F, + F: Future, { let platform = platform::test::platform(); let foreground = Rc::new(executor::Foreground::test()); - let ctx = Rc::new(RefCell::new(MutableAppContext::new( + let ctx = TestAppContext(Rc::new(RefCell::new(MutableAppContext::new( foreground.clone(), Rc::new(platform), asset_source, - ))); - let mut ctx_ref = ctx.borrow_mut(); - ctx_ref.weak_self = Some(Rc::downgrade(&ctx)); - let ctx = &mut *ctx_ref; + )))); + ctx.0.borrow_mut().weak_self = Some(Rc::downgrade(&ctx.0)); - // TODO - is there a better way of getting this to compile? - let ctx = unsafe { std::mem::transmute(ctx) }; let future = f(ctx); - - drop(ctx_ref); smol::block_on(foreground.run(future)) } @@ -208,42 +205,27 @@ impl App { where F: 'static + FnOnce(&mut MutableAppContext), { - let platform = self.platform(); + let platform = self.0.borrow().platform.clone(); platform.run(Box::new(move || { let mut ctx = self.0.borrow_mut(); on_finish_launching(&mut *ctx); })) } - pub fn on_window_invalidated( - &self, - window_id: usize, - callback: F, - ) { - self.0 - .borrow_mut() - .on_window_invalidated(window_id, callback); + pub fn font_cache(&self) -> Arc { + self.0.borrow().font_cache.clone() } - pub fn add_action(&self, name: S, handler: F) - where - S: Into, - V: View, - T: Any, - F: 'static + FnMut(&mut V, &T, &mut ViewContext), - { - self.0.borrow_mut().add_action(name, handler); - } - - pub fn add_global_action(&self, name: S, handler: F) - where - S: Into, - T: 'static + Any, - F: 'static + FnMut(&T, &mut MutableAppContext), - { - self.0.borrow_mut().add_global_action(name, handler); + fn update T>(&mut self, callback: F) -> T { + let mut state = self.0.borrow_mut(); + state.pending_flushes += 1; + let result = callback(&mut *state); + state.flush_effects(); + result } +} +impl TestAppContext { pub fn dispatch_action( &self, window_id: usize, @@ -259,10 +241,6 @@ impl App { ); } - pub fn add_bindings>(&self, bindings: T) { - self.0.borrow_mut().add_bindings(bindings); - } - pub fn dispatch_keystroke( &self, window_id: usize, @@ -329,7 +307,7 @@ impl App { handle } - pub fn read T>(&mut self, callback: F) -> T { + pub fn read T>(&self, callback: F) -> T { callback(self.0.borrow().downgrade()) } @@ -354,7 +332,7 @@ impl App { } } -impl UpdateModel for App { +impl UpdateModel for TestAppContext { fn update_model(&mut self, handle: &ModelHandle, update: F) -> S where T: Entity, @@ -368,7 +346,7 @@ impl UpdateModel for App { } } -impl UpdateView for App { +impl UpdateView for TestAppContext { fn update_view(&mut self, handle: &ViewHandle, update: F) -> S where T: View, @@ -1249,8 +1227,8 @@ impl MutableAppContext { } } -impl ModelAsRef for MutableAppContext { - fn model(&self, handle: &ModelHandle) -> &T { +impl ReadModel for MutableAppContext { + fn read_model(&self, handle: &ModelHandle) -> &T { if let Some(model) = self.ctx.models.get(&handle.model_id) { model .as_any() @@ -1287,8 +1265,8 @@ impl UpdateModel for MutableAppContext { } } -impl ViewAsRef for MutableAppContext { - fn view(&self, handle: &ViewHandle) -> &T { +impl ReadView for MutableAppContext { + fn read_view(&self, handle: &ViewHandle) -> &T { if let Some(window) = self.ctx.windows.get(&handle.window_id) { if let Some(view) = window.views.get(&handle.view_id) { view.as_any().downcast_ref().expect("Downcast is type safe") @@ -1387,8 +1365,8 @@ impl AppContext { } } -impl ModelAsRef for AppContext { - fn model(&self, handle: &ModelHandle) -> &T { +impl ReadModel for AppContext { + fn read_model(&self, handle: &ModelHandle) -> &T { if let Some(model) = self.models.get(&handle.model_id) { model .as_any() @@ -1400,8 +1378,8 @@ impl ModelAsRef for AppContext { } } -impl ViewAsRef for AppContext { - fn view(&self, handle: &ViewHandle) -> &T { +impl ReadView for AppContext { + fn read_view(&self, handle: &ViewHandle) -> &T { if let Some(window) = self.windows.get(&handle.window_id) { if let Some(view) = window.views.get(&handle.view_id) { view.as_any() @@ -1672,9 +1650,9 @@ impl<'a, T: Entity> ModelContext<'a, T> { } } -impl ModelAsRef for ModelContext<'_, M> { - fn model(&self, handle: &ModelHandle) -> &T { - self.app.model(handle) +impl ReadModel for ModelContext<'_, M> { + fn read_model(&self, handle: &ModelHandle) -> &T { + self.app.read_model(handle) } } @@ -1927,9 +1905,9 @@ impl<'a, T: View> ViewContext<'a, T> { } } -impl ModelAsRef for ViewContext<'_, V> { - fn model(&self, handle: &ModelHandle) -> &T { - self.app.model(handle) +impl ReadModel for ViewContext<'_, V> { + fn read_model(&self, handle: &ModelHandle) -> &T { + self.app.read_model(handle) } } @@ -1943,9 +1921,9 @@ impl UpdateModel for ViewContext<'_, V> { } } -impl ViewAsRef for ViewContext<'_, V> { - fn view(&self, handle: &ViewHandle) -> &T { - self.app.view(handle) +impl ReadView for ViewContext<'_, V> { + fn read_view(&self, handle: &ViewHandle) -> &T { + self.app.read_view(handle) } } @@ -1994,8 +1972,8 @@ impl ModelHandle { self.model_id } - pub fn as_ref<'a, A: ModelAsRef>(&self, app: &'a A) -> &'a T { - app.model(self) + pub fn read<'a, A: ReadModel>(&self, app: &'a A) -> &'a T { + app.read_model(self) } pub fn update(&self, app: &mut A, update: F) -> S @@ -2122,8 +2100,8 @@ impl ViewHandle { self.view_id } - pub fn as_ref<'a, A: ViewAsRef>(&self, app: &'a A) -> &'a T { - app.view(self) + pub fn read<'a, A: ReadView>(&self, app: &'a A) -> &'a T { + app.read_view(self) } pub fn update(&self, app: &mut A, update: F) -> S @@ -2470,9 +2448,9 @@ mod tests { ctx.notify(); ctx.emit(2); }); - assert_eq!(handle_1.as_ref(app).events, vec!["updated".to_string()]); + assert_eq!(handle_1.read(app).events, vec!["updated".to_string()]); assert_eq!( - handle_2.as_ref(app).events, + handle_2.read(app).events, vec![ "observed event 1".to_string(), "notified".to_string(), @@ -2518,10 +2496,10 @@ mod tests { }); handle_2.update(app, |_, c| c.emit(7)); - assert_eq!(handle_1.as_ref(app).events, vec![7]); + assert_eq!(handle_1.read(app).events, vec![7]); handle_2.update(app, |_, c| c.emit(5)); - assert_eq!(handle_1.as_ref(app).events, vec![7, 10, 5]); + assert_eq!(handle_1.read(app).events, vec![7, 10, 5]); }) } @@ -2544,9 +2522,9 @@ mod tests { handle_1.update(app, |_, c| { c.observe(&handle_2, move |model, observed, c| { - model.events.push(observed.as_ref(c).count); + model.events.push(observed.read(c).count); c.observe(&handle_2b, |model, observed, c| { - model.events.push(observed.as_ref(c).count * 2); + model.events.push(observed.read(c).count * 2); }); }); }); @@ -2555,13 +2533,13 @@ mod tests { model.count = 7; c.notify() }); - assert_eq!(handle_1.as_ref(app).events, vec![7]); + assert_eq!(handle_1.read(app).events, vec![7]); handle_2.update(app, |model, c| { model.count = 5; c.notify() }); - assert_eq!(handle_1.as_ref(app).events, vec![7, 10, 5]) + assert_eq!(handle_1.read(app).events, vec![7, 10, 5]) }) } @@ -2576,25 +2554,25 @@ mod tests { type Event = (); } - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let handle = app.add_model(|_| Model::default()); handle - .update(app, |_, c| { + .update(&mut app, |_, c| { c.spawn(async { 7 }, |model, output, _| { model.count = output; }) }) .await; - assert_eq!(handle.as_ref(app).count, 7); + app.read(|ctx| assert_eq!(handle.read(ctx).count, 7)); handle - .update(app, |_, c| { + .update(&mut app, |_, c| { c.spawn(async { 14 }, |model, output, _| { model.count = output; }) }) .await; - assert_eq!(handle.as_ref(app).count, 14); + app.read(|ctx| assert_eq!(handle.read(ctx).count, 14)); }); } @@ -2609,10 +2587,10 @@ mod tests { type Event = (); } - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let handle = app.add_model(|_| Model::default()); handle - .update(app, |_, c| { + .update(&mut app, |_, c| { c.spawn_stream( smol::stream::iter(vec![1, 2, 3]), |model, output, _| { @@ -2624,7 +2602,7 @@ mod tests { ) }) .await; - assert_eq!(handle.as_ref(app).events, [Some(1), Some(2), Some(3), None]) + app.read(|ctx| assert_eq!(handle.read(ctx).events, [Some(1), Some(2), Some(3), None])); }) } @@ -2674,9 +2652,9 @@ mod tests { ctx.emit(1); ctx.emit(2); }); - assert_eq!(handle_1.as_ref(app).events, vec!["updated".to_string()]); + assert_eq!(handle_1.read(app).events, vec!["updated".to_string()]); assert_eq!( - handle_2.as_ref(app).events, + handle_2.read(app).events, vec![ "observed event 1".to_string(), "observed event 2".to_string(), @@ -2742,13 +2720,13 @@ mod tests { }); handle_2.update(app, |_, c| c.emit(7)); - assert_eq!(handle_1.as_ref(app).events, vec![7]); + assert_eq!(handle_1.read(app).events, vec![7]); handle_2.update(app, |_, c| c.emit(5)); - assert_eq!(handle_1.as_ref(app).events, vec![7, 10, 5]); + assert_eq!(handle_1.read(app).events, vec![7, 10, 5]); handle_3.update(app, |_, c| c.emit(9)); - assert_eq!(handle_1.as_ref(app).events, vec![7, 10, 5, 9]); + assert_eq!(handle_1.read(app).events, vec![7, 10, 5, 9]); }) } @@ -2837,7 +2815,7 @@ mod tests { view.update(app, |_, c| { c.observe(&model, |me, observed, c| { - me.events.push(observed.as_ref(c).count) + me.events.push(observed.read(c).count) }); }); @@ -2845,7 +2823,7 @@ mod tests { model.count = 11; c.notify(); }); - assert_eq!(view.as_ref(app).events, vec![11]); + assert_eq!(view.read(app).events, vec![11]); }) } @@ -2942,7 +2920,7 @@ mod tests { }); assert_eq!( - view_1.as_ref(app).events, + view_1.read(app).events, [ "self focused".to_string(), "self blurred".to_string(), @@ -2975,24 +2953,24 @@ mod tests { } } - App::test_async((), |app| async move { - let (_, handle) = app.add_window(|_| View::default()); + App::test_async((), |mut app| async move { + let handle = app.add_window(|_| View::default()).1; handle - .update(app, |_, c| { + .update(&mut app, |_, c| { c.spawn(async { 7 }, |me, output, _| { me.count = output; }) }) .await; - assert_eq!(handle.as_ref(app).count, 7); + app.read(|ctx| assert_eq!(handle.read(ctx).count, 7)); handle - .update(app, |_, c| { + .update(&mut app, |_, c| { c.spawn(async { 14 }, |me, output, _| { me.count = output; }) }) .await; - assert_eq!(handle.as_ref(app).count, 14); + app.read(|ctx| assert_eq!(handle.read(ctx).count, 14)); }); } @@ -3017,10 +2995,10 @@ mod tests { } } - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let (_, handle) = app.add_window(|_| View::default()); handle - .update(app, |_, c| { + .update(&mut app, |_, c| { c.spawn_stream( smol::stream::iter(vec![1_usize, 2, 3]), |me, output, _| { @@ -3033,7 +3011,7 @@ mod tests { }) .await; - assert_eq!(handle.as_ref(app).events, [Some(1), Some(2), Some(3), None]) + app.read(|ctx| assert_eq!(handle.read(ctx).events, [Some(1), Some(2), Some(3), None])) }); } @@ -3335,49 +3313,49 @@ mod tests { type Event = (); } - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let model = app.add_model(|_| Model); let (_, view) = app.add_window(|_| View); - model.update(app, |_, ctx| { + model.update(&mut app, |_, ctx| { ctx.spawn(async {}, |_, _, _| {}).detach(); // Cancel this task drop(ctx.spawn(async {}, |_, _, _| {})); }); - view.update(app, |_, ctx| { + view.update(&mut app, |_, ctx| { ctx.spawn(async {}, |_, _, _| {}).detach(); // Cancel this task drop(ctx.spawn(async {}, |_, _, _| {})); }); - assert!(!app.future_handlers.borrow().is_empty()); + assert!(!app.0.borrow().future_handlers.borrow().is_empty()); app.finish_pending_tasks().await; - assert!(app.future_handlers.borrow().is_empty()); + assert!(app.0.borrow().future_handlers.borrow().is_empty()); app.finish_pending_tasks().await; // Don't block if there are no tasks - model.update(app, |_, ctx| { + model.update(&mut app, |_, ctx| { ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {}) .detach(); // Cancel this task drop(ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {})); }); - view.update(app, |_, ctx| { + view.update(&mut app, |_, ctx| { ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {}) .detach(); // Cancel this task drop(ctx.spawn_stream(smol::stream::iter(vec![1, 2, 3]), |_, _, _| {}, |_, _| {})); }); - assert!(!app.stream_handlers.borrow().is_empty()); + assert!(!app.0.borrow().stream_handlers.borrow().is_empty()); app.finish_pending_tasks().await; - assert!(app.stream_handlers.borrow().is_empty()); + assert!(app.0.borrow().stream_handlers.borrow().is_empty()); app.finish_pending_tasks().await; // Don't block if there are no tasks // Tasks are considered finished when we drop handles let mut tasks = Vec::new(); - model.update(app, |_, ctx| { + model.update(&mut app, |_, ctx| { tasks.push(Box::new(ctx.spawn(async {}, |_, _, _| {}))); tasks.push(Box::new(ctx.spawn_stream( smol::stream::iter(vec![1, 2, 3]), @@ -3386,7 +3364,7 @@ mod tests { ))); }); - view.update(app, |_, ctx| { + view.update(&mut app, |_, ctx| { tasks.push(Box::new(ctx.spawn(async {}, |_, _, _| {}))); tasks.push(Box::new(ctx.spawn_stream( smol::stream::iter(vec![1, 2, 3]), @@ -3395,12 +3373,12 @@ mod tests { ))); }); - assert!(!app.stream_handlers.borrow().is_empty()); + assert!(!app.0.borrow().stream_handlers.borrow().is_empty()); let finish_pending_tasks = app.finish_pending_tasks(); drop(tasks); finish_pending_tasks.await; - assert!(app.stream_handlers.borrow().is_empty()); + assert!(app.0.borrow().stream_handlers.borrow().is_empty()); app.finish_pending_tasks().await; // Don't block if there are no tasks }); } diff --git a/zed/src/editor/buffer_element.rs b/zed/src/editor/buffer_element.rs index e00c11f1fd..6141c0b7c6 100644 --- a/zed/src/editor/buffer_element.rs +++ b/zed/src/editor/buffer_element.rs @@ -37,7 +37,7 @@ impl BufferElement { ctx: &mut EventContext, ) -> bool { if paint.text_bounds.contains_point(position) { - let view = self.view.as_ref(ctx.app); + let view = self.view.read(ctx.app); let position = paint.point_for_position(view, layout, position, ctx.font_cache, ctx.app); ctx.dispatch_action("buffer:select", SelectAction::Begin { position, add: cmd }); @@ -48,7 +48,7 @@ impl BufferElement { } fn mouse_up(&self, _position: Vector2F, ctx: &mut EventContext) -> bool { - if self.view.as_ref(ctx.app).is_selecting() { + if self.view.read(ctx.app).is_selecting() { ctx.dispatch_action("buffer:select", SelectAction::End); true } else { @@ -63,7 +63,7 @@ impl BufferElement { paint: &mut PaintState, ctx: &mut EventContext, ) -> bool { - let view = self.view.as_ref(ctx.app); + let view = self.view.read(ctx.app); if view.is_selecting() { let rect = paint.text_bounds; @@ -145,7 +145,7 @@ impl BufferElement { return false; } - let view = self.view.as_ref(ctx.app); + let view = self.view.read(ctx.app); let font_cache = &ctx.font_cache; let layout_cache = &ctx.text_layout_cache; let max_glyph_width = view.em_width(font_cache); @@ -167,7 +167,7 @@ impl BufferElement { } fn paint_gutter(&mut self, rect: RectF, layout: &LayoutState, ctx: &mut PaintContext) { - let view = self.view.as_ref(ctx.app); + let view = self.view.read(ctx.app); let line_height = view.line_height(ctx.font_cache); let scroll_top = view.scroll_position().y() * line_height; @@ -197,7 +197,7 @@ impl BufferElement { } fn paint_text(&mut self, bounds: RectF, layout: &LayoutState, ctx: &mut PaintContext) { - let view = self.view.as_ref(ctx.app); + let view = self.view.read(ctx.app); let line_height = view.line_height(ctx.font_cache); let descent = view.font_descent(ctx.font_cache); let start_row = view.scroll_position().y() as u32; @@ -313,14 +313,14 @@ impl Element for BufferElement { let app = ctx.app; let mut size = constraint.max; if size.y().is_infinite() { - let view = self.view.as_ref(app); + let view = self.view.read(app); size.set_y((view.max_point(app).row() + 1) as f32 * view.line_height(ctx.font_cache)); } if size.x().is_infinite() { unimplemented!("we don't yet handle an infinite width constraint on buffer elements"); } - let view = self.view.as_ref(app); + let view = self.view.read(app); let font_cache = &ctx.font_cache; let layout_cache = &ctx.text_layout_cache; let line_height = view.line_height(font_cache); @@ -404,7 +404,7 @@ impl Element for BufferElement { if let Some(layout) = layout { let app = ctx.app.downgrade(); - let view = self.view.as_ref(app); + let view = self.view.read(app); view.clamp_scroll_left( layout .scroll_max(view, ctx.font_cache, ctx.text_layout_cache, app) @@ -437,7 +437,7 @@ impl Element for BufferElement { layout.text_size, ); - if self.view.as_ref(ctx.app).is_gutter_visible() { + if self.view.read(ctx.app).is_gutter_visible() { self.paint_gutter(gutter_bounds, layout, ctx); } self.paint_text(text_bounds, layout, ctx); diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index b7974a3a2e..fadf782280 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -125,7 +125,7 @@ impl BufferView { }); ctx.observe(&display_map, Self::on_display_map_changed); - let buffer_ref = buffer.as_ref(ctx); + let buffer_ref = buffer.read(ctx); Self { handle: ctx.handle().downgrade(), buffer, @@ -188,7 +188,7 @@ impl BufferView { return false; } - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); let visible_lines = viewport_height / line_height; let first_cursor_top = self .selections @@ -238,7 +238,7 @@ impl BufferView { layouts: &[Arc], app: &AppContext, ) { - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); let mut target_left = std::f32::INFINITY; let mut target_right = 0.0_f32; @@ -287,7 +287,7 @@ impl BufferView { ctx.emit(Event::Activate); } - let display_map = self.display_map.as_ref(ctx); + let display_map = self.display_map.read(ctx); let cursor = display_map .anchor_before(position, Bias::Left, ctx.app()) .unwrap(); @@ -312,8 +312,8 @@ impl BufferView { scroll_position: Vector2F, ctx: &mut ViewContext, ) { - let buffer = self.buffer.as_ref(ctx); - let map = self.display_map.as_ref(ctx); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); let cursor = map.anchor_before(position, Bias::Left, ctx.app()).unwrap(); if let Some(selection) = self.pending_selection.as_mut() { selection.set_head(buffer, cursor); @@ -347,8 +347,8 @@ impl BufferView { where T: IntoIterator>, { - let buffer = self.buffer.as_ref(ctx); - let map = self.display_map.as_ref(ctx); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); let mut selections = Vec::new(); for range in ranges { selections.push(Selection { @@ -366,7 +366,7 @@ impl BufferView { } fn insert(&mut self, text: &String, ctx: &mut ViewContext) { - let buffer = self.buffer.as_ref(ctx); + let buffer = self.buffer.read(ctx); let mut offset_ranges = SmallVec::<[Range; 32]>::new(); for selection in &self.selections { let start = selection.start.to_offset(buffer).unwrap(); @@ -381,7 +381,7 @@ impl BufferView { }; }); - let buffer = self.buffer.as_ref(ctx); + let buffer = self.buffer.read(ctx); let char_count = text.chars().count() as isize; let mut delta = 0_isize; self.selections = offset_ranges @@ -416,8 +416,8 @@ impl BufferView { } pub fn backspace(&mut self, _: &(), ctx: &mut ViewContext) { - let buffer = self.buffer.as_ref(ctx); - let map = self.display_map.as_ref(ctx); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); for selection in &mut self.selections { if selection.range(buffer).is_empty() { let head = selection.head().to_display_point(map, ctx.app()).unwrap(); @@ -439,7 +439,7 @@ impl BufferView { pub fn move_left(&mut self, _: &(), ctx: &mut ViewContext) { { let app = ctx.app(); - let map = self.display_map.as_ref(ctx); + let map = self.display_map.read(ctx); for selection in &mut self.selections { let start = selection.start.to_display_point(map, app).unwrap(); let end = selection.end.to_display_point(map, app).unwrap(); @@ -462,8 +462,8 @@ impl BufferView { pub fn select_left(&mut self, _: &(), ctx: &mut ViewContext) { { - let buffer = self.buffer.as_ref(ctx); - let map = self.display_map.as_ref(ctx); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); for selection in &mut self.selections { let head = selection.head().to_display_point(map, ctx.app()).unwrap(); let cursor = map @@ -483,7 +483,7 @@ impl BufferView { pub fn move_right(&mut self, _: &(), ctx: &mut ViewContext) { { let app = ctx.app(); - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); for selection in &mut self.selections { let start = selection.start.to_display_point(map, app).unwrap(); let end = selection.end.to_display_point(map, app).unwrap(); @@ -506,9 +506,9 @@ impl BufferView { pub fn select_right(&mut self, _: &(), ctx: &mut ViewContext) { { - let buffer = self.buffer.as_ref(ctx); + let buffer = self.buffer.read(ctx); let app = ctx.app(); - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); for selection in &mut self.selections { let head = selection.head().to_display_point(map, ctx.app()).unwrap(); let cursor = map @@ -526,7 +526,7 @@ impl BufferView { ctx.propagate_action(); } else { let app = ctx.app(); - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); for selection in &mut self.selections { let start = selection.start.to_display_point(map, app).unwrap(); let end = selection.end.to_display_point(map, app).unwrap(); @@ -551,8 +551,8 @@ impl BufferView { ctx.propagate_action(); } else { let app = ctx.app(); - let buffer = self.buffer.as_ref(app); - let map = self.display_map.as_ref(app); + let buffer = self.buffer.read(app); + let map = self.display_map.read(app); for selection in &mut self.selections { let head = selection.head().to_display_point(map, app).unwrap(); let (head, goal_column) = @@ -569,7 +569,7 @@ impl BufferView { ctx.propagate_action(); } else { let app = ctx.app(); - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); for selection in &mut self.selections { let start = selection.start.to_display_point(map, app).unwrap(); let end = selection.end.to_display_point(map, app).unwrap(); @@ -594,8 +594,8 @@ impl BufferView { ctx.propagate_action(); } else { let app = ctx.app(); - let buffer = self.buffer.as_ref(ctx); - let map = self.display_map.as_ref(ctx); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); for selection in &mut self.selections { let head = selection.head().to_display_point(map, app).unwrap(); let (head, goal_column) = @@ -615,7 +615,7 @@ impl BufferView { } fn merge_selections(&mut self, ctx: &AppContext) { - let buffer = self.buffer.as_ref(ctx); + let buffer = self.buffer.read(ctx); let mut i = 1; while i < self.selections.len() { if self.selections[i - 1] @@ -651,14 +651,14 @@ impl BufferView { self.selections .first() .unwrap() - .display_range(self.display_map.as_ref(app), app) + .display_range(self.display_map.read(app), app) } pub fn last_selection(&self, app: &AppContext) -> Range { self.selections .last() .unwrap() - .display_range(self.display_map.as_ref(app), app) + .display_range(self.display_map.read(app), app) } pub fn selections_in_range<'a>( @@ -666,7 +666,7 @@ impl BufferView { range: Range, app: &'a AppContext, ) -> impl 'a + Iterator> { - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); let start = map.anchor_before(range.start, Bias::Left, app).unwrap(); let start_index = self.selection_insertion_index(&start, app); @@ -686,7 +686,7 @@ impl BufferView { } fn selection_insertion_index(&self, start: &Anchor, app: &AppContext) -> usize { - let buffer = self.buffer.as_ref(app); + let buffer = self.buffer.read(app); match self .selections @@ -720,7 +720,7 @@ impl BufferView { let mut fold_ranges = Vec::new(); let app = ctx.app(); - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); for selection in &self.selections { let (start, end) = selection.display_range(map, app).sorted(); let buffer_start_row = start.to_buffer_point(map, Bias::Left, app).unwrap().row; @@ -750,8 +750,8 @@ impl BufferView { use super::RangeExt; let app = ctx.app(); - let map = self.display_map.as_ref(app); - let buffer = self.buffer.as_ref(app); + let map = self.display_map.read(app); + let buffer = self.buffer.read(app); let ranges = self .selections .iter() @@ -796,7 +796,7 @@ impl BufferView { let mut is_blank = true; for c in self .display_map - .as_ref(app) + .read(app) .chars_at(DisplayPoint::new(display_row, 0), app)? { if c == ' ' { @@ -810,7 +810,7 @@ impl BufferView { } fn foldable_range_for_line(&self, start_row: u32, app: &AppContext) -> Result> { - let map = self.display_map.as_ref(app); + let map = self.display_map.read(app); let max_point = self.max_point(app); let (start_indent, _) = self.line_indent(start_row, app)?; @@ -831,7 +831,7 @@ impl BufferView { pub fn fold_selected_ranges(&mut self, _: &(), ctx: &mut ViewContext) { self.display_map.update(ctx, |map, ctx| { - let buffer = self.buffer.as_ref(ctx); + let buffer = self.buffer.read(ctx); let ranges = self .selections .iter() @@ -842,23 +842,23 @@ impl BufferView { } pub fn line(&self, display_row: u32, app: &AppContext) -> Result { - self.display_map.as_ref(app).line(display_row, app) + self.display_map.read(app).line(display_row, app) } pub fn line_len(&self, display_row: u32, app: &AppContext) -> Result { - self.display_map.as_ref(app).line_len(display_row, app) + self.display_map.read(app).line_len(display_row, app) } pub fn rightmost_point(&self, app: &AppContext) -> DisplayPoint { - self.display_map.as_ref(app).rightmost_point() + self.display_map.read(app).rightmost_point() } pub fn max_point(&self, app: &AppContext) -> DisplayPoint { - self.display_map.as_ref(app).max_point(app) + self.display_map.read(app).max_point(app) } pub fn text(&self, app: &AppContext) -> String { - self.display_map.as_ref(app).text(app) + self.display_map.read(app).text(app) } pub fn font_size(&self) -> f32 { @@ -902,7 +902,7 @@ impl BufferView { let font_size = settings.buffer_font_size; let font_id = font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?; - let digit_count = ((self.buffer.as_ref(app).max_point().row + 1) as f32) + let digit_count = ((self.buffer.read(app).max_point().row + 1) as f32) .log10() .floor() as usize + 1; @@ -923,7 +923,7 @@ impl BufferView { layout_cache: &TextLayoutCache, app: &AppContext, ) -> Result>> { - let display_map = self.display_map.as_ref(app); + let display_map = self.display_map.read(app); let settings = smol::block_on(self.settings.read()); let font_size = settings.buffer_font_size; @@ -959,7 +959,7 @@ impl BufferView { layout_cache: &TextLayoutCache, app: &AppContext, ) -> Result>> { - let display_map = self.display_map.as_ref(app); + let display_map = self.display_map.read(app); rows.end = cmp::min(rows.end, display_map.max_point(app).row() + 1); if rows.start >= rows.end { @@ -1149,7 +1149,7 @@ impl workspace::ItemView for BufferView { } fn title(&self, app: &AppContext) -> std::string::String { - if let Some(path) = self.buffer.as_ref(app).path(app) { + if let Some(path) = self.buffer.read(app).path(app) { path.file_name() .expect("buffer's path is always to a file") .to_string_lossy() @@ -1160,7 +1160,7 @@ impl workspace::ItemView for BufferView { } fn entry_id(&self, app: &AppContext) -> Option<(usize, usize)> { - self.buffer.as_ref(app).entry_id() + self.buffer.read(app).entry_id() } fn clone_on_split(&self, ctx: &mut ViewContext) -> Option @@ -1177,7 +1177,7 @@ impl workspace::ItemView for BufferView { } fn is_dirty(&self, ctx: &AppContext) -> bool { - self.buffer.as_ref(ctx).is_dirty() + self.buffer.read(ctx).is_dirty() } } @@ -1255,7 +1255,7 @@ mod tests { view.begin_selection(DisplayPoint::new(2, 2), false, ctx); }); - let view = buffer_view.as_ref(app); + let view = buffer_view.read(app); let selections = view .selections_in_range( DisplayPoint::zero()..view.max_point(app.as_ref()), @@ -1271,7 +1271,7 @@ mod tests { view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx); }); - let view = buffer_view.as_ref(app); + let view = buffer_view.read(app); let selections = view .selections_in_range( DisplayPoint::zero()..view.max_point(app.as_ref()), @@ -1287,7 +1287,7 @@ mod tests { view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx); }); - let view = buffer_view.as_ref(app); + let view = buffer_view.read(app); let selections = view .selections_in_range( DisplayPoint::zero()..view.max_point(app.as_ref()), @@ -1304,7 +1304,7 @@ mod tests { view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx); }); - let view = buffer_view.as_ref(app); + let view = buffer_view.read(app); let selections = view .selections_in_range( DisplayPoint::zero()..view.max_point(app.as_ref()), @@ -1321,7 +1321,7 @@ mod tests { view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), ctx); }); - let view = buffer_view.as_ref(app); + let view = buffer_view.read(app); let selections = view .selections_in_range( DisplayPoint::zero()..view.max_point(app.as_ref()), @@ -1340,7 +1340,7 @@ mod tests { view.end_selection(ctx); }); - let view = buffer_view.as_ref(app); + let view = buffer_view.read(app); let selections = view .selections_in_range( DisplayPoint::zero()..view.max_point(app.as_ref()), @@ -1367,7 +1367,7 @@ mod tests { app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx)); let layouts = view - .as_ref(app) + .read(app) .layout_line_numbers(1000.0, &font_cache, &layout_cache, app.as_ref()) .unwrap(); assert_eq!(layouts.len(), 6); @@ -1460,7 +1460,7 @@ mod tests { ); view.unfold(&(), ctx); - assert_eq!(view.text(ctx.app()), buffer.as_ref(ctx).text()); + assert_eq!(view.text(ctx.app()), buffer.read(ctx).text()); }); }); } @@ -1529,7 +1529,7 @@ mod tests { }); assert_eq!( - buffer.as_ref(app).text(), + buffer.read(app).text(), "oe two three\nfou five six\nseven ten\n" ); }) diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index d67b4b510e..58f51cee94 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -22,7 +22,7 @@ pub struct FoldMap { impl FoldMap { pub fn new(buffer: ModelHandle, app: &AppContext) -> Self { - let text_summary = buffer.as_ref(app).text_summary(); + let text_summary = buffer.read(app).text_summary(); Self { buffer, folds: Vec::new(), @@ -72,7 +72,7 @@ impl FoldMap { let offset = self.to_display_offset(point, app)?; let mut cursor = self.transforms.cursor(); cursor.seek(&offset, SeekBias::Right); - let buffer = self.buffer.as_ref(app); + let buffer = self.buffer.read(app); Ok(Chars { cursor, offset: offset.0, @@ -95,7 +95,7 @@ impl FoldMap { app: &AppContext, ) -> Result<()> { let mut edits = Vec::new(); - let buffer = self.buffer.as_ref(app); + let buffer = self.buffer.read(app); for range in ranges.into_iter() { let start = range.start.to_offset(buffer)?; let end = range.end.to_offset(buffer)?; @@ -124,7 +124,7 @@ impl FoldMap { ranges: impl IntoIterator>, app: &AppContext, ) -> Result<()> { - let buffer = self.buffer.as_ref(app); + let buffer = self.buffer.read(app); let mut edits = Vec::new(); for range in ranges.into_iter() { @@ -184,7 +184,7 @@ impl FoldMap { .ok_or_else(|| anyhow!("display point {:?} is out of range", point))?; assert!(transform.display_text.is_none()); let end_buffer_offset = - (cursor.start().buffer.lines + overshoot).to_offset(self.buffer.as_ref(app))?; + (cursor.start().buffer.lines + overshoot).to_offset(self.buffer.read(app))?; offset += end_buffer_offset - cursor.start().buffer.chars; } Ok(DisplayOffset(offset)) @@ -208,7 +208,7 @@ impl FoldMap { } pub fn apply_edits(&mut self, edits: &[Edit], app: &AppContext) -> Result<()> { - let buffer = self.buffer.as_ref(app); + let buffer = self.buffer.read(app); let mut edits = edits.iter().cloned().peekable(); let mut new_transforms = SumTree::new(); @@ -597,7 +597,7 @@ mod tests { let mut map = FoldMap::new(buffer.clone(), app.as_ref()); { - let buffer = buffer.as_ref(app); + let buffer = buffer.read(app); let fold_count = rng.gen_range(0..10); let mut fold_ranges: Vec> = Vec::new(); @@ -632,7 +632,7 @@ mod tests { map.apply_edits(&edits, app.as_ref()).unwrap(); - let buffer = map.buffer.as_ref(app); + let buffer = map.buffer.read(app); let mut expected_text = buffer.text(); let mut expected_buffer_rows = Vec::new(); let mut next_row = buffer.max_point().row; @@ -694,7 +694,7 @@ mod tests { } fn merged_fold_ranges(&self, app: &AppContext) -> Vec> { - let buffer = self.buffer.as_ref(app); + let buffer = self.buffer.read(app); let mut fold_ranges = self .folds .iter() diff --git a/zed/src/editor/display_map/mod.rs b/zed/src/editor/display_map/mod.rs index 7bc17627dd..e44193104e 100644 --- a/zed/src/editor/display_map/mod.rs +++ b/zed/src/editor/display_map/mod.rs @@ -108,7 +108,7 @@ impl DisplayMap { app: &AppContext, ) -> Result { self.buffer - .as_ref(app) + .read(app) .anchor_before(point.to_buffer_point(self, bias, app)?) } @@ -119,7 +119,7 @@ impl DisplayMap { app: &AppContext, ) -> Result { self.buffer - .as_ref(app) + .read(app) .anchor_after(point.to_buffer_point(self, bias, app)?) } @@ -206,7 +206,7 @@ impl Point { impl Anchor { pub fn to_display_point(&self, map: &DisplayMap, app: &AppContext) -> Result { - self.to_point(map.buffer.as_ref(app))? + self.to_point(map.buffer.read(app))? .to_display_point(map, app) } } @@ -314,7 +314,7 @@ mod tests { }) .unwrap(); - let map = map.as_ref(app); + let map = map.read(app); assert_eq!( map.chars_at(DisplayPoint::new(1, 0), app.as_ref()) .unwrap() @@ -368,7 +368,7 @@ mod tests { let buffer = app.add_model(|_| Buffer::new(0, "aaa\n\t\tbbb")); let map = app.add_model(|ctx| DisplayMap::new(buffer.clone(), 4, ctx)); assert_eq!( - map.as_ref(app).max_point(app.as_ref()), + map.read(app).max_point(app.as_ref()), DisplayPoint::new(1, 11) ) }); diff --git a/zed/src/file_finder.rs b/zed/src/file_finder.rs index d03ce43294..169d2243a4 100644 --- a/zed/src/file_finder.rs +++ b/zed/src/file_finder.rs @@ -114,7 +114,7 @@ impl FileFinder { self.matches.len(), move |mut range, items, app| { let finder = handle.upgrade(app).unwrap(); - let finder = finder.as_ref(app); + let finder = finder.read(app); let start = range.start; range.end = cmp::min(range.end, finder.matches.len()); items.extend(finder.matches[range].iter().enumerate().filter_map( @@ -287,7 +287,7 @@ impl FileFinder { } fn workspace_updated(&mut self, _: ModelHandle, ctx: &mut ViewContext) { - self.spawn_search(self.query_buffer.as_ref(ctx).text(ctx.app()), ctx); + self.spawn_search(self.query_buffer.read(ctx).text(ctx.app()), ctx); } fn on_query_buffer_event( @@ -299,7 +299,7 @@ impl FileFinder { use buffer_view::Event::*; match event { Edited => { - let query = self.query_buffer.as_ref(ctx).text(ctx.app()); + let query = self.query_buffer.read(ctx).text(ctx.app()); if query.is_empty() { self.latest_search_id = util::post_inc(&mut self.search_count); self.matches.clear(); @@ -371,18 +371,18 @@ impl FileFinder { fn worktree<'a>(&'a self, tree_id: usize, app: &'a AppContext) -> Option<&'a Worktree> { self.workspace - .as_ref(app) + .read(app) .worktrees() .get(&tree_id) - .map(|worktree| worktree.as_ref(app)) + .map(|worktree| worktree.read(app)) } fn worktrees(&self, app: &AppContext) -> Vec { self.workspace - .as_ref(app) + .read(app) .worktrees() .iter() - .map(|worktree| worktree.as_ref(app).clone()) + .map(|worktree| worktree.read(app).clone()) .collect() } } @@ -400,7 +400,7 @@ mod tests { #[test] fn test_matching_paths() { - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let tmp_dir = TempDir::new("example").unwrap(); fs::create_dir(tmp_dir.path().join("a")).await.unwrap(); fs::write(tmp_dir.path().join("a/banana"), "banana") @@ -409,8 +409,10 @@ mod tests { fs::write(tmp_dir.path().join("a/bandana"), "bandana") .await .unwrap(); - super::init(app); - editor::init(app); + app.update(|ctx| { + super::init(ctx); + editor::init(ctx); + }); let settings = settings::channel(&app.font_cache()).unwrap().1; let workspace = app.add_model(|ctx| Workspace::new(vec![tmp_dir.path().into()], ctx)); @@ -424,14 +426,16 @@ mod tests { (), ); - let finder = workspace_view - .as_ref(app) - .modal() - .cloned() - .unwrap() - .downcast::() - .unwrap(); - let query_buffer = finder.as_ref(app).query_buffer.clone(); + let finder = app.read(|ctx| { + workspace_view + .read(ctx) + .modal() + .cloned() + .unwrap() + .downcast::() + .unwrap() + }); + let query_buffer = app.read(|ctx| finder.read(ctx).query_buffer.clone()); let chain = vec![finder.id(), query_buffer.id()]; app.dispatch_action(window_id, chain.clone(), "buffer:insert", "b".to_string()); diff --git a/zed/src/workspace/mod.rs b/zed/src/workspace/mod.rs index 91dd99419a..a441eb8b8b 100644 --- a/zed/src/workspace/mod.rs +++ b/zed/src/workspace/mod.rs @@ -109,9 +109,9 @@ mod tests { .unwrap(); assert_eq!( workspace_view_1 - .as_ref(app) + .read(app) .workspace - .as_ref(app) + .read(app) .worktrees() .len(), 2 diff --git a/zed/src/workspace/workspace.rs b/zed/src/workspace/workspace.rs index cc5cfec602..b4e5a85e58 100644 --- a/zed/src/workspace/workspace.rs +++ b/zed/src/workspace/workspace.rs @@ -101,7 +101,7 @@ impl Workspace { pub fn contains_path(&self, path: &Path, app: &AppContext) -> bool { self.worktrees .iter() - .any(|worktree| worktree.as_ref(app).contains_path(path)) + .any(|worktree| worktree.read(app).contains_path(path)) } pub fn open_paths(&mut self, paths: &[PathBuf], ctx: &mut ModelContext) { @@ -112,7 +112,7 @@ impl Workspace { pub fn open_path<'a>(&'a mut self, path: PathBuf, ctx: &mut ModelContext) { for tree in self.worktrees.iter() { - if tree.as_ref(ctx).contains_path(&path) { + if tree.read(ctx).contains_path(&path) { return; } } @@ -200,18 +200,18 @@ impl Entity for Workspace { #[cfg(test)] pub trait WorkspaceHandle { - fn file_entries(&self, app: &mut MutableAppContext) -> Vec<(usize, usize)>; + fn file_entries(&self, app: &AppContext) -> Vec<(usize, usize)>; } #[cfg(test)] impl WorkspaceHandle for ModelHandle { - fn file_entries(&self, app: &mut MutableAppContext) -> Vec<(usize, usize)> { - self.as_ref(app) + fn file_entries(&self, app: &AppContext) -> Vec<(usize, usize)> { + self.read(app) .worktrees() .iter() .flat_map(|tree| { let tree_id = tree.id(); - tree.as_ref(app) + tree.read(app) .files() .map(move |file| (tree_id, file.entry_id)) }) @@ -228,7 +228,7 @@ mod tests { #[test] fn test_open_entry() { - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let dir = temp_tree(json!({ "a": { "aa": "aa contents", @@ -240,12 +240,12 @@ mod tests { app.finish_pending_tasks().await; // Open and populate worktree. // Get the first file entry. - let tree = workspace.as_ref(app).worktrees.iter().next().unwrap(); - let entry_id = tree.as_ref(app).files().next().unwrap().entry_id; + let tree = app.read(|ctx| workspace.read(ctx).worktrees.iter().next().unwrap().clone()); + let entry_id = app.read(|ctx| tree.read(ctx).files().next().unwrap().entry_id); let entry = (tree.id(), entry_id); // Open the same entry twice before it finishes loading. - let (future_1, future_2) = workspace.update(app, |w, app| { + let (future_1, future_2) = workspace.update(&mut app, |w, app| { ( w.open_entry(entry, app).unwrap(), w.open_entry(entry, app).unwrap(), @@ -258,7 +258,7 @@ mod tests { // Open the same entry again now that it has loaded let handle_3 = workspace - .update(app, |w, app| w.open_entry(entry, app).unwrap()) + .update(&mut app, |w, app| w.open_entry(entry, app).unwrap()) .await .unwrap(); diff --git a/zed/src/workspace/workspace_view.rs b/zed/src/workspace/workspace_view.rs index aaf1e9eb9a..aece490d37 100644 --- a/zed/src/workspace/workspace_view.rs +++ b/zed/src/workspace/workspace_view.rs @@ -54,11 +54,11 @@ pub trait ItemViewHandle: Send + Sync { impl ItemViewHandle for ViewHandle { fn title(&self, app: &AppContext) -> String { - self.as_ref(app).title(app) + self.read(app).title(app) } fn entry_id(&self, app: &AppContext) -> Option<(usize, usize)> { - self.as_ref(app).entry_id(app) + self.read(app).entry_id(app) } fn boxed_clone(&self) -> Box { @@ -93,7 +93,7 @@ impl ItemViewHandle for ViewHandle { } fn is_dirty(&self, ctx: &AppContext) -> bool { - self.as_ref(ctx).is_dirty(ctx) + self.read(ctx).is_dirty(ctx) } fn id(&self) -> usize { @@ -154,7 +154,7 @@ impl WorkspaceView { } pub fn contains_paths(&self, paths: &[PathBuf], app: &AppContext) -> bool { - self.workspace.as_ref(app).contains_paths(paths, app) + self.workspace.read(app).contains_paths(paths, app) } pub fn open_paths(&self, paths: &[PathBuf], app: &mut MutableAppContext) { @@ -228,8 +228,8 @@ impl WorkspaceView { } pub fn open_example_entry(&mut self, ctx: &mut ViewContext) { - if let Some(tree) = self.workspace.as_ref(ctx).worktrees().iter().next() { - if let Some(file) = tree.as_ref(ctx).files().next() { + if let Some(tree) = self.workspace.read(ctx).worktrees().iter().next() { + if let Some(file) = tree.read(ctx).files().next() { info!("open_entry ({}, {})", tree.id(), file.entry_id); self.open_entry((tree.id(), file.entry_id), ctx); } else { @@ -322,7 +322,7 @@ impl WorkspaceView { ) -> ViewHandle { let new_pane = self.add_pane(ctx); self.activate_pane(new_pane.clone(), ctx); - if let Some(item) = pane.as_ref(ctx).active_item() { + if let Some(item) = pane.read(ctx).active_item() { if let Some(clone) = item.clone_on_split(ctx.app_mut()) { self.add_item(clone, ctx); } @@ -394,7 +394,7 @@ mod tests { #[test] fn test_open_entry() { - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let dir = temp_tree(json!({ "a": { "aa": "aa contents", @@ -406,70 +406,78 @@ mod tests { let settings = settings::channel(&app.font_cache()).unwrap().1; let workspace = app.add_model(|ctx| Workspace::new(vec![dir.path().into()], ctx)); app.finish_pending_tasks().await; // Open and populate worktree. - let entries = workspace.file_entries(app); + let entries = app.read(|ctx| workspace.file_entries(ctx)); let (_, workspace_view) = app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx)); // Open the first entry - workspace_view.update(app, |w, ctx| w.open_entry(entries[0], ctx)); + workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[0], ctx)); app.finish_pending_tasks().await; - assert_eq!( - workspace_view - .as_ref(app) - .active_pane() - .as_ref(app) - .items() - .len(), - 1 - ); + app.read(|ctx| { + assert_eq!( + workspace_view + .read(ctx) + .active_pane() + .read(ctx) + .items() + .len(), + 1 + ) + }); // Open the second entry - workspace_view.update(app, |w, ctx| w.open_entry(entries[1], ctx)); + workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[1], ctx)); app.finish_pending_tasks().await; - let active_pane = workspace_view.as_ref(app).active_pane().as_ref(app); - assert_eq!(active_pane.items().len(), 2); - assert_eq!( - active_pane.active_item().unwrap().entry_id(app.as_ref()), - Some(entries[1]) - ); + app.read(|ctx| { + let active_pane = workspace_view.read(ctx).active_pane().read(ctx); + assert_eq!(active_pane.items().len(), 2); + assert_eq!( + active_pane.active_item().unwrap().entry_id(ctx), + Some(entries[1]) + ); + }); // Open the first entry again - workspace_view.update(app, |w, ctx| w.open_entry(entries[0], ctx)); + workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[0], ctx)); app.finish_pending_tasks().await; - let active_pane = workspace_view.as_ref(app).active_pane().as_ref(app); - assert_eq!(active_pane.items().len(), 2); - assert_eq!( - active_pane.active_item().unwrap().entry_id(app.as_ref()), - Some(entries[0]) - ); + app.read(|ctx| { + let active_pane = workspace_view.read(ctx).active_pane().read(ctx); + assert_eq!(active_pane.items().len(), 2); + assert_eq!( + active_pane.active_item().unwrap().entry_id(ctx), + Some(entries[0]) + ); + }); // Open the third entry twice concurrently - workspace_view.update(app, |w, ctx| { + workspace_view.update(&mut app, |w, ctx| { w.open_entry(entries[2], ctx); w.open_entry(entries[2], ctx); }); app.finish_pending_tasks().await; - assert_eq!( - workspace_view - .as_ref(app) - .active_pane() - .as_ref(app) - .items() - .len(), - 3 - ); + app.read(|ctx| { + assert_eq!( + workspace_view + .read(ctx) + .active_pane() + .read(ctx) + .items() + .len(), + 3 + ); + }); }); } #[test] fn test_pane_actions() { - App::test_async((), |app| async move { - pane::init(app); + App::test_async((), |mut app| async move { + app.update(|ctx| pane::init(ctx)); let dir = temp_tree(json!({ "a": { @@ -479,37 +487,41 @@ mod tests { }, })); - let settings = settings::channel(app.font_cache()).unwrap().1; + let settings = settings::channel(&app.font_cache()).unwrap().1; let workspace = app.add_model(|ctx| Workspace::new(vec![dir.path().into()], ctx)); app.finish_pending_tasks().await; // Open and populate worktree. - let entries = workspace.file_entries(app); + let entries = app.read(|ctx| workspace.file_entries(ctx)); let (window_id, workspace_view) = app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx)); - workspace_view.update(app, |w, ctx| w.open_entry(entries[0], ctx)); + workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[0], ctx)); app.finish_pending_tasks().await; - let pane_1 = workspace_view.as_ref(app).active_pane().clone(); + let pane_1 = app.read(|ctx| workspace_view.read(ctx).active_pane().clone()); app.dispatch_action(window_id, vec![pane_1.id()], "pane:split_right", ()); - let pane_2 = workspace_view.as_ref(app).active_pane().clone(); - assert_ne!(pane_1, pane_2); + app.update(|ctx| { + let pane_2 = workspace_view.read(ctx).active_pane().clone(); + assert_ne!(pane_1, pane_2); - assert_eq!( - pane_2 - .as_ref(app) - .active_item() - .unwrap() - .entry_id(app.downgrade()), - Some(entries[0]) - ); + assert_eq!( + pane_2 + .read(ctx) + .active_item() + .unwrap() + .entry_id(ctx.as_ref()), + Some(entries[0]) + ); - app.dispatch_action(window_id, vec![pane_2.id()], "pane:close_active_item", ()); + ctx.dispatch_action(window_id, vec![pane_2.id()], "pane:close_active_item", ()); + }); - let w = workspace_view.as_ref(app); - assert_eq!(w.panes.len(), 1); - assert_eq!(w.active_pane(), &pane_1); + app.read(|ctx| { + let w = workspace_view.read(ctx); + assert_eq!(w.panes.len(), 1); + assert_eq!(w.active_pane(), &pane_1); + }) }); } } diff --git a/zed/src/worktree/worktree.rs b/zed/src/worktree/worktree.rs index 27f42d904d..63be9b6eef 100644 --- a/zed/src/worktree/worktree.rs +++ b/zed/src/worktree/worktree.rs @@ -409,7 +409,7 @@ pub trait WorktreeHandle { impl WorktreeHandle for ModelHandle { fn file(&self, entry_id: usize, app: &AppContext) -> Result { - if entry_id >= self.as_ref(app).entry_count() { + if entry_id >= self.read(app).entry_count() { return Err(anyhow!("Entry does not exist in tree")); } @@ -461,15 +461,15 @@ pub struct FileHandle { impl FileHandle { pub fn path(&self, app: &AppContext) -> PathBuf { - self.worktree.as_ref(app).entry_path(self.entry_id).unwrap() + self.worktree.read(app).entry_path(self.entry_id).unwrap() } pub fn load_history(&self, app: &AppContext) -> impl Future> { - self.worktree.as_ref(app).load_history(self.entry_id) + self.worktree.read(app).load_history(self.entry_id) } pub fn save<'a>(&self, content: Snapshot, ctx: &AppContext) -> Task> { - let worktree = self.worktree.as_ref(ctx); + let worktree = self.worktree.read(ctx); worktree.save(self.entry_id, content, ctx) } @@ -649,7 +649,7 @@ mod test { #[test] fn test_populate_and_search() { - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let dir = temp_tree(json!({ "root": { "apple": "", @@ -671,26 +671,28 @@ mod test { let tree = app.add_model(|ctx| Worktree::new(1, root_link_path, Some(ctx))); app.finish_pending_tasks().await; - let tree = tree.as_ref(app); - assert_eq!(tree.file_count(), 4); - let results = match_paths(&[tree.clone()], "bna", false, false, 10) - .iter() - .map(|result| tree.entry_path(result.entry_id)) - .collect::, _>>() - .unwrap(); - assert_eq!( - results, - vec![ - PathBuf::from("root_link/banana/carrot/date"), - PathBuf::from("root_link/banana/carrot/endive"), - ] - ); + app.read(|ctx| { + let tree = tree.read(ctx); + assert_eq!(tree.file_count(), 4); + let results = match_paths(&[tree.clone()], "bna", false, false, 10) + .iter() + .map(|result| tree.entry_path(result.entry_id)) + .collect::, _>>() + .unwrap(); + assert_eq!( + results, + vec![ + PathBuf::from("root_link/banana/carrot/date"), + PathBuf::from("root_link/banana/carrot/endive"), + ] + ); + }) }); } #[test] fn test_save_file() { - App::test_async((), |app| async move { + App::test_async((), |mut app| async move { let dir = temp_tree(json!({ "file1": "the old contents", })); @@ -698,17 +700,23 @@ mod test { let tree = app.add_model(|ctx| Worktree::new(1, dir.path(), Some(ctx))); app.finish_pending_tasks().await; - let entry = tree.as_ref(app).files().next().unwrap(); - assert_eq!(entry.path.file_name().unwrap(), "file1"); - let file_id = entry.entry_id; - let buffer = Buffer::new(1, "a line of text.\n".repeat(10 * 1024)); - tree.update(app, |tree, ctx| { + let entry = app.read(|ctx| { + let entry = tree.read(ctx).files().next().unwrap(); + assert_eq!(entry.path.file_name().unwrap(), "file1"); + entry + }); + let file_id = entry.entry_id; + + tree.update(&mut app, |tree, ctx| { smol::block_on(tree.save(file_id, buffer.snapshot(), ctx.app())).unwrap() }); - let history = tree.as_ref(app).load_history(file_id).await.unwrap(); + let history = app + .read(|ctx| tree.read(ctx).load_history(file_id)) + .await + .unwrap(); assert_eq!(history.base_text, buffer.text()); }); }