From 1c8eeb01c9ff7417a5039c6b3855baea79d445d8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 5 Aug 2022 16:34:26 +0200 Subject: [PATCH 01/27] Make project panel more compact This ensures more deeply-nested entries can be displayed without needing to show scrollbars. Adding scrollbars introduces UX issues when creating/renaming files because there are two scroll layers: the outer project panel AND the editor. Sublime Text and Atom dodged this issue by not displaying an inline editor and showing it as a modal instead. VS Code shows the editor inline but has a much more compact visualization. I think we should copy VS Code. --- styles/src/styleTree/projectPanel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 26f88c6784..7add861fa6 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -6,7 +6,7 @@ export default function projectPanel(theme: Theme) { return { ...panel, padding: { left: 12, right: 12, top: 6, bottom: 6 }, - indentWidth: 20, + indentWidth: 8, entry: { height: 24, iconColor: iconColor(theme, "muted"), From ffce2cb0845f12808974ccb2b22f51a5740c440c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 5 Aug 2022 12:44:34 -0400 Subject: [PATCH 02/27] Use One Dark as the default theme. --- assets/settings/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 505e8dd4eb..33eb64e201 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1,6 +1,6 @@ { // The name of the Zed theme to use for the UI - "theme": "cave-dark", + "theme": "one-dark", // The name of a font to use for rendering text in the editor "buffer_font_family": "Zed Mono", // The default font size for text in the editor From db52593d9bf11be7c1991e47b755df7742a1f2c0 Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Mon, 8 Aug 2022 13:17:19 -0400 Subject: [PATCH 03/27] Automatically trigger project search to occur when deploying --- crates/search/src/project_search.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index ab130c1350..39415b3832 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -477,6 +477,7 @@ impl ProjectSearchView { search.update(cx, |search, cx| { if let Some(query) = query { search.set_query(&query, cx); + search.search(cx); } search.focus_query_editor(cx) }); From a47a6f2f22b04b3d02630ec951fea88b34993bb1 Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Mon, 8 Aug 2022 15:59:33 -0400 Subject: [PATCH 04/27] Handle Cmd/Shift + Click go-to action on mouse-up instead of mouse-down --- crates/editor/src/editor.rs | 8 ++++ crates/editor/src/element.rs | 75 +++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 7c2d560a41..f7d9c9be79 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1787,6 +1787,14 @@ impl Editor { cx.notify(); } + pub fn are_selections_empty(&self) -> bool { + let pending_empty = match self.selections.pending_anchor() { + Some(Selection { start, end, .. }) => start == end, + None => true, + }; + pending_empty && self.columnar_selection_tail.is_none() + } + pub fn is_selecting(&self) -> bool { self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some() } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 95d760846f..25a71b93dc 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -113,7 +113,6 @@ impl EditorElement { fn mouse_down( &self, position: Vector2F, - cmd: bool, alt: bool, shift: bool, mut click_count: usize, @@ -121,20 +120,6 @@ impl EditorElement { paint: &mut PaintState, cx: &mut EventContext, ) -> bool { - if cmd && paint.text_bounds.contains_point(position) { - let (point, target_point) = - paint.point_for_position(&self.snapshot(cx), layout, position); - if point == target_point { - if shift { - cx.dispatch_action(GoToFetchedTypeDefinition { point }); - } else { - cx.dispatch_action(GoToFetchedDefinition { point }); - } - - return true; - } - } - if paint.gutter_bounds.contains_point(position) { click_count = 3; // Simulate triple-click when clicking the gutter to select lines } else if !paint.text_bounds.contains_point(position) { @@ -183,13 +168,39 @@ impl EditorElement { true } - fn mouse_up(&self, _position: Vector2F, cx: &mut EventContext) -> bool { - if self.view(cx.app.as_ref()).is_selecting() { + fn mouse_up( + &self, + position: Vector2F, + cmd: bool, + shift: bool, + layout: &mut LayoutState, + paint: &mut PaintState, + cx: &mut EventContext, + ) -> bool { + let view = self.view(cx.app.as_ref()); + let end_selection = view.is_selecting(); + let selections_empty = view.are_selections_empty(); + + if end_selection { cx.dispatch_action(Select(SelectPhase::End)); - true - } else { - false } + + if selections_empty && cmd && paint.text_bounds.contains_point(position) { + let (point, target_point) = + paint.point_for_position(&self.snapshot(cx), layout, position); + + if point == target_point { + if shift { + cx.dispatch_action(GoToFetchedTypeDefinition { point }); + } else { + cx.dispatch_action(GoToFetchedDefinition { point }); + } + + return true; + } + } + + end_selection } fn mouse_dragged( @@ -1533,36 +1544,28 @@ impl Element for EditorElement { } match event { - Event::MouseDown(MouseButtonEvent { + &Event::MouseDown(MouseButtonEvent { button: MouseButton::Left, position, - cmd, alt, shift, click_count, .. - }) => self.mouse_down( - *position, - *cmd, - *alt, - *shift, - *click_count, - layout, - paint, - cx, - ), + }) => self.mouse_down(position, alt, shift, click_count, layout, paint, cx), - Event::MouseDown(MouseButtonEvent { + &Event::MouseDown(MouseButtonEvent { button: MouseButton::Right, position, .. - }) => self.mouse_right_down(*position, layout, paint, cx), + }) => self.mouse_right_down(position, layout, paint, cx), - Event::MouseUp(MouseButtonEvent { + &Event::MouseUp(MouseButtonEvent { button: MouseButton::Left, position, + cmd, + shift, .. - }) => self.mouse_up(*position, cx), + }) => self.mouse_up(position, cmd, shift, layout, paint, cx), Event::MouseMoved(MouseMovedEvent { pressed_button: Some(MouseButton::Left), From ab760493cfc4f75bc6a3bbf2c578efa643017afd Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Tue, 9 Aug 2022 15:34:57 -0400 Subject: [PATCH 05/27] Route whether or not a window is fullscreen down into GPUI This still needs to be able to invalidate things to be useful but it's a good first cut at just making the information available to platform-agnostic code Co-authored-by: Mikayla --- crates/gpui/src/app.rs | 93 +++++++++++++++++++++++++- crates/gpui/src/platform.rs | 1 + crates/gpui/src/platform/mac/window.rs | 32 +++++++++ crates/gpui/src/platform/test.rs | 6 ++ 4 files changed, 129 insertions(+), 3 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 8285fda213..532f59f008 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1248,6 +1248,13 @@ impl MutableAppContext { .map_or(false, |window| window.is_active) } + pub fn window_is_fullscreen(&self, window_id: usize) -> bool { + self.cx + .windows + .get(&window_id) + .map_or(false, |window| window.is_fullscreen) + } + pub fn render_view(&mut self, params: RenderParams) -> Result { let window_id = params.window_id; let view_id = params.view_id; @@ -1934,6 +1941,7 @@ impl MutableAppContext { focused_view_id: Some(root_view.id()), is_active: false, invalidation: None, + is_fullscreen: false, }, ); root_view.update(this, |view, cx| view.on_focus(cx)); @@ -2010,6 +2018,13 @@ impl MutableAppContext { })); } + { + let mut app = self.upgrade(); + window.on_fullscreen(Box::new(move |is_fullscreen| { + app.update(|cx| cx.window_was_fullscreen_changed(window_id, is_fullscreen)) + })); + } + { let mut app = self.upgrade(); window.on_close(Box::new(move || { @@ -2151,7 +2166,9 @@ impl MutableAppContext { subscription_id, callback, } => self.handle_subscription_effect(entity_id, subscription_id, callback), + Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload), + Effect::GlobalSubscription { type_id, subscription_id, @@ -2161,21 +2178,27 @@ impl MutableAppContext { subscription_id, callback, ), + Effect::GlobalEvent { payload } => self.emit_global_event(payload), + Effect::Observation { entity_id, subscription_id, callback, } => self.handle_observation_effect(entity_id, subscription_id, callback), + Effect::ModelNotification { model_id } => { self.handle_model_notification_effect(model_id) } + Effect::ViewNotification { window_id, view_id } => { self.handle_view_notification_effect(window_id, view_id) } + Effect::GlobalNotification { type_id } => { self.handle_global_notification_effect(type_id) } + Effect::Deferred { callback, after_window_update, @@ -2186,15 +2209,19 @@ impl MutableAppContext { callback(self) } } + Effect::ModelRelease { model_id, model } => { self.handle_entity_release_effect(model_id, model.as_any()) } + Effect::ViewRelease { view_id, view } => { self.handle_entity_release_effect(view_id, view.as_any()) } + Effect::Focus { window_id, view_id } => { self.handle_focus_effect(window_id, view_id); } + Effect::FocusObservation { view_id, subscription_id, @@ -2202,6 +2229,7 @@ impl MutableAppContext { } => { self.handle_focus_observation_effect(view_id, subscription_id, callback) } + Effect::ResizeWindow { window_id } => { if let Some(window) = self.cx.windows.get_mut(&window_id) { window @@ -2209,6 +2237,7 @@ impl MutableAppContext { .get_or_insert(WindowInvalidation::default()); } } + Effect::WindowActivationObservation { window_id, subscription_id, @@ -2218,10 +2247,17 @@ impl MutableAppContext { subscription_id, callback, ), + Effect::ActivateWindow { window_id, is_active, } => self.handle_window_activation_effect(window_id, is_active), + + Effect::FullscreenWindow { + window_id, + is_fullscreen, + } => self.handle_fullscreen_effect(window_id, is_fullscreen), + Effect::RefreshWindows => { refreshing = true; } @@ -2294,6 +2330,13 @@ impl MutableAppContext { .push_back(Effect::ResizeWindow { window_id }); } + fn window_was_fullscreen_changed(&mut self, window_id: usize, is_fullscreen: bool) { + self.pending_effects.push_back(Effect::FullscreenWindow { + window_id, + is_fullscreen, + }); + } + fn window_changed_active_status(&mut self, window_id: usize, is_active: bool) { self.pending_effects.push_back(Effect::ActivateWindow { window_id, @@ -2608,13 +2651,36 @@ impl MutableAppContext { } } - fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) { + fn handle_fullscreen_effect(&mut self, window_id: usize, is_fullscreen: bool) { + //Short circuit evaluation if we're already g2g if self .cx .windows .get(&window_id) - .map(|w| w.is_active) - .map_or(false, |cur_active| cur_active == active) + .map(|w| w.is_fullscreen == is_fullscreen) + .unwrap_or(false) + { + return; + } + + self.update(|this| { + let window = this.cx.windows.get_mut(&window_id)?; + window.is_fullscreen = is_fullscreen; + + // self.emit_event(entity_id, payload); + + Some(()) + }); + } + + fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) { + //Short circuit evaluation if we're already g2g + if self + .cx + .windows + .get(&window_id) + .map(|w| w.is_active == active) + .unwrap_or(false) { return; } @@ -2622,6 +2688,8 @@ impl MutableAppContext { self.update(|this| { let window = this.cx.windows.get_mut(&window_id)?; window.is_active = active; + + //Handle focus let view_id = window.focused_view_id?; if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { if active { @@ -2632,6 +2700,7 @@ impl MutableAppContext { this.cx.views.insert((window_id, view_id), view); } + //Deliver events let callbacks = this .window_activation_observations .lock() @@ -2640,6 +2709,7 @@ impl MutableAppContext { for (id, callback) in callbacks { if let Some(mut callback) = callback { let alive = callback(active, this); + //Put entry back if alive { match this .window_activation_observations @@ -3072,6 +3142,7 @@ struct Window { root_view: AnyViewHandle, focused_view_id: Option, is_active: bool, + is_fullscreen: bool, invalidation: Option, } @@ -3138,6 +3209,10 @@ pub enum Effect { ResizeWindow { window_id: usize, }, + FullscreenWindow { + window_id: usize, + is_fullscreen: bool, + }, ActivateWindow { window_id: usize, is_active: bool, @@ -3256,6 +3331,14 @@ impl Debug for Effect { .field("window_id", window_id) .field("is_active", is_active) .finish(), + Effect::FullscreenWindow { + window_id, + is_fullscreen, + } => f + .debug_struct("Effect::FullscreenWindow") + .field("window_id", window_id) + .field("is_fullscreen", is_fullscreen) + .finish(), Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(), Effect::WindowShouldCloseSubscription { window_id, .. } => f .debug_struct("Effect::WindowShouldCloseSubscription") @@ -4032,6 +4115,10 @@ impl<'a, V: View> RenderContext<'a, V> { WeakViewHandle::new(self.window_id, self.view_id) } + pub fn window_id(&self) -> usize { + self.window_id + } + pub fn view_id(&self) -> usize { self.view_id } diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 833912587c..df7727ee89 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -112,6 +112,7 @@ pub trait Window: WindowContext { fn on_event(&mut self, callback: Box bool>); fn on_active_status_change(&mut self, callback: Box); fn on_resize(&mut self, callback: Box); + fn on_fullscreen(&mut self, callback: Box); fn on_should_close(&mut self, callback: Box bool>); fn on_close(&mut self, callback: Box); fn set_input_handler(&mut self, input_handler: Box); diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 908efd451c..2168b07ffe 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -128,6 +128,14 @@ unsafe fn build_classes() { sel!(windowDidResize:), window_did_resize as extern "C" fn(&Object, Sel, id), ); + decl.add_method( + sel!(windowDidEnterFullScreen:), + window_did_enter_fullscreen as extern "C" fn(&Object, Sel, id), + ); + decl.add_method( + sel!(windowDidExitFullScreen:), + window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id), + ); decl.add_method( sel!(windowDidBecomeKey:), window_did_change_key_status as extern "C" fn(&Object, Sel, id), @@ -276,6 +284,7 @@ struct WindowState { event_callback: Option bool>>, activate_callback: Option>, resize_callback: Option>, + fullscreen_callback: Option>, should_close_callback: Option bool>>, close_callback: Option>, input_handler: Option>, @@ -368,6 +377,7 @@ impl Window { should_close_callback: None, close_callback: None, activate_callback: None, + fullscreen_callback: None, input_handler: None, pending_key_down: None, performed_key_equivalent: false, @@ -467,6 +477,10 @@ impl platform::Window for Window { self.0.as_ref().borrow_mut().resize_callback = Some(callback); } + fn on_fullscreen(&mut self, callback: Box) { + self.0.as_ref().borrow_mut().fullscreen_callback = Some(callback); + } + fn on_should_close(&mut self, callback: Box bool>) { self.0.as_ref().borrow_mut().should_close_callback = Some(callback); } @@ -908,6 +922,24 @@ extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) { window_state.as_ref().borrow().move_traffic_light(); } +extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) { + window_fullscreen_changed(this, true); +} + +extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) { + window_fullscreen_changed(this, false); +} + +fn window_fullscreen_changed(this: &Object, is_fullscreen: bool) { + let window_state = unsafe { get_window_state(this) }; + let mut window_state_borrow = window_state.as_ref().borrow_mut(); + if let Some(mut callback) = window_state_borrow.fullscreen_callback.take() { + drop(window_state_borrow); + callback(is_fullscreen); + window_state.borrow_mut().fullscreen_callback = Some(callback); + } +} + extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) { let is_active = if selector == sel!(windowDidBecomeKey:) { true diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index 8ea55b5e0d..3eb9b1e88e 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -37,6 +37,7 @@ pub struct Window { event_handlers: Vec bool>>, resize_handlers: Vec>, close_handlers: Vec>, + fullscreen_handlers: Vec>, pub(crate) active_status_change_handlers: Vec>, pub(crate) should_close_handler: Option bool>>, pub(crate) title: Option, @@ -199,6 +200,7 @@ impl Window { close_handlers: Default::default(), should_close_handler: Default::default(), active_status_change_handlers: Default::default(), + fullscreen_handlers: Default::default(), scale_factor: 1.0, current_scene: None, title: None, @@ -253,6 +255,10 @@ impl super::Window for Window { self.active_status_change_handlers.push(callback); } + fn on_fullscreen(&mut self, callback: Box) { + self.fullscreen_handlers.push(callback) + } + fn on_resize(&mut self, callback: Box) { self.resize_handlers.push(callback); } From 46fef69b1a7423caa7278a79d25550a6cffd342c Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Tue, 9 Aug 2022 18:10:30 -0400 Subject: [PATCH 06/27] Refactor notification/observation callback pattern in MutableAppContext Pull out duplicate code and clarify some misc behavior. Some of this existing API feels like it's probably incorrect but that needs more thorough investigation Co-authored-by: Mikayla --- crates/gpui/src/app.rs | 531 +++++++++++++---------------------------- 1 file changed, 164 insertions(+), 367 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 532f59f008..a9467c9996 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -962,6 +962,92 @@ type WindowActivationCallback = Box b type DeserializeActionCallback = fn(json: &str) -> anyhow::Result>; type WindowShouldCloseSubscriptionCallback = Box bool>; +// type SubscriptionMappings = Arc>>>>; +struct SubscriptionMappings { + internal: Arc>>>>, +} + +impl Default for SubscriptionMappings { + fn default() -> Self { + SubscriptionMappings { + internal: Arc::new(Mutex::new(HashMap::new())), + } + } +} + +impl SubscriptionMappings { + fn clone_ref(&self) -> Self { + Self { + internal: self.internal.clone(), + } + } + + fn add_callback(&mut self, id: K, subscription_id: usize, callback: F) { + self.internal + .lock() + .entry(id) + .or_default() + .insert(subscription_id, Some(callback)); + } + + fn remove(&mut self, id: K) { + self.internal.lock().remove(&id); + } + + fn add_or_remove_callback(&mut self, id: K, subscription_id: usize, callback: F) { + match self + .internal + .lock() + .entry(id) + .or_default() + .entry(subscription_id) + { + btree_map::Entry::Vacant(entry) => { + entry.insert(Some(callback)); + } + + btree_map::Entry::Occupied(entry) => { + // TODO: This seems like it should never be called because no code + // should ever attempt to remove an existing callback + debug_assert!(entry.get().is_none()); + entry.remove(); + } + } + } + + fn emit_and_cleanup bool>( + &mut self, + id: K, + cx: &mut MutableAppContext, + mut call_callback: C, + ) { + let callbacks = self.internal.lock().remove(&id); + if let Some(callbacks) = callbacks { + for (subscription_id, callback) in callbacks { + if let Some(mut callback) = callback { + let alive = call_callback(&mut callback, cx); + if alive { + match self + .internal + .lock() + .entry(id) + .or_default() + .entry(subscription_id) + { + btree_map::Entry::Vacant(entry) => { + entry.insert(Some(callback)); + } + btree_map::Entry::Occupied(entry) => { + entry.remove(); + } + } + } + } + } + } + } +} + pub struct MutableAppContext { weak_self: Option>>, foreground_platform: Rc, @@ -976,18 +1062,17 @@ pub struct MutableAppContext { next_window_id: usize, next_subscription_id: usize, frame_count: usize, - subscriptions: Arc>>>>, - global_subscriptions: - Arc>>>>, - observations: Arc>>>>, - focus_observations: - Arc>>>>, - global_observations: - Arc>>>>, + + focus_observations: SubscriptionMappings, + global_subscriptions: SubscriptionMappings, + global_observations: SubscriptionMappings, + subscriptions: SubscriptionMappings, + observations: SubscriptionMappings, + window_activation_observations: SubscriptionMappings, + release_observations: Arc>>>, - window_activation_observations: - Arc>>>>, action_dispatch_observations: Arc>>, + presenters_and_platform_windows: HashMap>, Box)>, foreground: Rc, @@ -1395,7 +1480,7 @@ impl MutableAppContext { Subscription::GlobalSubscription { id: subscription_id, type_id, - subscriptions: Some(Arc::downgrade(&self.global_subscriptions)), + subscriptions: Some(Arc::downgrade(&self.global_subscriptions.internal)), } } @@ -1436,7 +1521,7 @@ impl MutableAppContext { Subscription::Subscription { id: subscription_id, entity_id: handle.id(), - subscriptions: Some(Arc::downgrade(&self.subscriptions)), + subscriptions: Some(Arc::downgrade(&self.subscriptions.internal)), } } @@ -1464,7 +1549,7 @@ impl MutableAppContext { Subscription::Observation { id: subscription_id, entity_id, - observations: Some(Arc::downgrade(&self.observations)), + observations: Some(Arc::downgrade(&self.observations.internal)), } } @@ -1476,6 +1561,7 @@ impl MutableAppContext { let subscription_id = post_inc(&mut self.next_subscription_id); let observed = handle.downgrade(); let view_id = handle.id(); + self.pending_effects.push_back(Effect::FocusObservation { view_id, subscription_id, @@ -1487,10 +1573,11 @@ impl MutableAppContext { } }), }); + Subscription::FocusObservation { id: subscription_id, view_id, - observations: Some(Arc::downgrade(&self.focus_observations)), + observations: Some(Arc::downgrade(&self.focus_observations.internal)), } } @@ -1502,20 +1589,16 @@ impl MutableAppContext { let type_id = TypeId::of::(); let id = post_inc(&mut self.next_subscription_id); - self.global_observations - .lock() - .entry(type_id) - .or_default() - .insert( - id, - Some(Box::new(move |cx: &mut MutableAppContext| observe(cx)) - as GlobalObservationCallback), - ); + self.global_observations.add_callback( + type_id, + id, + Box::new(move |cx: &mut MutableAppContext| observe(cx)), + ); Subscription::GlobalObservation { id, type_id, - observations: Some(Arc::downgrade(&self.global_observations)), + observations: Some(Arc::downgrade(&self.global_observations.internal)), } } @@ -1573,7 +1656,9 @@ impl MutableAppContext { Subscription::WindowActivationObservation { id: subscription_id, window_id, - observations: Some(Arc::downgrade(&self.window_activation_observations)), + observations: Some(Arc::downgrade( + &self.window_activation_observations.internal, + )), } } @@ -2107,8 +2192,8 @@ impl MutableAppContext { } for model_id in dropped_models { - self.subscriptions.lock().remove(&model_id); - self.observations.lock().remove(&model_id); + self.subscriptions.remove(model_id); + self.observations.remove(model_id); let mut model = self.cx.models.remove(&model_id).unwrap(); model.release(self); self.pending_effects @@ -2116,8 +2201,8 @@ impl MutableAppContext { } for (window_id, view_id) in dropped_views { - self.subscriptions.lock().remove(&view_id); - self.observations.lock().remove(&view_id); + self.subscriptions.remove(view_id); + self.observations.remove(view_id); let mut view = self.cx.views.remove(&(window_id, view_id)).unwrap(); view.release(self); let change_focus_to = self.cx.windows.get_mut(&window_id).and_then(|window| { @@ -2165,15 +2250,24 @@ impl MutableAppContext { entity_id, subscription_id, callback, - } => self.handle_subscription_effect(entity_id, subscription_id, callback), + } => self.subscriptions.add_or_remove_callback( + entity_id, + subscription_id, + callback, + ), - Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload), + Effect::Event { entity_id, payload } => { + let mut subscriptions = self.subscriptions.clone_ref(); + subscriptions.emit_and_cleanup(entity_id, self, |callback, this| { + callback(payload.as_ref(), this) + }) + } Effect::GlobalSubscription { type_id, subscription_id, callback, - } => self.handle_global_subscription_effect( + } => self.global_subscriptions.add_or_remove_callback( type_id, subscription_id, callback, @@ -2185,10 +2279,16 @@ impl MutableAppContext { entity_id, subscription_id, callback, - } => self.handle_observation_effect(entity_id, subscription_id, callback), + } => self.observations.add_or_remove_callback( + entity_id, + subscription_id, + callback, + ), Effect::ModelNotification { model_id } => { - self.handle_model_notification_effect(model_id) + let mut observations = self.observations.clone_ref(); + observations + .emit_and_cleanup(model_id, self, |callback, this| callback(this)); } Effect::ViewNotification { window_id, view_id } => { @@ -2196,7 +2296,11 @@ impl MutableAppContext { } Effect::GlobalNotification { type_id } => { - self.handle_global_notification_effect(type_id) + let mut subscriptions = self.global_observations.clone_ref(); + subscriptions.emit_and_cleanup(type_id, self, |callback, this| { + callback(this); + true + }); } Effect::Deferred { @@ -2227,7 +2331,11 @@ impl MutableAppContext { subscription_id, callback, } => { - self.handle_focus_observation_effect(view_id, subscription_id, callback) + self.focus_observations.add_or_remove_callback( + view_id, + subscription_id, + callback, + ); } Effect::ResizeWindow { window_id } => { @@ -2242,7 +2350,7 @@ impl MutableAppContext { window_id, subscription_id, callback, - } => self.handle_window_activation_observation_effect( + } => self.window_activation_observations.add_or_remove_callback( window_id, subscription_id, callback, @@ -2369,182 +2477,14 @@ impl MutableAppContext { self.presenters_and_platform_windows = presenters; } - fn handle_subscription_effect( - &mut self, - entity_id: usize, - subscription_id: usize, - callback: SubscriptionCallback, - ) { - match self - .subscriptions - .lock() - .entry(entity_id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - // Subscription was dropped before effect was processed - btree_map::Entry::Occupied(entry) => { - debug_assert!(entry.get().is_none()); - entry.remove(); - } - } - } - - fn emit_event(&mut self, entity_id: usize, payload: Box) { - let callbacks = self.subscriptions.lock().remove(&entity_id); - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = callback(payload.as_ref(), self); - if alive { - match self - .subscriptions - .lock() - .entry(entity_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } - } - - fn handle_global_subscription_effect( - &mut self, - type_id: TypeId, - subscription_id: usize, - callback: GlobalSubscriptionCallback, - ) { - match self - .global_subscriptions - .lock() - .entry(type_id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - // Subscription was dropped before effect was processed - btree_map::Entry::Occupied(entry) => { - debug_assert!(entry.get().is_none()); - entry.remove(); - } - } - } - fn emit_global_event(&mut self, payload: Box) { let type_id = (&*payload).type_id(); - let callbacks = self.global_subscriptions.lock().remove(&type_id); - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - callback(payload.as_ref(), self); - match self - .global_subscriptions - .lock() - .entry(type_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } - fn handle_observation_effect( - &mut self, - entity_id: usize, - subscription_id: usize, - callback: ObservationCallback, - ) { - match self - .observations - .lock() - .entry(entity_id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - // Observation was dropped before effect was processed - btree_map::Entry::Occupied(entry) => { - debug_assert!(entry.get().is_none()); - entry.remove(); - } - } - } - - fn handle_focus_observation_effect( - &mut self, - view_id: usize, - subscription_id: usize, - callback: FocusObservationCallback, - ) { - match self - .focus_observations - .lock() - .entry(view_id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - // Observation was dropped before effect was processed - btree_map::Entry::Occupied(entry) => { - debug_assert!(entry.get().is_none()); - entry.remove(); - } - } - } - - fn handle_model_notification_effect(&mut self, observed_id: usize) { - let callbacks = self.observations.lock().remove(&observed_id); - if let Some(callbacks) = callbacks { - if self.cx.models.contains_key(&observed_id) { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = callback(self); - if alive { - match self - .observations - .lock() - .entry(observed_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } - } + let mut subscriptions = self.global_subscriptions.clone_ref(); + subscriptions.emit_and_cleanup(type_id, self, |callback, this| { + callback(payload.as_ref(), this); + true //Always alive + }); } fn handle_view_notification_effect( @@ -2552,8 +2492,6 @@ impl MutableAppContext { observed_window_id: usize, observed_view_id: usize, ) { - let callbacks = self.observations.lock().remove(&observed_view_id); - if self .cx .views @@ -2567,54 +2505,8 @@ impl MutableAppContext { .insert(observed_view_id); } - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = callback(self); - if alive { - match self - .observations - .lock() - .entry(observed_view_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } - } - } - - fn handle_global_notification_effect(&mut self, observed_type_id: TypeId) { - let callbacks = self.global_observations.lock().remove(&observed_type_id); - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - callback(self); - match self - .global_observations - .lock() - .entry(observed_type_id) - .or_default() - .entry(id) - { - collections::btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - collections::btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } + let mut observations = self.observations.clone_ref(); + observations.emit_and_cleanup(observed_view_id, self, |callback, this| callback(this)); } } @@ -2627,30 +2519,6 @@ impl MutableAppContext { } } - fn handle_window_activation_observation_effect( - &mut self, - window_id: usize, - subscription_id: usize, - callback: WindowActivationCallback, - ) { - match self - .window_activation_observations - .lock() - .entry(window_id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - // Observation was dropped before effect was processed - btree_map::Entry::Occupied(entry) => { - debug_assert!(entry.get().is_none()); - entry.remove(); - } - } - } - fn handle_fullscreen_effect(&mut self, window_id: usize, is_fullscreen: bool) { //Short circuit evaluation if we're already g2g if self @@ -2667,8 +2535,6 @@ impl MutableAppContext { let window = this.cx.windows.get_mut(&window_id)?; window.is_fullscreen = is_fullscreen; - // self.emit_event(entity_id, payload); - Some(()) }); } @@ -2700,35 +2566,8 @@ impl MutableAppContext { this.cx.views.insert((window_id, view_id), view); } - //Deliver events - let callbacks = this - .window_activation_observations - .lock() - .remove(&window_id); - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = callback(active, this); - //Put entry back - if alive { - match this - .window_activation_observations - .lock() - .entry(window_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } + let mut observations = this.window_activation_observations.clone_ref(); + observations.emit_and_cleanup(window_id, this, |callback, this| callback(active, this)); Some(()) }); @@ -2759,30 +2598,9 @@ impl MutableAppContext { blurred_view.on_blur(this, window_id, blurred_id); this.cx.views.insert((window_id, blurred_id), blurred_view); - let callbacks = this.focus_observations.lock().remove(&blurred_id); - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = callback(false, this); - if alive { - match this - .focus_observations - .lock() - .entry(blurred_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } + let mut subscriptions = this.focus_observations.clone_ref(); + subscriptions + .emit_and_cleanup(blurred_id, this, |callback, this| callback(false, this)); } } @@ -2791,30 +2609,9 @@ impl MutableAppContext { focused_view.on_focus(this, window_id, focused_id); this.cx.views.insert((window_id, focused_id), focused_view); - let callbacks = this.focus_observations.lock().remove(&focused_id); - if let Some(callbacks) = callbacks { - for (id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = callback(true, this); - if alive { - match this - .focus_observations - .lock() - .entry(focused_id) - .or_default() - .entry(id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } + let mut subscriptions = this.focus_observations.clone_ref(); + subscriptions + .emit_and_cleanup(focused_id, this, |callback, this| callback(true, this)); } } }) @@ -5768,8 +5565,8 @@ mod tests { }); assert_eq!(cx.cx.models.len(), 1); - assert!(cx.subscriptions.lock().is_empty()); - assert!(cx.observations.lock().is_empty()); + assert!(cx.subscriptions.internal.lock().is_empty()); + assert!(cx.observations.internal.lock().is_empty()); } #[crate::test(self)] @@ -6019,8 +5816,8 @@ mod tests { }); assert_eq!(cx.cx.views.len(), 2); - assert!(cx.subscriptions.lock().is_empty()); - assert!(cx.observations.lock().is_empty()); + assert!(cx.subscriptions.internal.lock().is_empty()); + assert!(cx.observations.internal.lock().is_empty()); } #[crate::test(self)] From 43b9f3beb3be382f63e3a10112320e4478c44fcc Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Tue, 9 Aug 2022 18:52:25 -0400 Subject: [PATCH 07/27] Invalidate view when entering/exiting fullscreen This is required for `render_titlebar` to eventually adapt to fullscreen status to affect the size of left padding on workspace name to account for the traffic lights presence/absence Co-authored-by: Mikayla --- crates/gpui/src/app.rs | 102 +++++++++++++++++++++++++++++- crates/workspace/src/workspace.rs | 2 + 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index a9467c9996..480a9a1bdf 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -959,6 +959,7 @@ type GlobalObservationCallback = Box; type ReleaseObservationCallback = Box; type ActionObservationCallback = Box; type WindowActivationCallback = Box bool>; +type WindowFullscreenCallback = Box bool>; type DeserializeActionCallback = fn(json: &str) -> anyhow::Result>; type WindowShouldCloseSubscriptionCallback = Box bool>; @@ -1069,7 +1070,8 @@ pub struct MutableAppContext { subscriptions: SubscriptionMappings, observations: SubscriptionMappings, window_activation_observations: SubscriptionMappings, - + window_fullscreen_observations: SubscriptionMappings, + release_observations: Arc>>>, action_dispatch_observations: Arc>>, @@ -1126,6 +1128,7 @@ impl MutableAppContext { release_observations: Default::default(), global_observations: Default::default(), window_activation_observations: Default::default(), + window_fullscreen_observations: Default::default(), action_dispatch_observations: Default::default(), presenters_and_platform_windows: HashMap::new(), foreground, @@ -1662,6 +1665,26 @@ impl MutableAppContext { } } + fn observe_fullscreen(&mut self, window_id: usize, callback: F) -> Subscription + where + F: 'static + FnMut(bool, &mut MutableAppContext) -> bool, + { + let subscription_id = post_inc(&mut self.next_subscription_id); + self.pending_effects + .push_back(Effect::WindowFullscreenObservation { + window_id, + subscription_id, + callback: Box::new(callback), + }); + Subscription::WindowFullscreenObservation { + id: subscription_id, + window_id, + observations: Some(Arc::downgrade( + &self.window_activation_observations.internal, + )), + } + } + pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut MutableAppContext)) { self.pending_effects.push_back(Effect::Deferred { callback: Box::new(callback), @@ -2361,6 +2384,16 @@ impl MutableAppContext { is_active, } => self.handle_window_activation_effect(window_id, is_active), + Effect::WindowFullscreenObservation { + window_id, + subscription_id, + callback, + } => self.window_fullscreen_observations.add_or_remove_callback( + window_id, + subscription_id, + callback, + ), + Effect::FullscreenWindow { window_id, is_fullscreen, @@ -2535,6 +2568,11 @@ impl MutableAppContext { let window = this.cx.windows.get_mut(&window_id)?; window.is_fullscreen = is_fullscreen; + let mut observations = this.window_fullscreen_observations.clone_ref(); + observations.emit_and_cleanup(window_id, this, |callback, this| { + callback(is_fullscreen, this) + }); + Some(()) }); } @@ -3019,6 +3057,11 @@ pub enum Effect { subscription_id: usize, callback: WindowActivationCallback, }, + WindowFullscreenObservation { + window_id: usize, + subscription_id: usize, + callback: WindowFullscreenCallback, + }, RefreshWindows, ActionDispatchNotification { action_id: TypeId, @@ -3136,6 +3179,15 @@ impl Debug for Effect { .field("window_id", window_id) .field("is_fullscreen", is_fullscreen) .finish(), + Effect::WindowFullscreenObservation { + window_id, + subscription_id, + callback: _, + } => f + .debug_struct("Effect::WindowFullscreenObservation") + .field("window_id", window_id) + .field("subscription_id", subscription_id) + .finish(), Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(), Effect::WindowShouldCloseSubscription { window_id, .. } => f .debug_struct("Effect::WindowShouldCloseSubscription") @@ -3807,6 +3859,24 @@ impl<'a, T: View> ViewContext<'a, T> { }) } + pub fn observe_fullscreen(&mut self, mut callback: F) -> Subscription + where + F: 'static + FnMut(&mut T, bool, &mut ViewContext), + { + let observer = self.weak_handle(); + self.app + .observe_fullscreen(self.window_id(), move |active, cx| { + if let Some(observer) = observer.upgrade(cx) { + observer.update(cx, |observer, cx| { + callback(observer, active, cx); + }); + true + } else { + false + } + }) + } + pub fn emit(&mut self, payload: T::Event) { self.app.pending_effects.push_back(Effect::Event { entity_id: self.view_id, @@ -5128,6 +5198,12 @@ pub enum Subscription { observations: Option>>>>>, }, + WindowFullscreenObservation { + id: usize, + window_id: usize, + observations: + Option>>>>>, + }, } impl Subscription { @@ -5157,6 +5233,9 @@ impl Subscription { Subscription::WindowActivationObservation { observations, .. } => { observations.take(); } + Subscription::WindowFullscreenObservation { observations, .. } => { + observations.take(); + } } } } @@ -5291,6 +5370,27 @@ impl Drop for Subscription { } } } + Subscription::WindowFullscreenObservation { + id, + window_id, + observations, + } => { + if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) { + match observations + .lock() + .entry(*window_id) + .or_default() + .entry(*id) + { + btree_map::Entry::Vacant(entry) => { + entry.insert(None); + } + btree_map::Entry::Occupied(entry) => { + entry.remove(); + } + } + } + } } } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 045e9c6f90..302ebd65ee 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -823,6 +823,8 @@ enum FollowerItem { impl Workspace { pub fn new(project: ModelHandle, cx: &mut ViewContext) -> Self { + cx.observe_fullscreen(|_, _, cx| cx.notify()).detach(); + cx.observe_window_activation(Self::on_window_activation_changed) .detach(); cx.observe(&project, |_, _, cx| cx.notify()).detach(); From 3d9821b430dde5ab583b2f571c86fadf992afcf4 Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Tue, 9 Aug 2022 19:03:03 -0400 Subject: [PATCH 08/27] Jankily adjust left padding on workspace title in fullscreen This could seriously be done better Co-authored-by: Mikayla --- crates/gpui/src/platform/mac/window.rs | 12 ++++++------ crates/workspace/src/workspace.rs | 13 ++++++++++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 2168b07ffe..568356e938 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -129,12 +129,12 @@ unsafe fn build_classes() { window_did_resize as extern "C" fn(&Object, Sel, id), ); decl.add_method( - sel!(windowDidEnterFullScreen:), - window_did_enter_fullscreen as extern "C" fn(&Object, Sel, id), + sel!(windowWillEnterFullScreen:), + window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id), ); decl.add_method( - sel!(windowDidExitFullScreen:), - window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id), + sel!(windowWillExitFullScreen:), + window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id), ); decl.add_method( sel!(windowDidBecomeKey:), @@ -922,11 +922,11 @@ extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) { window_state.as_ref().borrow().move_traffic_light(); } -extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) { +extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) { window_fullscreen_changed(this, true); } -extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) { +extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) { window_fullscreen_changed(this, false); } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 302ebd65ee..a27754aa13 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1858,6 +1858,17 @@ impl Workspace { worktree_root_names.push_str(name); } + // TODO: There should be a better system in place for this + // (https://github.com/zed-industries/zed/issues/1290) + let is_fullscreen = cx.window_is_fullscreen(cx.window_id()); + let container_theme = if is_fullscreen { + let mut container_theme = theme.workspace.titlebar.container; + container_theme.padding.left = container_theme.padding.right; + container_theme + } else { + theme.workspace.titlebar.container + }; + ConstrainedBox::new( Container::new( Stack::new() @@ -1885,7 +1896,7 @@ impl Workspace { ) .boxed(), ) - .with_style(theme.workspace.titlebar.container) + .with_style(container_theme) .boxed(), ) .with_height(theme.workspace.titlebar.height) From 45c0539de0becaa9e68f07e92d16ac424ccfff31 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 9 Aug 2022 16:59:13 -0700 Subject: [PATCH 09/27] changed name of subscription mapping and moved out to file Co-authored-by: Keith --- crates/gpui/src/app.rs | 208 ++++++--------------- crates/gpui/src/app/callback_collection.rs | 106 +++++++++++ crates/gpui/src/presenter.rs | 4 +- 3 files changed, 165 insertions(+), 153 deletions(-) create mode 100644 crates/gpui/src/app/callback_collection.rs diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 480a9a1bdf..cc4c1191f6 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1,4 +1,5 @@ pub mod action; +mod callback_collection; use crate::{ elements::ElementBox, @@ -13,7 +14,8 @@ use crate::{ }; pub use action::*; use anyhow::{anyhow, Context, Result}; -use collections::btree_map; +use callback_collection::CallbackCollection; +use collections::{btree_map, hash_map::Entry, BTreeMap, HashMap, HashSet, VecDeque}; use keymap::MatchResult; use lazy_static::lazy_static; use parking_lot::Mutex; @@ -24,7 +26,6 @@ use smol::prelude::*; use std::{ any::{type_name, Any, TypeId}, cell::RefCell, - collections::{hash_map::Entry, BTreeMap, HashMap, HashSet, VecDeque}, fmt::{self, Debug}, hash::{Hash, Hasher}, marker::PhantomData, @@ -37,6 +38,8 @@ use std::{ time::Duration, }; +use self::callback_collection::Mapping; + pub trait Entity: 'static { type Event; @@ -963,92 +966,6 @@ type WindowFullscreenCallback = Box b type DeserializeActionCallback = fn(json: &str) -> anyhow::Result>; type WindowShouldCloseSubscriptionCallback = Box bool>; -// type SubscriptionMappings = Arc>>>>; -struct SubscriptionMappings { - internal: Arc>>>>, -} - -impl Default for SubscriptionMappings { - fn default() -> Self { - SubscriptionMappings { - internal: Arc::new(Mutex::new(HashMap::new())), - } - } -} - -impl SubscriptionMappings { - fn clone_ref(&self) -> Self { - Self { - internal: self.internal.clone(), - } - } - - fn add_callback(&mut self, id: K, subscription_id: usize, callback: F) { - self.internal - .lock() - .entry(id) - .or_default() - .insert(subscription_id, Some(callback)); - } - - fn remove(&mut self, id: K) { - self.internal.lock().remove(&id); - } - - fn add_or_remove_callback(&mut self, id: K, subscription_id: usize, callback: F) { - match self - .internal - .lock() - .entry(id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - - btree_map::Entry::Occupied(entry) => { - // TODO: This seems like it should never be called because no code - // should ever attempt to remove an existing callback - debug_assert!(entry.get().is_none()); - entry.remove(); - } - } - } - - fn emit_and_cleanup bool>( - &mut self, - id: K, - cx: &mut MutableAppContext, - mut call_callback: C, - ) { - let callbacks = self.internal.lock().remove(&id); - if let Some(callbacks) = callbacks { - for (subscription_id, callback) in callbacks { - if let Some(mut callback) = callback { - let alive = call_callback(&mut callback, cx); - if alive { - match self - .internal - .lock() - .entry(id) - .or_default() - .entry(subscription_id) - { - btree_map::Entry::Vacant(entry) => { - entry.insert(Some(callback)); - } - btree_map::Entry::Occupied(entry) => { - entry.remove(); - } - } - } - } - } - } - } -} - pub struct MutableAppContext { weak_self: Option>>, foreground_platform: Rc, @@ -1064,13 +981,13 @@ pub struct MutableAppContext { next_subscription_id: usize, frame_count: usize, - focus_observations: SubscriptionMappings, - global_subscriptions: SubscriptionMappings, - global_observations: SubscriptionMappings, - subscriptions: SubscriptionMappings, - observations: SubscriptionMappings, - window_activation_observations: SubscriptionMappings, - window_fullscreen_observations: SubscriptionMappings, + focus_observations: CallbackCollection, + global_subscriptions: CallbackCollection, + global_observations: CallbackCollection, + subscriptions: CallbackCollection, + observations: CallbackCollection, + window_activation_observations: CallbackCollection, + window_fullscreen_observations: CallbackCollection, release_observations: Arc>>>, action_dispatch_observations: Arc>>, @@ -1112,10 +1029,10 @@ impl MutableAppContext { font_cache, platform, }, - action_deserializers: HashMap::new(), - capture_actions: HashMap::new(), - actions: HashMap::new(), - global_actions: HashMap::new(), + action_deserializers: Default::default(), + capture_actions: Default::default(), + actions: Default::default(), + global_actions: Default::default(), keystroke_matcher: keymap::Matcher::default(), next_entity_id: 0, next_window_id: 0, @@ -1130,12 +1047,12 @@ impl MutableAppContext { window_activation_observations: Default::default(), window_fullscreen_observations: Default::default(), action_dispatch_observations: Default::default(), - presenters_and_platform_windows: HashMap::new(), + presenters_and_platform_windows: Default::default(), foreground, pending_effects: VecDeque::new(), pending_focus_index: None, - pending_notifications: HashSet::new(), - pending_global_notifications: HashSet::new(), + pending_notifications: Default::default(), + pending_global_notifications: Default::default(), pending_flushes: 0, flushing_effects: false, halt_action_dispatch: false, @@ -1480,10 +1397,11 @@ impl MutableAppContext { callback(payload, cx) }), }); + Subscription::GlobalSubscription { id: subscription_id, type_id, - subscriptions: Some(Arc::downgrade(&self.global_subscriptions.internal)), + subscriptions: Some(self.global_subscriptions.downgrade()), } } @@ -1524,7 +1442,7 @@ impl MutableAppContext { Subscription::Subscription { id: subscription_id, entity_id: handle.id(), - subscriptions: Some(Arc::downgrade(&self.subscriptions.internal)), + subscriptions: Some(self.subscriptions.downgrade()), } } @@ -1552,7 +1470,7 @@ impl MutableAppContext { Subscription::Observation { id: subscription_id, entity_id, - observations: Some(Arc::downgrade(&self.observations.internal)), + observations: Some(self.observations.downgrade()), } } @@ -1580,7 +1498,7 @@ impl MutableAppContext { Subscription::FocusObservation { id: subscription_id, view_id, - observations: Some(Arc::downgrade(&self.focus_observations.internal)), + observations: Some(self.focus_observations.downgrade()), } } @@ -1601,7 +1519,7 @@ impl MutableAppContext { Subscription::GlobalObservation { id, type_id, - observations: Some(Arc::downgrade(&self.global_observations.internal)), + observations: Some(self.global_observations.downgrade()), } } @@ -1659,9 +1577,7 @@ impl MutableAppContext { Subscription::WindowActivationObservation { id: subscription_id, window_id, - observations: Some(Arc::downgrade( - &self.window_activation_observations.internal, - )), + observations: Some(self.window_activation_observations.downgrade()), } } @@ -1679,9 +1595,7 @@ impl MutableAppContext { Subscription::WindowFullscreenObservation { id: subscription_id, window_id, - observations: Some(Arc::downgrade( - &self.window_activation_observations.internal, - )), + observations: Some(self.window_activation_observations.downgrade()), } } @@ -2280,7 +2194,7 @@ impl MutableAppContext { ), Effect::Event { entity_id, payload } => { - let mut subscriptions = self.subscriptions.clone_ref(); + let mut subscriptions = self.subscriptions.clone(); subscriptions.emit_and_cleanup(entity_id, self, |callback, this| { callback(payload.as_ref(), this) }) @@ -2309,7 +2223,7 @@ impl MutableAppContext { ), Effect::ModelNotification { model_id } => { - let mut observations = self.observations.clone_ref(); + let mut observations = self.observations.clone(); observations .emit_and_cleanup(model_id, self, |callback, this| callback(this)); } @@ -2319,7 +2233,7 @@ impl MutableAppContext { } Effect::GlobalNotification { type_id } => { - let mut subscriptions = self.global_observations.clone_ref(); + let mut subscriptions = self.global_observations.clone(); subscriptions.emit_and_cleanup(type_id, self, |callback, this| { callback(this); true @@ -2442,7 +2356,7 @@ impl MutableAppContext { } fn update_windows(&mut self) { - let mut invalidations = HashMap::new(); + let mut invalidations: HashMap<_, _> = Default::default(); for (window_id, window) in &mut self.cx.windows { if let Some(invalidation) = window.invalidation.take() { invalidations.insert(*window_id, invalidation); @@ -2513,7 +2427,7 @@ impl MutableAppContext { fn emit_global_event(&mut self, payload: Box) { let type_id = (&*payload).type_id(); - let mut subscriptions = self.global_subscriptions.clone_ref(); + let mut subscriptions = self.global_subscriptions.clone(); subscriptions.emit_and_cleanup(type_id, self, |callback, this| { callback(payload.as_ref(), this); true //Always alive @@ -2538,7 +2452,7 @@ impl MutableAppContext { .insert(observed_view_id); } - let mut observations = self.observations.clone_ref(); + let mut observations = self.observations.clone(); observations.emit_and_cleanup(observed_view_id, self, |callback, this| callback(this)); } } @@ -2568,7 +2482,7 @@ impl MutableAppContext { let window = this.cx.windows.get_mut(&window_id)?; window.is_fullscreen = is_fullscreen; - let mut observations = this.window_fullscreen_observations.clone_ref(); + let mut observations = this.window_fullscreen_observations.clone(); observations.emit_and_cleanup(window_id, this, |callback, this| { callback(is_fullscreen, this) }); @@ -2604,7 +2518,7 @@ impl MutableAppContext { this.cx.views.insert((window_id, view_id), view); } - let mut observations = this.window_activation_observations.clone_ref(); + let mut observations = this.window_activation_observations.clone(); observations.emit_and_cleanup(window_id, this, |callback, this| callback(active, this)); Some(()) @@ -2636,7 +2550,7 @@ impl MutableAppContext { blurred_view.on_blur(this, window_id, blurred_id); this.cx.views.insert((window_id, blurred_id), blurred_view); - let mut subscriptions = this.focus_observations.clone_ref(); + let mut subscriptions = this.focus_observations.clone(); subscriptions .emit_and_cleanup(blurred_id, this, |callback, this| callback(false, this)); } @@ -2647,7 +2561,7 @@ impl MutableAppContext { focused_view.on_focus(this, window_id, focused_id); this.cx.views.insert((window_id, focused_id), focused_view); - let mut subscriptions = this.focus_observations.clone_ref(); + let mut subscriptions = this.focus_observations.clone(); subscriptions .emit_and_cleanup(focused_id, this, |callback, this| callback(true, this)); } @@ -5153,35 +5067,39 @@ pub enum Subscription { Subscription { id: usize, entity_id: usize, - subscriptions: - Option>>>>>, + subscriptions: Option>>, }, GlobalSubscription { id: usize, type_id: TypeId, - subscriptions: Option< - Weak>>>>, - >, + subscriptions: Option>>, }, Observation { id: usize, entity_id: usize, - observations: - Option>>>>>, + observations: Option>>, }, GlobalObservation { id: usize, type_id: TypeId, - observations: Option< - Weak>>>>, - >, + observations: Option>>, }, FocusObservation { id: usize, view_id: usize, - observations: - Option>>>>>, + observations: Option>>, }, + WindowActivationObservation { + id: usize, + window_id: usize, + observations: Option>>, + }, + WindowFullscreenObservation { + id: usize, + window_id: usize, + observations: Option>>, + }, + ReleaseObservation { id: usize, entity_id: usize, @@ -5192,18 +5110,6 @@ pub enum Subscription { id: usize, observations: Option>>>, }, - WindowActivationObservation { - id: usize, - window_id: usize, - observations: - Option>>>>>, - }, - WindowFullscreenObservation { - id: usize, - window_id: usize, - observations: - Option>>>>>, - }, } impl Subscription { @@ -5665,8 +5571,8 @@ mod tests { }); assert_eq!(cx.cx.models.len(), 1); - assert!(cx.subscriptions.internal.lock().is_empty()); - assert!(cx.observations.internal.lock().is_empty()); + assert!(cx.subscriptions.is_empty()); + assert!(cx.observations.is_empty()); } #[crate::test(self)] @@ -5916,8 +5822,8 @@ mod tests { }); assert_eq!(cx.cx.views.len(), 2); - assert!(cx.subscriptions.internal.lock().is_empty()); - assert!(cx.observations.internal.lock().is_empty()); + assert!(cx.subscriptions.is_empty()); + assert!(cx.observations.is_empty()); } #[crate::test(self)] diff --git a/crates/gpui/src/app/callback_collection.rs b/crates/gpui/src/app/callback_collection.rs new file mode 100644 index 0000000000..4ec90fbac0 --- /dev/null +++ b/crates/gpui/src/app/callback_collection.rs @@ -0,0 +1,106 @@ +use std::sync::Arc; +use std::{hash::Hash, sync::Weak}; + +use parking_lot::Mutex; + +use collections::{btree_map, BTreeMap, HashMap}; + +use crate::MutableAppContext; + +pub type Mapping = Mutex>>>; + +pub struct CallbackCollection { + internal: Arc>, +} + +impl Clone for CallbackCollection { + fn clone(&self) -> Self { + Self { + internal: self.internal.clone(), + } + } +} + +impl Default for CallbackCollection { + fn default() -> Self { + CallbackCollection { + internal: Arc::new(Mutex::new(Default::default())), + } + } +} + +impl CallbackCollection { + pub fn downgrade(&self) -> Weak> { + Arc::downgrade(&self.internal) + } + + #[cfg(test)] + pub fn is_empty(&self) -> bool { + self.internal.lock().is_empty() + } + + pub fn add_callback(&mut self, id: K, subscription_id: usize, callback: F) { + self.internal + .lock() + .entry(id) + .or_default() + .insert(subscription_id, Some(callback)); + } + + pub fn remove(&mut self, id: K) { + self.internal.lock().remove(&id); + } + + pub fn add_or_remove_callback(&mut self, id: K, subscription_id: usize, callback: F) { + match self + .internal + .lock() + .entry(id) + .or_default() + .entry(subscription_id) + { + btree_map::Entry::Vacant(entry) => { + entry.insert(Some(callback)); + } + + btree_map::Entry::Occupied(entry) => { + // TODO: This seems like it should never be called because no code + // should ever attempt to remove an existing callback + debug_assert!(entry.get().is_none()); + entry.remove(); + } + } + } + + pub fn emit_and_cleanup bool>( + &mut self, + id: K, + cx: &mut MutableAppContext, + mut call_callback: C, + ) { + let callbacks = self.internal.lock().remove(&id); + if let Some(callbacks) = callbacks { + for (subscription_id, callback) in callbacks { + if let Some(mut callback) = callback { + let alive = call_callback(&mut callback, cx); + if alive { + match self + .internal + .lock() + .entry(id) + .or_default() + .entry(subscription_id) + { + btree_map::Entry::Vacant(entry) => { + entry.insert(Some(callback)); + } + btree_map::Entry::Occupied(entry) => { + entry.remove(); + } + } + } + } + } + } + } +} diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index d0af2473a6..a8aefad6e9 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -13,11 +13,11 @@ use crate::{ ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle, }; +use collections::{HashMap, HashSet}; use pathfinder_geometry::vector::{vec2f, Vector2F}; use serde_json::json; use smallvec::SmallVec; use std::{ - collections::{HashMap, HashSet}, marker::PhantomData, ops::{Deref, DerefMut, Range}, sync::Arc, @@ -52,7 +52,7 @@ impl Presenter { Self { window_id, rendered_views: cx.render_views(window_id, titlebar_height), - parents: HashMap::new(), + parents: Default::default(), cursor_regions: Default::default(), mouse_regions: Default::default(), font_cache, From 4271eb36241b97aee562df9f1d3da44cfed5755c Mon Sep 17 00:00:00 2001 From: K Simmons Date: Thu, 4 Aug 2022 20:55:10 -0700 Subject: [PATCH 10/27] Event dispatch moved to MutableAppContext. No longer dispatches from presenter. Not currently handling key presses properly --- crates/collab/src/integration_tests.rs | 29 +- crates/command_palette/src/command_palette.rs | 10 +- crates/contacts_panel/src/contacts_panel.rs | 4 +- crates/context_menu/src/context_menu.rs | 4 +- crates/diagnostics/src/diagnostics.rs | 4 +- crates/editor/src/editor.rs | 4 +- crates/editor/src/items.rs | 4 +- crates/gpui/src/app.rs | 521 ++++++++++-------- crates/gpui/src/presenter.rs | 64 +-- crates/gpui/src/test.rs | 20 +- crates/search/src/buffer_search.rs | 8 +- crates/search/src/project_search.rs | 7 +- crates/workspace/src/pane.rs | 4 +- crates/workspace/src/workspace.rs | 45 +- 14 files changed, 392 insertions(+), 336 deletions(-) diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 2a68c2056e..4118e5963c 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -18,6 +18,7 @@ use futures::{channel::mpsc, Future, StreamExt as _}; use gpui::{ executor::{self, Deterministic}, geometry::vector::vec2f, + test::EmptyView, ModelHandle, Task, TestAppContext, ViewHandle, }; use language::{ @@ -67,7 +68,7 @@ async fn test_share_project( cx_b2: &mut TestAppContext, ) { cx_a.foreground().forbid_parking(); - let (window_b, _) = cx_b.add_window(|_| EmptyView); + let (_, window_b) = cx_b.add_window(|_| EmptyView); let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; let client_a = server.create_client(cx_a, "user_a").await; let client_b = server.create_client(cx_b, "user_b").await; @@ -145,7 +146,7 @@ async fn test_share_project( .await .unwrap(); - let editor_b = cx_b.add_view(window_b, |cx| Editor::for_buffer(buffer_b, None, cx)); + let editor_b = cx_b.add_view(&window_b, |cx| Editor::for_buffer(buffer_b, None, cx)); // TODO // // Create a selection set as client B and see that selection set as client A. @@ -1736,8 +1737,8 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx)) .await .unwrap(); - let (window_b, _) = cx_b.add_window(|_| EmptyView); - let editor_b = cx_b.add_view(window_b, |cx| { + let (_, window_b) = cx_b.add_window(|_| EmptyView); + let editor_b = cx_b.add_view(&window_b, |cx| { Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx) }); @@ -5387,8 +5388,8 @@ impl TestClient { project: &ModelHandle, cx: &mut TestAppContext, ) -> ViewHandle { - let (window_id, _) = cx.add_window(|_| EmptyView); - cx.add_view(window_id, |cx| Workspace::new(project.clone(), cx)) + let (_, root_view) = cx.add_window(|_| EmptyView); + cx.add_view(&root_view, |cx| Workspace::new(project.clone(), cx)) } async fn simulate_host( @@ -5901,19 +5902,3 @@ fn channel_messages(channel: &Channel) -> Vec<(String, String, bool)> { }) .collect() } - -struct EmptyView; - -impl gpui::Entity for EmptyView { - type Event = (); -} - -impl gpui::View for EmptyView { - fn ui_name() -> &'static str { - "empty view" - } - - fn render(&mut self, _: &mut gpui::RenderContext) -> gpui::ElementBox { - gpui::Element::boxed(gpui::elements::Empty::new()) - } -} diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 5f438057ee..5f213284e8 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -85,8 +85,8 @@ impl CommandPalette { let focused_view_id = cx.focused_view_id(window_id).unwrap_or(workspace.id()); cx.as_mut().defer(move |cx| { - let this = cx.add_view(window_id, |cx| Self::new(focused_view_id, cx)); workspace.update(cx, |workspace, cx| { + let this = cx.add_view(|cx| Self::new(focused_view_id, cx)); workspace.toggle_modal(cx, |_, cx| { cx.subscribe(&this, Self::on_event).detach(); this @@ -110,10 +110,10 @@ impl CommandPalette { } => { let window_id = *window_id; let focused_view_id = *focused_view_id; - let action = (*action).boxed_clone(); + let action = action.boxed_clone(); workspace.dismiss_modal(cx); cx.as_mut() - .defer(move |cx| cx.dispatch_action_at(window_id, focused_view_id, &*action)) + .defer(move |cx| cx.dispatch_any_action_at(window_id, focused_view_id, action)) } } } @@ -345,8 +345,8 @@ mod tests { }); let project = Project::test(app_state.fs.clone(), [], cx).await; - let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); - let editor = cx.add_view(window_id, |cx| { + let (_, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); + let editor = cx.add_view(&workspace, |cx| { let mut editor = Editor::single_line(None, cx); editor.set_text("abc", cx); editor diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index aef9037879..4aff5b1a74 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -1248,8 +1248,8 @@ mod tests { .0 .read_with(cx, |worktree, _| worktree.id().to_proto()); - let workspace = cx.add_view(0, |cx| Workspace::new(project.clone(), cx)); - let panel = cx.add_view(0, |cx| { + let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx)); + let panel = cx.add_view(&workspace, |cx| { ContactsPanel::new( user_store.clone(), project_store.clone(), diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index d49f817de6..b17718577f 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -156,9 +156,7 @@ impl ContextMenu { fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { if let Some(ix) = self.selected_index { if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) { - let window_id = cx.window_id(); - let view_id = cx.view_id(); - cx.dispatch_action_at(window_id, view_id, action.as_ref()); + cx.dispatch_any_action(action.boxed_clone()); self.reset(cx); } } diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 8d5746f8fb..e9692c5493 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -786,7 +786,7 @@ mod tests { .await; let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await; - let workspace = cx.add_view(0, |cx| Workspace::new(project.clone(), cx)); + let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx)); // Create some diagnostics project.update(cx, |project, cx| { @@ -873,7 +873,7 @@ mod tests { }); // Open the project diagnostics view while there are already diagnostics. - let view = cx.add_view(0, |cx| { + let view = cx.add_view(&workspace, |cx| { ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx) }); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 7c2d560a41..e4ff272440 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7099,10 +7099,10 @@ mod tests { fn test_navigation_history(cx: &mut gpui::MutableAppContext) { cx.set_global(Settings::test(cx)); use workspace::Item; - let pane = cx.add_view(Default::default(), |cx| Pane::new(cx)); + let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(cx)); let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx); - cx.add_window(Default::default(), |cx| { + cx.add_view(&pane, |cx| { let mut editor = build_editor(buffer.clone(), cx); let handle = cx.handle(); editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle))); diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 5bb8d4d0b2..9837c5070f 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -54,8 +54,8 @@ impl FollowableItem for Editor { }) }) .unwrap_or_else(|| { - cx.add_view(pane.window_id(), |cx| { - Editor::for_buffer(buffer, Some(project), cx) + pane.update(&mut cx, |_, cx| { + cx.add_view(|cx| Editor::for_buffer(buffer, Some(project), cx)) }) }); editor.update(&mut cx, |editor, cx| { diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index cc4c1191f6..a1b782039a 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -229,18 +229,12 @@ impl App { move |action| { let mut cx = cx.borrow_mut(); if let Some(key_window_id) = cx.cx.platform.key_window_id() { - if let Some((presenter, _)) = - cx.presenters_and_platform_windows.get(&key_window_id) - { - let presenter = presenter.clone(); - let path = presenter.borrow().dispatch_path(cx.as_ref()); - cx.dispatch_action_any(key_window_id, &path, action); - } else { - cx.dispatch_global_action_any(action); + if let Some(view_id) = cx.focused_view_id(key_window_id) { + cx.handle_dispatch_action_any_effect(key_window_id, Some(view_id), action); + return; } - } else { - cx.dispatch_global_action_any(action); } + cx.dispatch_global_action_any(action); } })); @@ -462,15 +456,9 @@ impl TestAppContext { pub fn dispatch_action(&self, window_id: usize, action: A) { let mut cx = self.cx.borrow_mut(); - let dispatch_path = cx - .presenters_and_platform_windows - .get(&window_id) - .unwrap() - .0 - .borrow() - .dispatch_path(cx.as_ref()); - - cx.dispatch_action_any(window_id, &dispatch_path, &action); + if let Some(view_id) = cx.focused_view_id(window_id) { + cx.handle_dispatch_action_any_effect(window_id, Some(view_id), &action); + } } pub fn dispatch_global_action(&self, action: A) { @@ -485,9 +473,8 @@ impl TestAppContext { .unwrap() .0 .clone(); - let dispatch_path = presenter.borrow().dispatch_path(cx.as_ref()); - if cx.dispatch_keystroke(window_id, dispatch_path, &keystroke) { + if cx.dispatch_keystroke(window_id, &keystroke) { return true; } if presenter.borrow_mut().dispatch_event( @@ -533,6 +520,18 @@ impl TestAppContext { (window_id, view) } + pub fn add_view( + &mut self, + parent_handle: impl Into, + build_view: F, + ) -> ViewHandle + where + T: View, + F: FnOnce(&mut ViewContext) -> T, + { + self.cx.borrow_mut().add_view(parent_handle, build_view) + } + pub fn window_ids(&self) -> Vec { self.cx.borrow().window_ids().collect() } @@ -541,26 +540,6 @@ impl TestAppContext { self.cx.borrow().root_view(window_id) } - pub fn add_view(&mut self, window_id: usize, build_view: F) -> ViewHandle - where - T: View, - F: FnOnce(&mut ViewContext) -> T, - { - self.cx.borrow_mut().add_view(window_id, build_view) - } - - pub fn add_option_view( - &mut self, - window_id: usize, - build_view: F, - ) -> Option> - where - T: View, - F: FnOnce(&mut ViewContext) -> Option, - { - self.cx.borrow_mut().add_option_view(window_id, build_view) - } - pub fn read T>(&self, callback: F) -> T { callback(self.cx.borrow().as_ref()) } @@ -786,14 +765,6 @@ impl AsyncAppContext { self.update(|cx| cx.add_model(build_model)) } - pub fn add_view(&mut self, window_id: usize, build_view: F) -> ViewHandle - where - T: View, - F: FnOnce(&mut ViewContext) -> T, - { - self.update(|cx| cx.add_view(window_id, build_view)) - } - pub fn add_window( &mut self, window_options: WindowOptions, @@ -1021,6 +992,7 @@ impl MutableAppContext { cx: AppContext { models: Default::default(), views: Default::default(), + parents: Default::default(), windows: Default::default(), globals: Default::default(), element_states: Default::default(), @@ -1645,17 +1617,7 @@ impl MutableAppContext { ) -> impl Iterator, SmallVec<[&Binding; 1]>)> { let mut action_types: HashSet<_> = self.global_actions.keys().copied().collect(); - let presenter = self - .presenters_and_platform_windows - .get(&window_id) - .unwrap() - .0 - .clone(); - let mut dispatch_path = Vec::new(); - presenter - .borrow() - .compute_dispatch_path_from(view_id, &mut dispatch_path); - for view_id in dispatch_path { + for view_id in self.parents(window_id, view_id) { if let Some(view) = self.views.get(&(window_id, view_id)) { let view_type = view.as_any().type_id(); if let Some(actions) = self.actions.get(&view_type) { @@ -1684,9 +1646,8 @@ impl MutableAppContext { pub fn is_action_available(&self, action: &dyn Action) -> bool { let action_type = action.as_any().type_id(); if let Some(window_id) = self.cx.platform.key_window_id() { - if let Some((presenter, _)) = self.presenters_and_platform_windows.get(&window_id) { - let dispatch_path = presenter.borrow().dispatch_path(&self.cx); - for view_id in dispatch_path { + if let Some(focused_view_id) = self.focused_view_id(window_id) { + for view_id in self.parents(window_id, focused_view_id) { if let Some(view) = self.views.get(&(window_id, view_id)) { let view_type = view.as_any().type_id(); if let Some(actions) = self.actions.get(&view_type) { @@ -1724,83 +1685,76 @@ impl MutableAppContext { None } - pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: &dyn Action) { - let presenter = self - .presenters_and_platform_windows - .get(&window_id) - .unwrap() - .0 - .clone(); - let mut dispatch_path = Vec::new(); - presenter - .borrow() - .compute_dispatch_path_from(view_id, &mut dispatch_path); - self.dispatch_action_any(window_id, &dispatch_path, action); - } + // pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: &dyn Action) { + // let presenter = self + // .presenters_and_platform_windows + // .get(&window_id) + // .unwrap() + // .0 + // .clone(); + // let mut dispatch_path = Vec::new(); + // presenter + // .borrow() + // .compute_dispatch_path_from(view_id, &mut dispatch_path); + // self.dispatch_action_any(window_id, &dispatch_path, action); + // } - pub fn dispatch_action( + // pub fn dispatch_action( + // &mut self, + // window_id: usize, + // dispatch_path: Vec, + // action: &A, + // ) { + // self.dispatch_action_any(window_id, &dispatch_path, action); + // } + + // Traverses the parent tree. Walks down the tree toward the passed + // view calling visit with true. Then walks back up the tree calling visit with false. + // If `visit` returns false this function will immediately return. + // Returns a bool indicating if the traversal was completed early. + fn visit_dispatch_path( &mut self, window_id: usize, - dispatch_path: Vec, - action: &A, - ) { - self.dispatch_action_any(window_id, &dispatch_path, action); - } - - pub(crate) fn dispatch_action_any( - &mut self, - window_id: usize, - path: &[usize], - action: &dyn Action, + view_id: usize, + mut visit: impl FnMut(usize, bool, &mut MutableAppContext) -> bool, ) -> bool { - self.update(|this| { - this.halt_action_dispatch = false; - for (capture_phase, view_id) in path - .iter() - .map(|view_id| (true, *view_id)) - .chain(path.iter().rev().map(|view_id| (false, *view_id))) - { - if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { - let type_id = view.as_any().type_id(); + // List of view ids from the leaf to the root of the window + let mut path = vec![view_id]; + let mut current_view = view_id; + while let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, current_view)) { + current_view = *parent_id; + path.push(current_view); + } - if let Some((name, mut handlers)) = this - .actions_mut(capture_phase) - .get_mut(&type_id) - .and_then(|h| h.remove_entry(&action.id())) - { - for handler in handlers.iter_mut().rev() { - this.halt_action_dispatch = true; - handler(view.as_mut(), action, this, window_id, view_id); - if this.halt_action_dispatch { - break; - } - } - this.actions_mut(capture_phase) - .get_mut(&type_id) - .unwrap() - .insert(name, handlers); - } - - this.cx.views.insert((window_id, view_id), view); - - if this.halt_action_dispatch { - break; - } - } + // Walk down from the root to the leaf calling visit with capture_phase = true + for view_id in path.iter().rev() { + if !visit(*view_id, true, self) { + return false; } + } - if !this.halt_action_dispatch { - this.halt_action_dispatch = this.dispatch_global_action_any(action); + // Walk up from the leaf to the root calling visit with capture_phase = false + for view_id in path.iter() { + if !visit(*view_id, false, self) { + return false; } + } - this.pending_effects - .push_back(Effect::ActionDispatchNotification { - action_id: action.id(), - }); - this.halt_action_dispatch + true + } + + // Returns an iterator over all of the view ids from the passed view up to the root of the window + // Includes the passed view itself + fn parents(&self, window_id: usize, mut view_id: usize) -> impl Iterator + '_ { + std::iter::from_fn(move || { + if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) { + view_id = *parent_id; + Some(view_id) + } else { + None + } }) } - fn actions_mut( &mut self, capture_phase: bool, @@ -1836,34 +1790,34 @@ impl MutableAppContext { self.keystroke_matcher.clear_bindings(); } - pub fn dispatch_keystroke( - &mut self, - window_id: usize, - dispatch_path: Vec, - keystroke: &Keystroke, - ) -> bool { - let mut context_chain = Vec::new(); - for view_id in &dispatch_path { - let view = self - .cx - .views - .get(&(window_id, *view_id)) - .expect("view in responder chain does not exist"); - context_chain.push(view.keymap_context(self.as_ref())); - } - + pub fn dispatch_keystroke(&mut self, window_id: usize, keystroke: &Keystroke) -> bool { let mut pending = false; - for (i, cx) in context_chain.iter().enumerate().rev() { - match self - .keystroke_matcher - .push_keystroke(keystroke.clone(), dispatch_path[i], cx) - { - MatchResult::None => {} - MatchResult::Pending => pending = true, - MatchResult::Action(action) => { - if self.dispatch_action_any(window_id, &dispatch_path[0..=i], action.as_ref()) { - self.keystroke_matcher.clear_pending(); - return true; + + if let Some(view_id) = self.focused_view_id(window_id) { + for view_id in self.parents(window_id, view_id).collect::>() { + let keymap_context = self + .cx + .views + .get(&(window_id, view_id)) + .expect("View passed to visit does not exist") + .keymap_context(self.as_ref()); + + match self.keystroke_matcher.push_keystroke( + keystroke.clone(), + view_id, + &keymap_context, + ) { + MatchResult::None => {} + MatchResult::Pending => pending = true, + MatchResult::Action(action) => { + if self.handle_dispatch_action_any_effect( + window_id, + Some(view_id), + action.as_ref(), + ) { + self.keystroke_matcher.clear_pending(); + return true; + } } } } @@ -1917,15 +1871,14 @@ impl MutableAppContext { { self.update(|this| { let type_id = TypeId::of::(); - let mut state = this - .cx - .globals - .remove(&type_id) - .expect("no global has been added for this type"); - let result = update(state.downcast_mut().unwrap(), this); - this.cx.globals.insert(type_id, state); - this.notify_global(type_id); - result + if let Some(mut state) = this.cx.globals.remove(&type_id) { + let result = update(state.downcast_mut().unwrap(), this); + this.cx.globals.insert(type_id, state); + this.notify_global(type_id); + result + } else { + panic!("No global added for {}", std::any::type_name::()); + } }) } @@ -1955,7 +1908,9 @@ impl MutableAppContext { { self.update(|this| { let window_id = post_inc(&mut this.next_window_id); - let root_view = this.add_view(window_id, build_root_view); + let root_view = this + .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx))) + .unwrap(); this.cx.windows.insert( window_id, Window { @@ -1979,7 +1934,9 @@ impl MutableAppContext { F: FnOnce(&mut ViewContext) -> T, { self.update(|this| { - let root_view = this.add_view(window_id, build_root_view); + let root_view = this + .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx))) + .unwrap(); let window = this.cx.windows.get_mut(&window_id).unwrap(); window.root_view = root_view.clone().into(); window.focused_view_id = Some(root_view.id()); @@ -2009,11 +1966,7 @@ impl MutableAppContext { app.update(|cx| { if let Some(presenter) = presenter.upgrade() { if let Event::KeyDown(KeyDownEvent { keystroke, .. }) = &event { - if cx.dispatch_keystroke( - window_id, - presenter.borrow().dispatch_path(cx.as_ref()), - keystroke, - ) { + if cx.dispatch_keystroke(window_id, keystroke) { return true; } } @@ -2079,18 +2032,45 @@ impl MutableAppContext { ) } - pub fn add_view(&mut self, window_id: usize, build_view: F) -> ViewHandle + pub fn add_view( + &mut self, + parent_handle: impl Into, + build_view: F, + ) -> ViewHandle where T: View, F: FnOnce(&mut ViewContext) -> T, { - self.add_option_view(window_id, |cx| Some(build_view(cx))) - .unwrap() + let parent_handle = parent_handle.into(); + self.build_and_insert_view( + parent_handle.window_id, + ParentId::View(parent_handle.view_id), + |cx| Some(build_view(cx)), + ) + .unwrap() } pub fn add_option_view( + &mut self, + parent_handle: impl Into, + build_view: F, + ) -> Option> + where + T: View, + F: FnOnce(&mut ViewContext) -> Option, + { + let parent_handle = parent_handle.into(); + self.build_and_insert_view( + parent_handle.window_id, + ParentId::View(parent_handle.view_id), + build_view, + ) + } + + pub(crate) fn build_and_insert_view( &mut self, window_id: usize, + parent_id: ParentId, build_view: F, ) -> Option> where @@ -2102,6 +2082,7 @@ impl MutableAppContext { let mut cx = ViewContext::new(this, window_id, view_id); let handle = if let Some(view) = build_view(&mut cx) { this.cx.views.insert((window_id, view_id), Box::new(view)); + this.cx.parents.insert((window_id, view_id), parent_id); if let Some(window) = this.cx.windows.get_mut(&window_id) { window .invalidation @@ -2154,6 +2135,7 @@ impl MutableAppContext { None } }); + self.cx.parents.remove(&(window_id, view_id)); if let Some(view_id) = change_focus_to { self.handle_focus_effect(window_id, Some(view_id)); @@ -2316,6 +2298,17 @@ impl MutableAppContext { Effect::RefreshWindows => { refreshing = true; } + Effect::DispatchActionFrom { + window_id, + view_id, + action, + } => { + self.handle_dispatch_action_any_effect( + window_id, + Some(view_id), + action.as_ref(), + ); + } Effect::ActionDispatchNotification { action_id } => { self.handle_action_dispatch_notification_effect(action_id) } @@ -2403,6 +2396,23 @@ impl MutableAppContext { self.pending_effects.push_back(Effect::RefreshWindows); } + pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: impl Action) { + self.dispatch_any_action_at(window_id, view_id, Box::new(action)); + } + + pub fn dispatch_any_action_at( + &mut self, + window_id: usize, + view_id: usize, + action: Box, + ) { + self.pending_effects.push_back(Effect::DispatchActionFrom { + window_id, + view_id, + action, + }); + } + fn perform_window_refresh(&mut self) { let mut presenters = mem::take(&mut self.presenters_and_platform_windows); for (window_id, (presenter, window)) in &mut presenters { @@ -2569,6 +2579,55 @@ impl MutableAppContext { }) } + fn handle_dispatch_action_any_effect( + &mut self, + window_id: usize, + view_id: Option, + action: &dyn Action, + ) -> bool { + self.update(|this| { + if let Some(view_id) = view_id { + this.visit_dispatch_path(window_id, view_id, |view_id, capture_phase, this| { + if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { + let type_id = view.as_any().type_id(); + + if let Some((name, mut handlers)) = this + .actions_mut(capture_phase) + .get_mut(&type_id) + .and_then(|h| h.remove_entry(&action.id())) + { + for handler in handlers.iter_mut().rev() { + this.halt_action_dispatch = true; + handler(view.as_mut(), action, this, window_id, view_id); + if this.halt_action_dispatch { + break; + } + } + this.actions_mut(capture_phase) + .get_mut(&type_id) + .unwrap() + .insert(name, handlers); + } + + this.cx.views.insert((window_id, view_id), view); + } + + !this.halt_action_dispatch + }); + } + + if !this.halt_action_dispatch { + this.halt_action_dispatch = this.dispatch_global_action_any(action); + } + + this.pending_effects + .push_back(Effect::ActionDispatchNotification { + action_id: action.id(), + }); + this.halt_action_dispatch + }) + } + fn handle_action_dispatch_notification_effect(&mut self, action_id: TypeId) { let mut callbacks = mem::take(&mut *self.action_dispatch_observations.lock()); for (_, callback) in &mut callbacks { @@ -2750,9 +2809,15 @@ impl Deref for MutableAppContext { } } +pub enum ParentId { + View(usize), + Root, +} + pub struct AppContext { models: HashMap>, views: HashMap<(usize, usize), Box>, + parents: HashMap<(usize, usize), ParentId>, windows: HashMap, globals: HashMap>, element_states: HashMap>, @@ -2977,6 +3042,11 @@ pub enum Effect { callback: WindowFullscreenCallback, }, RefreshWindows, + DispatchActionFrom { + window_id: usize, + view_id: usize, + action: Box, + }, ActionDispatchNotification { action_id: TypeId, }, @@ -3060,6 +3130,13 @@ impl Debug for Effect { .field("view_id", view_id) .field("subscription_id", subscription_id) .finish(), + Effect::DispatchActionFrom { + window_id, view_id, .. + } => f + .debug_struct("Effect::DispatchActionFrom") + .field("window_id", window_id) + .field("view_id", view_id) + .finish(), Effect::ActionDispatchNotification { action_id, .. } => f .debug_struct("Effect::ActionDispatchNotification") .field("action_id", action_id) @@ -3640,7 +3717,11 @@ impl<'a, T: View> ViewContext<'a, T> { S: View, F: FnOnce(&mut ViewContext) -> S, { - self.app.add_view(self.window_id, build_view) + self.app + .build_and_insert_view(self.window_id, ParentId::View(self.view_id), |cx| { + Some(build_view(cx)) + }) + .unwrap() } pub fn add_option_view(&mut self, build_view: F) -> Option> @@ -3648,7 +3729,8 @@ impl<'a, T: View> ViewContext<'a, T> { S: View, F: FnOnce(&mut ViewContext) -> Option, { - self.app.add_option_view(self.window_id, build_view) + self.app + .build_and_insert_view(self.window_id, ParentId::View(self.view_id), build_view) } pub fn replace_root_view(&mut self, build_root_view: F) -> ViewHandle @@ -3658,7 +3740,9 @@ impl<'a, T: View> ViewContext<'a, T> { { let window_id = self.window_id; self.update(|this| { - let root_view = this.add_view(window_id, build_root_view); + let root_view = this + .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx))) + .unwrap(); let window = this.cx.windows.get_mut(&window_id).unwrap(); window.root_view = root_view.clone().into(); window.focused_view_id = Some(root_view.id()); @@ -3802,6 +3886,11 @@ impl<'a, T: View> ViewContext<'a, T> { self.app.notify_view(self.window_id, self.view_id); } + pub fn dispatch_any_action(&mut self, action: Box) { + self.app + .dispatch_any_action_at(self.window_id, self.view_id, action) + } + pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext)) { let handle = self.handle(); self.app.defer(move |cx| { @@ -5797,9 +5886,9 @@ mod tests { } } - let (window_id, _) = cx.add_window(Default::default(), |cx| View::new(None, cx)); - let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx)); - let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx)); + let (_, root_view) = cx.add_window(Default::default(), |cx| View::new(None, cx)); + let handle_1 = cx.add_view(&root_view, |cx| View::new(None, cx)); + let handle_2 = cx.add_view(&root_view, |cx| View::new(Some(handle_1.clone()), cx)); assert_eq!(cx.cx.views.len(), 3); handle_1.update(cx, |view, cx| { @@ -5973,8 +6062,8 @@ mod tests { type Event = usize; } - let (window_id, handle_1) = cx.add_window(Default::default(), |_| View::default()); - let handle_2 = cx.add_view(window_id, |_| View::default()); + let (_, handle_1) = cx.add_window(Default::default(), |_| View::default()); + let handle_2 = cx.add_view(&handle_1, |_| View::default()); let handle_3 = cx.add_model(|_| Model); handle_1.update(cx, |_, cx| { @@ -6214,9 +6303,9 @@ mod tests { type Event = (); } - let (window_id, _) = cx.add_window(Default::default(), |_| View); - let observing_view = cx.add_view(window_id, |_| View); - let emitting_view = cx.add_view(window_id, |_| View); + let (_, root_view) = cx.add_window(Default::default(), |_| View); + let observing_view = cx.add_view(&root_view, |_| View); + let emitting_view = cx.add_view(&root_view, |_| View); let observing_model = cx.add_model(|_| Model); let observed_model = cx.add_model(|_| Model); @@ -6390,8 +6479,8 @@ mod tests { type Event = (); } - let (window_id, _) = cx.add_window(Default::default(), |_| View); - let observing_view = cx.add_view(window_id, |_| View); + let (_, root_view) = cx.add_window(Default::default(), |_| View); + let observing_view = cx.add_view(root_view, |_| View); let observing_model = cx.add_model(|_| Model); let observed_model = cx.add_model(|_| Model); @@ -6513,9 +6602,9 @@ mod tests { } } - let (window_id, _) = cx.add_window(Default::default(), |_| View); - let observing_view = cx.add_view(window_id, |_| View); - let observed_view = cx.add_view(window_id, |_| View); + let (_, root_view) = cx.add_window(Default::default(), |_| View); + let observing_view = cx.add_view(&root_view, |_| View); + let observed_view = cx.add_view(&root_view, |_| View); let observation_count = Rc::new(RefCell::new(0)); observing_view.update(cx, |_, cx| { @@ -6587,11 +6676,11 @@ mod tests { } let view_events: Arc>> = Default::default(); - let (window_id, view_1) = cx.add_window(Default::default(), |_| View { + let (_, view_1) = cx.add_window(Default::default(), |_| View { events: view_events.clone(), name: "view 1".to_string(), }); - let view_2 = cx.add_view(window_id, |_| View { + let view_2 = cx.add_view(&view_1, |_| View { events: view_events.clone(), name: "view 2".to_string(), }); @@ -6813,11 +6902,6 @@ mod tests { } }); - let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 }); - let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 }); - let view_3 = cx.add_view(window_id, |_| ViewA { id: 3 }); - let view_4 = cx.add_view(window_id, |_| ViewB { id: 4 }); - let observed_actions = Rc::new(RefCell::new(Vec::new())); cx.observe_actions({ let observed_actions = observed_actions.clone(); @@ -6825,9 +6909,14 @@ mod tests { }) .detach(); - cx.dispatch_action( + let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 }); + let view_2 = cx.add_view(&view_1, |_| ViewB { id: 2 }); + let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 }); + let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 }); + + cx.handle_dispatch_action_any_effect( window_id, - vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()], + Some(view_4.id()), &Action("bar".to_string()), ); @@ -6848,10 +6937,15 @@ mod tests { assert_eq!(*observed_actions.borrow(), [Action::default().id()]); // Remove view_1, which doesn't propagate the action + + let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewA { id: 1 }); + let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 }); + let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 }); + actions.borrow_mut().clear(); - cx.dispatch_action( + cx.handle_dispatch_action_any_effect( window_id, - vec![view_2.id(), view_3.id(), view_4.id()], + Some(view_4.id()), &Action("bar".to_string()), ); @@ -6924,8 +7018,9 @@ mod tests { view_3.keymap_context.set.insert("c".into()); let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1); - let view_2 = cx.add_view(window_id, |_| view_2); - let view_3 = cx.add_view(window_id, |_| view_3); + let view_2 = cx.add_view(&view_1, |_| view_2); + let view_3 = cx.add_view(&view_2, |_| view_3); + cx.focus(window_id, Some(view_3.id())); // This keymap's only binding dispatches an action on view 2 because that view will have // "a" and "b" in its context, but not "c". @@ -6963,20 +7058,12 @@ mod tests { } }); - cx.dispatch_keystroke( - window_id, - vec![view_1.id(), view_2.id(), view_3.id()], - &Keystroke::parse("a").unwrap(), - ); + cx.dispatch_keystroke(window_id, &Keystroke::parse("a").unwrap()); assert_eq!(&*actions.borrow(), &["2 a"]); actions.borrow_mut().clear(); - cx.dispatch_keystroke( - window_id, - vec![view_1.id(), view_2.id(), view_3.id()], - &Keystroke::parse("b").unwrap(), - ); + cx.dispatch_keystroke(window_id, &Keystroke::parse("b").unwrap()); assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]); } @@ -7130,8 +7217,8 @@ mod tests { } } - let window_id = cx.add_window(|_| View).0; - let view = cx.add_view(window_id, |_| View); + let (_, root_view) = cx.add_window(|_| View); + let view = cx.add_view(&root_view, |_| View); let condition = view.condition(&cx, |_, _| false); cx.update(|_| drop(view)); @@ -7164,7 +7251,7 @@ mod tests { Some("render count: 0") ); - let view = cx.add_view(window_id, |cx| { + let view = cx.add_view(&root_view, |cx| { cx.refresh_windows(); View(0) }); diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index a8aefad6e9..57d3a1a3fd 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -26,7 +26,6 @@ use std::{ pub struct Presenter { window_id: usize, pub(crate) rendered_views: HashMap, - parents: HashMap, cursor_regions: Vec, mouse_regions: Vec<(MouseRegion, usize)>, font_cache: Arc, @@ -52,7 +51,6 @@ impl Presenter { Self { window_id, rendered_views: cx.render_views(window_id, titlebar_height), - parents: Default::default(), cursor_regions: Default::default(), mouse_regions: Default::default(), font_cache, @@ -67,22 +65,22 @@ impl Presenter { } } - pub fn dispatch_path(&self, app: &AppContext) -> Vec { - let mut path = Vec::new(); - if let Some(view_id) = app.focused_view_id(self.window_id) { - self.compute_dispatch_path_from(view_id, &mut path) - } - path - } + // pub fn dispatch_path(&self, app: &AppContext) -> Vec { + // let mut path = Vec::new(); + // if let Some(view_id) = app.focused_view_id(self.window_id) { + // self.compute_dispatch_path_from(view_id, &mut path) + // } + // path + // } - pub(crate) fn compute_dispatch_path_from(&self, mut view_id: usize, path: &mut Vec) { - path.push(view_id); - while let Some(parent_id) = self.parents.get(&view_id).copied() { - path.push(parent_id); - view_id = parent_id; - } - path.reverse(); - } + // pub(crate) fn compute_dispatch_path_from(&self, mut view_id: usize, path: &mut Vec) { + // path.push(view_id); + // while let Some(parent_id) = self.parents.get(&view_id).copied() { + // path.push(parent_id); + // view_id = parent_id; + // } + // path.reverse(); + // } pub fn invalidate( &mut self, @@ -93,7 +91,6 @@ impl Presenter { for view_id in &invalidation.removed { invalidation.updated.remove(&view_id); self.rendered_views.remove(&view_id); - self.parents.remove(&view_id); } for view_id in &invalidation.updated { self.rendered_views.insert( @@ -191,7 +188,6 @@ impl Presenter { LayoutContext { window_id: self.window_id, rendered_views: &mut self.rendered_views, - parents: &mut self.parents, font_cache: &self.font_cache, font_system: cx.platform().fonts(), text_layout_cache: &self.text_layout_cache, @@ -344,21 +340,11 @@ impl Presenter { } invalidated_views.extend(event_cx.invalidated_views); - let dispatch_directives = event_cx.dispatched_actions; for view_id in invalidated_views { cx.notify_view(self.window_id, view_id); } - let mut dispatch_path = Vec::new(); - for directive in dispatch_directives { - dispatch_path.clear(); - if let Some(view_id) = directive.dispatcher_view_id { - self.compute_dispatch_path_from(view_id, &mut dispatch_path); - } - cx.dispatch_action_any(self.window_id, &dispatch_path, directive.action.as_ref()); - } - handled } else { false @@ -372,9 +358,6 @@ impl Presenter { cx: &'a mut MutableAppContext, ) -> (bool, EventContext<'a>) { let mut hover_regions = Vec::new(); - // let mut unhovered_regions = Vec::new(); - // let mut hovered_regions = Vec::new(); - if let Event::MouseMoved( e @ MouseMovedEvent { position, @@ -446,7 +429,6 @@ impl Presenter { ) -> EventContext<'a> { EventContext { rendered_views: &mut self.rendered_views, - dispatched_actions: Default::default(), font_cache: &self.font_cache, text_layout_cache: &self.text_layout_cache, view_stack: Default::default(), @@ -473,15 +455,9 @@ impl Presenter { } } -pub struct DispatchDirective { - pub dispatcher_view_id: Option, - pub action: Box, -} - pub struct LayoutContext<'a> { window_id: usize, rendered_views: &'a mut HashMap, - parents: &'a mut HashMap, view_stack: Vec, pub font_cache: &'a Arc, pub font_system: Arc, @@ -506,9 +482,6 @@ impl<'a> LayoutContext<'a> { } fn layout(&mut self, view_id: usize, constraint: SizeConstraint) -> Vector2F { - if let Some(parent_id) = self.view_stack.last() { - self.parents.insert(view_id, *parent_id); - } self.view_stack.push(view_id); let mut rendered_view = self.rendered_views.remove(&view_id).unwrap(); let size = rendered_view.layout(constraint, self); @@ -637,7 +610,6 @@ impl<'a> Deref for PaintContext<'a> { pub struct EventContext<'a> { rendered_views: &'a mut HashMap, - dispatched_actions: Vec, pub font_cache: &'a FontCache, pub text_layout_cache: &'a TextLayoutCache, pub app: &'a mut MutableAppContext, @@ -692,10 +664,8 @@ impl<'a> EventContext<'a> { } pub fn dispatch_any_action(&mut self, action: Box) { - self.dispatched_actions.push(DispatchDirective { - dispatcher_view_id: self.view_stack.last().copied(), - action, - }); + self.app + .dispatch_any_action_at(self.window_id, *self.view_stack.last().unwrap(), action) } pub fn dispatch_action(&mut self, action: A) { diff --git a/crates/gpui/src/test.rs b/crates/gpui/src/test.rs index c8a69c4e7d..4122ad09b7 100644 --- a/crates/gpui/src/test.rs +++ b/crates/gpui/src/test.rs @@ -1,6 +1,6 @@ use crate::{ - executor, platform, Entity, FontCache, Handle, LeakDetector, MutableAppContext, Platform, - Subscription, TestAppContext, + elements::Empty, executor, platform, Element, ElementBox, Entity, FontCache, Handle, + LeakDetector, MutableAppContext, Platform, RenderContext, Subscription, TestAppContext, View, }; use futures::StreamExt; use parking_lot::Mutex; @@ -162,3 +162,19 @@ where Observation { rx, _subscription } } + +pub struct EmptyView; + +impl Entity for EmptyView { + type Event = (); +} + +impl View for EmptyView { + fn ui_name() -> &'static str { + "empty view" + } + + fn render(&mut self, _: &mut RenderContext) -> ElementBox { + Element::boxed(Empty::new()) + } +} diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 52631e71b4..ada785f854 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -600,7 +600,7 @@ impl BufferSearchBar { mod tests { use super::*; use editor::{DisplayPoint, Editor}; - use gpui::{color::Color, TestAppContext}; + use gpui::{color::Color, test::EmptyView, TestAppContext}; use language::Buffer; use std::sync::Arc; use unindent::Unindent as _; @@ -629,11 +629,13 @@ mod tests { cx, ) }); - let editor = cx.add_view(Default::default(), |cx| { + let (_, root_view) = cx.add_window(|_| EmptyView); + + let editor = cx.add_view(&root_view, |cx| { Editor::for_buffer(buffer.clone(), None, cx) }); - let search_bar = cx.add_view(Default::default(), |cx| { + let search_bar = cx.add_view(&root_view, |cx| { let mut search_bar = BufferSearchBar::new(cx); search_bar.set_active_pane_item(Some(&editor), cx); search_bar.show(false, true, cx); diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 39415b3832..6cbd4c7e2d 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -933,7 +933,8 @@ mod tests { cx.update(|cx| { let mut settings = Settings::test(cx); settings.theme = Arc::new(theme); - cx.set_global(settings) + cx.set_global(settings); + cx.set_global(ActiveSearches::default()); }); let fs = FakeFs::new(cx.background()); @@ -949,9 +950,7 @@ mod tests { .await; let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; let search = cx.add_model(|cx| ProjectSearch::new(project, cx)); - let search_view = cx.add_view(Default::default(), |cx| { - ProjectSearchView::new(search.clone(), cx) - }); + let (_, search_view) = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx)); search_view.update(cx, |search_view, cx| { search_view diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a05b9ac1a8..354331974f 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -386,7 +386,7 @@ impl Pane { project_entry_id: ProjectEntryId, focus_item: bool, cx: &mut ViewContext, - build_item: impl FnOnce(&mut MutableAppContext) -> Box, + build_item: impl FnOnce(&mut ViewContext) -> Box, ) -> Box { let existing_item = pane.update(cx, |pane, cx| { for (ix, item) in pane.items.iter().enumerate() { @@ -403,7 +403,7 @@ impl Pane { if let Some(existing_item) = existing_item { existing_item } else { - let item = build_item(cx); + let item = pane.update(cx, |_, cx| build_item(cx)); Self::add_item(workspace, pane, item.boxed_clone(), true, focus_item, cx); item } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index a27754aa13..d1a239cbb4 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -59,7 +59,7 @@ use waiting_room::WaitingRoom; type ProjectItemBuilders = HashMap< TypeId, - fn(usize, ModelHandle, AnyModelHandle, &mut MutableAppContext) -> Box, + fn(ModelHandle, AnyModelHandle, &mut ViewContext) -> Box, >; type FollowableItemBuilder = fn( @@ -219,9 +219,9 @@ pub fn init(app_state: Arc, cx: &mut MutableAppContext) { pub fn register_project_item(cx: &mut MutableAppContext) { cx.update_default_global(|builders: &mut ProjectItemBuilders, _| { - builders.insert(TypeId::of::(), |window_id, project, model, cx| { + builders.insert(TypeId::of::(), |project, model, cx| { let item = model.downcast::().unwrap(); - Box::new(cx.add_view(window_id, |cx| I::for_project_item(project, item, cx))) + Box::new(cx.add_view(|cx| I::for_project_item(project, item, cx))) }); }); } @@ -1475,12 +1475,11 @@ impl Workspace { ) -> Task< Result<( ProjectEntryId, - impl 'static + FnOnce(&mut MutableAppContext) -> Box, + impl 'static + FnOnce(&mut ViewContext) -> Box, )>, > { let project = self.project().clone(); let project_item = project.update(cx, |project, cx| project.open_path(path, cx)); - let window_id = cx.window_id(); cx.as_mut().spawn(|mut cx| async move { let (project_entry_id, project_item) = project_item.await?; let build_item = cx.update(|cx| { @@ -1490,7 +1489,7 @@ impl Workspace { .cloned() })?; let build_item = - move |cx: &mut MutableAppContext| build_item(window_id, project, project_item, cx); + move |cx: &mut ViewContext| build_item(project, project_item, cx); Ok((project_entry_id, build_item)) }) } @@ -2732,7 +2731,7 @@ fn open_new(app_state: &Arc, cx: &mut MutableAppContext) { (app_state.initialize_workspace)(&mut workspace, app_state, cx); workspace }); - cx.dispatch_action(window_id, vec![workspace.id()], &NewFile); + cx.dispatch_action_at(window_id, workspace.id(), NewFile); } #[cfg(test)] @@ -2751,10 +2750,10 @@ mod tests { let fs = FakeFs::new(cx.background()); let project = Project::test(fs, [], cx).await; - let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx)); + let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx)); // Adding an item with no ambiguity renders the tab without detail. - let item1 = cx.add_view(window_id, |_| { + let item1 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.tab_descriptions = Some(vec!["c", "b1/c", "a/b1/c"]); item @@ -2766,7 +2765,7 @@ mod tests { // Adding an item that creates ambiguity increases the level of detail on // both tabs. - let item2 = cx.add_view(window_id, |_| { + let item2 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]); item @@ -2780,7 +2779,7 @@ mod tests { // Adding an item that creates ambiguity increases the level of detail only // on the ambiguous tabs. In this case, the ambiguity can't be resolved so // we stop at the highest detail available. - let item3 = cx.add_view(window_id, |_| { + let item3 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.tab_descriptions = Some(vec!["c", "b2/c", "a/b2/c"]); item @@ -2820,12 +2819,12 @@ mod tests { project.worktrees(cx).next().unwrap().read(cx).id() }); - let item1 = cx.add_view(window_id, |_| { + let item1 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.project_path = Some((worktree_id, "one.txt").into()); item }); - let item2 = cx.add_view(window_id, |_| { + let item2 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.project_path = Some((worktree_id, "two.txt").into()); item @@ -2914,19 +2913,19 @@ mod tests { let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx)); // When there are no dirty items, there's nothing to do. - let item1 = cx.add_view(window_id, |_| TestItem::new()); + let item1 = cx.add_view(&workspace, |_| TestItem::new()); workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx)); let task = workspace.update(cx, |w, cx| w.prepare_to_close(cx)); assert_eq!(task.await.unwrap(), true); // When there are dirty untitled items, prompt to save each one. If the user // cancels any prompt, then abort. - let item2 = cx.add_view(window_id, |_| { + let item2 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.is_dirty = true; item }); - let item3 = cx.add_view(window_id, |_| { + let item3 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.is_dirty = true; item.project_entry_ids = vec![ProjectEntryId::from_proto(1)]; @@ -2953,27 +2952,27 @@ mod tests { let project = Project::test(fs, None, cx).await; let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); - let item1 = cx.add_view(window_id, |_| { + let item1 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.is_dirty = true; item.project_entry_ids = vec![ProjectEntryId::from_proto(1)]; item }); - let item2 = cx.add_view(window_id, |_| { + let item2 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.is_dirty = true; item.has_conflict = true; item.project_entry_ids = vec![ProjectEntryId::from_proto(2)]; item }); - let item3 = cx.add_view(window_id, |_| { + let item3 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.is_dirty = true; item.has_conflict = true; item.project_entry_ids = vec![ProjectEntryId::from_proto(3)]; item }); - let item4 = cx.add_view(window_id, |_| { + let item4 = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.is_dirty = true; item @@ -3144,7 +3143,7 @@ mod tests { let project = Project::test(fs, [], cx).await; let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); - let item = cx.add_view(window_id, |_| { + let item = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.project_entry_ids = vec![ProjectEntryId::from_proto(1)]; item @@ -3259,9 +3258,9 @@ mod tests { let fs = FakeFs::new(cx.background()); let project = Project::test(fs, [], cx).await; - let (window_id, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); + let (_, workspace) = cx.add_window(|cx| Workspace::new(project, cx)); - let item = cx.add_view(window_id, |_| { + let item = cx.add_view(&workspace, |_| { let mut item = TestItem::new(); item.project_entry_ids = vec![ProjectEntryId::from_proto(1)]; item From 6442ec59e71f44fb44920e6d1dec326338e9279b Mon Sep 17 00:00:00 2001 From: K Simmons Date: Fri, 5 Aug 2022 12:38:05 -0700 Subject: [PATCH 11/27] Switch action dispatch to use MutableAppContext parent utilities and delete parent map from presenter --- crates/gpui/src/app.rs | 101 +++++++++++++++-------------- crates/gpui/src/presenter.rs | 41 +++++++++++- crates/workspace/src/pane.rs | 1 + crates/workspace/src/sidebar.rs | 1 + crates/workspace/src/status_bar.rs | 2 + crates/workspace/src/workspace.rs | 6 ++ 6 files changed, 100 insertions(+), 52 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index a1b782039a..ac9ef6f829 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -230,7 +230,7 @@ impl App { let mut cx = cx.borrow_mut(); if let Some(key_window_id) = cx.cx.platform.key_window_id() { if let Some(view_id) = cx.focused_view_id(key_window_id) { - cx.handle_dispatch_action_any_effect(key_window_id, Some(view_id), action); + cx.handle_dispatch_action_from_effect(key_window_id, Some(view_id), action); return; } } @@ -457,7 +457,7 @@ impl TestAppContext { pub fn dispatch_action(&self, window_id: usize, action: A) { let mut cx = self.cx.borrow_mut(); if let Some(view_id) = cx.focused_view_id(window_id) { - cx.handle_dispatch_action_any_effect(window_id, Some(view_id), &action); + cx.handle_dispatch_action_from_effect(window_id, Some(view_id), &action); } } @@ -477,6 +477,7 @@ impl TestAppContext { if cx.dispatch_keystroke(window_id, &keystroke) { return true; } + if presenter.borrow_mut().dispatch_event( Event::KeyDown(KeyDownEvent { keystroke: keystroke.clone(), @@ -1606,6 +1607,12 @@ impl MutableAppContext { } } + pub(crate) fn name_for_view(&self, window_id: usize, view_id: usize) -> Option<&str> { + self.views + .get(&(window_id, view_id)) + .map(|view| view.ui_name()) + } + pub fn all_action_names<'a>(&'a self) -> impl Iterator + 'a { self.action_deserializers.keys().copied() } @@ -1685,29 +1692,6 @@ impl MutableAppContext { None } - // pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: &dyn Action) { - // let presenter = self - // .presenters_and_platform_windows - // .get(&window_id) - // .unwrap() - // .0 - // .clone(); - // let mut dispatch_path = Vec::new(); - // presenter - // .borrow() - // .compute_dispatch_path_from(view_id, &mut dispatch_path); - // self.dispatch_action_any(window_id, &dispatch_path, action); - // } - - // pub fn dispatch_action( - // &mut self, - // window_id: usize, - // dispatch_path: Vec, - // action: &A, - // ) { - // self.dispatch_action_any(window_id, &dispatch_path, action); - // } - // Traverses the parent tree. Walks down the tree toward the passed // view calling visit with true. Then walks back up the tree calling visit with false. // If `visit` returns false this function will immediately return. @@ -1719,12 +1703,7 @@ impl MutableAppContext { mut visit: impl FnMut(usize, bool, &mut MutableAppContext) -> bool, ) -> bool { // List of view ids from the leaf to the root of the window - let mut path = vec![view_id]; - let mut current_view = view_id; - while let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, current_view)) { - current_view = *parent_id; - path.push(current_view); - } + let path = self.parents(window_id, view_id).collect::>(); // Walk down from the root to the leaf calling visit with capture_phase = true for view_id in path.iter().rev() { @@ -1746,15 +1725,18 @@ impl MutableAppContext { // Returns an iterator over all of the view ids from the passed view up to the root of the window // Includes the passed view itself fn parents(&self, window_id: usize, mut view_id: usize) -> impl Iterator + '_ { - std::iter::from_fn(move || { - if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) { - view_id = *parent_id; - Some(view_id) - } else { - None - } - }) + std::iter::once(view_id) + .into_iter() + .chain(std::iter::from_fn(move || { + if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) { + view_id = *parent_id; + Some(view_id) + } else { + None + } + })) } + fn actions_mut( &mut self, capture_phase: bool, @@ -1793,8 +1775,8 @@ impl MutableAppContext { pub fn dispatch_keystroke(&mut self, window_id: usize, keystroke: &Keystroke) -> bool { let mut pending = false; - if let Some(view_id) = self.focused_view_id(window_id) { - for view_id in self.parents(window_id, view_id).collect::>() { + if let Some(focused_view_id) = self.focused_view_id(window_id) { + for view_id in self.parents(window_id, focused_view_id).collect::>() { let keymap_context = self .cx .views @@ -1810,7 +1792,7 @@ impl MutableAppContext { MatchResult::None => {} MatchResult::Pending => pending = true, MatchResult::Action(action) => { - if self.handle_dispatch_action_any_effect( + if self.handle_dispatch_action_from_effect( window_id, Some(view_id), action.as_ref(), @@ -2303,7 +2285,7 @@ impl MutableAppContext { view_id, action, } => { - self.handle_dispatch_action_any_effect( + self.handle_dispatch_action_from_effect( window_id, Some(view_id), action.as_ref(), @@ -2579,7 +2561,7 @@ impl MutableAppContext { }) } - fn handle_dispatch_action_any_effect( + fn handle_dispatch_action_from_effect( &mut self, window_id: usize, view_id: Option, @@ -2587,6 +2569,7 @@ impl MutableAppContext { ) -> bool { self.update(|this| { if let Some(view_id) = view_id { + this.halt_action_dispatch = false; this.visit_dispatch_path(window_id, view_id, |view_id, capture_phase, this| { if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { let type_id = view.as_any().type_id(); @@ -2809,6 +2792,7 @@ impl Deref for MutableAppContext { } } +#[derive(Debug)] pub enum ParentId { View(usize), Root, @@ -2817,7 +2801,7 @@ pub enum ParentId { pub struct AppContext { models: HashMap>, views: HashMap<(usize, usize), Box>, - parents: HashMap<(usize, usize), ParentId>, + pub(crate) parents: HashMap<(usize, usize), ParentId>, windows: HashMap, globals: HashMap>, element_states: HashMap>, @@ -3733,6 +3717,21 @@ impl<'a, T: View> ViewContext<'a, T> { .build_and_insert_view(self.window_id, ParentId::View(self.view_id), build_view) } + pub fn reparent(&mut self, view_handle: impl Into) { + let view_handle = view_handle.into(); + if self.window_id != view_handle.window_id { + panic!("Can't reparent view to a view from a different window"); + } + self.cx + .parents + .remove(&(view_handle.window_id, view_handle.view_id)); + let new_parent_id = self.view_id; + self.cx.parents.insert( + (view_handle.window_id, view_handle.view_id), + ParentId::View(new_parent_id), + ); + } + pub fn replace_root_view(&mut self, build_root_view: F) -> ViewHandle where V: View, @@ -6914,7 +6913,7 @@ mod tests { let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 }); let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 }); - cx.handle_dispatch_action_any_effect( + cx.handle_dispatch_action_from_effect( window_id, Some(view_4.id()), &Action("bar".to_string()), @@ -6938,12 +6937,12 @@ mod tests { // Remove view_1, which doesn't propagate the action - let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewA { id: 1 }); + let (window_id, view_2) = cx.add_window(Default::default(), |_| ViewB { id: 2 }); let view_3 = cx.add_view(&view_2, |_| ViewA { id: 3 }); let view_4 = cx.add_view(&view_3, |_| ViewB { id: 4 }); actions.borrow_mut().clear(); - cx.handle_dispatch_action_any_effect( + cx.handle_dispatch_action_from_effect( window_id, Some(view_4.id()), &Action("bar".to_string()), @@ -7019,8 +7018,10 @@ mod tests { let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1); let view_2 = cx.add_view(&view_1, |_| view_2); - let view_3 = cx.add_view(&view_2, |_| view_3); - cx.focus(window_id, Some(view_3.id())); + let view_3 = cx.add_view(&view_2, |cx| { + cx.focus_self(); + view_3 + }); // This keymap's only binding dispatches an action on view 2 because that view will have // "a" and "b" in its context, but not "c". diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 57d3a1a3fd..9cba57810b 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -10,8 +10,8 @@ use crate::{ text_layout::TextLayoutCache, Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity, FontSystem, ModelHandle, MouseButtonEvent, MouseMovedEvent, MouseRegion, MouseRegionId, - ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, - View, ViewHandle, WeakModelHandle, WeakViewHandle, + ParentId, ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, + UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle, }; use collections::{HashMap, HashSet}; use pathfinder_geometry::vector::{vec2f, Vector2F}; @@ -482,6 +482,43 @@ impl<'a> LayoutContext<'a> { } fn layout(&mut self, view_id: usize, constraint: SizeConstraint) -> Vector2F { + let print_error = |view_id| { + format!( + "{} with id {}", + self.app.name_for_view(self.window_id, view_id).unwrap(), + view_id, + ) + }; + match ( + self.view_stack.last(), + self.app.parents.get(&(self.window_id, view_id)), + ) { + (Some(layout_parent), Some(ParentId::View(app_parent))) => { + if layout_parent != app_parent { + panic!( + "View {} was laid out with parent {} when it was constructed with parent {}", + print_error(view_id), + print_error(*layout_parent), + print_error(*app_parent)) + } + } + (None, Some(ParentId::View(app_parent))) => panic!( + "View {} was laid out without a parent when it was constructed with parent {}", + print_error(view_id), + print_error(*app_parent) + ), + (Some(layout_parent), Some(ParentId::Root)) => panic!( + "View {} was laid out with parent {} when it was constructed as a window root", + print_error(view_id), + print_error(*layout_parent), + ), + (_, None) => panic!( + "View {} did not have a registered parent in the app context", + print_error(view_id), + ), + _ => {} + } + self.view_stack.push(view_id); let mut rendered_view = self.rendered_views.remove(&view_id).unwrap(); let size = rendered_view.layout(constraint, self); diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 354331974f..572e1032b3 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -441,6 +441,7 @@ impl Pane { pane.active_item_index = usize::MAX; }; + cx.reparent(&item); pane.items.insert(item_ix, item); pane.activate_item(item_ix, activate_pane, focus_item, false, cx); cx.notify(); diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index 542cd51cb6..b7ed8140c9 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -140,6 +140,7 @@ impl Sidebar { } }), ]; + cx.reparent(&view); self.items.push(Item { icon_path, tooltip, diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index f84940e8fb..ca44cf7c27 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -81,6 +81,7 @@ impl StatusBar { where T: 'static + StatusItemView, { + cx.reparent(&item); self.left_items.push(Box::new(item)); cx.notify(); } @@ -89,6 +90,7 @@ impl StatusBar { where T: 'static + StatusItemView, { + cx.reparent(&item); self.right_items.push(Box::new(item)); cx.notify(); } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d1a239cbb4..02ad18eb3d 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -708,6 +708,12 @@ impl Into for Box { } } +impl Into for &Box { + fn into(self) -> AnyViewHandle { + self.to_any() + } +} + impl Clone for Box { fn clone(&self) -> Box { self.boxed_clone() From 690ea57211bc29584eafd86a3262c493e244a55f Mon Sep 17 00:00:00 2001 From: K Simmons Date: Sun, 7 Aug 2022 19:23:22 -0700 Subject: [PATCH 12/27] WIP compiling but failing with circular reference --- crates/chat_panel/src/chat_panel.rs | 6 +- crates/command_palette/src/command_palette.rs | 5 +- crates/contacts_panel/src/contact_finder.rs | 6 +- crates/contacts_panel/src/contacts_panel.rs | 8 +- crates/context_menu/src/context_menu.rs | 4 +- crates/diagnostics/src/diagnostics.rs | 2 +- crates/editor/src/editor.rs | 8 +- crates/file_finder/src/file_finder.rs | 6 +- crates/go_to_line/src/go_to_line.rs | 6 +- .../grammars/context-predicate/src/parser.c | 909 ++++++++++-------- crates/gpui/src/app.rs | 151 ++- crates/outline/src/outline.rs | 6 +- crates/picker/src/picker.rs | 6 +- crates/project_symbols/src/project_symbols.rs | 6 +- crates/search/src/buffer_search.rs | 6 +- crates/search/src/project_search.rs | 8 +- crates/terminal/src/connected_view.rs | 5 +- crates/terminal/src/terminal.rs | 7 + crates/theme_selector/src/theme_selector.rs | 6 +- crates/workspace/src/pane.rs | 15 +- crates/workspace/src/workspace.rs | 2 +- styles/package-lock.json | 1 + 22 files changed, 664 insertions(+), 515 deletions(-) diff --git a/crates/chat_panel/src/chat_panel.rs b/crates/chat_panel/src/chat_panel.rs index fa913971df..7f947fef16 100644 --- a/crates/chat_panel/src/chat_panel.rs +++ b/crates/chat_panel/src/chat_panel.rs @@ -8,8 +8,8 @@ use gpui::{ elements::*, platform::CursorStyle, views::{ItemType, Select, SelectStyle}, - AppContext, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, - Task, View, ViewContext, ViewHandle, + AnyViewHandle, AppContext, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, + Subscription, Task, View, ViewContext, ViewHandle, }; use menu::Confirm; use postage::prelude::Stream; @@ -397,7 +397,7 @@ impl View for ChatPanel { .boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { if matches!( *self.rpc.status().borrow(), client::Status::Connected { .. } diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 5f213284e8..5d6f6e14a8 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -4,7 +4,8 @@ use gpui::{ actions, elements::{ChildView, Flex, Label, ParentElement}, keymap::Keystroke, - Action, Element, Entity, MouseState, MutableAppContext, View, ViewContext, ViewHandle, + Action, AnyViewHandle, Element, Entity, MouseState, MutableAppContext, View, ViewContext, + ViewHandle, }; use picker::{Picker, PickerDelegate}; use settings::Settings; @@ -132,7 +133,7 @@ impl View for CommandPalette { ChildView::new(self.picker.clone()).boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.picker); } } diff --git a/crates/contacts_panel/src/contact_finder.rs b/crates/contacts_panel/src/contact_finder.rs index 4027160950..978466dfcb 100644 --- a/crates/contacts_panel/src/contact_finder.rs +++ b/crates/contacts_panel/src/contact_finder.rs @@ -1,7 +1,7 @@ use client::{ContactRequestStatus, User, UserStore}; use gpui::{ - actions, elements::*, Entity, ModelHandle, MouseState, MutableAppContext, RenderContext, Task, - View, ViewContext, ViewHandle, + actions, elements::*, AnyViewHandle, Entity, ModelHandle, MouseState, MutableAppContext, + RenderContext, Task, View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; use settings::Settings; @@ -42,7 +42,7 @@ impl View for ContactFinder { ChildView::new(self.picker.clone()).boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.picker); } } diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index 4aff5b1a74..9bc7972b29 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -13,9 +13,9 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f}, impl_actions, impl_internal_actions, platform::CursorStyle, - AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MouseButton, - MutableAppContext, RenderContext, Subscription, View, ViewContext, ViewHandle, WeakModelHandle, - WeakViewHandle, + AnyViewHandle, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, + MouseButton, MutableAppContext, RenderContext, Subscription, View, ViewContext, ViewHandle, + WeakModelHandle, WeakViewHandle, }; use join_project_notification::JoinProjectNotification; use menu::{Confirm, SelectNext, SelectPrev}; @@ -1152,7 +1152,7 @@ impl View for ContactsPanel { .boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.filter_editor); } diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index b17718577f..e301e62467 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -1,6 +1,6 @@ use gpui::{ elements::*, geometry::vector::Vector2F, impl_internal_actions, keymap, platform::CursorStyle, - Action, AppContext, Axis, Entity, MouseButton, MutableAppContext, RenderContext, + Action, AnyViewHandle, AppContext, Axis, Entity, MouseButton, MutableAppContext, RenderContext, SizeConstraint, Subscription, View, ViewContext, }; use menu::*; @@ -106,7 +106,7 @@ impl View for ContextMenu { .boxed() } - fn on_blur(&mut self, cx: &mut ViewContext) { + fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { self.reset(cx); } } diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index e9692c5493..42a3bb9f13 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -99,7 +99,7 @@ impl View for ProjectDiagnosticsEditor { } } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { if !self.path_states.is_empty() { cx.focus(&self.editor); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index e4ff272440..6e84b275aa 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -29,8 +29,8 @@ use gpui::{ geometry::vector::{vec2f, Vector2F}, impl_actions, impl_internal_actions, platform::CursorStyle, - text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, - ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View, + text_layout, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, + Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use highlight_matching_bracket::refresh_matching_bracket_highlights; @@ -6025,7 +6025,7 @@ impl View for Editor { "Editor" } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { let focused_event = EditorFocused(cx.handle()); cx.emit_global(focused_event); if let Some(rename) = self.pending_rename.as_ref() { @@ -6046,7 +6046,7 @@ impl View for Editor { } } - fn on_blur(&mut self, cx: &mut ViewContext) { + fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { let blurred_event = EditorBlurred(cx.handle()); cx.emit_global(blurred_event); self.focused = false; diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index d69c95605d..aeec799015 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -1,7 +1,7 @@ use fuzzy::PathMatch; use gpui::{ - actions, elements::*, AppContext, Entity, ModelHandle, MouseState, MutableAppContext, - RenderContext, Task, View, ViewContext, ViewHandle, + actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId}; @@ -53,7 +53,7 @@ impl View for FileFinder { ChildView::new(self.picker.clone()).boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.picker); } } diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index f2df235a7b..3ca50cee42 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -1,7 +1,7 @@ use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor}; use gpui::{ - actions, elements::*, geometry::vector::Vector2F, Axis, Entity, MutableAppContext, - RenderContext, View, ViewContext, ViewHandle, + actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, Axis, Entity, + MutableAppContext, RenderContext, View, ViewContext, ViewHandle, }; use menu::{Cancel, Confirm}; use settings::Settings; @@ -183,7 +183,7 @@ impl View for GoToLine { .named("go to line") } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.line_editor); } } diff --git a/crates/gpui/grammars/context-predicate/src/parser.c b/crates/gpui/grammars/context-predicate/src/parser.c index e2af5e03ca..57a7364a43 100644 --- a/crates/gpui/grammars/context-predicate/src/parser.c +++ b/crates/gpui/grammars/context-predicate/src/parser.c @@ -35,115 +35,132 @@ enum { sym_parenthesized = 16, }; -static const char * const ts_symbol_names[] = { - [ts_builtin_sym_end] = "end", - [sym_identifier] = "identifier", - [anon_sym_BANG] = "!", - [anon_sym_AMP_AMP] = "&&", - [anon_sym_PIPE_PIPE] = "||", - [anon_sym_EQ_EQ] = "==", - [anon_sym_BANG_EQ] = "!=", - [anon_sym_LPAREN] = "(", - [anon_sym_RPAREN] = ")", - [sym_source] = "source", - [sym__expression] = "_expression", - [sym_not] = "not", - [sym_and] = "and", - [sym_or] = "or", - [sym_equal] = "equal", - [sym_not_equal] = "not_equal", - [sym_parenthesized] = "parenthesized", +static const char *const ts_symbol_names[] = { + [ts_builtin_sym_end] = "end", + [sym_identifier] = "identifier", + [anon_sym_BANG] = "!", + [anon_sym_AMP_AMP] = "&&", + [anon_sym_PIPE_PIPE] = "||", + [anon_sym_EQ_EQ] = "==", + [anon_sym_BANG_EQ] = "!=", + [anon_sym_LPAREN] = "(", + [anon_sym_RPAREN] = ")", + [sym_source] = "source", + [sym__expression] = "_expression", + [sym_not] = "not", + [sym_and] = "and", + [sym_or] = "or", + [sym_equal] = "equal", + [sym_not_equal] = "not_equal", + [sym_parenthesized] = "parenthesized", }; static const TSSymbol ts_symbol_map[] = { - [ts_builtin_sym_end] = ts_builtin_sym_end, - [sym_identifier] = sym_identifier, - [anon_sym_BANG] = anon_sym_BANG, - [anon_sym_AMP_AMP] = anon_sym_AMP_AMP, - [anon_sym_PIPE_PIPE] = anon_sym_PIPE_PIPE, - [anon_sym_EQ_EQ] = anon_sym_EQ_EQ, - [anon_sym_BANG_EQ] = anon_sym_BANG_EQ, - [anon_sym_LPAREN] = anon_sym_LPAREN, - [anon_sym_RPAREN] = anon_sym_RPAREN, - [sym_source] = sym_source, - [sym__expression] = sym__expression, - [sym_not] = sym_not, - [sym_and] = sym_and, - [sym_or] = sym_or, - [sym_equal] = sym_equal, - [sym_not_equal] = sym_not_equal, - [sym_parenthesized] = sym_parenthesized, + [ts_builtin_sym_end] = ts_builtin_sym_end, + [sym_identifier] = sym_identifier, + [anon_sym_BANG] = anon_sym_BANG, + [anon_sym_AMP_AMP] = anon_sym_AMP_AMP, + [anon_sym_PIPE_PIPE] = anon_sym_PIPE_PIPE, + [anon_sym_EQ_EQ] = anon_sym_EQ_EQ, + [anon_sym_BANG_EQ] = anon_sym_BANG_EQ, + [anon_sym_LPAREN] = anon_sym_LPAREN, + [anon_sym_RPAREN] = anon_sym_RPAREN, + [sym_source] = sym_source, + [sym__expression] = sym__expression, + [sym_not] = sym_not, + [sym_and] = sym_and, + [sym_or] = sym_or, + [sym_equal] = sym_equal, + [sym_not_equal] = sym_not_equal, + [sym_parenthesized] = sym_parenthesized, }; static const TSSymbolMetadata ts_symbol_metadata[] = { - [ts_builtin_sym_end] = { - .visible = false, - .named = true, - }, - [sym_identifier] = { - .visible = true, - .named = true, - }, - [anon_sym_BANG] = { - .visible = true, - .named = false, - }, - [anon_sym_AMP_AMP] = { - .visible = true, - .named = false, - }, - [anon_sym_PIPE_PIPE] = { - .visible = true, - .named = false, - }, - [anon_sym_EQ_EQ] = { - .visible = true, - .named = false, - }, - [anon_sym_BANG_EQ] = { - .visible = true, - .named = false, - }, - [anon_sym_LPAREN] = { - .visible = true, - .named = false, - }, - [anon_sym_RPAREN] = { - .visible = true, - .named = false, - }, - [sym_source] = { - .visible = true, - .named = true, - }, - [sym__expression] = { - .visible = false, - .named = true, - }, - [sym_not] = { - .visible = true, - .named = true, - }, - [sym_and] = { - .visible = true, - .named = true, - }, - [sym_or] = { - .visible = true, - .named = true, - }, - [sym_equal] = { - .visible = true, - .named = true, - }, - [sym_not_equal] = { - .visible = true, - .named = true, - }, - [sym_parenthesized] = { - .visible = true, - .named = true, - }, + [ts_builtin_sym_end] = + { + .visible = false, + .named = true, + }, + [sym_identifier] = + { + .visible = true, + .named = true, + }, + [anon_sym_BANG] = + { + .visible = true, + .named = false, + }, + [anon_sym_AMP_AMP] = + { + .visible = true, + .named = false, + }, + [anon_sym_PIPE_PIPE] = + { + .visible = true, + .named = false, + }, + [anon_sym_EQ_EQ] = + { + .visible = true, + .named = false, + }, + [anon_sym_BANG_EQ] = + { + .visible = true, + .named = false, + }, + [anon_sym_LPAREN] = + { + .visible = true, + .named = false, + }, + [anon_sym_RPAREN] = + { + .visible = true, + .named = false, + }, + [sym_source] = + { + .visible = true, + .named = true, + }, + [sym__expression] = + { + .visible = false, + .named = true, + }, + [sym_not] = + { + .visible = true, + .named = true, + }, + [sym_and] = + { + .visible = true, + .named = true, + }, + [sym_or] = + { + .visible = true, + .named = true, + }, + [sym_equal] = + { + .visible = true, + .named = true, + }, + [sym_not_equal] = + { + .visible = true, + .named = true, + }, + [sym_parenthesized] = + { + .visible = true, + .named = true, + }, }; enum { @@ -152,340 +169,378 @@ enum { field_right = 3, }; -static const char * const ts_field_names[] = { - [0] = NULL, - [field_expression] = "expression", - [field_left] = "left", - [field_right] = "right", +static const char *const ts_field_names[] = { + [0] = NULL, + [field_expression] = "expression", + [field_left] = "left", + [field_right] = "right", }; static const TSFieldMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = { - [1] = {.index = 0, .length = 1}, - [2] = {.index = 1, .length = 2}, + [1] = {.index = 0, .length = 1}, + [2] = {.index = 1, .length = 2}, }; static const TSFieldMapEntry ts_field_map_entries[] = { - [0] = - {field_expression, 1}, - [1] = - {field_left, 0}, + [0] = {field_expression, 1}, + [1] = {field_left, 0}, {field_right, 2}, }; -static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = { - [0] = {0}, +static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT] + [MAX_ALIAS_SEQUENCE_LENGTH] = { + [0] = {0}, }; static const uint16_t ts_non_terminal_alias_map[] = { - 0, + 0, }; static bool ts_lex(TSLexer *lexer, TSStateId state) { START_LEXER(); eof = lexer->eof(lexer); switch (state) { - case 0: - if (eof) ADVANCE(7); - if (lookahead == '!') ADVANCE(10); - if (lookahead == '&') ADVANCE(2); - if (lookahead == '(') ADVANCE(15); - if (lookahead == ')') ADVANCE(16); - if (lookahead == '=') ADVANCE(4); - if (lookahead == '|') ADVANCE(5); - if (lookahead == '\t' || - lookahead == '\n' || - lookahead == '\r' || - lookahead == ' ') SKIP(0) - if (lookahead == '-' || - ('0' <= lookahead && lookahead <= '9') || - ('A' <= lookahead && lookahead <= 'Z') || - lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(8); - END_STATE(); - case 1: - if (lookahead == '!') ADVANCE(9); - if (lookahead == '(') ADVANCE(15); - if (lookahead == '\t' || - lookahead == '\n' || - lookahead == '\r' || - lookahead == ' ') SKIP(1) - if (lookahead == '-' || - ('0' <= lookahead && lookahead <= '9') || - ('A' <= lookahead && lookahead <= 'Z') || - lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(8); - END_STATE(); - case 2: - if (lookahead == '&') ADVANCE(11); - END_STATE(); - case 3: - if (lookahead == '=') ADVANCE(14); - END_STATE(); - case 4: - if (lookahead == '=') ADVANCE(13); - END_STATE(); - case 5: - if (lookahead == '|') ADVANCE(12); - END_STATE(); - case 6: - if (eof) ADVANCE(7); - if (lookahead == '!') ADVANCE(3); - if (lookahead == '&') ADVANCE(2); - if (lookahead == ')') ADVANCE(16); - if (lookahead == '=') ADVANCE(4); - if (lookahead == '|') ADVANCE(5); - if (lookahead == '\t' || - lookahead == '\n' || - lookahead == '\r' || - lookahead == ' ') SKIP(6) - END_STATE(); - case 7: - ACCEPT_TOKEN(ts_builtin_sym_end); - END_STATE(); - case 8: - ACCEPT_TOKEN(sym_identifier); - if (lookahead == '-' || - ('0' <= lookahead && lookahead <= '9') || - ('A' <= lookahead && lookahead <= 'Z') || - lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(8); - END_STATE(); - case 9: - ACCEPT_TOKEN(anon_sym_BANG); - END_STATE(); - case 10: - ACCEPT_TOKEN(anon_sym_BANG); - if (lookahead == '=') ADVANCE(14); - END_STATE(); - case 11: - ACCEPT_TOKEN(anon_sym_AMP_AMP); - END_STATE(); - case 12: - ACCEPT_TOKEN(anon_sym_PIPE_PIPE); - END_STATE(); - case 13: - ACCEPT_TOKEN(anon_sym_EQ_EQ); - END_STATE(); - case 14: - ACCEPT_TOKEN(anon_sym_BANG_EQ); - END_STATE(); - case 15: - ACCEPT_TOKEN(anon_sym_LPAREN); - END_STATE(); - case 16: - ACCEPT_TOKEN(anon_sym_RPAREN); - END_STATE(); - default: - return false; + case 0: + if (eof) + ADVANCE(7); + if (lookahead == '!') + ADVANCE(10); + if (lookahead == '&') + ADVANCE(2); + if (lookahead == '(') + ADVANCE(15); + if (lookahead == ')') + ADVANCE(16); + if (lookahead == '=') + ADVANCE(4); + if (lookahead == '|') + ADVANCE(5); + if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' || + lookahead == ' ') + SKIP(0) + if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) + ADVANCE(8); + END_STATE(); + case 1: + if (lookahead == '!') + ADVANCE(9); + if (lookahead == '(') + ADVANCE(15); + if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' || + lookahead == ' ') + SKIP(1) + if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) + ADVANCE(8); + END_STATE(); + case 2: + if (lookahead == '&') + ADVANCE(11); + END_STATE(); + case 3: + if (lookahead == '=') + ADVANCE(14); + END_STATE(); + case 4: + if (lookahead == '=') + ADVANCE(13); + END_STATE(); + case 5: + if (lookahead == '|') + ADVANCE(12); + END_STATE(); + case 6: + if (eof) + ADVANCE(7); + if (lookahead == '!') + ADVANCE(3); + if (lookahead == '&') + ADVANCE(2); + if (lookahead == ')') + ADVANCE(16); + if (lookahead == '=') + ADVANCE(4); + if (lookahead == '|') + ADVANCE(5); + if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' || + lookahead == ' ') + SKIP(6) + END_STATE(); + case 7: + ACCEPT_TOKEN(ts_builtin_sym_end); + END_STATE(); + case 8: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) + ADVANCE(8); + END_STATE(); + case 9: + ACCEPT_TOKEN(anon_sym_BANG); + END_STATE(); + case 10: + ACCEPT_TOKEN(anon_sym_BANG); + if (lookahead == '=') + ADVANCE(14); + END_STATE(); + case 11: + ACCEPT_TOKEN(anon_sym_AMP_AMP); + END_STATE(); + case 12: + ACCEPT_TOKEN(anon_sym_PIPE_PIPE); + END_STATE(); + case 13: + ACCEPT_TOKEN(anon_sym_EQ_EQ); + END_STATE(); + case 14: + ACCEPT_TOKEN(anon_sym_BANG_EQ); + END_STATE(); + case 15: + ACCEPT_TOKEN(anon_sym_LPAREN); + END_STATE(); + case 16: + ACCEPT_TOKEN(anon_sym_RPAREN); + END_STATE(); + default: + return false; } } static const TSLexMode ts_lex_modes[STATE_COUNT] = { - [0] = {.lex_state = 0}, - [1] = {.lex_state = 1}, - [2] = {.lex_state = 1}, - [3] = {.lex_state = 1}, - [4] = {.lex_state = 1}, - [5] = {.lex_state = 1}, - [6] = {.lex_state = 6}, - [7] = {.lex_state = 0}, - [8] = {.lex_state = 0}, - [9] = {.lex_state = 0}, - [10] = {.lex_state = 0}, - [11] = {.lex_state = 0}, - [12] = {.lex_state = 0}, - [13] = {.lex_state = 0}, - [14] = {.lex_state = 0}, - [15] = {.lex_state = 0}, - [16] = {.lex_state = 0}, - [17] = {.lex_state = 0}, + [0] = {.lex_state = 0}, [1] = {.lex_state = 1}, [2] = {.lex_state = 1}, + [3] = {.lex_state = 1}, [4] = {.lex_state = 1}, [5] = {.lex_state = 1}, + [6] = {.lex_state = 6}, [7] = {.lex_state = 0}, [8] = {.lex_state = 0}, + [9] = {.lex_state = 0}, [10] = {.lex_state = 0}, [11] = {.lex_state = 0}, + [12] = {.lex_state = 0}, [13] = {.lex_state = 0}, [14] = {.lex_state = 0}, + [15] = {.lex_state = 0}, [16] = {.lex_state = 0}, [17] = {.lex_state = 0}, }; static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { - [0] = { - [ts_builtin_sym_end] = ACTIONS(1), - [sym_identifier] = ACTIONS(1), - [anon_sym_BANG] = ACTIONS(1), - [anon_sym_AMP_AMP] = ACTIONS(1), - [anon_sym_PIPE_PIPE] = ACTIONS(1), - [anon_sym_EQ_EQ] = ACTIONS(1), - [anon_sym_BANG_EQ] = ACTIONS(1), - [anon_sym_LPAREN] = ACTIONS(1), - [anon_sym_RPAREN] = ACTIONS(1), - }, - [1] = { - [sym_source] = STATE(15), - [sym__expression] = STATE(13), - [sym_not] = STATE(13), - [sym_and] = STATE(13), - [sym_or] = STATE(13), - [sym_equal] = STATE(13), - [sym_not_equal] = STATE(13), - [sym_parenthesized] = STATE(13), - [sym_identifier] = ACTIONS(3), - [anon_sym_BANG] = ACTIONS(5), - [anon_sym_LPAREN] = ACTIONS(7), - }, - [2] = { - [sym__expression] = STATE(7), - [sym_not] = STATE(7), - [sym_and] = STATE(7), - [sym_or] = STATE(7), - [sym_equal] = STATE(7), - [sym_not_equal] = STATE(7), - [sym_parenthesized] = STATE(7), - [sym_identifier] = ACTIONS(3), - [anon_sym_BANG] = ACTIONS(5), - [anon_sym_LPAREN] = ACTIONS(7), - }, - [3] = { - [sym__expression] = STATE(14), - [sym_not] = STATE(14), - [sym_and] = STATE(14), - [sym_or] = STATE(14), - [sym_equal] = STATE(14), - [sym_not_equal] = STATE(14), - [sym_parenthesized] = STATE(14), - [sym_identifier] = ACTIONS(3), - [anon_sym_BANG] = ACTIONS(5), - [anon_sym_LPAREN] = ACTIONS(7), - }, - [4] = { - [sym__expression] = STATE(11), - [sym_not] = STATE(11), - [sym_and] = STATE(11), - [sym_or] = STATE(11), - [sym_equal] = STATE(11), - [sym_not_equal] = STATE(11), - [sym_parenthesized] = STATE(11), - [sym_identifier] = ACTIONS(3), - [anon_sym_BANG] = ACTIONS(5), - [anon_sym_LPAREN] = ACTIONS(7), - }, - [5] = { - [sym__expression] = STATE(12), - [sym_not] = STATE(12), - [sym_and] = STATE(12), - [sym_or] = STATE(12), - [sym_equal] = STATE(12), - [sym_not_equal] = STATE(12), - [sym_parenthesized] = STATE(12), - [sym_identifier] = ACTIONS(3), - [anon_sym_BANG] = ACTIONS(5), - [anon_sym_LPAREN] = ACTIONS(7), - }, + [0] = + { + [ts_builtin_sym_end] = ACTIONS(1), + [sym_identifier] = ACTIONS(1), + [anon_sym_BANG] = ACTIONS(1), + [anon_sym_AMP_AMP] = ACTIONS(1), + [anon_sym_PIPE_PIPE] = ACTIONS(1), + [anon_sym_EQ_EQ] = ACTIONS(1), + [anon_sym_BANG_EQ] = ACTIONS(1), + [anon_sym_LPAREN] = ACTIONS(1), + [anon_sym_RPAREN] = ACTIONS(1), + }, + [1] = + { + [sym_source] = STATE(15), + [sym__expression] = STATE(13), + [sym_not] = STATE(13), + [sym_and] = STATE(13), + [sym_or] = STATE(13), + [sym_equal] = STATE(13), + [sym_not_equal] = STATE(13), + [sym_parenthesized] = STATE(13), + [sym_identifier] = ACTIONS(3), + [anon_sym_BANG] = ACTIONS(5), + [anon_sym_LPAREN] = ACTIONS(7), + }, + [2] = + { + [sym__expression] = STATE(7), + [sym_not] = STATE(7), + [sym_and] = STATE(7), + [sym_or] = STATE(7), + [sym_equal] = STATE(7), + [sym_not_equal] = STATE(7), + [sym_parenthesized] = STATE(7), + [sym_identifier] = ACTIONS(3), + [anon_sym_BANG] = ACTIONS(5), + [anon_sym_LPAREN] = ACTIONS(7), + }, + [3] = + { + [sym__expression] = STATE(14), + [sym_not] = STATE(14), + [sym_and] = STATE(14), + [sym_or] = STATE(14), + [sym_equal] = STATE(14), + [sym_not_equal] = STATE(14), + [sym_parenthesized] = STATE(14), + [sym_identifier] = ACTIONS(3), + [anon_sym_BANG] = ACTIONS(5), + [anon_sym_LPAREN] = ACTIONS(7), + }, + [4] = + { + [sym__expression] = STATE(11), + [sym_not] = STATE(11), + [sym_and] = STATE(11), + [sym_or] = STATE(11), + [sym_equal] = STATE(11), + [sym_not_equal] = STATE(11), + [sym_parenthesized] = STATE(11), + [sym_identifier] = ACTIONS(3), + [anon_sym_BANG] = ACTIONS(5), + [anon_sym_LPAREN] = ACTIONS(7), + }, + [5] = + { + [sym__expression] = STATE(12), + [sym_not] = STATE(12), + [sym_and] = STATE(12), + [sym_or] = STATE(12), + [sym_equal] = STATE(12), + [sym_not_equal] = STATE(12), + [sym_parenthesized] = STATE(12), + [sym_identifier] = ACTIONS(3), + [anon_sym_BANG] = ACTIONS(5), + [anon_sym_LPAREN] = ACTIONS(7), + }, }; static const uint16_t ts_small_parse_table[] = { - [0] = 3, - ACTIONS(11), 1, - anon_sym_EQ_EQ, - ACTIONS(13), 1, - anon_sym_BANG_EQ, - ACTIONS(9), 4, - ts_builtin_sym_end, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [13] = 1, - ACTIONS(15), 4, - ts_builtin_sym_end, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [20] = 1, - ACTIONS(17), 4, - ts_builtin_sym_end, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [27] = 1, - ACTIONS(19), 4, - ts_builtin_sym_end, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [34] = 1, - ACTIONS(21), 4, - ts_builtin_sym_end, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [41] = 1, - ACTIONS(23), 4, - ts_builtin_sym_end, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [48] = 2, - ACTIONS(27), 1, - anon_sym_AMP_AMP, - ACTIONS(25), 3, - ts_builtin_sym_end, - anon_sym_PIPE_PIPE, - anon_sym_RPAREN, - [57] = 3, - ACTIONS(27), 1, - anon_sym_AMP_AMP, - ACTIONS(29), 1, - ts_builtin_sym_end, - ACTIONS(31), 1, - anon_sym_PIPE_PIPE, - [67] = 3, - ACTIONS(27), 1, - anon_sym_AMP_AMP, - ACTIONS(31), 1, - anon_sym_PIPE_PIPE, - ACTIONS(33), 1, - anon_sym_RPAREN, - [77] = 1, - ACTIONS(35), 1, - ts_builtin_sym_end, - [81] = 1, - ACTIONS(37), 1, - sym_identifier, - [85] = 1, - ACTIONS(39), 1, - sym_identifier, + [0] = 3, + ACTIONS(11), + 1, + anon_sym_EQ_EQ, + ACTIONS(13), + 1, + anon_sym_BANG_EQ, + ACTIONS(9), + 4, + ts_builtin_sym_end, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [13] = 1, + ACTIONS(15), + 4, + ts_builtin_sym_end, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [20] = 1, + ACTIONS(17), + 4, + ts_builtin_sym_end, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [27] = 1, + ACTIONS(19), + 4, + ts_builtin_sym_end, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [34] = 1, + ACTIONS(21), + 4, + ts_builtin_sym_end, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [41] = 1, + ACTIONS(23), + 4, + ts_builtin_sym_end, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [48] = 2, + ACTIONS(27), + 1, + anon_sym_AMP_AMP, + ACTIONS(25), + 3, + ts_builtin_sym_end, + anon_sym_PIPE_PIPE, + anon_sym_RPAREN, + [57] = 3, + ACTIONS(27), + 1, + anon_sym_AMP_AMP, + ACTIONS(29), + 1, + ts_builtin_sym_end, + ACTIONS(31), + 1, + anon_sym_PIPE_PIPE, + [67] = 3, + ACTIONS(27), + 1, + anon_sym_AMP_AMP, + ACTIONS(31), + 1, + anon_sym_PIPE_PIPE, + ACTIONS(33), + 1, + anon_sym_RPAREN, + [77] = 1, + ACTIONS(35), + 1, + ts_builtin_sym_end, + [81] = 1, + ACTIONS(37), + 1, + sym_identifier, + [85] = 1, + ACTIONS(39), + 1, + sym_identifier, }; static const uint32_t ts_small_parse_table_map[] = { - [SMALL_STATE(6)] = 0, - [SMALL_STATE(7)] = 13, - [SMALL_STATE(8)] = 20, - [SMALL_STATE(9)] = 27, - [SMALL_STATE(10)] = 34, - [SMALL_STATE(11)] = 41, - [SMALL_STATE(12)] = 48, - [SMALL_STATE(13)] = 57, - [SMALL_STATE(14)] = 67, - [SMALL_STATE(15)] = 77, - [SMALL_STATE(16)] = 81, - [SMALL_STATE(17)] = 85, + [SMALL_STATE(6)] = 0, [SMALL_STATE(7)] = 13, [SMALL_STATE(8)] = 20, + [SMALL_STATE(9)] = 27, [SMALL_STATE(10)] = 34, [SMALL_STATE(11)] = 41, + [SMALL_STATE(12)] = 48, [SMALL_STATE(13)] = 57, [SMALL_STATE(14)] = 67, + [SMALL_STATE(15)] = 77, [SMALL_STATE(16)] = 81, [SMALL_STATE(17)] = 85, }; static const TSParseActionEntry ts_parse_actions[] = { - [0] = {.entry = {.count = 0, .reusable = false}}, - [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), - [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6), - [5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), - [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3), - [9] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__expression, 1), - [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16), - [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), - [15] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not, 2, .production_id = 1), - [17] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_equal, 3, .production_id = 2), - [19] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not_equal, 3, .production_id = 2), - [21] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesized, 3, .production_id = 1), - [23] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_and, 3, .production_id = 2), - [25] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_or, 3, .production_id = 2), - [27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4), - [29] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source, 1), - [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5), - [33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), - [35] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), - [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8), - [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9), + [0] = {.entry = {.count = 0, .reusable = false}}, + [1] = {.entry = {.count = 1, .reusable = false}}, + RECOVER(), + [3] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(6), + [5] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(2), + [7] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(3), + [9] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym__expression, 1), + [11] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(16), + [13] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(17), + [15] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_not, 2, .production_id = 1), + [17] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_equal, 3, .production_id = 2), + [19] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_not_equal, 3, .production_id = 2), + [21] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_parenthesized, 3, .production_id = 1), + [23] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_and, 3, .production_id = 2), + [25] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_or, 3, .production_id = 2), + [27] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(4), + [29] = {.entry = {.count = 1, .reusable = true}}, + REDUCE(sym_source, 1), + [31] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(5), + [33] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(10), + [35] = {.entry = {.count = 1, .reusable = true}}, + ACCEPT_INPUT(), + [37] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(8), + [39] = {.entry = {.count = 1, .reusable = true}}, + SHIFT(9), }; #ifdef __cplusplus @@ -497,30 +552,30 @@ extern "C" { extern const TSLanguage *tree_sitter_context_predicate(void) { static const TSLanguage language = { - .version = LANGUAGE_VERSION, - .symbol_count = SYMBOL_COUNT, - .alias_count = ALIAS_COUNT, - .token_count = TOKEN_COUNT, - .external_token_count = EXTERNAL_TOKEN_COUNT, - .state_count = STATE_COUNT, - .large_state_count = LARGE_STATE_COUNT, - .production_id_count = PRODUCTION_ID_COUNT, - .field_count = FIELD_COUNT, - .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, - .parse_table = &ts_parse_table[0][0], - .small_parse_table = ts_small_parse_table, - .small_parse_table_map = ts_small_parse_table_map, - .parse_actions = ts_parse_actions, - .symbol_names = ts_symbol_names, - .field_names = ts_field_names, - .field_map_slices = ts_field_map_slices, - .field_map_entries = ts_field_map_entries, - .symbol_metadata = ts_symbol_metadata, - .public_symbol_map = ts_symbol_map, - .alias_map = ts_non_terminal_alias_map, - .alias_sequences = &ts_alias_sequences[0][0], - .lex_modes = ts_lex_modes, - .lex_fn = ts_lex, + .version = LANGUAGE_VERSION, + .symbol_count = SYMBOL_COUNT, + .alias_count = ALIAS_COUNT, + .token_count = TOKEN_COUNT, + .external_token_count = EXTERNAL_TOKEN_COUNT, + .state_count = STATE_COUNT, + .large_state_count = LARGE_STATE_COUNT, + .production_id_count = PRODUCTION_ID_COUNT, + .field_count = FIELD_COUNT, + .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, + .parse_table = &ts_parse_table[0][0], + .small_parse_table = ts_small_parse_table, + .small_parse_table_map = ts_small_parse_table_map, + .parse_actions = ts_parse_actions, + .symbol_names = ts_symbol_names, + .field_names = ts_field_names, + .field_map_slices = ts_field_map_slices, + .field_map_entries = ts_field_map_entries, + .symbol_metadata = ts_symbol_metadata, + .public_symbol_map = ts_symbol_map, + .alias_map = ts_non_terminal_alias_map, + .alias_sequences = &ts_alias_sequences[0][0], + .lex_modes = ts_lex_modes, + .lex_fn = ts_lex, }; return &language; } diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index ac9ef6f829..8246ea31ed 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -55,8 +55,8 @@ pub trait Entity: 'static { pub trait View: Entity + Sized { fn ui_name() -> &'static str; fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox; - fn on_focus(&mut self, _: &mut ViewContext) {} - fn on_blur(&mut self, _: &mut ViewContext) {} + fn on_focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext) {} + fn on_focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext) {} fn keymap_context(&self, _: &AppContext) -> keymap::Context { Self::default_keymap_context() } @@ -1903,7 +1903,7 @@ impl MutableAppContext { is_fullscreen: false, }, ); - root_view.update(this, |view, cx| view.on_focus(cx)); + root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx)); this.open_platform_window(window_id, window_options); (window_id, root_view) @@ -2500,14 +2500,16 @@ impl MutableAppContext { window.is_active = active; //Handle focus - let view_id = window.focused_view_id?; - if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { - if active { - view.on_focus(this, window_id, view_id); - } else { - view.on_blur(this, window_id, view_id); + let focused_id = window.focused_view_id?; + for view_id in this.parents(window_id, focused_id).collect::>() { + if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { + if active { + view.on_focus_in(this, window_id, view_id, focused_id); + } else { + view.on_focus_out(this, window_id, view_id, focused_id); + } + this.cx.views.insert((window_id, view_id), view); } - this.cx.views.insert((window_id, view_id), view); } let mut observations = this.window_activation_observations.clone(); @@ -2537,26 +2539,45 @@ impl MutableAppContext { blurred_id }); - if let Some(blurred_id) = blurred_id { - if let Some(mut blurred_view) = this.cx.views.remove(&(window_id, blurred_id)) { - blurred_view.on_blur(this, window_id, blurred_id); - this.cx.views.insert((window_id, blurred_id), blurred_view); + let blurred_parents = blurred_id + .map(|blurred_id| this.parents(window_id, blurred_id).collect::>()) + .unwrap_or_default(); + let focused_parents = focused_id + .map(|focused_id| this.parents(window_id, focused_id).collect::>()) + .unwrap_or_default(); - let mut subscriptions = this.focus_observations.clone(); - subscriptions - .emit_and_cleanup(blurred_id, this, |callback, this| callback(false, this)); + if let Some(blurred_id) = blurred_id { + for view_id in blurred_parents.iter().copied() { + // We've reached a common anscestor. Break. + if focused_parents.contains(&view_id) { + break; + } + + if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { + view.on_focus_out(this, window_id, view_id, blurred_id); + this.cx.views.insert((window_id, view_id), view); + } } + + let mut subscriptions = this.focus_observations.clone(); + subscriptions + .emit_and_cleanup(blurred_id, this, |callback, this| callback(false, this)); } if let Some(focused_id) = focused_id { - if let Some(mut focused_view) = this.cx.views.remove(&(window_id, focused_id)) { - focused_view.on_focus(this, window_id, focused_id); - this.cx.views.insert((window_id, focused_id), focused_view); - - let mut subscriptions = this.focus_observations.clone(); - subscriptions - .emit_and_cleanup(focused_id, this, |callback, this| callback(true, this)); + for view_id in focused_parents { + if blurred_parents.contains(&view_id) { + break; + } + if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { + view.on_focus_in(this, window_id, view_id, focused_id); + this.cx.views.insert((window_id, focused_id), view); + } } + + let mut subscriptions = this.focus_observations.clone(); + subscriptions + .emit_and_cleanup(focused_id, this, |callback, this| callback(true, this)); } }) } @@ -2742,7 +2763,7 @@ impl ReadView for MutableAppContext { if let Some(view) = self.cx.views.get(&(handle.window_id, handle.view_id)) { view.as_any().downcast_ref().expect("downcast is type safe") } else { - panic!("circular view reference"); + panic!("circular view reference for type {}", type_name::()); } } } @@ -3216,8 +3237,20 @@ pub trait AnyView { ) -> Option>>>; fn ui_name(&self) -> &'static str; fn render<'a>(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox; - fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize); - fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize); + fn on_focus_in( + &mut self, + cx: &mut MutableAppContext, + window_id: usize, + view_id: usize, + focused_id: usize, + ); + fn on_focus_out( + &mut self, + cx: &mut MutableAppContext, + window_id: usize, + view_id: usize, + focused_id: usize, + ); fn keymap_context(&self, cx: &AppContext) -> keymap::Context; fn debug_json(&self, cx: &AppContext) -> serde_json::Value; @@ -3242,6 +3275,14 @@ pub trait AnyView { window_id: usize, view_id: usize, ); + fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle { + AnyViewHandle::new( + window_id, + view_id, + self.as_any().type_id(), + cx.ref_counts.clone(), + ) + } } impl AnyView for T @@ -3275,14 +3316,48 @@ where View::render(self, &mut RenderContext::new(params, cx)) } - fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) { + fn on_focus_in( + &mut self, + cx: &mut MutableAppContext, + window_id: usize, + view_id: usize, + focused_id: usize, + ) { let mut cx = ViewContext::new(cx, window_id, view_id); - View::on_focus(self, &mut cx); + let focused_view_handle: AnyViewHandle = if view_id == focused_id { + cx.handle().into() + } else { + let focused_type = cx + .views + .get(&(window_id, focused_id)) + .unwrap() + .as_any() + .type_id(); + AnyViewHandle::new(window_id, focused_id, focused_type, cx.ref_counts.clone()) + }; + View::on_focus_in(self, focused_view_handle, &mut cx); } - fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize) { + fn on_focus_out( + &mut self, + cx: &mut MutableAppContext, + window_id: usize, + view_id: usize, + blurred_id: usize, + ) { let mut cx = ViewContext::new(cx, window_id, view_id); - View::on_blur(self, &mut cx); + let blurred_view_handle: AnyViewHandle = if view_id == blurred_id { + cx.handle().into() + } else { + let blurred_type = cx + .views + .get(&(window_id, blurred_id)) + .unwrap() + .as_any() + .type_id(); + AnyViewHandle::new(window_id, blurred_id, blurred_type, cx.ref_counts.clone()) + }; + View::on_focus_out(self, blurred_view_handle, &mut cx); } fn keymap_context(&self, cx: &AppContext) -> keymap::Context { @@ -6665,12 +6740,16 @@ mod tests { "View" } - fn on_focus(&mut self, _: &mut ViewContext) { - self.events.lock().push(format!("{} focused", &self.name)); + fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext) { + if cx.handle().id() == focused.id() { + self.events.lock().push(format!("{} focused", &self.name)); + } } - fn on_blur(&mut self, _: &mut ViewContext) { - self.events.lock().push(format!("{} blurred", &self.name)); + fn on_focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext) { + if cx.handle().id() == blurred.id() { + self.events.lock().push(format!("{} blurred", &self.name)); + } } } @@ -7018,7 +7097,7 @@ mod tests { let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1); let view_2 = cx.add_view(&view_1, |_| view_2); - let view_3 = cx.add_view(&view_2, |cx| { + cx.add_view(&view_2, |cx| { cx.focus_self(); view_3 }); diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 19b309116a..8a8c559cf3 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -4,8 +4,8 @@ use editor::{ }; use fuzzy::StringMatch; use gpui::{ - actions, elements::*, geometry::vector::Vector2F, AppContext, Entity, MouseState, - MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, + actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Entity, + MouseState, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, }; use language::Outline; use ordered_float::OrderedFloat; @@ -52,7 +52,7 @@ impl View for OutlineView { ChildView::new(self.picker.clone()).boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.picker); } } diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index 6f247ebb6e..d3f729ba83 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -7,8 +7,8 @@ use gpui::{ geometry::vector::{vec2f, Vector2F}, keymap, platform::CursorStyle, - AppContext, Axis, Element, ElementBox, Entity, MouseButton, MouseState, MutableAppContext, - RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, + AnyViewHandle, AppContext, Axis, Element, ElementBox, Entity, MouseButton, MouseState, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev}; use settings::Settings; @@ -118,7 +118,7 @@ impl View for Picker { cx } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.query_editor); } } diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 8f2305eaff..755bca20d6 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -3,8 +3,8 @@ use editor::{ }; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, elements::*, AppContext, Entity, ModelHandle, MouseState, MutableAppContext, - RenderContext, Task, View, ViewContext, ViewHandle, + actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, }; use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate}; @@ -51,7 +51,7 @@ impl View for ProjectSymbolsView { ChildView::new(self.picker.clone()).boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.picker); } } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index ada785f854..d9a048b604 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -6,8 +6,8 @@ use crate::{ use collections::HashMap; use editor::{Anchor, Autoscroll, Editor}; use gpui::{ - actions, elements::*, impl_actions, platform::CursorStyle, Action, AppContext, Entity, - MouseButton, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, + actions, elements::*, impl_actions, platform::CursorStyle, Action, AnyViewHandle, AppContext, + Entity, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use language::OffsetRangeExt; @@ -80,7 +80,7 @@ impl View for BufferSearchBar { "BufferSearchBar" } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.query_editor); } diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 6cbd4c7e2d..bcbeb0ac5f 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -6,9 +6,9 @@ use crate::{ use collections::HashMap; use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll, MAX_TAB_TITLE_LEN}; use gpui::{ - actions, elements::*, platform::CursorStyle, Action, AppContext, ElementBox, Entity, - ModelContext, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, - View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle, + actions, elements::*, platform::CursorStyle, Action, AnyViewHandle, AppContext, ElementBox, + Entity, ModelContext, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, + Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle, }; use menu::Confirm; use project::{search::SearchQuery, Project}; @@ -190,7 +190,7 @@ impl View for ProjectSearchView { } } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { let handle = cx.weak_handle(); cx.update_global(|state: &mut ActiveSearches, cx| { state diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index 8b3099990a..ed9b994e75 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -6,7 +6,8 @@ use gpui::{ geometry::vector::Vector2F, impl_internal_actions, keymap::Keystroke, - AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle, + AnyViewHandle, AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, + ViewContext, ViewHandle, }; use workspace::pane; @@ -190,7 +191,7 @@ impl View for ConnectedView { .boxed() } - fn on_focus(&mut self, _cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, _cx: &mut ViewContext) { self.has_new_content = false; } diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 4e5ca37a9d..b71f6bdcb2 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -161,6 +161,13 @@ impl Dimensions for TerminalSize { fn columns(&self) -> usize { self.num_columns() } + + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + cx.emit(Event::Activate); + cx.defer(|view, cx| { + cx.focus(view.content.handle()); + }); + } } #[derive(Error, Debug)] diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 106e6ad429..d1e81b11a7 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -1,7 +1,7 @@ use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{ - actions, elements::*, AppContext, Element, ElementBox, Entity, MouseState, MutableAppContext, - RenderContext, View, ViewContext, ViewHandle, + actions, elements::*, AnyViewHandle, AppContext, Element, ElementBox, Entity, MouseState, + MutableAppContext, RenderContext, View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; use settings::Settings; @@ -249,7 +249,7 @@ impl View for ThemeSelector { ChildView::new(self.picker.clone()).boxed() } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.picker); } } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 572e1032b3..f2cfee3ec1 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -13,9 +13,9 @@ use gpui::{ }, impl_actions, impl_internal_actions, platform::{CursorStyle, NavigationDirection}, - AppContext, AsyncAppContext, Entity, EventContext, ModelHandle, MouseButton, MouseButtonEvent, - MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, ViewHandle, - WeakViewHandle, + AnyViewHandle, AppContext, AsyncAppContext, Entity, EventContext, ModelHandle, MouseButton, + MouseButtonEvent, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, + ViewHandle, WeakViewHandle, }; use project::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; @@ -830,6 +830,7 @@ impl Pane { pub fn focus_active_item(&mut self, cx: &mut ViewContext) { if let Some(active_item) = self.active_item() { cx.focus(active_item); + self.activate(cx); } } @@ -1210,8 +1211,12 @@ impl View for Pane { .named("pane") } - fn on_focus(&mut self, cx: &mut ViewContext) { - self.focus_active_item(cx); + fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext) { + if cx.handle().id() == focused.id() { + self.focus_active_item(cx); + } else { + self.activate(cx); + } } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 02ad18eb3d..c8e804f59b 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -2489,7 +2489,7 @@ impl View for Workspace { .named("workspace") } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.focus(&self.active_pane); } } diff --git a/styles/package-lock.json b/styles/package-lock.json index 5499f1852c..582f1c8496 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "styles", "version": "1.0.0", "license": "ISC", "dependencies": { From 049149320c5c0e6ace074450a860037544e1c2cd Mon Sep 17 00:00:00 2001 From: K Simmons Date: Mon, 8 Aug 2022 12:21:29 -0700 Subject: [PATCH 13/27] build fix --- crates/terminal/src/terminal.rs | 7 ------- crates/terminal/src/terminal_view.rs | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index b71f6bdcb2..4e5ca37a9d 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -161,13 +161,6 @@ impl Dimensions for TerminalSize { fn columns(&self) -> usize { self.num_columns() } - - fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.emit(Event::Activate); - cx.defer(|view, cx| { - cx.focus(view.content.handle()); - }); - } } #[derive(Error, Debug)] diff --git a/crates/terminal/src/terminal_view.rs b/crates/terminal/src/terminal_view.rs index ba6f49af02..75c9658bd6 100644 --- a/crates/terminal/src/terminal_view.rs +++ b/crates/terminal/src/terminal_view.rs @@ -152,7 +152,7 @@ impl View for TerminalView { } } - fn on_focus(&mut self, cx: &mut ViewContext) { + fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { cx.emit(Event::Activate); cx.defer(|view, cx| { cx.focus(view.content.handle()); From 6f180ed822ea5a2bb92e1ffc88ab035a7f6912c0 Mon Sep 17 00:00:00 2001 From: K Simmons Date: Tue, 9 Aug 2022 15:09:38 -0700 Subject: [PATCH 14/27] Pane focus working. Modals seem broken now --- crates/diagnostics/src/diagnostics.rs | 4 --- crates/editor/src/editor.rs | 3 -- crates/editor/src/items.rs | 4 --- crates/editor/src/link_go_to_definition.rs | 5 ++- crates/editor/src/mouse_context_menu.rs | 3 +- crates/gpui/src/app.rs | 14 ++------ crates/search/src/project_search.rs | 31 ++---------------- crates/terminal/src/terminal.rs | 1 - crates/terminal/src/terminal_view.rs | 9 +---- crates/workspace/src/pane.rs | 34 +++++++++++-------- crates/workspace/src/workspace.rs | 38 ++++++++-------------- 11 files changed, 43 insertions(+), 103 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 42a3bb9f13..facccadb76 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -568,10 +568,6 @@ impl workspace::Item for ProjectDiagnosticsEditor { unreachable!() } - fn should_activate_item_on_event(event: &Self::Event) -> bool { - Editor::should_activate_item_on_event(event) - } - fn should_update_tab_on_event(event: &Event) -> bool { Editor::should_update_tab_on_event(event) } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 6e84b275aa..128dae965c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1561,7 +1561,6 @@ impl Editor { ) { if !self.focused { cx.focus_self(); - cx.emit(Event::Activate); } let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); @@ -1623,7 +1622,6 @@ impl Editor { ) { if !self.focused { cx.focus_self(); - cx.emit(Event::Activate); } let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); @@ -5969,7 +5967,6 @@ fn compute_scroll_position( #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Event { - Activate, BufferEdited, Edited, Reparsed, diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 9837c5070f..59f9a98448 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -469,10 +469,6 @@ impl Item for Editor { }) } - fn should_activate_item_on_event(event: &Event) -> bool { - matches!(event, Event::Activate) - } - fn should_close_item_on_event(event: &Event) -> bool { matches!(event, Event::Closed) } diff --git a/crates/editor/src/link_go_to_definition.rs b/crates/editor/src/link_go_to_definition.rs index cc4592b6d4..cbdeb30191 100644 --- a/crates/editor/src/link_go_to_definition.rs +++ b/crates/editor/src/link_go_to_definition.rs @@ -8,8 +8,8 @@ use util::TryFutureExt; use workspace::Workspace; use crate::{ - Anchor, DisplayPoint, Editor, EditorSnapshot, Event, GoToDefinition, GoToTypeDefinition, - Select, SelectPhase, + Anchor, DisplayPoint, Editor, EditorSnapshot, GoToDefinition, GoToTypeDefinition, Select, + SelectPhase, }; #[derive(Clone, PartialEq)] @@ -355,7 +355,6 @@ fn go_to_fetched_definition_of_kind( editor_handle.update(cx, |editor, cx| { if !editor.focused { cx.focus_self(); - cx.emit(Event::Activate); } }); diff --git a/crates/editor/src/mouse_context_menu.rs b/crates/editor/src/mouse_context_menu.rs index 3098e96e07..202b009e3c 100644 --- a/crates/editor/src/mouse_context_menu.rs +++ b/crates/editor/src/mouse_context_menu.rs @@ -2,7 +2,7 @@ use context_menu::ContextMenuItem; use gpui::{geometry::vector::Vector2F, impl_internal_actions, MutableAppContext, ViewContext}; use crate::{ - DisplayPoint, Editor, EditorMode, Event, FindAllReferences, GoToDefinition, GoToTypeDefinition, + DisplayPoint, Editor, EditorMode, FindAllReferences, GoToDefinition, GoToTypeDefinition, Rename, SelectMode, ToggleCodeActions, }; @@ -25,7 +25,6 @@ pub fn deploy_context_menu( ) { if !editor.focused { cx.focus_self(); - cx.emit(Event::Activate); } // Don't show context menu for inline editors diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 8246ea31ed..722e8be997 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1239,7 +1239,7 @@ impl MutableAppContext { let mut view = self .cx .views - .remove(&(params.window_id, params.view_id)) + .remove(&(window_id, view_id)) .ok_or(anyhow!("view not found"))?; let element = view.render(params, self); self.cx.views.insert((window_id, view_id), view); @@ -1781,7 +1781,7 @@ impl MutableAppContext { .cx .views .get(&(window_id, view_id)) - .expect("View passed to visit does not exist") + .unwrap() .keymap_context(self.as_ref()); match self.keystroke_matcher.push_keystroke( @@ -2548,11 +2548,6 @@ impl MutableAppContext { if let Some(blurred_id) = blurred_id { for view_id in blurred_parents.iter().copied() { - // We've reached a common anscestor. Break. - if focused_parents.contains(&view_id) { - break; - } - if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { view.on_focus_out(this, window_id, view_id, blurred_id); this.cx.views.insert((window_id, view_id), view); @@ -2566,12 +2561,9 @@ impl MutableAppContext { if let Some(focused_id) = focused_id { for view_id in focused_parents { - if blurred_parents.contains(&view_id) { - break; - } if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) { view.on_focus_in(this, window_id, view_id, focused_id); - this.cx.views.insert((window_id, focused_id), view); + this.cx.views.insert((window_id, view_id), view); } } diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index bcbeb0ac5f..475923d6ef 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -73,7 +73,6 @@ pub struct ProjectSearchView { regex: bool, query_contains_error: bool, active_match_index: Option, - results_editor_was_focused: bool, } pub struct ProjectSearchBar { @@ -197,12 +196,6 @@ impl View for ProjectSearchView { .0 .insert(self.model.read(cx).project.downgrade(), handle) }); - - if self.results_editor_was_focused && !self.model.read(cx).match_ranges.is_empty() { - self.focus_results_editor(cx); - } else { - cx.focus(&self.query_editor); - } } } @@ -330,14 +323,6 @@ impl Item for ProjectSearchView { .update(cx, |editor, cx| editor.navigate(data, cx)) } - fn should_activate_item_on_event(event: &Self::Event) -> bool { - if let ViewEvent::EditorEvent(editor_event) = event { - Editor::should_activate_item_on_event(editor_event) - } else { - false - } - } - fn should_update_tab_on_event(event: &ViewEvent) -> bool { matches!(event, ViewEvent::UpdateTab) } @@ -385,12 +370,6 @@ impl ProjectSearchView { cx.emit(ViewEvent::EditorEvent(event.clone())) }) .detach(); - cx.observe_focus(&query_editor, |this, _, focused, _| { - if focused { - this.results_editor_was_focused = false; - } - }) - .detach(); let results_editor = cx.add_view(|cx| { let mut editor = Editor::for_multibuffer(excerpts, Some(project), cx); @@ -399,12 +378,7 @@ impl ProjectSearchView { }); cx.observe(&results_editor, |_, _, cx| cx.emit(ViewEvent::UpdateTab)) .detach(); - cx.observe_focus(&results_editor, |this, _, focused, _| { - if focused { - this.results_editor_was_focused = true; - } - }) - .detach(); + cx.subscribe(&results_editor, |this, _, event, cx| { if matches!(event, editor::Event::SelectionsChanged { .. }) { this.update_match_index(cx); @@ -423,7 +397,6 @@ impl ProjectSearchView { regex, query_contains_error: false, active_match_index: None, - results_editor_was_focused: false, }; this.model_changed(false, cx); this @@ -905,6 +878,8 @@ impl ToolbarItemView for ProjectSearchBar { self.subscription = None; self.active_project_search = None; if let Some(search) = active_pane_item.and_then(|i| i.downcast::()) { + let query_editor = search.read(cx).query_editor.clone(); + cx.reparent(query_editor); self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify())); self.active_project_search = Some(search); ToolbarItemLocation::PrimaryLeft { diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 4e5ca37a9d..b54685c458 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -60,7 +60,6 @@ const DEBUG_LINE_HEIGHT: f32 = 5.; pub enum Event { TitleChanged, CloseTerminal, - Activate, Bell, Wakeup, } diff --git a/crates/terminal/src/terminal_view.rs b/crates/terminal/src/terminal_view.rs index 75c9658bd6..a3492c2a94 100644 --- a/crates/terminal/src/terminal_view.rs +++ b/crates/terminal/src/terminal_view.rs @@ -153,10 +153,7 @@ impl View for TerminalView { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.emit(Event::Activate); - cx.defer(|view, cx| { - cx.focus(view.content.handle()); - }); + cx.focus(self.content.handle()); } fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap::Context { @@ -314,10 +311,6 @@ impl Item for TerminalView { fn should_close_item_on_event(event: &Self::Event) -> bool { matches!(event, &Event::CloseTerminal) } - - fn should_activate_item_on_event(event: &Self::Event) -> bool { - matches!(event, &Event::Activate) - } } ///Get's the working directory for the given workspace, respecting the user's settings. diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index f2cfee3ec1..4a96699dee 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -13,9 +13,9 @@ use gpui::{ }, impl_actions, impl_internal_actions, platform::{CursorStyle, NavigationDirection}, - AnyViewHandle, AppContext, AsyncAppContext, Entity, EventContext, ModelHandle, MouseButton, - MouseButtonEvent, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, - ViewHandle, WeakViewHandle, + AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext, + ModelHandle, MouseButton, MouseButtonEvent, MutableAppContext, PromptLevel, Quad, + RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use project::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; @@ -132,7 +132,7 @@ pub fn init(cx: &mut MutableAppContext) { } pub enum Event { - Activate, + Focused, ActivateItem { local: bool }, Remove, RemoveItem, @@ -144,6 +144,7 @@ pub struct Pane { items: Vec>, is_active: bool, active_item_index: usize, + last_focused_view: Option, autoscroll: bool, nav_history: Rc>, toolbar: ViewHandle, @@ -193,6 +194,7 @@ impl Pane { items: Vec::new(), is_active: true, active_item_index: 0, + last_focused_view: None, autoscroll: false, nav_history: Rc::new(RefCell::new(NavHistory { mode: NavigationMode::Normal, @@ -219,10 +221,6 @@ impl Pane { } } - pub fn activate(&self, cx: &mut ViewContext) { - cx.emit(Event::Activate); - } - pub fn go_back( workspace: &mut Workspace, pane: Option>, @@ -287,7 +285,7 @@ impl Pane { mode: NavigationMode, cx: &mut ViewContext, ) -> Task<()> { - workspace.activate_pane(pane.clone(), cx); + cx.focus(pane.clone()); let to_load = pane.update(cx, |pane, cx| { loop { @@ -523,7 +521,7 @@ impl Pane { self.focus_active_item(cx); } if activate_pane { - self.activate(cx); + cx.emit(Event::Focused); } self.autoscroll = true; cx.notify(); @@ -830,7 +828,6 @@ impl Pane { pub fn focus_active_item(&mut self, cx: &mut ViewContext) { if let Some(active_item) = self.active_item() { cx.focus(active_item); - self.activate(cx); } } @@ -1212,11 +1209,20 @@ impl View for Pane { } fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext) { - if cx.handle().id() == focused.id() { - self.focus_active_item(cx); + if cx.is_self_focused() { + if let Some(last_focused_view) = self + .last_focused_view + .as_ref() + .and_then(|handle| handle.upgrade(cx)) + { + cx.focus(last_focused_view); + } else { + self.focus_active_item(cx); + } } else { - self.activate(cx); + self.last_focused_view = Some(focused.downgrade()); } + cx.emit(Event::Focused); } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index c8e804f59b..c4b625c725 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -297,9 +297,6 @@ pub trait Item: View { project: ModelHandle, cx: &mut ViewContext, ) -> Task>; - fn should_activate_item_on_event(_: &Self::Event) -> bool { - false - } fn should_close_item_on_event(_: &Self::Event) -> bool { false } @@ -577,15 +574,6 @@ impl ItemHandle for ViewHandle { return; } - if T::should_activate_item_on_event(event) { - pane.update(cx, |pane, cx| { - if let Some(ix) = pane.index_for_item(&item) { - pane.activate_item(ix, true, true, false, cx); - pane.activate(cx); - } - }); - } - if T::should_update_tab_on_event(event) { pane.update(cx, |_, cx| { cx.emit(pane::Event::ChangeItemTitle); @@ -1438,7 +1426,7 @@ impl Workspace { }) .detach(); self.panes.push(pane.clone()); - self.activate_pane(pane.clone(), cx); + cx.focus(pane.clone()); cx.emit(Event::PaneAdded(pane.clone())); pane } @@ -1533,7 +1521,6 @@ impl Workspace { } }); if let Some((pane, ix)) = result { - self.activate_pane(pane.clone(), cx); pane.update(cx, |pane, cx| pane.activate_item(ix, true, true, false, cx)); true } else { @@ -1544,7 +1531,7 @@ impl Workspace { fn activate_pane_at_index(&mut self, action: &ActivatePane, cx: &mut ViewContext) { let panes = self.center.panes(); if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) { - self.activate_pane(pane, cx); + cx.focus(pane); } else { self.split_pane(self.active_pane.clone(), SplitDirection::Right, cx); } @@ -1560,7 +1547,7 @@ impl Workspace { let next_ix = (ix + 1) % panes.len(); panes[next_ix].clone() }; - self.activate_pane(next_pane, cx); + cx.focus(next_pane); } pub fn activate_previous_pane(&mut self, cx: &mut ViewContext) { @@ -1573,10 +1560,10 @@ impl Workspace { let prev_ix = if ix == 0 { panes.len() - 1 } else { ix - 1 }; panes[prev_ix].clone() }; - self.activate_pane(prev_pane, cx); + cx.focus(prev_pane); } - fn activate_pane(&mut self, pane: ViewHandle, cx: &mut ViewContext) { + fn handle_pane_focused(&mut self, pane: ViewHandle, cx: &mut ViewContext) { if self.active_pane != pane { self.active_pane .update(cx, |pane, cx| pane.set_active(false, cx)); @@ -1587,7 +1574,6 @@ impl Workspace { status_bar.set_active_pane(&self.active_pane, cx); }); self.active_item_path_changed(cx); - cx.focus(&self.active_pane); cx.notify(); } @@ -1614,8 +1600,8 @@ impl Workspace { pane::Event::Remove => { self.remove_pane(pane, cx); } - pane::Event::Activate => { - self.activate_pane(pane, cx); + pane::Event::Focused => { + self.handle_pane_focused(pane, cx); } pane::Event::ActivateItem { local } => { if *local { @@ -1648,7 +1634,6 @@ impl Workspace { ) -> Option> { pane.read(cx).active_item().map(|item| { let new_pane = self.add_pane(cx); - self.activate_pane(new_pane.clone(), cx); if let Some(clone) = item.clone_on_split(cx.as_mut()) { Pane::add_item(self, new_pane.clone(), clone, true, true, cx); } @@ -1661,7 +1646,7 @@ impl Workspace { fn remove_pane(&mut self, pane: ViewHandle, cx: &mut ViewContext) { if self.center.remove(&pane).unwrap() { self.panes.retain(|p| p != &pane); - self.activate_pane(self.panes.last().unwrap().clone(), cx); + cx.focus(self.panes.last().unwrap().clone()); self.unfollow(&pane, cx); self.last_leaders_by_pane.remove(&pane.downgrade()); cx.notify(); @@ -2490,7 +2475,10 @@ impl View for Workspace { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.active_pane); + if cx.is_self_focused() { + println!("Active Pane Focused"); + cx.focus(&self.active_pane); + } } } @@ -3110,7 +3098,7 @@ mod tests { // once for project entry 0, and once for project entry 2. After those two // prompts, the task should complete. let close = workspace.update(cx, |workspace, cx| { - workspace.activate_pane(left_pane.clone(), cx); + cx.focus(left_pane.clone()); Pane::close_items(workspace, left_pane.clone(), cx, |_| true) }); From f5a6a112c8318f8c766d2a211d5954ae86787411 Mon Sep 17 00:00:00 2001 From: K Simmons Date: Tue, 9 Aug 2022 15:51:17 -0700 Subject: [PATCH 15/27] Address picker issues --- crates/command_palette/src/command_palette.rs | 4 +++- crates/file_finder/src/file_finder.rs | 4 +++- crates/outline/src/outline.rs | 4 +++- crates/picker/src/picker.rs | 4 +++- crates/project_symbols/src/project_symbols.rs | 4 +++- crates/search/src/buffer_search.rs | 4 +++- crates/terminal/src/terminal_view.rs | 4 +++- crates/theme_selector/src/theme_selector.rs | 4 +++- crates/workspace/src/workspace.rs | 1 - 9 files changed, 24 insertions(+), 9 deletions(-) diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 5d6f6e14a8..6bef826e5b 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -134,7 +134,9 @@ impl View for CommandPalette { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.picker); + if cx.is_self_focused() { + cx.focus(&self.picker); + } } } diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index aeec799015..dbdc3ec329 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -54,7 +54,9 @@ impl View for FileFinder { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.picker); + if cx.is_self_focused() { + cx.focus(&self.picker); + } } } diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 8a8c559cf3..414a48ed10 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -53,7 +53,9 @@ impl View for OutlineView { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.picker); + if cx.is_self_focused() { + cx.focus(&self.picker); + } } } diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index d3f729ba83..19a01fcbad 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -119,7 +119,9 @@ impl View for Picker { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.query_editor); + if cx.is_self_focused() { + cx.focus(&self.query_editor); + } } } diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 755bca20d6..c310cfb043 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -52,7 +52,9 @@ impl View for ProjectSymbolsView { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.picker); + if cx.is_self_focused() { + cx.focus(&self.picker); + } } } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index d9a048b604..bc6f37202d 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -81,7 +81,9 @@ impl View for BufferSearchBar { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.query_editor); + if cx.is_self_focused() { + cx.focus(&self.query_editor); + } } fn render(&mut self, cx: &mut RenderContext) -> ElementBox { diff --git a/crates/terminal/src/terminal_view.rs b/crates/terminal/src/terminal_view.rs index a3492c2a94..1b4544a3dc 100644 --- a/crates/terminal/src/terminal_view.rs +++ b/crates/terminal/src/terminal_view.rs @@ -153,7 +153,9 @@ impl View for TerminalView { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(self.content.handle()); + if cx.is_self_focused() { + cx.focus(self.content.handle()); + } } fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap::Context { diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index d1e81b11a7..dcda882168 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -250,6 +250,8 @@ impl View for ThemeSelector { } fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - cx.focus(&self.picker); + if cx.is_self_focused() { + cx.focus(&self.picker); + } } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index c4b625c725..7043c3a683 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -2476,7 +2476,6 @@ impl View for Workspace { fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { if cx.is_self_focused() { - println!("Active Pane Focused"); cx.focus(&self.active_pane); } } From 3bdf05c0cdc389796fa4d22c1b05fc6c0f51f2dc Mon Sep 17 00:00:00 2001 From: K Simmons Date: Tue, 9 Aug 2022 16:11:01 -0700 Subject: [PATCH 16/27] fix up command palette --- crates/command_palette/src/command_palette.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 6bef826e5b..46327cf1bc 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -86,8 +86,8 @@ impl CommandPalette { let focused_view_id = cx.focused_view_id(window_id).unwrap_or(workspace.id()); cx.as_mut().defer(move |cx| { + let this = cx.add_view(workspace.clone(), |cx| Self::new(focused_view_id, cx)); workspace.update(cx, |workspace, cx| { - let this = cx.add_view(|cx| Self::new(focused_view_id, cx)); workspace.toggle_modal(cx, |_, cx| { cx.subscribe(&this, Self::on_event).detach(); this From 3460a24da703749f5eb5a5a6087e81cb0b1b61e6 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 10 Aug 2022 09:11:06 -0700 Subject: [PATCH 17/27] Changed CI and default.json to run clippy --- .github/workflows/ci.yml | 6 +++++- assets/settings/default.json | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e596fad9bd..ac20fdc3ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: run: | rustup set profile minimal rustup update stable + rustup component add clippy rustup target add wasm32-wasi - name: Install Node @@ -39,7 +40,10 @@ jobs: uses: actions/checkout@v2 with: clean: false - + + - name: Run clippy + run: cargo clippy + - name: Run tests run: cargo test --workspace --no-fail-fast diff --git a/assets/settings/default.json b/assets/settings/default.json index 33eb64e201..9cf915d1a6 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -145,5 +145,22 @@ "tab_size": 2 } }, - "lsp": {} + //LSP Specific settings. + "lsp": { + //Specify the LSP name as a key here. + //As of 8/10/22, supported LSPs are: + //pyright + //gopls + //rust-analyzer + //typescript-language-server + //vscode-json-languageserver + "rust_analyzer": { + //These initialization options are merged into Zed's defaults + "initialization_options": { + "checkOnSave": { + "command": "clippy" + } + } + } + } } From ee0e6a010939eb0f60d57cff22346093fc3d6535 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 10 Aug 2022 15:07:02 -0700 Subject: [PATCH 18/27] Added env toml so readme db instructions are correct --- .gitignore | 1 - crates/collab/{.env.template.toml => .env.toml} | 0 2 files changed, 1 deletion(-) rename crates/collab/{.env.template.toml => .env.toml} (100%) diff --git a/.gitignore b/.gitignore index d3d0634a40..fcebdc84a2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ /plugins/bin /script/node_modules /styles/node_modules -/crates/collab/.env.toml /crates/collab/static/styles.css /vendor/bin /assets/themes/*.json diff --git a/crates/collab/.env.template.toml b/crates/collab/.env.toml similarity index 100% rename from crates/collab/.env.template.toml rename to crates/collab/.env.toml From d68f227ec4f2fd8ee87428cc6b085babbf16b7a5 Mon Sep 17 00:00:00 2001 From: K Simmons Date: Wed, 10 Aug 2022 16:26:53 -0700 Subject: [PATCH 19/27] Fix failing tests --- crates/collab/src/integration_tests.rs | 32 ++++++++++++++++++++++---- crates/gpui/src/app.rs | 3 ++- crates/workspace/src/workspace.rs | 13 +++++++++-- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 4118e5963c..02b8d2f81e 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -4246,7 +4246,10 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T // Clients A and B follow each other in split panes workspace_a.update(cx_a, |workspace, cx| { workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx); - assert_ne!(*workspace.active_pane(), pane_a1); + let pane_a1 = pane_a1.clone(); + cx.defer(move |workspace, _| { + assert_ne!(*workspace.active_pane(), pane_a1); + }); }); workspace_a .update(cx_a, |workspace, cx| { @@ -4259,7 +4262,10 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T .unwrap(); workspace_b.update(cx_b, |workspace, cx| { workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx); - assert_ne!(*workspace.active_pane(), pane_b1); + let pane_b1 = pane_b1.clone(); + cx.defer(move |workspace, _| { + assert_ne!(*workspace.active_pane(), pane_b1); + }); }); workspace_b .update(cx_b, |workspace, cx| { @@ -4271,17 +4277,26 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T .await .unwrap(); + workspace_a.update(cx_a, |workspace, cx| { + workspace.activate_next_pane(cx); + }); + // Wait for focus effects to be fully flushed + workspace_a.update(cx_a, |workspace, _| { + assert_eq!(*workspace.active_pane(), pane_a1); + }); + workspace_a .update(cx_a, |workspace, cx| { - workspace.activate_next_pane(cx); - assert_eq!(*workspace.active_pane(), pane_a1); workspace.open_path((worktree_id, "3.txt"), true, cx) }) .await .unwrap(); + workspace_b.update(cx_b, |workspace, cx| { + workspace.activate_next_pane(cx); + }); + workspace_b .update(cx_b, |workspace, cx| { - workspace.activate_next_pane(cx); assert_eq!(*workspace.active_pane(), pane_b1); workspace.open_path((worktree_id, "4.txt"), true, cx) }) @@ -4311,17 +4326,24 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T Some((worktree_id, "3.txt").into()) ); workspace.activate_next_pane(cx); + }); + + workspace_a.update(cx_a, |workspace, cx| { assert_eq!( workspace.active_item(cx).unwrap().project_path(cx), Some((worktree_id, "4.txt").into()) ); }); + workspace_b.update(cx_b, |workspace, cx| { assert_eq!( workspace.active_item(cx).unwrap().project_path(cx), Some((worktree_id, "4.txt").into()) ); workspace.activate_next_pane(cx); + }); + + workspace_b.update(cx_b, |workspace, cx| { assert_eq!( workspace.active_item(cx).unwrap().project_path(cx), Some((worktree_id, "3.txt").into()) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 722e8be997..c028c5de73 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -7089,7 +7089,7 @@ mod tests { let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1); let view_2 = cx.add_view(&view_1, |_| view_2); - cx.add_view(&view_2, |cx| { + let _view_3 = cx.add_view(&view_2, |cx| { cx.focus_self(); view_3 }); @@ -7135,6 +7135,7 @@ mod tests { assert_eq!(&*actions.borrow(), &["2 a"]); actions.borrow_mut().clear(); + cx.dispatch_keystroke(window_id, &Keystroke::parse("b").unwrap()); assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 7043c3a683..5f188ef910 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1,3 +1,7 @@ +/// NOTE: Focus only 'takes' after an update has flushed_effects. Pane sends an event in on_focus_in +/// which the workspace uses to change the activated pane. +/// This may cause issues when you're trying to write tests that use workspace focus to add items at +/// specific locations. pub mod pane; pub mod pane_group; pub mod sidebar; @@ -3088,16 +3092,21 @@ mod tests { workspace .split_pane(left_pane.clone(), SplitDirection::Right, cx) .unwrap(); - workspace.add_item(Box::new(cx.add_view(|_| item_3_4.clone())), cx); left_pane }); + //Need to cause an effect flush in order to respect new focus + workspace.update(cx, |workspace, cx| { + workspace.add_item(Box::new(cx.add_view(|_| item_3_4.clone())), cx); + cx.focus(left_pane.clone()); + }); + // When closing all of the items in the left pane, we should be prompted twice: // once for project entry 0, and once for project entry 2. After those two // prompts, the task should complete. + let close = workspace.update(cx, |workspace, cx| { - cx.focus(left_pane.clone()); Pane::close_items(workspace, left_pane.clone(), cx, |_| true) }); From 4d38dcfc54ecc634ecec2ee5623b0dd66f871f3e Mon Sep 17 00:00:00 2001 From: K Simmons Date: Wed, 10 Aug 2022 16:27:45 -0700 Subject: [PATCH 20/27] Fix workspace --- crates/workspace/src/workspace.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 5f188ef910..0d4ced4293 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1,5 +1,6 @@ /// NOTE: Focus only 'takes' after an update has flushed_effects. Pane sends an event in on_focus_in /// which the workspace uses to change the activated pane. +/// /// This may cause issues when you're trying to write tests that use workspace focus to add items at /// specific locations. pub mod pane; From e7540d2833cd436691aed7dad8c71090e02a3a7f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 10 Aug 2022 09:11:06 -0700 Subject: [PATCH 21/27] Changed CI and default.json to run clippy --- .github/workflows/ci.yml | 6 +++++- assets/settings/default.json | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e596fad9bd..e54324c8c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: run: | rustup set profile minimal rustup update stable + rustup component add clippy rustup target add wasm32-wasi - name: Install Node @@ -39,7 +40,10 @@ jobs: uses: actions/checkout@v2 with: clean: false - + + - name: Run clippy + run: cargo clippy --workspace -- -D warnings + - name: Run tests run: cargo test --workspace --no-fail-fast diff --git a/assets/settings/default.json b/assets/settings/default.json index 33eb64e201..9cf915d1a6 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -145,5 +145,22 @@ "tab_size": 2 } }, - "lsp": {} + //LSP Specific settings. + "lsp": { + //Specify the LSP name as a key here. + //As of 8/10/22, supported LSPs are: + //pyright + //gopls + //rust-analyzer + //typescript-language-server + //vscode-json-languageserver + "rust_analyzer": { + //These initialization options are merged into Zed's defaults + "initialization_options": { + "checkOnSave": { + "command": "clippy" + } + } + } + } } From 8ba2f771485dec94fac03484b1b4a374ae88bc40 Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Wed, 10 Aug 2022 17:39:24 -0400 Subject: [PATCH 22/27] One big cleanup pass of clippy lints Co-authored-by: Mikayla --- .cargo/config.toml | 6 + .../src/activity_indicator.rs | 8 +- crates/auto_update/src/auto_update.rs | 5 +- crates/chat_panel/src/chat_panel.rs | 4 +- crates/client/src/channel.rs | 14 +- crates/client/src/client.rs | 30 ++- crates/client/src/http.rs | 4 +- crates/client/src/test.rs | 9 +- crates/client/src/user.rs | 2 +- crates/clock/src/clock.rs | 6 +- crates/collab/src/api.rs | 2 +- crates/collab/src/auth.rs | 4 +- crates/collab/src/db.rs | 33 ++- crates/collab/src/integration_tests.rs | 194 +++++++------- crates/collab/src/rpc.rs | 6 +- crates/collab/src/rpc/store.rs | 22 +- crates/command_palette/src/command_palette.rs | 4 +- crates/contacts_panel/src/contact_finder.rs | 4 +- crates/contacts_panel/src/contacts_panel.rs | 39 ++- crates/diagnostics/src/diagnostics.rs | 22 +- crates/editor/src/display_map.rs | 37 ++- crates/editor/src/display_map/block_map.rs | 45 ++-- crates/editor/src/display_map/fold_map.rs | 49 ++-- crates/editor/src/display_map/tab_map.rs | 10 +- crates/editor/src/display_map/wrap_map.rs | 14 +- crates/editor/src/editor.rs | 253 +++++++++--------- crates/editor/src/element.rs | 33 ++- crates/editor/src/hover_popover.rs | 4 +- crates/editor/src/items.rs | 37 +-- crates/editor/src/link_go_to_definition.rs | 12 +- crates/editor/src/multi_buffer.rs | 126 ++++----- crates/editor/src/multi_buffer/anchor.rs | 8 +- crates/editor/src/selections_collection.rs | 17 +- crates/file_finder/src/file_finder.rs | 4 +- crates/fsevent/examples/events.rs | 2 +- crates/fsevent/src/fsevent.rs | 8 +- crates/fuzzy/src/char_bag.rs | 12 +- crates/fuzzy/src/fuzzy.rs | 34 +-- crates/gpui/build.rs | 2 +- crates/gpui/examples/text.rs | 10 +- crates/gpui/src/app.rs | 64 ++--- crates/gpui/src/elements.rs | 6 +- crates/gpui/src/elements/empty.rs | 3 +- crates/gpui/src/elements/expanded.rs | 4 +- crates/gpui/src/elements/image.rs | 4 +- crates/gpui/src/elements/list.rs | 23 +- .../gpui/src/elements/mouse_event_handler.rs | 2 +- crates/gpui/src/elements/overlay.rs | 2 +- crates/gpui/src/elements/stack.rs | 5 +- crates/gpui/src/elements/text.rs | 2 +- crates/gpui/src/elements/uniform_list.rs | 23 +- crates/gpui/src/executor.rs | 8 +- crates/gpui/src/font_cache.rs | 6 +- crates/gpui/src/fonts.rs | 3 +- crates/gpui/src/geometry.rs | 11 +- crates/gpui/src/keymap.rs | 27 +- crates/gpui/src/platform.rs | 2 +- crates/gpui/src/platform/mac/event.rs | 2 +- crates/gpui/src/platform/mac/fonts.rs | 14 +- crates/gpui/src/platform/mac/platform.rs | 8 +- crates/gpui/src/platform/mac/renderer.rs | 45 ++-- crates/gpui/src/platform/mac/window.rs | 41 +-- crates/gpui/src/platform/test.rs | 2 +- crates/gpui/src/presenter.rs | 32 +-- crates/gpui/src/scene/mouse_region.rs | 2 + crates/gpui/src/text_layout.rs | 28 +- crates/gpui_macros/src/gpui_macros.rs | 2 +- crates/language/src/buffer.rs | 102 ++++--- crates/language/src/diagnostic_set.rs | 27 +- crates/language/src/highlight_map.rs | 5 +- crates/language/src/language.rs | 7 +- crates/language/src/proto.rs | 12 +- crates/language/src/tests.rs | 76 +++--- crates/lsp/src/lsp.rs | 16 +- crates/outline/src/outline.rs | 8 +- crates/plugin/src/lib.rs | 2 +- crates/plugin_runtime/build.rs | 7 +- crates/plugin_runtime/src/lib.rs | 4 +- crates/plugin_runtime/src/plugin.rs | 16 +- crates/project/src/fs.rs | 2 +- crates/project/src/lsp_command.rs | 10 +- crates/project/src/project.rs | 92 +++---- crates/project/src/project_tests.rs | 32 +-- crates/project/src/search.rs | 2 +- crates/project/src/worktree.rs | 62 ++--- crates/project_panel/src/project_panel.rs | 59 ++-- crates/rpc/src/conn.rs | 7 +- crates/rpc/src/peer.rs | 3 +- crates/rpc/src/proto.rs | 15 +- crates/search/src/buffer_search.rs | 27 +- crates/search/src/project_search.rs | 14 +- crates/search/src/search.rs | 8 +- crates/settings/src/keymap_file.rs | 52 ++-- crates/settings/src/settings.rs | 13 +- crates/snippet/src/snippet.rs | 8 +- crates/sum_tree/src/cursor.rs | 8 +- crates/sum_tree/src/sum_tree.rs | 10 +- crates/sum_tree/src/tree_map.rs | 4 +- crates/terminal/src/connected_el.rs | 38 +-- crates/terminal/src/connected_view.rs | 6 +- crates/terminal/src/mappings/colors.rs | 2 +- crates/terminal/src/mappings/keys.rs | 4 +- crates/terminal/src/modal.rs | 4 +- crates/terminal/src/terminal.rs | 47 ++-- crates/terminal/src/terminal_view.rs | 6 +- crates/text/src/anchor.rs | 20 +- crates/text/src/locator.rs | 4 + crates/text/src/operation_queue.rs | 10 + crates/text/src/patch.rs | 4 +- crates/text/src/point.rs | 2 +- crates/text/src/rope.rs | 10 +- crates/text/src/tests.rs | 12 +- crates/text/src/text.rs | 51 ++-- crates/theme_selector/src/theme_selector.rs | 2 +- crates/util/src/lib.rs | 4 +- crates/util/src/test/marked_text.rs | 10 +- crates/vim/src/motion.rs | 11 +- crates/vim/src/normal.rs | 2 +- crates/vim/src/normal/change.rs | 4 +- crates/vim/src/normal/delete.rs | 2 +- crates/vim/src/state.rs | 7 +- crates/vim/src/vim_test_context.rs | 2 +- crates/vim/src/visual.rs | 8 +- crates/workspace/src/pane.rs | 32 ++- crates/workspace/src/pane_group.rs | 2 +- crates/workspace/src/sidebar.rs | 11 +- crates/workspace/src/status_bar.rs | 6 +- crates/workspace/src/toolbar.rs | 13 +- crates/workspace/src/waiting_room.rs | 2 +- crates/workspace/src/workspace.rs | 65 +++-- crates/zed/src/feedback.rs | 3 +- crates/zed/src/languages/c.rs | 2 +- crates/zed/src/languages/go.rs | 6 +- crates/zed/src/languages/python.rs | 2 +- crates/zed/src/languages/typescript.rs | 2 +- crates/zed/src/main.rs | 18 +- crates/zed/src/settings_file.rs | 8 +- crates/zed/src/zed.rs | 34 +-- 138 files changed, 1328 insertions(+), 1366 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000000..4dddb54d24 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[target.'cfg(all())'] +rustflags = [ + "-Aclippy::reversed_empty_ranges", + "-Aclippy::missing_safety_doc", + "-Aclippy::let_unit_value", +] diff --git a/crates/activity_indicator/src/activity_indicator.rs b/crates/activity_indicator/src/activity_indicator.rs index 02ad100df8..7d4d01e8a1 100644 --- a/crates/activity_indicator/src/activity_indicator.rs +++ b/crates/activity_indicator/src/activity_indicator.rs @@ -15,9 +15,9 @@ use workspace::{ItemHandle, StatusItemView, Workspace}; actions!(lsp_status, [ShowErrorMessage]); -const DOWNLOAD_ICON: &'static str = "icons/download_12.svg"; -const WARNING_ICON: &'static str = "icons/triangle_exclamation_12.svg"; -const DONE_ICON: &'static str = "icons/circle_check_12.svg"; +const DOWNLOAD_ICON: &str = "icons/download_12.svg"; +const WARNING_ICON: &str = "icons/triangle_exclamation_12.svg"; +const DONE_ICON: &str = "icons/circle_check_12.svg"; pub enum Event { ShowError { lsp_name: Arc, error: String }, @@ -76,7 +76,7 @@ impl ActivityIndicator { cx.subscribe(&this, move |workspace, _, event, cx| match event { Event::ShowError { lsp_name, error } => { if let Some(buffer) = project - .update(cx, |project, cx| project.create_buffer(&error, None, cx)) + .update(cx, |project, cx| project.create_buffer(error, None, cx)) .log_err() { buffer.update(cx, |buffer, cx| { diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index 6e4f171f60..d32835547c 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -13,8 +13,7 @@ use std::{env, ffi::OsString, path::PathBuf, sync::Arc, time::Duration}; use update_notification::UpdateNotification; use workspace::Workspace; -const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &'static str = - "auto-updater-should-show-updated-notification"; +const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification"; const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60); lazy_static! { @@ -61,7 +60,7 @@ pub fn init( server_url: String, cx: &mut MutableAppContext, ) { - if let Some(version) = ZED_APP_VERSION.clone().or(cx.platform().app_version().ok()) { + if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) { let auto_updater = cx.add_model(|cx| { let updater = AutoUpdater::new(version, db.clone(), http_client, server_url.clone()); updater.start_polling(cx).detach(); diff --git a/crates/chat_panel/src/chat_panel.rs b/crates/chat_panel/src/chat_panel.rs index 7f947fef16..3ff7062f40 100644 --- a/crates/chat_panel/src/chat_panel.rs +++ b/crates/chat_panel/src/chat_panel.rs @@ -70,7 +70,7 @@ impl ChatPanel { let theme = &cx.global::().theme.chat_panel.channel_select; SelectStyle { header: theme.header.container, - menu: theme.menu.clone(), + menu: theme.menu, } }) }); @@ -91,7 +91,7 @@ impl ChatPanel { let _observe_status = cx.spawn_weak(|this, mut cx| { let mut status = rpc.status(); async move { - while let Some(_) = status.recv().await { + while (status.recv().await).is_some() { if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |_, cx| cx.notify()); } else { diff --git a/crates/client/src/channel.rs b/crates/client/src/channel.rs index 0d44c67191..a88f872d11 100644 --- a/crates/client/src/channel.rs +++ b/crates/client/src/channel.rs @@ -145,7 +145,7 @@ impl ChannelList { } pub fn available_channels(&self) -> Option<&[ChannelDetails]> { - self.available_channels.as_ref().map(Vec::as_slice) + self.available_channels.as_deref() } pub fn get_channel( @@ -601,8 +601,8 @@ mod tests { let user_id = 5; let http_client = FakeHttpClient::with_404_response(); - let mut client = Client::new(http_client.clone()); - let server = FakeServer::for_client(user_id, &mut client, &cx).await; + let client = Client::new(http_client.clone()); + let server = FakeServer::for_client(user_id, &client, cx).await; Channel::init(&client); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx)); @@ -623,7 +623,7 @@ mod tests { }, ) .await; - channel_list.next_notification(&cx).await; + channel_list.next_notification(cx).await; channel_list.read_with(cx, |list, _| { assert_eq!( list.available_channels().unwrap(), @@ -701,7 +701,7 @@ mod tests { .await; assert_eq!( - channel.next_event(&cx).await, + channel.next_event(cx).await, ChannelEvent::MessagesUpdated { old_range: 0..0, new_count: 2, @@ -749,7 +749,7 @@ mod tests { .await; assert_eq!( - channel.next_event(&cx).await, + channel.next_event(cx).await, ChannelEvent::MessagesUpdated { old_range: 2..2, new_count: 1, @@ -798,7 +798,7 @@ mod tests { .await; assert_eq!( - channel.next_event(&cx).await, + channel.next_event(cx).await, ChannelEvent::MessagesUpdated { old_range: 0..0, new_count: 2, diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index af084dc88d..e328108a52 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -41,13 +41,13 @@ pub use user::*; lazy_static! { pub static ref ZED_SERVER_URL: String = - std::env::var("ZED_SERVER_URL").unwrap_or("https://zed.dev".to_string()); + std::env::var("ZED_SERVER_URL").unwrap_or_else(|_| "https://zed.dev".to_string()); pub static ref IMPERSONATE_LOGIN: Option = std::env::var("ZED_IMPERSONATE") .ok() .and_then(|s| if s.is_empty() { None } else { Some(s) }); } -pub const ZED_SECRET_CLIENT_TOKEN: &'static str = "618033988749894"; +pub const ZED_SECRET_CLIENT_TOKEN: &str = "618033988749894"; actions!(client, [Authenticate]); @@ -65,10 +65,13 @@ pub struct Client { http: Arc, state: RwLock, + #[allow(clippy::type_complexity)] #[cfg(any(test, feature = "test-support"))] authenticate: RwLock< Option Task>>>, >, + + #[allow(clippy::type_complexity)] #[cfg(any(test, feature = "test-support"))] establish_connection: RwLock< Option< @@ -149,6 +152,7 @@ struct ClientState { entities_by_type_and_remote_id: HashMap<(TypeId, u64), AnyWeakEntityHandle>, models_by_message_type: HashMap, entity_types_by_message_type: HashMap, + #[allow(clippy::type_complexity)] message_handlers: HashMap< TypeId, Arc< @@ -596,7 +600,7 @@ impl Client { let mut status_rx = self.status(); let _ = status_rx.next().await; futures::select_biased! { - authenticate = self.authenticate(&cx).fuse() => { + authenticate = self.authenticate(cx).fuse() => { match authenticate { Ok(creds) => credentials = Some(creds), Err(err) => { @@ -819,7 +823,7 @@ impl Client { .get("Location") .ok_or_else(|| anyhow!("missing location header in /rpc response"))? .to_str() - .map_err(|error| EstablishConnectionError::other(error))? + .map_err(EstablishConnectionError::other)? .to_string(); } // Until we switch the zed.dev domain to point to the new Next.js app, there @@ -1051,7 +1055,7 @@ fn write_credentials_to_keychain(credentials: &Credentials, cx: &AsyncAppContext ) } -const WORKTREE_URL_PREFIX: &'static str = "zed://worktrees/"; +const WORKTREE_URL_PREFIX: &str = "zed://worktrees/"; pub fn encode_worktree_url(id: u64, access_token: &str) -> String { format!("{}{}/{}", WORKTREE_URL_PREFIX, id, access_token) @@ -1081,8 +1085,8 @@ mod tests { cx.foreground().forbid_parking(); let user_id = 5; - let mut client = Client::new(FakeHttpClient::with_404_response()); - let server = FakeServer::for_client(user_id, &mut client, &cx).await; + let client = Client::new(FakeHttpClient::with_404_response()); + let server = FakeServer::for_client(user_id, &client, cx).await; let mut status = client.status(); assert!(matches!( status.next().await, @@ -1169,8 +1173,8 @@ mod tests { cx.foreground().forbid_parking(); let user_id = 5; - let mut client = Client::new(FakeHttpClient::with_404_response()); - let server = FakeServer::for_client(user_id, &mut client, &cx).await; + let client = Client::new(FakeHttpClient::with_404_response()); + let server = FakeServer::for_client(user_id, &client, cx).await; let (done_tx1, mut done_rx1) = smol::channel::unbounded(); let (done_tx2, mut done_rx2) = smol::channel::unbounded(); @@ -1215,8 +1219,8 @@ mod tests { cx.foreground().forbid_parking(); let user_id = 5; - let mut client = Client::new(FakeHttpClient::with_404_response()); - let server = FakeServer::for_client(user_id, &mut client, &cx).await; + let client = Client::new(FakeHttpClient::with_404_response()); + let server = FakeServer::for_client(user_id, &client, cx).await; let model = cx.add_model(|_| Model::default()); let (done_tx1, _done_rx1) = smol::channel::unbounded(); @@ -1243,8 +1247,8 @@ mod tests { cx.foreground().forbid_parking(); let user_id = 5; - let mut client = Client::new(FakeHttpClient::with_404_response()); - let server = FakeServer::for_client(user_id, &mut client, &cx).await; + let client = Client::new(FakeHttpClient::with_404_response()); + let server = FakeServer::for_client(user_id, &client, cx).await; let model = cx.add_model(|_| Model::default()); let (done_tx, mut done_rx) = smol::channel::unbounded(); diff --git a/crates/client/src/http.rs b/crates/client/src/http.rs index 7f4cafa17d..5139bb8d03 100644 --- a/crates/client/src/http.rs +++ b/crates/client/src/http.rs @@ -16,7 +16,7 @@ pub type Request = isahc::Request; pub type Response = isahc::Response; pub trait HttpClient: Send + Sync { - fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result>; + fn send(&self, req: Request) -> BoxFuture>; fn get<'a>( &'a self, @@ -45,7 +45,7 @@ pub fn client() -> Arc { } impl HttpClient for isahc::HttpClient { - fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result> { + fn send(&self, req: Request) -> BoxFuture> { Box::pin(async move { self.send_async(req).await }) } } diff --git a/crates/client/src/test.rs b/crates/client/src/test.rs index 92183e2566..c634978a57 100644 --- a/crates/client/src/test.rs +++ b/crates/client/src/test.rs @@ -56,7 +56,7 @@ impl FakeServer { } }) .override_establish_connection({ - let peer = Arc::downgrade(&server.peer).clone(); + let peer = Arc::downgrade(&server.peer); let state = Arc::downgrade(&server.state); move |credentials, cx| { let peer = peer.clone(); @@ -123,6 +123,7 @@ impl FakeServer { self.peer.send(self.connection_id(), message).unwrap(); } + #[allow(clippy::await_holding_lock)] pub async fn receive(&self) -> Result> { self.executor.start_waiting(); let message = self @@ -194,7 +195,7 @@ pub struct FakeHttpClient { } impl FakeHttpClient { - pub fn new(handler: F) -> Arc + pub fn create(handler: F) -> Arc where Fut: 'static + Send + Future>, F: 'static + Send + Sync + Fn(Request) -> Fut, @@ -205,7 +206,7 @@ impl FakeHttpClient { } pub fn with_404_response() -> Arc { - Self::new(|_| async move { + Self::create(|_| async move { Ok(isahc::Response::builder() .status(404) .body(Default::default()) @@ -221,7 +222,7 @@ impl fmt::Debug for FakeHttpClient { } impl HttpClient for FakeHttpClient { - fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result> { + fn send(&self, req: Request) -> BoxFuture> { let future = (self.handler)(req); Box::pin(async move { future.await.map(Into::into) }) } diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index 5e56b53b87..149d22e77a 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -17,7 +17,7 @@ pub struct User { impl PartialOrd for User { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } diff --git a/crates/clock/src/clock.rs b/crates/clock/src/clock.rs index e122a8b96a..89f8fda3ee 100644 --- a/crates/clock/src/clock.rs +++ b/crates/clock/src/clock.rs @@ -54,14 +54,14 @@ impl<'a> Add<&'a Self> for Local { type Output = Local; fn add(self, other: &'a Self) -> Self::Output { - cmp::max(&self, other).clone() + *cmp::max(&self, other) } } impl<'a> AddAssign<&'a Local> for Local { fn add_assign(&mut self, other: &Self) { if *self < *other { - *self = other.clone(); + *self = *other; } } } @@ -177,7 +177,7 @@ impl Global { false } - pub fn iter<'a>(&'a self) -> impl 'a + Iterator { + pub fn iter(&self) -> impl Iterator + '_ { self.0.iter().enumerate().map(|(replica_id, seq)| Local { replica_id: replica_id as ReplicaId, value: *seq, diff --git a/crates/collab/src/api.rs b/crates/collab/src/api.rs index f3209cab73..eafeae0864 100644 --- a/crates/collab/src/api.rs +++ b/crates/collab/src/api.rs @@ -394,7 +394,7 @@ async fn create_access_token( } else { return Err(Error::Http( StatusCode::UNAUTHORIZED, - format!("you do not have permission to impersonate other users"), + "you do not have permission to impersonate other users".to_string(), )); } } diff --git a/crates/collab/src/auth.rs b/crates/collab/src/auth.rs index b61043109b..a1fac6a2b6 100644 --- a/crates/collab/src/auth.rs +++ b/crates/collab/src/auth.rs @@ -44,7 +44,7 @@ pub async fn validate_header(mut req: Request, next: Next) -> impl Into let state = req.extensions().get::>().unwrap(); let mut credentials_valid = false; for password_hash in state.db.get_access_token_hashes(user_id).await? { - if verify_access_token(&access_token, &password_hash)? { + if verify_access_token(access_token, &password_hash)? { credentials_valid = true; break; } @@ -100,7 +100,7 @@ pub fn encrypt_access_token(access_token: &str, public_key: String) -> Result(&'a self) -> Option<&'a tests::FakeDb>; + fn as_fake(&self) -> Option<&tests::FakeDb>; } pub struct PostgresDb { @@ -165,7 +165,7 @@ impl PostgresDb { pub async fn new(url: &str, max_connections: u32) -> Result { let pool = DbOptions::new() .max_connections(max_connections) - .connect(&url) + .connect(url) .await .context("failed to connect to postgres database")?; Ok(Self { pool }) @@ -568,7 +568,7 @@ impl Db for PostgresDb { for count in counts { extension_counts .entry(count.worktree_id as u64) - .or_insert(HashMap::default()) + .or_insert_with(HashMap::default) .insert(count.extension, count.count as usize); } Ok(extension_counts) @@ -863,20 +863,18 @@ impl Db for PostgresDb { should_notify, }); } + } else if accepted { + contacts.push(Contact::Accepted { + user_id: user_id_a, + should_notify: should_notify && !a_to_b, + }); + } else if a_to_b { + contacts.push(Contact::Incoming { + user_id: user_id_a, + should_notify, + }); } else { - if accepted { - contacts.push(Contact::Accepted { - user_id: user_id_a, - should_notify: should_notify && !a_to_b, - }); - } else if a_to_b { - contacts.push(Contact::Incoming { - user_id: user_id_a, - should_notify, - }); - } else { - contacts.push(Contact::Outgoing { user_id: user_id_a }); - } + contacts.push(Contact::Outgoing { user_id: user_id_a }); } } @@ -1331,7 +1329,7 @@ macro_rules! id_type { } #[allow(unused)] - pub fn to_proto(&self) -> u64 { + pub fn to_proto(self) -> u64 { self.0 as u64 } } @@ -2408,6 +2406,7 @@ pub mod tests { } impl TestDb { + #[allow(clippy::await_holding_lock)] pub async fn postgres() -> Self { lazy_static! { static ref LOCK: Mutex<()> = Mutex::new(()); diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 02b8d2f81e..2327aa6aad 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -157,7 +157,7 @@ async fn test_share_project( // Edit the buffer as client B and see that edit as client A. editor_b.update(cx_b, |editor, cx| editor.handle_input("ok, ", cx)); buffer_a - .condition(&cx_a, |buffer, _| buffer.text() == "ok, b-contents") + .condition(cx_a, |buffer, _| buffer.text() == "ok, b-contents") .await; // TODO @@ -482,7 +482,7 @@ async fn test_cancel_join_request( client_b.client.clone(), client_b.user_store.clone(), client_b.project_store.clone(), - client_b.language_registry.clone().clone(), + client_b.language_registry.clone(), FakeFs::new(cx.background()), cx, ) @@ -504,7 +504,7 @@ async fn test_cancel_join_request( deterministic.run_until_parked(); assert_eq!( &*project_a_events.borrow(), - &[project::Event::ContactCancelledJoinRequest(user_b.clone())] + &[project::Event::ContactCancelledJoinRequest(user_b)] ); } @@ -554,17 +554,17 @@ async fn test_offline_projects( user_store: ModelHandle, cx: &mut gpui::MutableAppContext, ) { - let open_project_ids = project_store - .read(cx) - .projects(cx) - .filter_map(|project| project.read(cx).remote_id()) - .collect::>(); - let user_store = user_store.read(cx); for contact in user_store.contacts() { if contact.user.id == user_store.current_user().unwrap().id { for project in &contact.projects { - if !open_project_ids.contains(&project.id) { + let store_contains_project = project_store + .read(cx) + .projects(cx) + .filter_map(|project| project.read(cx).remote_id()) + .any(|x| x == project.id); + + if !store_contains_project { panic!( concat!( "current user's contact data has a project", @@ -903,7 +903,7 @@ async fn test_propagate_saves_and_fs_changes( client_a.fs.insert_file("/a/file4", "4".into()).await; worktree_a - .condition(&cx_a, |tree, _| { + .condition(cx_a, |tree, _| { tree.paths() .map(|p| p.to_string_lossy()) .collect::>() @@ -911,7 +911,7 @@ async fn test_propagate_saves_and_fs_changes( }) .await; worktree_b - .condition(&cx_b, |tree, _| { + .condition(cx_b, |tree, _| { tree.paths() .map(|p| p.to_string_lossy()) .collect::>() @@ -919,7 +919,7 @@ async fn test_propagate_saves_and_fs_changes( }) .await; worktree_c - .condition(&cx_c, |tree, _| { + .condition(cx_c, |tree, _| { tree.paths() .map(|p| p.to_string_lossy()) .collect::>() @@ -929,17 +929,17 @@ async fn test_propagate_saves_and_fs_changes( // Ensure buffer files are updated as well. buffer_a - .condition(&cx_a, |buf, _| { + .condition(cx_a, |buf, _| { buf.file().unwrap().path().to_str() == Some("file1-renamed") }) .await; buffer_b - .condition(&cx_b, |buf, _| { + .condition(cx_b, |buf, _| { buf.file().unwrap().path().to_str() == Some("file1-renamed") }) .await; buffer_c - .condition(&cx_c, |buf, _| { + .condition(cx_c, |buf, _| { buf.file().unwrap().path().to_str() == Some("file1-renamed") }) .await; @@ -1246,7 +1246,7 @@ async fn test_buffer_conflict_after_save(cx_a: &mut TestAppContext, cx_b: &mut T buffer_b.update(cx_b, |buf, cx| buf.save(cx)).await.unwrap(); buffer_b - .condition(&cx_b, |buffer_b, _| !buffer_b.is_dirty()) + .condition(cx_b, |buffer_b, _| !buffer_b.is_dirty()) .await; buffer_b.read_with(cx_b, |buf, _| { assert!(!buf.has_conflict()); @@ -1299,7 +1299,7 @@ async fn test_buffer_reloading(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont .await .unwrap(); buffer_b - .condition(&cx_b, |buf, _| { + .condition(cx_b, |buf, _| { buf.text() == new_contents.to_string() && !buf.is_dirty() }) .await; @@ -1349,7 +1349,7 @@ async fn test_editing_while_guest_opens_buffer( let text = buffer_a.read_with(cx_a, |buf, _| buf.text()); let buffer_b = buffer_b.await.unwrap(); - buffer_b.condition(&cx_b, |buf, _| buf.text() == text).await; + buffer_b.condition(cx_b, |buf, _| buf.text() == text).await; } #[gpui::test(iterations = 10)] @@ -1374,7 +1374,7 @@ async fn test_leaving_worktree_while_opening_buffer( // See that a guest has joined as client A. project_a - .condition(&cx_a, |p, _| p.collaborators().len() == 1) + .condition(cx_a, |p, _| p.collaborators().len() == 1) .await; // Begin opening a buffer as client B, but leave the project before the open completes. @@ -1386,7 +1386,7 @@ async fn test_leaving_worktree_while_opening_buffer( // See that the guest has left. project_a - .condition(&cx_a, |p, _| p.collaborators().len() == 0) + .condition(cx_a, |p, _| p.collaborators().is_empty()) .await; } @@ -1421,7 +1421,7 @@ async fn test_leaving_project(cx_a: &mut TestAppContext, cx_b: &mut TestAppConte // Drop client B's connection and ensure client A observes client B leaving the project. client_b.disconnect(&cx_b.to_async()).unwrap(); project_a - .condition(cx_a, |p, _| p.collaborators().len() == 0) + .condition(cx_a, |p, _| p.collaborators().is_empty()) .await; // Rejoin the project as client B @@ -1437,7 +1437,7 @@ async fn test_leaving_project(cx_a: &mut TestAppContext, cx_b: &mut TestAppConte server.disconnect_client(client_b.current_user_id(cx_b)); cx_a.foreground().advance_clock(rpc::RECEIVE_TIMEOUT); project_a - .condition(cx_a, |p, _| p.collaborators().len() == 0) + .condition(cx_a, |p, _| p.collaborators().is_empty()) .await; } @@ -1639,7 +1639,6 @@ async fn test_collaborating_with_diagnostics( buffer .snapshot() .diagnostics_in_range::<_, Point>(0..buffer.len(), false) - .map(|entry| entry) .collect::>(), &[ DiagnosticEntry { @@ -1744,7 +1743,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu let fake_language_server = fake_language_servers.next().await.unwrap(); buffer_b - .condition(&cx_b, |buffer, _| !buffer.completion_triggers().is_empty()) + .condition(cx_b, |buffer, _| !buffer.completion_triggers().is_empty()) .await; // Type a completion trigger character as the guest. @@ -1808,12 +1807,12 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu .await .unwrap(); buffer_a - .condition(&cx_a, |buffer, _| buffer.text() == "fn main() { a. }") + .condition(cx_a, |buffer, _| buffer.text() == "fn main() { a. }") .await; // Confirm a completion on the guest. editor_b - .condition(&cx_b, |editor, _| editor.context_menu_visible()) + .condition(cx_b, |editor, _| editor.context_menu_visible()) .await; editor_b.update(cx_b, |editor, cx| { editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx); @@ -1844,12 +1843,12 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu // The additional edit is applied. buffer_a - .condition(&cx_a, |buffer, _| { + .condition(cx_a, |buffer, _| { buffer.text() == "use d::SomeTrait;\nfn main() { a.first_method() }" }) .await; buffer_b - .condition(&cx_b, |buffer, _| { + .condition(cx_b, |buffer, _| { buffer.text() == "use d::SomeTrait;\nfn main() { a.first_method() }" }) .await; @@ -2256,9 +2255,9 @@ async fn test_references(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { Path::new("three.rs") ); - assert_eq!(references[0].range.to_offset(&two_buffer), 24..27); - assert_eq!(references[1].range.to_offset(&two_buffer), 35..38); - assert_eq!(references[2].range.to_offset(&three_buffer), 37..40); + assert_eq!(references[0].range.to_offset(two_buffer), 24..27); + assert_eq!(references[1].range.to_offset(two_buffer), 35..38); + assert_eq!(references[2].range.to_offset(three_buffer), 37..40); }); } @@ -2707,7 +2706,7 @@ async fn test_collaborating_with_code_actions( cx_b: &mut TestAppContext, ) { cx_a.foreground().forbid_parking(); - cx_b.update(|cx| editor::init(cx)); + cx_b.update(editor::init); let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; let client_a = server.create_client(cx_a, "user_a").await; let client_b = server.create_client(cx_b, "user_b").await; @@ -2839,7 +2838,7 @@ async fn test_collaborating_with_code_actions( ); }); editor_b - .condition(&cx_b, |editor, _| editor.context_menu_visible()) + .condition(cx_b, |editor, _| editor.context_menu_visible()) .await; fake_language_server.remove_request_handler::(); @@ -2912,7 +2911,7 @@ async fn test_collaborating_with_code_actions( #[gpui::test(iterations = 10)] async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); - cx_b.update(|cx| editor::init(cx)); + cx_b.update(editor::init); let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; let client_a = server.create_client(cx_a, "user_a").await; let client_b = server.create_client(cx_b, "user_b").await; @@ -3098,7 +3097,7 @@ async fn test_language_server_statuses( ) { deterministic.forbid_parking(); - cx_b.update(|cx| editor::init(cx)); + cx_b.update(editor::init); let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; let client_a = server.create_client(cx_a, "user_a").await; let client_b = server.create_client(cx_b, "user_b").await; @@ -3207,24 +3206,24 @@ async fn test_basic_chat(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { // Create an org that includes these 2 users. let db = &server.app_state.db; let org_id = db.create_org("Test Org", "test-org").await.unwrap(); - db.add_org_member(org_id, client_a.current_user_id(&cx_a), false) + db.add_org_member(org_id, client_a.current_user_id(cx_a), false) .await .unwrap(); - db.add_org_member(org_id, client_b.current_user_id(&cx_b), false) + db.add_org_member(org_id, client_b.current_user_id(cx_b), false) .await .unwrap(); // Create a channel that includes all the users. let channel_id = db.create_org_channel(org_id, "test-channel").await.unwrap(); - db.add_channel_member(channel_id, client_a.current_user_id(&cx_a), false) + db.add_channel_member(channel_id, client_a.current_user_id(cx_a), false) .await .unwrap(); - db.add_channel_member(channel_id, client_b.current_user_id(&cx_b), false) + db.add_channel_member(channel_id, client_b.current_user_id(cx_b), false) .await .unwrap(); db.create_channel_message( channel_id, - client_b.current_user_id(&cx_b), + client_b.current_user_id(cx_b), "hello A, it's B.", OffsetDateTime::now_utc(), 1, @@ -3251,7 +3250,7 @@ async fn test_basic_chat(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { }); channel_a.read_with(cx_a, |channel, _| assert!(channel.messages().is_empty())); channel_a - .condition(&cx_a, |channel, _| { + .condition(cx_a, |channel, _| { channel_messages(channel) == [("user_b".to_string(), "hello A, it's B.".to_string(), false)] }) @@ -3277,7 +3276,7 @@ async fn test_basic_chat(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { }); channel_b.read_with(cx_b, |channel, _| assert!(channel.messages().is_empty())); channel_b - .condition(&cx_b, |channel, _| { + .condition(cx_b, |channel, _| { channel_messages(channel) == [("user_b".to_string(), "hello A, it's B.".to_string(), false)] }) @@ -3304,7 +3303,7 @@ async fn test_basic_chat(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { .unwrap(); channel_b - .condition(&cx_b, |channel, _| { + .condition(cx_b, |channel, _| { channel_messages(channel) == [ ("user_b".to_string(), "hello A, it's B.".to_string(), false), @@ -3344,10 +3343,10 @@ async fn test_chat_message_validation(cx_a: &mut TestAppContext) { let db = &server.app_state.db; let org_id = db.create_org("Test Org", "test-org").await.unwrap(); let channel_id = db.create_org_channel(org_id, "test-channel").await.unwrap(); - db.add_org_member(org_id, client_a.current_user_id(&cx_a), false) + db.add_org_member(org_id, client_a.current_user_id(cx_a), false) .await .unwrap(); - db.add_channel_member(channel_id, client_a.current_user_id(&cx_a), false) + db.add_channel_member(channel_id, client_a.current_user_id(cx_a), false) .await .unwrap(); @@ -3406,24 +3405,24 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon // Create an org that includes these 2 users. let db = &server.app_state.db; let org_id = db.create_org("Test Org", "test-org").await.unwrap(); - db.add_org_member(org_id, client_a.current_user_id(&cx_a), false) + db.add_org_member(org_id, client_a.current_user_id(cx_a), false) .await .unwrap(); - db.add_org_member(org_id, client_b.current_user_id(&cx_b), false) + db.add_org_member(org_id, client_b.current_user_id(cx_b), false) .await .unwrap(); // Create a channel that includes all the users. let channel_id = db.create_org_channel(org_id, "test-channel").await.unwrap(); - db.add_channel_member(channel_id, client_a.current_user_id(&cx_a), false) + db.add_channel_member(channel_id, client_a.current_user_id(cx_a), false) .await .unwrap(); - db.add_channel_member(channel_id, client_b.current_user_id(&cx_b), false) + db.add_channel_member(channel_id, client_b.current_user_id(cx_b), false) .await .unwrap(); db.create_channel_message( channel_id, - client_b.current_user_id(&cx_b), + client_b.current_user_id(cx_b), "hello A, it's B.", OffsetDateTime::now_utc(), 2, @@ -3451,7 +3450,7 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon }); channel_a.read_with(cx_a, |channel, _| assert!(channel.messages().is_empty())); channel_a - .condition(&cx_a, |channel, _| { + .condition(cx_a, |channel, _| { channel_messages(channel) == [("user_b".to_string(), "hello A, it's B.".to_string(), false)] }) @@ -3477,7 +3476,7 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon }); channel_b.read_with(cx_b, |channel, _| assert!(channel.messages().is_empty())); channel_b - .condition(&cx_b, |channel, _| { + .condition(cx_b, |channel, _| { channel_messages(channel) == [("user_b".to_string(), "hello A, it's B.".to_string(), false)] }) @@ -3485,7 +3484,7 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon // Disconnect client B, ensuring we can still access its cached channel data. server.forbid_connections(); - server.disconnect_client(client_b.current_user_id(&cx_b)); + server.disconnect_client(client_b.current_user_id(cx_b)); cx_b.foreground().advance_clock(rpc::RECEIVE_TIMEOUT); while !matches!( status_b.next().await, @@ -3554,7 +3553,7 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon // Verify that B sees the new messages upon reconnection, as well as the message client B // sent while offline. channel_b - .condition(&cx_b, |channel, _| { + .condition(cx_b, |channel, _| { channel_messages(channel) == [ ("user_b".to_string(), "hello A, it's B.".to_string(), false), @@ -3573,7 +3572,7 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon .await .unwrap(); channel_b - .condition(&cx_b, |channel, _| { + .condition(cx_b, |channel, _| { channel_messages(channel) == [ ("user_b".to_string(), "hello A, it's B.".to_string(), false), @@ -3592,7 +3591,7 @@ async fn test_chat_reconnection(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon .await .unwrap(); channel_a - .condition(&cx_a, |channel, _| { + .condition(cx_a, |channel, _| { channel_messages(channel) == [ ("user_b".to_string(), "hello A, it's B.".to_string(), false), @@ -3701,7 +3700,7 @@ async fn test_contacts( } project_a - .condition(&cx_a, |project, _| { + .condition(cx_a, |project, _| { project.collaborators().contains_key(&client_b.peer_id) }) .await; @@ -3766,6 +3765,7 @@ async fn test_contacts( }); } + #[allow(clippy::type_complexity)] fn contacts(user_store: &UserStore) -> Vec<(&str, bool, Vec<(&str, Vec<&str>)>)> { user_store .contacts() @@ -3831,27 +3831,27 @@ async fn test_contact_requests( // All users see the pending request appear in all their clients. assert_eq!( - client_a.summarize_contacts(&cx_a).outgoing_requests, + client_a.summarize_contacts(cx_a).outgoing_requests, &["user_b"] ); assert_eq!( - client_a2.summarize_contacts(&cx_a2).outgoing_requests, + client_a2.summarize_contacts(cx_a2).outgoing_requests, &["user_b"] ); assert_eq!( - client_b.summarize_contacts(&cx_b).incoming_requests, + client_b.summarize_contacts(cx_b).incoming_requests, &["user_a", "user_c"] ); assert_eq!( - client_b2.summarize_contacts(&cx_b2).incoming_requests, + client_b2.summarize_contacts(cx_b2).incoming_requests, &["user_a", "user_c"] ); assert_eq!( - client_c.summarize_contacts(&cx_c).outgoing_requests, + client_c.summarize_contacts(cx_c).outgoing_requests, &["user_b"] ); assert_eq!( - client_c2.summarize_contacts(&cx_c2).outgoing_requests, + client_c2.summarize_contacts(cx_c2).outgoing_requests, &["user_b"] ); @@ -3861,15 +3861,15 @@ async fn test_contact_requests( disconnect_and_reconnect(&client_c, cx_c).await; executor.run_until_parked(); assert_eq!( - client_a.summarize_contacts(&cx_a).outgoing_requests, + client_a.summarize_contacts(cx_a).outgoing_requests, &["user_b"] ); assert_eq!( - client_b.summarize_contacts(&cx_b).incoming_requests, + client_b.summarize_contacts(cx_b).incoming_requests, &["user_a", "user_c"] ); assert_eq!( - client_c.summarize_contacts(&cx_c).outgoing_requests, + client_c.summarize_contacts(cx_c).outgoing_requests, &["user_b"] ); @@ -3885,18 +3885,18 @@ async fn test_contact_requests( executor.run_until_parked(); // User B sees user A as their contact now in all client, and the incoming request from them is removed. - let contacts_b = client_b.summarize_contacts(&cx_b); + let contacts_b = client_b.summarize_contacts(cx_b); assert_eq!(contacts_b.current, &["user_a", "user_b"]); assert_eq!(contacts_b.incoming_requests, &["user_c"]); - let contacts_b2 = client_b2.summarize_contacts(&cx_b2); + let contacts_b2 = client_b2.summarize_contacts(cx_b2); assert_eq!(contacts_b2.current, &["user_a", "user_b"]); assert_eq!(contacts_b2.incoming_requests, &["user_c"]); // User A sees user B as their contact now in all clients, and the outgoing request to them is removed. - let contacts_a = client_a.summarize_contacts(&cx_a); + let contacts_a = client_a.summarize_contacts(cx_a); assert_eq!(contacts_a.current, &["user_a", "user_b"]); assert!(contacts_a.outgoing_requests.is_empty()); - let contacts_a2 = client_a2.summarize_contacts(&cx_a2); + let contacts_a2 = client_a2.summarize_contacts(cx_a2); assert_eq!(contacts_a2.current, &["user_a", "user_b"]); assert!(contacts_a2.outgoing_requests.is_empty()); @@ -3906,20 +3906,20 @@ async fn test_contact_requests( disconnect_and_reconnect(&client_c, cx_c).await; executor.run_until_parked(); assert_eq!( - client_a.summarize_contacts(&cx_a).current, + client_a.summarize_contacts(cx_a).current, &["user_a", "user_b"] ); assert_eq!( - client_b.summarize_contacts(&cx_b).current, + client_b.summarize_contacts(cx_b).current, &["user_a", "user_b"] ); assert_eq!( - client_b.summarize_contacts(&cx_b).incoming_requests, + client_b.summarize_contacts(cx_b).incoming_requests, &["user_c"] ); - assert_eq!(client_c.summarize_contacts(&cx_c).current, &["user_c"]); + assert_eq!(client_c.summarize_contacts(cx_c).current, &["user_c"]); assert_eq!( - client_c.summarize_contacts(&cx_c).outgoing_requests, + client_c.summarize_contacts(cx_c).outgoing_requests, &["user_b"] ); @@ -3935,18 +3935,18 @@ async fn test_contact_requests( executor.run_until_parked(); // User B doesn't see user C as their contact, and the incoming request from them is removed. - let contacts_b = client_b.summarize_contacts(&cx_b); + let contacts_b = client_b.summarize_contacts(cx_b); assert_eq!(contacts_b.current, &["user_a", "user_b"]); assert!(contacts_b.incoming_requests.is_empty()); - let contacts_b2 = client_b2.summarize_contacts(&cx_b2); + let contacts_b2 = client_b2.summarize_contacts(cx_b2); assert_eq!(contacts_b2.current, &["user_a", "user_b"]); assert!(contacts_b2.incoming_requests.is_empty()); // User C doesn't see user B as their contact, and the outgoing request to them is removed. - let contacts_c = client_c.summarize_contacts(&cx_c); + let contacts_c = client_c.summarize_contacts(cx_c); assert_eq!(contacts_c.current, &["user_c"]); assert!(contacts_c.outgoing_requests.is_empty()); - let contacts_c2 = client_c2.summarize_contacts(&cx_c2); + let contacts_c2 = client_c2.summarize_contacts(cx_c2); assert_eq!(contacts_c2.current, &["user_c"]); assert!(contacts_c2.outgoing_requests.is_empty()); @@ -3956,20 +3956,20 @@ async fn test_contact_requests( disconnect_and_reconnect(&client_c, cx_c).await; executor.run_until_parked(); assert_eq!( - client_a.summarize_contacts(&cx_a).current, + client_a.summarize_contacts(cx_a).current, &["user_a", "user_b"] ); assert_eq!( - client_b.summarize_contacts(&cx_b).current, + client_b.summarize_contacts(cx_b).current, &["user_a", "user_b"] ); assert!(client_b - .summarize_contacts(&cx_b) + .summarize_contacts(cx_b) .incoming_requests .is_empty()); - assert_eq!(client_c.summarize_contacts(&cx_c).current, &["user_c"]); + assert_eq!(client_c.summarize_contacts(cx_c).current, &["user_c"]); assert!(client_c - .summarize_contacts(&cx_c) + .summarize_contacts(cx_c) .outgoing_requests .is_empty()); @@ -4553,13 +4553,13 @@ async fn test_peers_simultaneously_following_each_other( futures::try_join!(a_follow_b, b_follow_a).unwrap(); workspace_a.read_with(cx_a, |workspace, _| { assert_eq!( - workspace.leader_for_pane(&workspace.active_pane()), + workspace.leader_for_pane(workspace.active_pane()), Some(client_b_id) ); }); workspace_b.read_with(cx_b, |workspace, _| { assert_eq!( - workspace.leader_for_pane(&workspace.active_pane()), + workspace.leader_for_pane(workspace.active_pane()), Some(client_a_id) ); }); @@ -4740,7 +4740,7 @@ async fn test_random_collaboration( fake_server.handle_request::({ let rng = rng.clone(); - let project = project.clone(); + let project = project; move |params, mut cx| { let highlights = if let Some(project) = project.upgrade(&cx) { project.update(&mut cx, |project, cx| { @@ -5027,10 +5027,12 @@ async fn test_random_collaboration( for guest_buffer in &guest_client.buffers { let buffer_id = guest_buffer.read_with(&guest_cx, |buffer, _| buffer.remote_id()); let host_buffer = host_project.read_with(&host_cx, |project, cx| { - project.buffer_for_id(buffer_id, cx).expect(&format!( - "host does not have buffer for guest:{}, peer:{}, id:{}", - guest_client.username, guest_client.peer_id, buffer_id - )) + project.buffer_for_id(buffer_id, cx).unwrap_or_else(|| { + panic!( + "host does not have buffer for guest:{}, peer:{}, id:{}", + guest_client.username, guest_client.peer_id, buffer_id + ) + }) }); let path = host_buffer.read_with(&host_cx, |buffer, cx| buffer.file().unwrap().full_path(cx)); @@ -5174,7 +5176,7 @@ impl TestServer { languages: Arc::new(LanguageRegistry::new(Task::ready(()))), themes: ThemeRegistry::new((), cx.font_cache()), fs: fs.clone(), - build_window_options: || Default::default(), + build_window_options: Default::default, initialize_workspace: |_, _, _| unimplemented!(), }); @@ -5540,7 +5542,7 @@ impl TestClient { log::info!("Host: creating file {:?}", path,); - if fs.create_dir(&parent_path).await.is_ok() + if fs.create_dir(parent_path).await.is_ok() && fs.create_file(&path, Default::default()).await.is_ok() { break; @@ -5587,7 +5589,7 @@ impl TestClient { let buffer = if client.buffers.is_empty() || rng.lock().gen() { let worktree = if let Some(worktree) = project.read_with(cx, |project, cx| { project - .worktrees(&cx) + .worktrees(cx) .filter(|worktree| { let worktree = worktree.read(cx); worktree.is_visible() @@ -5820,7 +5822,7 @@ impl TestClient { let worktree = project .read_with(cx, |project, cx| { project - .worktrees(&cx) + .worktrees(cx) .filter(|worktree| { let worktree = worktree.read(cx); worktree.is_visible() diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index a4a48af5be..6346e15830 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -832,7 +832,7 @@ impl Server { // First, we send the metadata associated with each worktree. for (receipt, replica_id) in &receipts_with_replica_ids { self.peer.respond( - receipt.clone(), + *receipt, proto::JoinProjectResponse { variant: Some(proto::join_project_response::Variant::Accept( proto::join_project_response::Accept { @@ -1711,7 +1711,7 @@ impl Server { Ok(()) } - pub(crate) async fn store<'a>(&'a self) -> StoreGuard<'a> { + pub(crate) async fn store(&self) -> StoreGuard { #[cfg(test)] tokio::task::yield_now().await; let guard = self.store.lock().await; @@ -1796,7 +1796,7 @@ impl Header for ProtocolVersion { { let version = values .next() - .ok_or_else(|| axum::headers::Error::invalid())? + .ok_or_else(axum::headers::Error::invalid)? .to_str() .map_err(|_| axum::headers::Error::invalid())? .parse() diff --git a/crates/collab/src/rpc/store.rs b/crates/collab/src/rpc/store.rs index f5cc87cca8..fe18e0404b 100644 --- a/crates/collab/src/rpc/store.rs +++ b/crates/collab/src/rpc/store.rs @@ -159,8 +159,10 @@ impl Store { let connection_projects = mem::take(&mut connection.projects); let connection_channels = mem::take(&mut connection.channels); - let mut result = RemovedConnectionState::default(); - result.user_id = user_id; + let mut result = RemovedConnectionState { + user_id, + ..Default::default() + }; // Leave all channels. for channel_id in connection_channels { @@ -223,10 +225,10 @@ impl Store { .user_id) } - pub fn connection_ids_for_user<'a>( - &'a self, + pub fn connection_ids_for_user( + &self, user_id: UserId, - ) -> impl 'a + Iterator { + ) -> impl Iterator + '_ { self.connections_by_user_id .get(&user_id) .into_iter() @@ -425,14 +427,14 @@ impl Store { } for guest_connection in project.guests.keys() { - if let Some(connection) = self.connections.get_mut(&guest_connection) { + if let Some(connection) = self.connections.get_mut(guest_connection) { connection.projects.remove(&project_id); } } for requester_user_id in project.join_requests.keys() { if let Some(requester_connection_ids) = - self.connections_by_user_id.get_mut(&requester_user_id) + self.connections_by_user_id.get_mut(requester_user_id) { for requester_connection_id in requester_connection_ids.iter() { if let Some(requester_connection) = @@ -544,6 +546,7 @@ impl Store { Some(receipts) } + #[allow(clippy::type_complexity)] pub fn accept_join_project_request( &mut self, responder_connection_id: ConnectionId, @@ -638,6 +641,7 @@ impl Store { }) } + #[allow(clippy::too_many_arguments)] pub fn update_worktree( &mut self, connection_id: ConnectionId, @@ -660,7 +664,7 @@ impl Store { worktree.root_name = worktree_root_name.to_string(); for entry_id in removed_entries { - worktree.entries.remove(&entry_id); + worktree.entries.remove(entry_id); } for entry in updated_entries { @@ -760,7 +764,7 @@ impl Store { pub fn check_invariants(&self) { for (connection_id, connection) in &self.connections { for project_id in &connection.projects { - let project = &self.projects.get(&project_id).unwrap(); + let project = &self.projects.get(project_id).unwrap(); if project.host_connection_id != *connection_id { assert!(project.guests.contains_key(connection_id)); } diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 46327cf1bc..9b51415069 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -83,7 +83,9 @@ impl CommandPalette { fn toggle(_: &mut Workspace, _: &Toggle, cx: &mut ViewContext) { let workspace = cx.handle(); let window_id = cx.window_id(); - let focused_view_id = cx.focused_view_id(window_id).unwrap_or(workspace.id()); + let focused_view_id = cx + .focused_view_id(window_id) + .unwrap_or_else(|| workspace.id()); cx.as_mut().defer(move |cx| { let this = cx.add_view(workspace.clone(), |cx| Self::new(focused_view_id, cx)); diff --git a/crates/contacts_panel/src/contact_finder.rs b/crates/contacts_panel/src/contact_finder.rs index 978466dfcb..d7c096aaa9 100644 --- a/crates/contacts_panel/src/contact_finder.rs +++ b/crates/contacts_panel/src/contact_finder.rs @@ -111,7 +111,7 @@ impl PickerDelegate for ContactFinder { ) -> ElementBox { let theme = &cx.global::().theme; let user = &self.potential_contacts[ix]; - let request_status = self.user_store.read(cx).contact_request_status(&user); + let request_status = self.user_store.read(cx).contact_request_status(user); let icon_path = match request_status { ContactRequestStatus::None | ContactRequestStatus::RequestReceived => { @@ -121,7 +121,7 @@ impl PickerDelegate for ContactFinder { "icons/x_mark_8.svg" } }; - let button_style = if self.user_store.read(cx).is_contact_request_pending(&user) { + let button_style = if self.user_store.read(cx).is_contact_request_pending(user) { &theme.contact_finder.disabled_contact_button } else { &theme.contact_finder.contact_button diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index 9bc7972b29..9198efceba 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -131,9 +131,9 @@ impl ContactsPanel { move |_, cx| { if let Some(workspace_handle) = workspace.upgrade(cx) { cx.subscribe(&workspace_handle.read(cx).project().clone(), { - let workspace = workspace.clone(); - move |_, project, event, cx| match event { - project::Event::ContactRequestedJoin(user) => { + let workspace = workspace; + move |_, project, event, cx| { + if let project::Event::ContactRequestedJoin(user) = event { if let Some(workspace) = workspace.upgrade(cx) { workspace.update(cx, |workspace, cx| { workspace.show_notification(user.id as usize, cx, |cx| { @@ -148,7 +148,6 @@ impl ContactsPanel { }); } } - _ => {} } }) .detach(); @@ -161,17 +160,16 @@ impl ContactsPanel { cx.subscribe(&user_store, move |_, user_store, event, cx| { if let Some(workspace) = workspace.upgrade(cx) { - workspace.update(cx, |workspace, cx| match event { - client::Event::Contact { user, kind } => match kind { - ContactEventKind::Requested | ContactEventKind::Accepted => workspace - .show_notification(user.id as usize, cx, |cx| { + workspace.update(cx, |workspace, cx| { + if let client::Event::Contact { user, kind } = event { + if let ContactEventKind::Requested | ContactEventKind::Accepted = kind { + workspace.show_notification(user.id as usize, cx, |cx| { cx.add_view(|cx| { ContactNotification::new(user.clone(), *kind, user_store, cx) }) - }), - _ => {} - }, - _ => {} + }) + } + } }); } @@ -188,7 +186,7 @@ impl ContactsPanel { match &this.entries[ix] { ContactEntry::Header(section) => { - let is_collapsed = this.collapsed_sections.contains(§ion); + let is_collapsed = this.collapsed_sections.contains(section); Self::render_header( *section, &theme.contacts_panel, @@ -229,7 +227,7 @@ impl ContactsPanel { contact.clone(), current_user_id, *project_ix, - open_project.clone(), + *open_project, &theme.contacts_panel, &theme.tooltip, is_last_project_for_contact, @@ -238,7 +236,7 @@ impl ContactsPanel { ) } ContactEntry::OfflineProject(project) => Self::render_offline_project( - project.clone(), + *project, &theme.contacts_panel, &theme.tooltip, is_selected, @@ -345,6 +343,7 @@ impl ContactsPanel { .boxed() } + #[allow(clippy::too_many_arguments)] fn render_project( contact: Arc, current_user_id: Option, @@ -370,7 +369,7 @@ impl ContactsPanel { .or(theme.contact_avatar.height) .unwrap_or(0.); let row = &theme.project_row.default; - let tree_branch = theme.tree_branch.clone(); + let tree_branch = theme.tree_branch; let line_height = row.name.text.line_height(font_cache); let cap_height = row.name.text.cap_height(font_cache); let baseline_offset = @@ -641,7 +640,7 @@ impl ContactsPanel { let button_style = if is_contact_request_pending { &theme.disabled_button } else { - &theme.contact_button.style_for(mouse_state, false) + theme.contact_button.style_for(mouse_state, false) }; render_icon_button(button_style, "icons/x_mark_8.svg") .aligned() @@ -663,7 +662,7 @@ impl ContactsPanel { let button_style = if is_contact_request_pending { &theme.disabled_button } else { - &theme.contact_button.style_for(mouse_state, false) + theme.contact_button.style_for(mouse_state, false) }; render_icon_button(button_style, "icons/check_8.svg") .aligned() @@ -685,7 +684,7 @@ impl ContactsPanel { let button_style = if is_contact_request_pending { &theme.disabled_button } else { - &theme.contact_button.style_for(mouse_state, false) + theme.contact_button.style_for(mouse_state, false) }; render_icon_button(button_style, "icons/x_mark_8.svg") .aligned() @@ -1224,7 +1223,7 @@ mod tests { let client = Client::new(http_client.clone()); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx)); let project_store = cx.add_model(|_| ProjectStore::new(project::Db::open_fake())); - let server = FakeServer::for_client(current_user_id, &client, &cx).await; + let server = FakeServer::for_client(current_user_id, &client, cx).await; let fs = FakeFs::new(cx.background()); fs.insert_tree("/private_dir", json!({ "one.rs": "" })) .await; diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index facccadb76..e14a44b058 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -365,7 +365,7 @@ impl ProjectDiagnosticsEditor { if !diagnostic.message.is_empty() { group_state.block_count += 1; blocks_to_add.push(BlockProperties { - position: (excerpt_id.clone(), entry.range.start.clone()), + position: (excerpt_id.clone(), entry.range.start), height: diagnostic.message.matches('\n').count() as u8 + 1, style: BlockStyle::Fixed, render: diagnostic_block_renderer(diagnostic, true), @@ -460,7 +460,7 @@ impl ProjectDiagnosticsEditor { for selection in &mut selections { if let Some(new_excerpt_id) = new_excerpt_ids_by_selection_id.get(&selection.id) { let group_ix = match groups.binary_search_by(|probe| { - probe.excerpts.last().unwrap().cmp(&new_excerpt_id) + probe.excerpts.last().unwrap().cmp(new_excerpt_id) }) { Ok(ix) | Err(ix) => ix, }; @@ -468,7 +468,7 @@ impl ProjectDiagnosticsEditor { let offset = excerpts_snapshot .anchor_in_excerpt( group.excerpts[group.primary_excerpt_ix].clone(), - group.primary_diagnostic.range.start.clone(), + group.primary_diagnostic.range.start, ) .to_offset(&excerpts_snapshot); selection.start = offset; @@ -486,10 +486,8 @@ impl ProjectDiagnosticsEditor { if self.editor.is_focused(cx) { cx.focus_self(); } - } else { - if cx.handle().is_focused(cx) { - cx.focus(&self.editor); - } + } else if cx.handle().is_focused(cx) { + cx.focus(&self.editor); } cx.notify(); } @@ -725,12 +723,12 @@ fn compare_diagnostics( ) -> Ordering { lhs.range .start - .to_offset(&snapshot) + .to_offset(snapshot) .cmp(&rhs.range.start.to_offset(snapshot)) .then_with(|| { lhs.range .end - .to_offset(&snapshot) + .to_offset(snapshot) .cmp(&rhs.range.end.to_offset(snapshot)) }) .then_with(|| lhs.diagnostic.message.cmp(&rhs.diagnostic.message)) @@ -873,7 +871,7 @@ mod tests { ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx) }); - view.next_notification(&cx).await; + view.next_notification(cx).await; view.update(cx, |view, cx| { assert_eq!( editor_blocks(&view.editor, cx), @@ -960,7 +958,7 @@ mod tests { project.disk_based_diagnostics_finished(0, cx); }); - view.next_notification(&cx).await; + view.next_notification(cx).await; view.update(cx, |view, cx| { assert_eq!( editor_blocks(&view.editor, cx), @@ -1074,7 +1072,7 @@ mod tests { project.disk_based_diagnostics_finished(0, cx); }); - view.next_notification(&cx).await; + view.next_notification(cx).await; view.update(cx, |view, cx| { assert_eq!( editor_blocks(&view.editor, cx), diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index ab5b7155a5..58fc2e4fe7 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -253,7 +253,7 @@ impl DisplaySnapshot { self.buffer_snapshot.len() == 0 } - pub fn buffer_rows<'a>(&'a self, start_row: u32) -> DisplayBufferRows<'a> { + pub fn buffer_rows(&self, start_row: u32) -> DisplayBufferRows { self.blocks_snapshot.buffer_rows(start_row) } @@ -313,7 +313,7 @@ impl DisplaySnapshot { fn point_to_display_point(&self, point: Point, bias: Bias) -> DisplayPoint { let fold_point = self.folds_snapshot.to_fold_point(point, bias); let tab_point = self.tabs_snapshot.to_tab_point(fold_point); - let wrap_point = self.wraps_snapshot.from_tab_point(tab_point); + let wrap_point = self.wraps_snapshot.tab_point_to_wrap_point(tab_point); let block_point = self.blocks_snapshot.to_block_point(wrap_point); DisplayPoint(block_point) } @@ -336,16 +336,12 @@ impl DisplaySnapshot { .map(|h| h.text) } - pub fn chunks<'a>( - &'a self, - display_rows: Range, - language_aware: bool, - ) -> DisplayChunks<'a> { + pub fn chunks(&self, display_rows: Range, language_aware: bool) -> DisplayChunks<'_> { self.blocks_snapshot .chunks(display_rows, language_aware, Some(&self.text_highlights)) } - pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator + 'a { + pub fn chars_at(&self, point: DisplayPoint) -> impl Iterator + '_ { let mut column = 0; let mut chars = self.text_chunks(point.row()).flat_map(str::chars); while column < point.column() { @@ -372,15 +368,15 @@ impl DisplaySnapshot { } pub fn column_from_chars(&self, display_row: u32, char_count: u32) -> u32 { - let mut count = 0; let mut column = 0; - for c in self.chars_at(DisplayPoint::new(display_row, 0)) { - if c == '\n' || count >= char_count { + + for (count, c) in self.chars_at(DisplayPoint::new(display_row, 0)).enumerate() { + if c == '\n' || count >= char_count as usize { break; } - count += 1; column += c.len_utf8() as u32; } + column } @@ -401,20 +397,17 @@ impl DisplaySnapshot { DisplayPoint(point) } - pub fn folds_in_range<'a, T>( - &'a self, - range: Range, - ) -> impl Iterator> + pub fn folds_in_range(&self, range: Range) -> impl Iterator> where T: ToOffset, { self.folds_snapshot.folds_in_range(range) } - pub fn blocks_in_range<'a>( - &'a self, + pub fn blocks_in_range( + &self, rows: Range, - ) -> impl Iterator { + ) -> impl Iterator { self.blocks_snapshot.blocks_in_range(rows) } @@ -1015,7 +1008,7 @@ pub mod tests { }); let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); - buffer.condition(&cx, |buf, _| !buf.is_parsing()).await; + buffer.condition(cx, |buf, _| !buf.is_parsing()).await; let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let font_cache = cx.font_cache(); @@ -1102,7 +1095,7 @@ pub mod tests { cx.update(|cx| cx.set_global(Settings::test(cx))); let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); - buffer.condition(&cx, |buf, _| !buf.is_parsing()).await; + buffer.condition(cx, |buf, _| !buf.is_parsing()).await; let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let font_cache = cx.font_cache(); @@ -1173,7 +1166,7 @@ pub mod tests { let (text, highlighted_ranges) = marked_text_ranges(r#"constˇ «a»: B = "c «d»""#, false); let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); - buffer.condition(&cx, |buf, _| !buf.is_parsing()).await; + buffer.condition(cx, |buf, _| !buf.is_parsing()).await; let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx)); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 5237901170..210daccac2 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -20,7 +20,7 @@ use std::{ use sum_tree::{Bias, SumTree}; use text::{Edit, Point}; -const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize]; +const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize]; pub struct BlockMap { next_block_id: AtomicUsize, @@ -102,6 +102,7 @@ struct Transform { block: Option, } +#[allow(clippy::large_enum_variant)] #[derive(Clone)] pub enum TransformBlock { Custom(Arc), @@ -317,7 +318,7 @@ impl BlockMap { let start_block_ix = match self.blocks[last_block_ix..].binary_search_by(|probe| { probe .position - .to_point(&buffer) + .to_point(buffer) .cmp(&new_buffer_start) .then(Ordering::Greater) }) { @@ -335,7 +336,7 @@ impl BlockMap { match self.blocks[start_block_ix..].binary_search_by(|probe| { probe .position - .to_point(&buffer) + .to_point(buffer) .cmp(&new_buffer_end) .then(Ordering::Greater) }) { @@ -349,14 +350,14 @@ impl BlockMap { self.blocks[start_block_ix..end_block_ix] .iter() .map(|block| { - let mut position = block.position.to_point(&buffer); + let mut position = block.position.to_point(buffer); match block.disposition { BlockDisposition::Above => position.column = 0, BlockDisposition::Below => { position.column = buffer.line_len(position.row) } } - let position = wrap_snapshot.from_point(position, Bias::Left); + let position = wrap_snapshot.make_wrap_point(position, Bias::Left); (position.row(), TransformBlock::Custom(block.clone())) }), ); @@ -366,7 +367,7 @@ impl BlockMap { .map(|excerpt_boundary| { ( wrap_snapshot - .from_point(Point::new(excerpt_boundary.row, 0), Bias::Left) + .make_wrap_point(Point::new(excerpt_boundary.row, 0), Bias::Left) .row(), TransformBlock::ExcerptHeader { key: excerpt_boundary.key, @@ -385,7 +386,7 @@ impl BlockMap { // Place excerpt headers above custom blocks on the same row. blocks_in_edit.sort_unstable_by(|(row_a, block_a), (row_b, block_b)| { - row_a.cmp(&row_b).then_with(|| match (block_a, block_b) { + row_a.cmp(row_b).then_with(|| match (block_a, block_b) { ( TransformBlock::ExcerptHeader { .. }, TransformBlock::ExcerptHeader { .. }, @@ -498,9 +499,9 @@ impl<'a> BlockMapWriter<'a> { ids.push(id); let position = block.position; - let point = position.to_point(&buffer); + let point = position.to_point(buffer); let wrap_row = wrap_snapshot - .from_point(Point::new(point.row, 0), Bias::Left) + .make_wrap_point(Point::new(point.row, 0), Bias::Left) .row(); let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0)); let end_row = wrap_snapshot @@ -510,7 +511,7 @@ impl<'a> BlockMapWriter<'a> { let block_ix = match self .0 .blocks - .binary_search_by(|probe| probe.position.cmp(&position, &buffer)) + .binary_search_by(|probe| probe.position.cmp(&position, buffer)) { Ok(ix) | Err(ix) => ix, }; @@ -543,11 +544,11 @@ impl<'a> BlockMapWriter<'a> { let mut last_block_buffer_row = None; self.0.blocks.retain(|block| { if block_ids.contains(&block.id) { - let buffer_row = block.position.to_point(&buffer).row; + let buffer_row = block.position.to_point(buffer).row; if last_block_buffer_row != Some(buffer_row) { last_block_buffer_row = Some(buffer_row); let wrap_row = wrap_snapshot - .from_point(Point::new(buffer_row, 0), Bias::Left) + .make_wrap_point(Point::new(buffer_row, 0), Bias::Left) .row(); let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0)); let end_row = wrap_snapshot @@ -620,7 +621,7 @@ impl BlockSnapshot { } } - pub fn buffer_rows<'a>(&'a self, start_row: u32) -> BlockBufferRows<'a> { + pub fn buffer_rows(&self, start_row: u32) -> BlockBufferRows { let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(); cursor.seek(&BlockRow(start_row), Bias::Right, &()); let (output_start, input_start) = cursor.start(); @@ -638,10 +639,10 @@ impl BlockSnapshot { } } - pub fn blocks_in_range<'a>( - &'a self, + pub fn blocks_in_range( + &self, rows: Range, - ) -> impl Iterator { + ) -> impl Iterator { let mut cursor = self.transforms.cursor::(); cursor.seek(&BlockRow(rows.start), Bias::Right, &()); std::iter::from_fn(move || { @@ -1025,7 +1026,7 @@ mod tests { let buffer_snapshot = buffer.read(cx).snapshot(cx); let subscription = buffer.update(cx, |buffer, _| buffer.subscribe()); let (fold_map, folds_snapshot) = FoldMap::new(buffer_snapshot.clone()); - let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), 1.try_into().unwrap()); + let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot, 1.try_into().unwrap()); let (wrap_map, wraps_snapshot) = WrapMap::new(tabs_snapshot, font_id, 14.0, None, cx); let mut block_map = BlockMap::new(wraps_snapshot.clone(), 1, 1); @@ -1194,7 +1195,7 @@ mod tests { let buffer = MultiBuffer::build_simple(text, cx); let buffer_snapshot = buffer.read(cx).snapshot(cx); let (_, folds_snapshot) = FoldMap::new(buffer_snapshot.clone()); - let (_, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), 1.try_into().unwrap()); + let (_, tabs_snapshot) = TabMap::new(folds_snapshot, 1.try_into().unwrap()); let (_, wraps_snapshot) = WrapMap::new(tabs_snapshot, font_id, 14.0, Some(60.), cx); let mut block_map = BlockMap::new(wraps_snapshot.clone(), 1, 1); @@ -1262,11 +1263,11 @@ mod tests { let mut buffer_snapshot = buffer.read(cx).snapshot(cx); let (fold_map, folds_snapshot) = FoldMap::new(buffer_snapshot.clone()); - let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), tab_size); + let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot, tab_size); let (wrap_map, wraps_snapshot) = WrapMap::new(tabs_snapshot, font_id, font_size, wrap_width, cx); let mut block_map = BlockMap::new( - wraps_snapshot.clone(), + wraps_snapshot, buffer_start_header_height, excerpt_header_height, ); @@ -1383,7 +1384,7 @@ mod tests { position.column = buffer_snapshot.line_len(position.row); } }; - let row = wraps_snapshot.from_point(position, Bias::Left).row(); + let row = wraps_snapshot.make_wrap_point(position, Bias::Left).row(); ( row, ExpectedBlock::Custom { @@ -1396,7 +1397,7 @@ mod tests { expected_blocks.extend(buffer_snapshot.excerpt_boundaries_in_range(0..).map( |boundary| { let position = - wraps_snapshot.from_point(Point::new(boundary.row, 0), Bias::Left); + wraps_snapshot.make_wrap_point(Point::new(boundary.row, 0), Bias::Left); ( position.row(), ExpectedBlock::ExcerptHeader { diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index a6e5536d15..970910f969 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -41,27 +41,27 @@ impl FoldPoint { &mut self.0.column } - pub fn to_buffer_point(&self, snapshot: &FoldSnapshot) -> Point { + pub fn to_buffer_point(self, snapshot: &FoldSnapshot) -> Point { let mut cursor = snapshot.transforms.cursor::<(FoldPoint, Point)>(); - cursor.seek(self, Bias::Right, &()); + cursor.seek(&self, Bias::Right, &()); let overshoot = self.0 - cursor.start().0 .0; cursor.start().1 + overshoot } - pub fn to_buffer_offset(&self, snapshot: &FoldSnapshot) -> usize { + pub fn to_buffer_offset(self, snapshot: &FoldSnapshot) -> usize { let mut cursor = snapshot.transforms.cursor::<(FoldPoint, Point)>(); - cursor.seek(self, Bias::Right, &()); + cursor.seek(&self, Bias::Right, &()); let overshoot = self.0 - cursor.start().0 .0; snapshot .buffer_snapshot .point_to_offset(cursor.start().1 + overshoot) } - pub fn to_offset(&self, snapshot: &FoldSnapshot) -> FoldOffset { + pub fn to_offset(self, snapshot: &FoldSnapshot) -> FoldOffset { let mut cursor = snapshot .transforms .cursor::<(FoldPoint, TransformSummary)>(); - cursor.seek(self, Bias::Right, &()); + cursor.seek(&self, Bias::Right, &()); let overshoot = self.0 - cursor.start().1.output.lines; let mut offset = cursor.start().1.output.len; if !overshoot.is_zero() { @@ -600,10 +600,7 @@ impl FoldSnapshot { self.transforms.summary().output.longest_row } - pub fn folds_in_range<'a, T>( - &'a self, - range: Range, - ) -> impl Iterator> + pub fn folds_in_range(&self, range: Range) -> impl Iterator> where T: ToOffset, { @@ -689,7 +686,7 @@ impl FoldSnapshot { let ranges = &highlights.1; let start_ix = match ranges.binary_search_by(|probe| { - let cmp = probe.end.cmp(&transform_start, &self.buffer_snapshot()); + let cmp = probe.end.cmp(&transform_start, self.buffer_snapshot()); if cmp.is_gt() { Ordering::Greater } else { @@ -1040,11 +1037,7 @@ impl<'a> Iterator for FoldChunks<'a> { return None; } - let transform = if let Some(item) = self.transform_cursor.item() { - item - } else { - return None; - }; + let transform = self.transform_cursor.item()?; // If we're in a fold, then return the fold's display text and // advance the transform and buffer cursors to the end of the fold. @@ -1150,11 +1143,11 @@ impl Ord for HighlightEndpoint { pub struct FoldOffset(pub usize); impl FoldOffset { - pub fn to_point(&self, snapshot: &FoldSnapshot) -> FoldPoint { + pub fn to_point(self, snapshot: &FoldSnapshot) -> FoldPoint { let mut cursor = snapshot .transforms .cursor::<(FoldOffset, TransformSummary)>(); - cursor.seek(self, Bias::Right, &()); + cursor.seek(&self, Bias::Right, &()); let overshoot = if cursor.item().map_or(true, |t| t.is_fold()) { Point::new(0, (self.0 - cursor.start().0 .0) as u32) } else { @@ -1214,7 +1207,7 @@ mod tests { let buffer_snapshot = buffer.read(cx).snapshot(cx); let mut map = FoldMap::new(buffer_snapshot.clone()).0; - let (mut writer, _, _) = map.write(buffer_snapshot.clone(), vec![]); + let (mut writer, _, _) = map.write(buffer_snapshot, vec![]); let (snapshot2, edits) = writer.fold(vec![ Point::new(0, 2)..Point::new(2, 2), Point::new(2, 4)..Point::new(4, 1), @@ -1245,8 +1238,7 @@ mod tests { ); buffer.snapshot(cx) }); - let (snapshot3, edits) = - map.read(buffer_snapshot.clone(), subscription.consume().into_inner()); + let (snapshot3, edits) = map.read(buffer_snapshot, subscription.consume().into_inner()); assert_eq!(snapshot3.text(), "123a…c123c…eeeee"); assert_eq!( edits, @@ -1276,7 +1268,7 @@ mod tests { let (mut writer, _, _) = map.write(buffer_snapshot.clone(), vec![]); writer.unfold(Some(Point::new(0, 4)..Point::new(0, 4)), true); - let (snapshot6, _) = map.read(buffer_snapshot.clone(), vec![]); + let (snapshot6, _) = map.read(buffer_snapshot, vec![]); assert_eq!(snapshot6.text(), "123aaaaa\nbbbbbb\nccc123456eee"); } @@ -1314,7 +1306,7 @@ mod tests { // Create two adjacent folds. let (mut writer, _, _) = map.write(buffer_snapshot.clone(), vec![]); writer.fold(vec![0..2, 2..5]); - let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]); + let (snapshot, _) = map.read(buffer_snapshot, vec![]); assert_eq!(snapshot.text(), "…fghijkl"); // Edit within one of the folds. @@ -1322,8 +1314,7 @@ mod tests { buffer.edit([(0..1, "12345")], None, cx); buffer.snapshot(cx) }); - let (snapshot, _) = - map.read(buffer_snapshot.clone(), subscription.consume().into_inner()); + let (snapshot, _) = map.read(buffer_snapshot, subscription.consume().into_inner()); assert_eq!(snapshot.text(), "12345…fghijkl"); } } @@ -1340,7 +1331,7 @@ mod tests { Point::new(1, 2)..Point::new(3, 2), Point::new(3, 1)..Point::new(4, 1), ]); - let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]); + let (snapshot, _) = map.read(buffer_snapshot, vec![]); assert_eq!(snapshot.text(), "aa…eeeee"); } @@ -1357,14 +1348,14 @@ mod tests { Point::new(0, 2)..Point::new(2, 2), Point::new(3, 1)..Point::new(4, 1), ]); - let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]); + let (snapshot, _) = map.read(buffer_snapshot, vec![]); assert_eq!(snapshot.text(), "aa…cccc\nd…eeeee"); let buffer_snapshot = buffer.update(cx, |buffer, cx| { buffer.edit([(Point::new(2, 2)..Point::new(3, 1), "")], None, cx); buffer.snapshot(cx) }); - let (snapshot, _) = map.read(buffer_snapshot.clone(), subscription.consume().into_inner()); + let (snapshot, _) = map.read(buffer_snapshot, subscription.consume().into_inner()); assert_eq!(snapshot.text(), "aa…eeeee"); } @@ -1661,7 +1652,7 @@ mod tests { Point::new(3, 1)..Point::new(4, 1), ]); - let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]); + let (snapshot, _) = map.read(buffer_snapshot, vec![]); assert_eq!(snapshot.text(), "aa…cccc\nd…eeeee\nffffff\n"); assert_eq!( snapshot.buffer_rows(0).collect::>(), diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 4f718a9139..4d89767a19 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -253,7 +253,7 @@ impl TabSnapshot { ) } - pub fn from_point(&self, point: Point, bias: Bias) -> TabPoint { + pub fn make_tab_point(&self, point: Point, bias: Bias) -> TabPoint { self.to_tab_point(self.fold_snapshot.to_fold_point(point, bias)) } @@ -290,7 +290,7 @@ impl TabSnapshot { } fn collapse_tabs( - mut chars: impl Iterator, + chars: impl Iterator, column: usize, bias: Bias, tab_size: NonZeroU32, @@ -298,7 +298,7 @@ impl TabSnapshot { let mut expanded_bytes = 0; let mut expanded_chars = 0; let mut collapsed_bytes = 0; - while let Some(c) = chars.next() { + for c in chars { if expanded_bytes >= column { break; } @@ -410,7 +410,7 @@ impl<'a> std::ops::AddAssign<&'a Self> for TextSummary { } // Handles a tab width <= 16 -const SPACES: &'static str = " "; +const SPACES: &str = " "; pub struct TabChunks<'a> { fold_chunks: fold_map::FoldChunks<'a>, @@ -518,7 +518,7 @@ mod tests { let (mut fold_map, _) = FoldMap::new(buffer_snapshot.clone()); fold_map.randomly_mutate(&mut rng); - let (folds_snapshot, _) = fold_map.read(buffer_snapshot.clone(), vec![]); + let (folds_snapshot, _) = fold_map.read(buffer_snapshot, vec![]); log::info!("FoldMap text: {:?}", folds_snapshot.text()); let (_, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), tab_size); diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index aa90f942db..ee6ce2860d 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -285,7 +285,7 @@ impl WrapMap { if tab_snapshot.version <= self.snapshot.tab_snapshot.version { to_remove_len += 1; } else { - let interpolated_edits = self.snapshot.interpolate(tab_snapshot.clone(), &edits); + let interpolated_edits = self.snapshot.interpolate(tab_snapshot.clone(), edits); self.edits_since_sync = self.edits_since_sync.compose(&interpolated_edits); self.interpolated_edits = self.interpolated_edits.compose(&interpolated_edits); } @@ -394,7 +394,7 @@ impl WrapSnapshot { new_rows: Range, } - let mut tab_edits_iter = tab_edits.into_iter().peekable(); + let mut tab_edits_iter = tab_edits.iter().peekable(); let mut row_edits = Vec::new(); while let Some(edit) = tab_edits_iter.next() { let mut row_edit = RowEdit { @@ -671,11 +671,11 @@ impl WrapSnapshot { self.tab_snapshot.to_point(self.to_tab_point(point), bias) } - pub fn from_point(&self, point: Point, bias: Bias) -> WrapPoint { - self.from_tab_point(self.tab_snapshot.from_point(point, bias)) + pub fn make_wrap_point(&self, point: Point, bias: Bias) -> WrapPoint { + self.tab_point_to_wrap_point(self.tab_snapshot.make_tab_point(point, bias)) } - pub fn from_tab_point(&self, point: TabPoint) -> WrapPoint { + pub fn tab_point_to_wrap_point(&self, point: TabPoint) -> WrapPoint { let mut cursor = self.transforms.cursor::<(TabPoint, WrapPoint)>(); cursor.seek(&point, Bias::Right, &()); WrapPoint(cursor.start().1 .0 + (point.0 - cursor.start().0 .0)) @@ -691,7 +691,7 @@ impl WrapSnapshot { } } - self.from_tab_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias)) + self.tab_point_to_wrap_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias)) } pub fn prev_row_boundary(&self, mut point: WrapPoint) -> u32 { @@ -1301,7 +1301,7 @@ mod tests { end_row += 1; let mut expected_text = self.text_chunks(start_row).collect::(); - if expected_text.ends_with("\n") { + if expected_text.ends_with('\n') { expected_text.push('\n'); } let mut expected_text = expected_text diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a07a59e877..e8d3ad4650 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -425,6 +425,7 @@ pub struct Editor { vertical_scroll_margin: f32, placeholder_text: Option>, highlighted_rows: Option>, + #[allow(clippy::type_complexity)] background_highlights: BTreeMap Color, Vec>)>, nav_history: Option, context_menu: Option, @@ -475,6 +476,7 @@ impl Default for SelectionHistoryMode { #[derive(Default)] struct SelectionHistory { + #[allow(clippy::type_complexity)] selections_by_transaction: HashMap]>, Option]>>)>, mode: SelectionHistoryMode, @@ -492,6 +494,7 @@ impl SelectionHistory { .insert(transaction_id, (selections, None)); } + #[allow(clippy::type_complexity)] fn transaction( &self, transaction_id: TransactionId, @@ -499,6 +502,7 @@ impl SelectionHistory { self.selections_by_transaction.get(&transaction_id) } + #[allow(clippy::type_complexity)] fn transaction_mut( &mut self, transaction_id: TransactionId, @@ -1023,7 +1027,7 @@ impl Editor { background_highlights: Default::default(), nav_history: None, context_menu: None, - mouse_context_menu: cx.add_view(|cx| context_menu::ContextMenu::new(cx)), + mouse_context_menu: cx.add_view(context_menu::ContextMenu::new), completion_tasks: Default::default(), next_completion_id: 0, available_code_actions: Default::default(), @@ -1649,7 +1653,7 @@ impl Editor { if let Some(tail) = self.columnar_selection_tail.as_ref() { let tail = tail.to_display_point(&display_map); self.select_columns(tail, position, goal_column, &display_map, cx); - } else if let Some(mut pending) = self.selections.pending_anchor().clone() { + } else if let Some(mut pending) = self.selections.pending_anchor() { let buffer = self.buffer.read(cx).snapshot(cx); let head; let tail; @@ -1764,10 +1768,10 @@ impl Editor { if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) { let start = display_map .clip_point(DisplayPoint::new(row, start_column), Bias::Left) - .to_point(&display_map); + .to_point(display_map); let end = display_map .clip_point(DisplayPoint::new(row, end_column), Bias::Right) - .to_point(&display_map); + .to_point(display_map); if reversed { Some(end..start) } else { @@ -1915,7 +1919,7 @@ impl Editor { cursor.row -= 1; cursor.column = buffer.line_len(cursor.row); } - new_selection.map(|_| cursor.clone()) + new_selection.map(|_| cursor) }) .collect(); @@ -2279,7 +2283,7 @@ impl Editor { let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone()); let completions = project.update(cx, |project, cx| { - project.completions(&buffer, buffer_position.clone(), cx) + project.completions(&buffer, buffer_position, cx) }); let id = post_inc(&mut self.next_completion_id); @@ -2369,7 +2373,7 @@ impl Editor { }; let selections = self.selections.all::(cx); let buffer = buffer_handle.read(cx); - let old_range = completion.old_range.to_offset(&buffer); + let old_range = completion.old_range.to_offset(buffer); let old_text = buffer.text_for_range(old_range.clone()).collect::(); let newest_selection = self.selections.newest_anchor(); @@ -2807,7 +2811,7 @@ impl Editor { let mut tabstop_ranges = tabstop .iter() .flat_map(|tabstop_range| { - let mut delta = 0 as isize; + let mut delta = 0_isize; insertion_ranges.iter().map(move |insertion_range| { let insertion_start = insertion_range.start as isize + delta; delta += @@ -2871,7 +2875,7 @@ impl Editor { } if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) { self.change_selections(Some(Autoscroll::Fit), cx, |s| { - s.select_anchor_ranges(current_ranges.into_iter().cloned()) + s.select_anchor_ranges(current_ranges.iter().cloned()) }); // If snippet state is not at the last tabstop, push it back on the stack if snippet.active_index + 1 < snippet.ranges.len() { @@ -2953,7 +2957,7 @@ impl Editor { } }) }); - this.insert(&"", cx); + this.insert("", cx); }); } @@ -3220,13 +3224,13 @@ impl Editor { } let buffer = &display_map.buffer_snapshot; - let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer); + let mut edit_start = Point::new(rows.start, 0).to_offset(buffer); let edit_end; let cursor_buffer_row; if buffer.max_point().row >= rows.end { // If there's a line after the range, delete the \n from the end of the row range // and position the cursor on the next line. - edit_end = Point::new(rows.end, 0).to_offset(&buffer); + edit_end = Point::new(rows.end, 0).to_offset(buffer); cursor_buffer_row = rows.end; } else { // If there isn't a line after the range, delete the \n from the line before the @@ -3292,7 +3296,7 @@ impl Editor { while let Some(next_selection) = selections_iter.peek() { let next_rows = next_selection.spanned_rows(false, &display_map); - if next_rows.start <= rows.end - 1 { + if next_rows.start < rows.end { rows.end = next_rows.end; selections_iter.next().unwrap(); } else { @@ -3414,7 +3418,7 @@ impl Editor { } // If we didn't move line(s), preserve the existing selections - new_selections.extend(contiguous_row_selections.drain(..)); + new_selections.append(&mut contiguous_row_selections); } self.transact(cx, |this, cx| { @@ -3519,7 +3523,7 @@ impl Editor { } // If we didn't move line(s), preserve the existing selections - new_selections.extend(contiguous_row_selections.drain(..)); + new_selections.append(&mut contiguous_row_selections); } self.transact(cx, |this, cx| { @@ -3831,7 +3835,7 @@ impl Editor { if !selection.is_empty() && !line_mode { selection.goal = SelectionGoal::None; } - let (cursor, goal) = movement::up(&map, selection.start, selection.goal, false); + let (cursor, goal) = movement::up(map, selection.start, selection.goal, false); selection.collapse_to(cursor, goal); }); }) @@ -3863,7 +3867,7 @@ impl Editor { if !selection.is_empty() && !line_mode { selection.goal = SelectionGoal::None; } - let (cursor, goal) = movement::down(&map, selection.end, selection.goal, false); + let (cursor, goal) = movement::down(map, selection.end, selection.goal, false); selection.collapse_to(cursor, goal); }); }); @@ -4779,12 +4783,10 @@ impl Editor { } else { search_start = buffer.len(); } + } else if search_start == 0 { + break; } else { - if search_start == 0 { - break; - } else { - search_start = 0; - } + search_start = 0; } } } @@ -5107,13 +5109,7 @@ impl Editor { })?; let rename = workspace.project().clone().update(cx, |project, cx| { - project.perform_rename( - buffer.clone(), - range.start.clone(), - new_name.clone(), - true, - cx, - ) + project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx) }); Some(cx.spawn(|workspace, mut cx| async move { @@ -5292,7 +5288,7 @@ impl Editor { fn push_to_selection_history(&mut self) { self.selection_history.push(SelectionHistoryEntry { - selections: self.selections.disjoint_anchors().clone(), + selections: self.selections.disjoint_anchors(), select_next_state: self.select_next_state.clone(), add_selections_state: self.add_selections_state.clone(), }); @@ -5325,7 +5321,7 @@ impl Editor { .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx)) { self.selection_history - .insert_transaction(tx_id, self.selections.disjoint_anchors().clone()); + .insert_transaction(tx_id, self.selections.disjoint_anchors()); } } @@ -5339,7 +5335,7 @@ impl Editor { .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx)) { if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) { - *end_selections = Some(self.selections.disjoint_anchors().clone()); + *end_selections = Some(self.selections.disjoint_anchors()); } else { log::error!("unexpectedly ended a transaction that wasn't started by this editor"); } @@ -5441,7 +5437,7 @@ impl Editor { } let end = end.unwrap_or(max_point); - return start.to_point(display_map)..end.to_point(display_map); + start.to_point(display_map)..end.to_point(display_map) } pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext) { @@ -5588,6 +5584,7 @@ impl Editor { cx.notify(); } + #[allow(clippy::type_complexity)] pub fn clear_background_highlights( &mut self, cx: &mut ViewContext, @@ -5629,7 +5626,7 @@ impl Editor { .chain(write_highlights) .flat_map(move |ranges| { let start_ix = match ranges.binary_search_by(|probe| { - let cmp = probe.end.cmp(&left_position, &buffer); + let cmp = probe.end.cmp(&left_position, buffer); if cmp.is_ge() { Ordering::Greater } else { @@ -5642,7 +5639,7 @@ impl Editor { let right_position = right_position.clone(); ranges[start_ix..] .iter() - .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le()) + .take_while(move |range| range.start.cmp(&right_position, buffer).is_le()) }) } @@ -5657,7 +5654,7 @@ impl Editor { for (color_fetcher, ranges) in self.background_highlights.values() { let color = color_fetcher(theme); let start_ix = match ranges.binary_search_by(|probe| { - let cmp = probe.end.cmp(&search_range.start, &buffer); + let cmp = probe.end.cmp(&search_range.start, buffer); if cmp.is_gt() { Ordering::Greater } else { @@ -5667,7 +5664,7 @@ impl Editor { Ok(i) | Err(i) => i, }; for range in &ranges[start_ix..] { - if range.start.cmp(&search_range.end, &buffer).is_ge() { + if range.start.cmp(&search_range.end, buffer).is_ge() { break; } let start = range @@ -5899,7 +5896,7 @@ impl Editor { let (_, ranges) = self.text_highlights::(cx)?; Some( ranges - .into_iter() + .iter() .map(move |range| { range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot) }) @@ -6138,10 +6135,8 @@ impl View for Editor { let new_selected_ranges = if let Some(range_utf16) = range_utf16 { let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end); Some(this.selection_replacement_ranges(range_utf16, cx)) - } else if let Some(marked_ranges) = this.marked_text_ranges(cx) { - Some(marked_ranges) } else { - None + this.marked_text_ranges(cx) }; if let Some(new_selected_ranges) = new_selected_ranges { @@ -6202,7 +6197,7 @@ impl View for Editor { let snapshot = this.buffer.read(cx).read(cx); this.selections .disjoint_anchors() - .into_iter() + .iter() .map(|selection| { selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot) }) @@ -6385,9 +6380,9 @@ impl InvalidationStack { if selections.len() == region.ranges().len() { selections .iter() - .zip(region.ranges().iter().map(|r| r.to_offset(&buffer))) + .zip(region.ranges().iter().map(|r| r.to_offset(buffer))) .all(|(selection, invalidation_range)| { - let head = selection.head().to_offset(&buffer); + let head = selection.head().to_offset(buffer); invalidation_range.start <= head && invalidation_range.end >= head }) } else { @@ -6602,7 +6597,7 @@ pub fn styled_runs_for_code_label<'a>( } else { return Default::default(); }; - let mut muted_style = style.clone(); + let mut muted_style = style; muted_style.highlight(fade_out); let mut runs = SmallVec::<[(Range, HighlightStyle); 3]>::new(); @@ -7104,7 +7099,7 @@ mod tests { fn test_navigation_history(cx: &mut gpui::MutableAppContext) { cx.set_global(Settings::test(cx)); use workspace::Item; - let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(cx)); + let (_, pane) = cx.add_window(Default::default(), Pane::new); let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx); cx.add_view(&pane, |cx| { @@ -7194,7 +7189,7 @@ mod tests { Box::new(NavigationData { cursor_anchor: invalid_anchor.clone(), cursor_position: invalid_point, - scroll_top_anchor: invalid_anchor.clone(), + scroll_top_anchor: invalid_anchor, scroll_top_row: invalid_point.row, scroll_position: Default::default(), }), @@ -8704,98 +8699,102 @@ mod tests { fn test_transpose(cx: &mut gpui::MutableAppContext) { cx.set_global(Settings::test(cx)); - cx.add_window(Default::default(), |cx| { - let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx); + _ = cx + .add_window(Default::default(), |cx| { + let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx); - editor.change_selections(None, cx, |s| s.select_ranges([1..1])); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bac"); - assert_eq!(editor.selections.ranges(cx), [2..2]); + editor.change_selections(None, cx, |s| s.select_ranges([1..1])); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bac"); + assert_eq!(editor.selections.ranges(cx), [2..2]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bca"); - assert_eq!(editor.selections.ranges(cx), [3..3]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bca"); + assert_eq!(editor.selections.ranges(cx), [3..3]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bac"); - assert_eq!(editor.selections.ranges(cx), [3..3]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bac"); + assert_eq!(editor.selections.ranges(cx), [3..3]); - editor - }) - .1; + editor + }) + .1; - cx.add_window(Default::default(), |cx| { - let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx); + _ = cx + .add_window(Default::default(), |cx| { + let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx); - editor.change_selections(None, cx, |s| s.select_ranges([3..3])); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "acb\nde"); - assert_eq!(editor.selections.ranges(cx), [3..3]); + editor.change_selections(None, cx, |s| s.select_ranges([3..3])); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "acb\nde"); + assert_eq!(editor.selections.ranges(cx), [3..3]); - editor.change_selections(None, cx, |s| s.select_ranges([4..4])); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "acbd\ne"); - assert_eq!(editor.selections.ranges(cx), [5..5]); + editor.change_selections(None, cx, |s| s.select_ranges([4..4])); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "acbd\ne"); + assert_eq!(editor.selections.ranges(cx), [5..5]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "acbde\n"); - assert_eq!(editor.selections.ranges(cx), [6..6]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "acbde\n"); + assert_eq!(editor.selections.ranges(cx), [6..6]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "acbd\ne"); - assert_eq!(editor.selections.ranges(cx), [6..6]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "acbd\ne"); + assert_eq!(editor.selections.ranges(cx), [6..6]); - editor - }) - .1; + editor + }) + .1; - cx.add_window(Default::default(), |cx| { - let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx); + _ = cx + .add_window(Default::default(), |cx| { + let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx); - editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4])); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bacd\ne"); - assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]); + editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4])); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bacd\ne"); + assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bcade\n"); - assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bcade\n"); + assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bcda\ne"); - assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bcda\ne"); + assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bcade\n"); - assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bcade\n"); + assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "bcaed\n"); - assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "bcaed\n"); + assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]); - editor - }) - .1; + editor + }) + .1; - cx.add_window(Default::default(), |cx| { - let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx); + _ = cx + .add_window(Default::default(), |cx| { + let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx); - editor.change_selections(None, cx, |s| s.select_ranges([4..4])); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "🏀🍐✋"); - assert_eq!(editor.selections.ranges(cx), [8..8]); + editor.change_selections(None, cx, |s| s.select_ranges([4..4])); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "🏀🍐✋"); + assert_eq!(editor.selections.ranges(cx), [8..8]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "🏀✋🍐"); - assert_eq!(editor.selections.ranges(cx), [11..11]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "🏀✋🍐"); + assert_eq!(editor.selections.ranges(cx), [11..11]); - editor.transpose(&Default::default(), cx); - assert_eq!(editor.text(cx), "🏀🍐✋"); - assert_eq!(editor.selections.ranges(cx), [11..11]); + editor.transpose(&Default::default(), cx); + assert_eq!(editor.text(cx), "🏀🍐✋"); + assert_eq!(editor.selections.ranges(cx), [11..11]); - editor - }) - .1; + editor + }) + .1; } #[gpui::test] @@ -9347,7 +9346,7 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, view) = cx.add_window(|cx| build_editor(buffer, cx)); - view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) + view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; view.update(cx, |view, cx| { @@ -9506,7 +9505,7 @@ mod tests { let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx)); editor - .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx)) + .condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx)) .await; editor.update(cx, |editor, cx| { @@ -9566,7 +9565,7 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, view) = cx.add_window(|cx| build_editor(buffer, cx)); - view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) + view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; view.update(cx, |view, cx| { @@ -9742,7 +9741,7 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, view) = cx.add_window(|cx| build_editor(buffer, cx)); - view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) + view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; view.update(cx, |view, cx| { @@ -9824,7 +9823,7 @@ mod tests { let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx)); editor - .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) + .condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; editor.update(cx, |editor, cx| { @@ -10028,7 +10027,7 @@ mod tests { })) .await; - let fs = FakeFs::new(cx.background().clone()); + let fs = FakeFs::new(cx.background()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; @@ -10142,7 +10141,7 @@ mod tests { })) .await; - let fs = FakeFs::new(cx.background().clone()); + let fs = FakeFs::new(cx.background()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; @@ -10425,7 +10424,7 @@ mod tests { .map(|completion_text| lsp::CompletionItem { label: completion_text.to_string(), text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { - range: replace_range.clone(), + range: replace_range, new_text: completion_text.to_string(), })), ..Default::default() @@ -10856,7 +10855,7 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, view) = cx.add_window(|cx| build_editor(buffer, cx)); - view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) + view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; view.update(cx, |view, cx| { @@ -11084,7 +11083,7 @@ mod tests { let match_indices = [4, 6, 7, 8]; assert_eq!( combine_syntax_and_fuzzy_match_highlights( - &string, + string, Default::default(), syntax_ranges.into_iter(), &match_indices, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 25a71b93dc..da1e78179a 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -110,6 +110,7 @@ impl EditorElement { self.update_view(cx, |view, cx| view.snapshot(cx)) } + #[allow(clippy::too_many_arguments)] fn mouse_down( &self, position: Vector2F, @@ -696,6 +697,7 @@ impl EditorElement { cx.scene.pop_layer(); } + #[allow(clippy::too_many_arguments)] fn paint_highlighted_range( &self, range: Range, @@ -857,7 +859,7 @@ impl EditorElement { .style .placeholder_text .as_ref() - .unwrap_or_else(|| &self.style.text); + .unwrap_or(&self.style.text); let placeholder_text = snapshot.placeholder_text(); let placeholder_lines = placeholder_text .as_ref() @@ -866,7 +868,7 @@ impl EditorElement { .skip(rows.start as usize) .chain(iter::repeat("")) .take(rows.len()); - return placeholder_lines + placeholder_lines .map(|line| { cx.text_layout_cache.layout_str( line, @@ -881,7 +883,7 @@ impl EditorElement { )], ) }) - .collect(); + .collect() } else { let style = &self.style; let chunks = snapshot.chunks(rows.clone(), true).map(|chunk| { @@ -926,14 +928,15 @@ impl EditorElement { layout_highlighted_chunks( chunks, &style.text, - &cx.text_layout_cache, - &cx.font_cache, + cx.text_layout_cache, + cx.font_cache, MAX_LINE_LEN, rows.len() as usize, ) } } + #[allow(clippy::too_many_arguments)] fn layout_blocks( &mut self, rows: Range, @@ -1299,7 +1302,9 @@ impl Element for EditorElement { } // Render the local selections in the leader's color when following. - let local_replica_id = view.leader_replica_id.unwrap_or(view.replica_id(cx)); + let local_replica_id = view + .leader_replica_id + .unwrap_or_else(|| view.replica_id(cx)); selections.push(( local_replica_id, @@ -1357,19 +1362,19 @@ impl Element for EditorElement { self.update_view(cx.app, |view, cx| { let clamped = view.clamp_scroll_left(scroll_max.x()); - let autoscrolled; - if autoscroll_horizontally { - autoscrolled = view.autoscroll_horizontally( + + let autoscrolled = if autoscroll_horizontally { + view.autoscroll_horizontally( start_row, text_size.x(), scroll_width, em_width, &line_layouts, cx, - ); + ) } else { - autoscrolled = false; - } + false + }; if clamped || autoscrolled { snapshot = view.snapshot(cx); @@ -1991,8 +1996,8 @@ mod tests { let layouts = editor.update(cx, |editor, cx| { let snapshot = editor.snapshot(cx); let mut presenter = cx.build_presenter(window_id, 30.); - let mut layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx); - element.layout_line_numbers(0..6, &Default::default(), &snapshot, &mut layout_cx) + let layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx); + element.layout_line_numbers(0..6, &Default::default(), &snapshot, &layout_cx) }); assert_eq!(layouts.len(), 6); } diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 37a2a66e05..d8240920c0 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -158,7 +158,7 @@ fn show_hover( // query the LSP for hover info let hover_request = cx.update(|cx| { project.update(cx, |project, cx| { - project.hover(&buffer, buffer_position.clone(), cx) + project.hover(&buffer, buffer_position, cx) }) }); @@ -222,7 +222,7 @@ fn show_hover( Some(InfoPopover { project: project.clone(), - symbol_range: range.clone(), + symbol_range: range, contents: hover_result.contents, }) }); diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 59f9a98448..cb7632d5e2 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -76,14 +76,14 @@ impl FollowableItem for Editor { }) .collect::>>()?; if !selections.is_empty() { - editor.set_selections_from_remote(selections.into(), cx); + editor.set_selections_from_remote(selections, cx); } if let Some(anchor) = state.scroll_top_anchor { editor.set_scroll_top_anchor( Anchor { buffer_id: Some(state.buffer_id as usize), - excerpt_id: excerpt_id.clone(), + excerpt_id, text_anchor: language::proto::deserialize_anchor(anchor) .ok_or_else(|| anyhow!("invalid scroll top"))?, }, @@ -198,19 +198,17 @@ impl FollowableItem for Editor { if !selections.is_empty() { self.set_selections_from_remote(selections, cx); self.request_autoscroll_remotely(Autoscroll::Newest, cx); - } else { - if let Some(anchor) = message.scroll_top_anchor { - self.set_scroll_top_anchor( - Anchor { - buffer_id: Some(buffer_id), - excerpt_id: excerpt_id.clone(), - text_anchor: language::proto::deserialize_anchor(anchor) - .ok_or_else(|| anyhow!("invalid scroll top"))?, - }, - vec2f(message.scroll_x, message.scroll_y), - cx, - ); - } + } else if let Some(anchor) = message.scroll_top_anchor { + self.set_scroll_top_anchor( + Anchor { + buffer_id: Some(buffer_id), + excerpt_id, + text_anchor: language::proto::deserialize_anchor(anchor) + .ok_or_else(|| anyhow!("invalid scroll top"))?, + }, + vec2f(message.scroll_x, message.scroll_y), + cx, + ); } } } @@ -436,8 +434,7 @@ impl Item for Editor { .buffer() .read(cx) .as_singleton() - .expect("cannot call save_as on an excerpt list") - .clone(); + .expect("cannot call save_as on an excerpt list"); project.update(cx, |project, cx| { project.save_buffer_as(buffer, abs_path, cx) @@ -503,6 +500,12 @@ pub struct CursorPosition { _observe_active_editor: Option, } +impl Default for CursorPosition { + fn default() -> Self { + Self::new() + } +} + impl CursorPosition { pub fn new() -> Self { Self { diff --git a/crates/editor/src/link_go_to_definition.rs b/crates/editor/src/link_go_to_definition.rs index cbdeb30191..c1544306d6 100644 --- a/crates/editor/src/link_go_to_definition.rs +++ b/crates/editor/src/link_go_to_definition.rs @@ -83,7 +83,7 @@ pub fn update_go_to_definition_link( &point, &editor.link_go_to_definition_state.last_mouse_location, ) { - if a.cmp(&b, &snapshot.buffer_snapshot).is_eq() { + if a.cmp(b, &snapshot.buffer_snapshot).is_eq() { return; } } @@ -126,7 +126,7 @@ pub fn cmd_shift_changed( LinkDefinitionKind::Symbol }; - show_link_definition(kind, editor, point.clone(), snapshot, cx); + show_link_definition(kind, editor, point, snapshot, cx); } else { hide_link_definition(editor, cx) } @@ -204,12 +204,10 @@ pub fn show_link_definition( // query the LSP for definition info let definition_request = cx.update(|cx| { project.update(cx, |project, cx| match definition_kind { - LinkDefinitionKind::Symbol => { - project.definition(&buffer, buffer_position.clone(), cx) - } + LinkDefinitionKind::Symbol => project.definition(&buffer, buffer_position, cx), LinkDefinitionKind::Type => { - project.type_definition(&buffer, buffer_position.clone(), cx) + project.type_definition(&buffer, buffer_position, cx) } }) }); @@ -363,7 +361,7 @@ fn go_to_fetched_definition_of_kind( editor_handle.update(cx, |editor, cx| { editor.select( &Select(SelectPhase::Begin { - position: point.clone(), + position: point, add: false, click_count: 1, }), diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index b9e8b7e682..53021870c6 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -33,7 +33,7 @@ use text::{ use theme::SyntaxTheme; use util::post_inc; -const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize]; +const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize]; pub type ExcerptId = Locator; @@ -289,10 +289,16 @@ impl MultiBuffer { self.read(cx).has_conflict() } + // The `is_empty` signature doesn't match what clippy expects + #[allow(clippy::len_without_is_empty)] pub fn len(&self, cx: &AppContext) -> usize { self.read(cx).len() } + pub fn is_empty(&self, cx: &AppContext) -> bool { + self.len(cx) != 0 + } + pub fn symbols_containing( &self, offset: T, @@ -338,6 +344,7 @@ impl MultiBuffer { _ => Default::default(), }; + #[allow(clippy::type_complexity)] let mut buffer_edits: HashMap, Arc, bool, u32)>> = Default::default(); let mut cursor = snapshot.excerpts.cursor::(); @@ -594,13 +601,13 @@ impl MultiBuffer { break; } - let mut start = excerpt.range.context.start.clone(); - let mut end = excerpt.range.context.end.clone(); + let mut start = excerpt.range.context.start; + let mut end = excerpt.range.context.end; if excerpt.id == selection.start.excerpt_id { - start = selection.start.text_anchor.clone(); + start = selection.start.text_anchor; } if excerpt.id == selection.end.excerpt_id { - end = selection.end.text_anchor.clone(); + end = selection.end.text_anchor; } selections_by_buffer .entry(excerpt.buffer_id) @@ -666,7 +673,7 @@ impl MultiBuffer { while let Some(transaction) = self.history.pop_undo() { let mut undone = false; for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions { - if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) { + if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) { undone |= buffer.update(cx, |buffer, cx| { let undo_to = *buffer_transaction_id; if let Some(entry) = buffer.peek_undo_stack() { @@ -693,7 +700,7 @@ impl MultiBuffer { while let Some(transaction) = self.history.pop_redo() { let mut redone = false; for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions { - if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(&buffer_id) { + if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) { redone |= buffer.update(cx, |buffer, cx| { let redo_to = *buffer_transaction_id; if let Some(entry) = buffer.peek_redo_stack() { @@ -982,8 +989,8 @@ impl MultiBuffer { } // If point is at the end of the buffer, the last excerpt is returned - pub fn point_to_buffer_offset<'a, T: ToOffset>( - &'a self, + pub fn point_to_buffer_offset( + &self, point: T, cx: &AppContext, ) -> Option<(ModelHandle, usize)> { @@ -1004,8 +1011,8 @@ impl MultiBuffer { }) } - pub fn range_to_buffer_ranges<'a, T: ToOffset>( - &'a self, + pub fn range_to_buffer_ranges( + &self, range: Range, cx: &AppContext, ) -> Vec<(ModelHandle, Range)> { @@ -1112,8 +1119,8 @@ impl MultiBuffer { cx.notify(); } - pub fn text_anchor_for_position<'a, T: ToOffset>( - &'a self, + pub fn text_anchor_for_position( + &self, position: T, cx: &AppContext, ) -> Option<(ModelHandle, language::Anchor)> { @@ -1439,7 +1446,7 @@ impl MultiBuffer { .flat_map(|b| &b.excerpts) .cloned() .collect::>(); - if excerpt_ids.len() == 0 || (rng.gen() && excerpt_ids.len() < max_excerpts) { + if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) { let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() { let text = RandomCharIter::new(&mut *rng).take(10).collect::(); buffers.push(cx.add_model(|cx| Buffer::new(0, text, cx))); @@ -1514,8 +1521,8 @@ impl MultiBuffer { .choose(rng) .map(|state| state.buffer.clone()); - if rng.gen() && buffer.is_some() { - buffer.unwrap().update(cx, |buffer, cx| { + if let Some(buffer) = buffer { + buffer.update(cx, |buffer, cx| { if rng.gen() { buffer.randomly_edit(rng, mutation_count, cx); } else { @@ -1542,10 +1549,7 @@ impl MultiBufferSnapshot { .collect() } - pub fn reversed_chars_at<'a, T: ToOffset>( - &'a self, - position: T, - ) -> impl Iterator + 'a { + pub fn reversed_chars_at(&self, position: T) -> impl Iterator + '_ { let mut offset = position.to_offset(self); let mut cursor = self.excerpts.cursor::(); cursor.seek(&offset, Bias::Left, &()); @@ -1579,16 +1583,13 @@ impl MultiBufferSnapshot { .flat_map(|c| c.chars().rev()) } - pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator + 'a { + pub fn chars_at(&self, position: T) -> impl Iterator + '_ { let offset = position.to_offset(self); self.text_for_range(offset..self.len()) .flat_map(|chunk| chunk.chars()) } - pub fn text_for_range<'a, T: ToOffset>( - &'a self, - range: Range, - ) -> impl Iterator { + pub fn text_for_range(&self, range: Range) -> impl Iterator + '_ { self.chunks(range, false).map(|chunk| chunk.text) } @@ -1655,6 +1656,10 @@ impl MultiBufferSnapshot { self.excerpts.summary().text.len } + pub fn is_empty(&self) -> bool { + self.excerpts.summary().text.len == 0 + } + pub fn max_buffer_row(&self) -> u32 { self.excerpts.summary().max_buffer_row } @@ -1737,7 +1742,7 @@ impl MultiBufferSnapshot { *cursor.start() + overshoot } - pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range) -> MultiBufferBytes<'a> { + pub fn bytes_in_range(&self, range: Range) -> MultiBufferBytes { let range = range.start.to_offset(self)..range.end.to_offset(self); let mut excerpts = self.excerpts.cursor::(); excerpts.seek(&range.start, Bias::Right, &()); @@ -1760,7 +1765,7 @@ impl MultiBufferSnapshot { } } - pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> { + pub fn buffer_rows(&self, start_row: u32) -> MultiBufferRows { let mut result = MultiBufferRows { buffer_row_range: 0..0, excerpts: self.excerpts.cursor(), @@ -1769,11 +1774,7 @@ impl MultiBufferSnapshot { result } - pub fn chunks<'a, T: ToOffset>( - &'a self, - range: Range, - language_aware: bool, - ) -> MultiBufferChunks<'a> { + pub fn chunks(&self, range: Range, language_aware: bool) -> MultiBufferChunks { let range = range.start.to_offset(self)..range.end.to_offset(self); let mut chunks = MultiBufferChunks { range: range.clone(), @@ -2033,7 +2034,7 @@ impl MultiBufferSnapshot { self.excerpts.summary().text.clone() } - pub fn text_summary_for_range<'a, D, O>(&'a self, range: Range) -> D + pub fn text_summary_for_range(&self, range: Range) -> D where D: TextDimension, O: ToOffset, @@ -2204,15 +2205,15 @@ impl MultiBufferSnapshot { let (anchor_ix, anchor) = anchors.next().unwrap(); let mut anchor = anchor.clone(); - // Leave min and max anchors unchanged. - if *old_excerpt_id == ExcerptId::max() || *old_excerpt_id == ExcerptId::min() { - kept_position = true; - } - // If the old excerpt still exists at this location, then leave - // the anchor unchanged. - else if next_excerpt.map_or(false, |excerpt| { + let id_invalid = + *old_excerpt_id == ExcerptId::max() || *old_excerpt_id == ExcerptId::min(); + let still_exists = next_excerpt.map_or(false, |excerpt| { excerpt.id == *old_excerpt_id && excerpt.contains(&anchor) - }) { + }); + + // Leave min and max anchors unchanged if invalid or + // if the old excerpt still exists at this location + if id_invalid || still_exists { kept_position = true; } // If the old excerpt no longer exists at this location, then attempt to @@ -2239,7 +2240,7 @@ impl MultiBufferSnapshot { .cmp(&excerpt.range.context.end, &excerpt.buffer) .is_gt() { - text_anchor = excerpt.range.context.end.clone(); + text_anchor = excerpt.range.context.end; } Anchor { buffer_id: Some(excerpt.buffer_id), @@ -2256,7 +2257,7 @@ impl MultiBufferSnapshot { .cmp(&excerpt.range.context.start, &excerpt.buffer) .is_lt() { - text_anchor = excerpt.range.context.start.clone(); + text_anchor = excerpt.range.context.start; } Anchor { buffer_id: Some(excerpt.buffer_id), @@ -2349,10 +2350,10 @@ impl MultiBufferSnapshot { } } - pub fn excerpt_boundaries_in_range<'a, R, T>( - &'a self, + pub fn excerpt_boundaries_in_range( + &self, range: R, - ) -> impl Iterator + 'a + ) -> impl Iterator + '_ where R: RangeBounds, T: ToOffset, @@ -2635,13 +2636,12 @@ impl MultiBufferSnapshot { cursor .take_while(move |excerpt| excerpt.id <= range.end.excerpt_id) .flat_map(move |excerpt| { - let mut query_range = - excerpt.range.context.start.clone()..excerpt.range.context.end.clone(); + let mut query_range = excerpt.range.context.start..excerpt.range.context.end; if excerpt.id == range.start.excerpt_id { - query_range.start = range.start.text_anchor.clone(); + query_range.start = range.start.text_anchor; } if excerpt.id == range.end.excerpt_id { - query_range.end = range.end.text_anchor.clone(); + query_range.end = range.end.text_anchor; } excerpt @@ -2652,12 +2652,12 @@ impl MultiBufferSnapshot { let mut start = Anchor { buffer_id: Some(excerpt.buffer_id), excerpt_id: excerpt.id.clone(), - text_anchor: selection.start.clone(), + text_anchor: selection.start, }; let mut end = Anchor { buffer_id: Some(excerpt.buffer_id), excerpt_id: excerpt.id.clone(), - text_anchor: selection.end.clone(), + text_anchor: selection.end, }; if range.start.cmp(&start, self).is_gt() { start = range.start.clone(); @@ -2862,11 +2862,7 @@ impl Excerpt { } } - fn chunks_in_range<'a>( - &'a self, - range: Range, - language_aware: bool, - ) -> ExcerptChunks<'a> { + fn chunks_in_range(&self, range: Range, language_aware: bool) -> ExcerptChunks { let content_start = self.range.context.start.to_offset(&self.buffer); let chunks_start = content_start + range.start; let chunks_end = content_start + cmp::min(range.end, self.text_summary.len); @@ -2913,12 +2909,12 @@ impl Excerpt { .cmp(&self.range.context.start, &self.buffer) .is_lt() { - self.range.context.start.clone() + self.range.context.start } else if text_anchor .cmp(&self.range.context.end, &self.buffer) .is_gt() { - self.range.context.end.clone() + self.range.context.end } else { text_anchor } @@ -3835,7 +3831,7 @@ mod tests { "Removing excerpt {}: {:?}", ix, buffer - .text_for_range(range.to_offset(&buffer)) + .text_for_range(range.to_offset(buffer)) .collect::(), ); } @@ -3851,7 +3847,7 @@ mod tests { let bias = if rng.gen() { Bias::Left } else { Bias::Right }; log::info!("Creating anchor at {} with bias {:?}", offset, bias); anchors.push(multibuffer.anchor_at(offset, bias)); - anchors.sort_by(|a, b| a.cmp(&b, &multibuffer)); + anchors.sort_by(|a, b| a.cmp(b, &multibuffer)); } 40..=44 if !anchors.is_empty() => { let multibuffer = multibuffer.read(cx).read(cx); @@ -3896,7 +3892,7 @@ mod tests { let prev_excerpt_id = excerpt_ids .get(prev_excerpt_ix) .cloned() - .unwrap_or(ExcerptId::max()); + .unwrap_or_else(ExcerptId::max); let excerpt_ix = (prev_excerpt_ix + 1).min(expected_excerpts.len()); log::info!( @@ -3984,11 +3980,7 @@ mod tests { assert_eq!( snapshot.max_buffer_row(), - expected_buffer_rows - .into_iter() - .filter_map(|r| r) - .max() - .unwrap() + expected_buffer_rows.into_iter().flatten().max().unwrap() ); let mut excerpt_starts = excerpt_starts.into_iter(); diff --git a/crates/editor/src/multi_buffer/anchor.rs b/crates/editor/src/multi_buffer/anchor.rs index 1340ea814d..cb8a1692b9 100644 --- a/crates/editor/src/multi_buffer/anchor.rs +++ b/crates/editor/src/multi_buffer/anchor.rs @@ -34,7 +34,7 @@ impl Anchor { &self.excerpt_id } - pub fn cmp<'a>(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Ordering { + pub fn cmp(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Ordering { let excerpt_id_cmp = self.excerpt_id.cmp(&other.excerpt_id); if excerpt_id_cmp.is_eq() { if self.excerpt_id == ExcerptId::min() || self.excerpt_id == ExcerptId::max() { @@ -111,15 +111,15 @@ impl AnchorRangeExt for Range { fn cmp(&self, other: &Range, buffer: &MultiBufferSnapshot) -> Ordering { match self.start.cmp(&other.start, buffer) { Ordering::Equal => other.end.cmp(&self.end, buffer), - ord @ _ => ord, + ord => ord, } } fn to_offset(&self, content: &MultiBufferSnapshot) -> Range { - self.start.to_offset(&content)..self.end.to_offset(&content) + self.start.to_offset(content)..self.end.to_offset(content) } fn to_point(&self, content: &MultiBufferSnapshot) -> Range { - self.start.to_point(&content)..self.end.to_point(&content) + self.start.to_point(content)..self.end.to_point(content) } } diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index a05a46fc6d..9d6450f8ec 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -68,7 +68,7 @@ impl SelectionsCollection { self.pending = other.pending.clone(); } - pub fn count<'a>(&self) -> usize { + pub fn count(&self) -> usize { let mut count = self.disjoint.len(); if self.pending.is_some() { count += 1; @@ -365,7 +365,7 @@ impl<'a> MutableSelectionsCollection<'a> { let mut changed = false; self.collection.disjoint = self .disjoint - .into_iter() + .iter() .filter(|selection| { let found = selection.id == selection_id; changed |= found; @@ -464,7 +464,7 @@ impl<'a> MutableSelectionsCollection<'a> { return true; } - return false; + false } pub fn insert_range(&mut self, range: Range) @@ -729,8 +729,7 @@ impl<'a> MutableSelectionsCollection<'a> { kept_end }; if !kept_head { - selections_with_lost_position - .insert(selection.id, selection.head().excerpt_id.clone()); + selections_with_lost_position.insert(selection.id, selection.head().excerpt_id); } Selection { @@ -761,10 +760,8 @@ impl<'a> MutableSelectionsCollection<'a> { kept_end }; if !kept_head { - selections_with_lost_position.insert( - pending.selection.id, - pending.selection.head().excerpt_id.clone(), - ); + selections_with_lost_position + .insert(pending.selection.id, pending.selection.head().excerpt_id); } pending.selection.start = start; @@ -814,5 +811,5 @@ fn resolve>( selection: &Selection, buffer: &MultiBufferSnapshot, ) -> Selection { - selection.map(|p| p.summary::(&buffer)) + selection.map(|p| p.summary::(buffer)) } diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index dbdc3ec329..768e58407e 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -262,7 +262,7 @@ impl PickerDelegate for FileFinder { self.labels_for_match(path_match); Flex::column() .with_child( - Label::new(file_name.to_string(), style.label.clone()) + Label::new(file_name, style.label.clone()) .with_highlights(file_name_positions) .boxed(), ) @@ -333,7 +333,7 @@ mod tests { cx.dispatch_action(window_id, SelectNext); cx.dispatch_action(window_id, Confirm); active_pane - .condition(&cx, |pane, _| pane.active_item().is_some()) + .condition(cx, |pane, _| pane.active_item().is_some()) .await; cx.read(|cx| { let active_item = active_pane.read(cx).active_item().unwrap(); diff --git a/crates/fsevent/examples/events.rs b/crates/fsevent/examples/events.rs index 73ec6405d4..43678dd6d6 100644 --- a/crates/fsevent/examples/events.rs +++ b/crates/fsevent/examples/events.rs @@ -4,7 +4,7 @@ use std::{env::args, path::Path, time::Duration}; fn main() { let paths = args().skip(1).collect::>(); let paths = paths.iter().map(Path::new).collect::>(); - assert!(paths.len() > 0, "Must pass 1 or more paths as arguments"); + assert!(!paths.is_empty(), "Must pass 1 or more paths as arguments"); let (stream, _handle) = EventStream::new(&paths, Duration::from_millis(100)); stream.run(|events| { eprintln!("event batch"); diff --git a/crates/fsevent/src/fsevent.rs b/crates/fsevent/src/fsevent.rs index 4b4d3766bd..59c03ccc65 100644 --- a/crates/fsevent/src/fsevent.rs +++ b/crates/fsevent/src/fsevent.rs @@ -233,11 +233,9 @@ impl EventStream { } } - if !events.is_empty() { - if !callback(events) { - fs::FSEventStreamStop(stream_ref); - cf::CFRunLoopStop(cf::CFRunLoopGetCurrent()); - } + if !events.is_empty() && !callback(events) { + fs::FSEventStreamStop(stream_ref); + cf::CFRunLoopStop(cf::CFRunLoopGetCurrent()); } } } diff --git a/crates/fuzzy/src/char_bag.rs b/crates/fuzzy/src/char_bag.rs index 135c5a768e..8fc36368a1 100644 --- a/crates/fuzzy/src/char_bag.rs +++ b/crates/fuzzy/src/char_bag.rs @@ -10,15 +10,15 @@ impl CharBag { fn insert(&mut self, c: char) { let c = c.to_ascii_lowercase(); - if c >= 'a' && c <= 'z' { + if ('a'..='z').contains(&c) { let mut count = self.0; - let idx = c as u8 - 'a' as u8; - count = count >> (idx * 2); + let idx = c as u8 - b'a'; + count >>= idx * 2; count = ((count << 1) | 1) & 3; - count = count << idx * 2; + count <<= idx * 2; self.0 |= count; - } else if c >= '0' && c <= '9' { - let idx = c as u8 - '0' as u8; + } else if ('0'..='9').contains(&c) { + let idx = c as u8 - b'0'; self.0 |= 1 << (idx + 52); } else if c == '-' { self.0 |= 1 << 62; diff --git a/crates/fuzzy/src/fuzzy.rs b/crates/fuzzy/src/fuzzy.rs index 401ab33d7f..2f108b6274 100644 --- a/crates/fuzzy/src/fuzzy.rs +++ b/crates/fuzzy/src/fuzzy.rs @@ -35,7 +35,7 @@ trait Match: Ord { trait MatchCandidate { fn has_chars(&self, bag: CharBag) -> bool; - fn to_string<'a>(&'a self) -> Cow<'a, str>; + fn to_string(&self) -> Cow<'_, str>; } #[derive(Clone, Debug)] @@ -64,6 +64,9 @@ pub trait PathMatchCandidateSet<'a>: Send + Sync { type Candidates: Iterator>; fn id(&self) -> usize; fn len(&self) -> usize; + fn is_empty(&self) -> bool { + self.len() == 0 + } fn prefix(&self) -> Arc; fn candidates(&'a self, start: usize) -> Self::Candidates; } @@ -239,7 +242,7 @@ pub async fn match_strings( if results.is_empty() { results = segment_result; } else { - util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(&a)); + util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(a)); } } results @@ -299,7 +302,7 @@ pub async fn match_paths<'a, Set: PathMatchCandidateSet<'a>>( candidate_set.prefix(), candidates, results, - &cancel_flag, + cancel_flag, ); } if tree_end >= segment_end { @@ -317,7 +320,7 @@ pub async fn match_paths<'a, Set: PathMatchCandidateSet<'a>>( if results.is_empty() { results = segment_result; } else { - util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(&a)); + util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(a)); } } results @@ -426,7 +429,7 @@ impl<'a> Matcher<'a> { lowercase_candidate_chars.push(c.to_ascii_lowercase()); } - if !self.find_last_positions(&lowercase_prefix, &lowercase_candidate_chars) { + if !self.find_last_positions(lowercase_prefix, &lowercase_candidate_chars) { continue; } @@ -439,13 +442,13 @@ impl<'a> Matcher<'a> { let score = self.score_match( &candidate_chars, &lowercase_candidate_chars, - &prefix, - &lowercase_prefix, + prefix, + lowercase_prefix, ); if score > 0.0 { let mut mat = build_match(&candidate, score); - if let Err(i) = results.binary_search_by(|m| mat.cmp(&m)) { + if let Err(i) = results.binary_search_by(|m| mat.cmp(m)) { if results.len() < self.max_results { mat.set_positions(self.match_positions.clone()); results.insert(i, mat); @@ -523,6 +526,7 @@ impl<'a> Matcher<'a> { score } + #[allow(clippy::too_many_arguments)] fn recursive_score_match( &mut self, path: &[char], @@ -579,9 +583,9 @@ impl<'a> Matcher<'a> { if last == '/' { char_score = 0.9; - } else if last == '-' || last == '_' || last == ' ' || last.is_numeric() { - char_score = 0.8; - } else if last.is_lowercase() && curr.is_uppercase() { + } else if (last == '-' || last == '_' || last == ' ' || last.is_numeric()) + || (last.is_lowercase() && curr.is_uppercase()) + { char_score = 0.8; } else if last == '.' { char_score = 0.7; @@ -662,18 +666,18 @@ mod tests { let mut query: &[char] = &['d', 'c']; let mut matcher = Matcher::new(query, query, query.into(), false, 10); let result = matcher.find_last_positions(&['a', 'b', 'c'], &['b', 'd', 'e', 'f']); - assert_eq!(result, false); + assert!(!result); query = &['c', 'd']; let mut matcher = Matcher::new(query, query, query.into(), false, 10); let result = matcher.find_last_positions(&['a', 'b', 'c'], &['b', 'd', 'e', 'f']); - assert_eq!(result, true); + assert!(result); assert_eq!(matcher.last_positions, vec![2, 4]); query = &['z', '/', 'z', 'f']; let mut matcher = Matcher::new(query, query, query.into(), false, 10); let result = matcher.find_last_positions(&['z', 'e', 'd', '/'], &['z', 'e', 'd', '/', 'f']); - assert_eq!(result, true); + assert!(result); assert_eq!(matcher.last_positions, vec![0, 3, 4, 8]); } @@ -741,7 +745,7 @@ mod tests { fn match_query<'a>( query: &str, smart_case: bool, - paths: &Vec<&'a str>, + paths: &[&'a str], ) -> Vec<(&'a str, Vec)> { let lowercase_query = query.to_lowercase().chars().collect::>(); let query = query.chars().collect::>(); diff --git a/crates/gpui/build.rs b/crates/gpui/build.rs index a9d126763d..836d586c26 100644 --- a/crates/gpui/build.rs +++ b/crates/gpui/build.rs @@ -41,7 +41,7 @@ fn compile_context_predicate_parser() { .compile("tree_sitter_context_predicate"); } -const SHADER_HEADER_PATH: &'static str = "./src/platform/mac/shaders/shaders.h"; +const SHADER_HEADER_PATH: &str = "./src/platform/mac/shaders/shaders.h"; fn compile_metal_shaders() { let shader_path = "./src/platform/mac/shaders/shaders.metal"; diff --git a/crates/gpui/examples/text.rs b/crates/gpui/examples/text.rs index 8e0153fe38..d4e873f039 100644 --- a/crates/gpui/examples/text.rs +++ b/crates/gpui/examples/text.rs @@ -85,11 +85,11 @@ impl gpui::Element for TextElement { text, font_size, &[ - (1, normal.clone()), - (1, bold.clone()), - (1, normal.clone()), - (1, bold.clone()), - (text.len() - 4, normal.clone()), + (1, normal), + (1, bold), + (1, normal), + (1, bold), + (text.len() - 4, normal), ], ); diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index c028c5de73..9071f98dfe 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -432,7 +432,7 @@ impl TestAppContext { first_entity_id: usize, ) -> Self { let mut cx = MutableAppContext::new( - foreground.clone(), + foreground, background, platform, foreground_platform.clone(), @@ -964,6 +964,7 @@ pub struct MutableAppContext { release_observations: Arc>>>, action_dispatch_observations: Arc>>, + #[allow(clippy::type_complexity)] presenters_and_platform_windows: HashMap>, Box)>, foreground: Rc, @@ -1172,7 +1173,9 @@ impl MutableAppContext { F: 'static + FnMut(&mut V, &A, &mut ViewContext) -> Option>>, { self.add_action(move |view, action, cx| { - handler(view, action, cx).map(|task| task.detach_and_log_err(cx)); + if let Some(task) = handler(view, action, cx) { + task.detach_and_log_err(cx); + } }) } @@ -1240,7 +1243,7 @@ impl MutableAppContext { .cx .views .remove(&(window_id, view_id)) - .ok_or(anyhow!("view not found"))?; + .ok_or_else(|| anyhow!("view not found"))?; let element = view.render(params, self); self.cx.views.insert((window_id, view_id), view); Ok(element) @@ -1252,6 +1255,7 @@ impl MutableAppContext { titlebar_height: f32, ) -> HashMap { self.start_frame(); + #[allow(clippy::needless_collect)] let view_ids = self .views .keys() @@ -1263,6 +1267,7 @@ impl MutableAppContext { } }) .collect::>(); + view_ids .into_iter() .map(|view_id| { @@ -2401,7 +2406,7 @@ impl MutableAppContext { let mut invalidation = self .cx .windows - .get_mut(&window_id) + .get_mut(window_id) .unwrap() .invalidation .take(); @@ -2626,7 +2631,7 @@ impl MutableAppContext { fn handle_action_dispatch_notification_effect(&mut self, action_id: TypeId) { let mut callbacks = mem::take(&mut *self.action_dispatch_observations.lock()); - for (_, callback) in &mut callbacks { + for callback in callbacks.values_mut() { callback(action_id, self); } self.action_dispatch_observations.lock().extend(callbacks); @@ -3228,7 +3233,7 @@ pub trait AnyView { cx: &mut MutableAppContext, ) -> Option>>>; fn ui_name(&self) -> &'static str; - fn render<'a>(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox; + fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox; fn on_focus_in( &mut self, cx: &mut MutableAppContext, @@ -3304,7 +3309,7 @@ where T::ui_name() } - fn render<'a>(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox { + fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox { View::render(self, &mut RenderContext::new(params, cx)) } @@ -3611,7 +3616,7 @@ impl Deref for ModelContext<'_, M> { type Target = MutableAppContext; fn deref(&self) -> &Self::Target { - &self.app + self.app } } @@ -4140,7 +4145,7 @@ impl Deref for ViewContext<'_, M> { type Target = MutableAppContext; fn deref(&self) -> &Self::Target { - &self.app + self.app } } @@ -4290,7 +4295,7 @@ impl ModelHandle { cx.read_model(self) } - pub fn read_with<'a, C, F, S>(&self, cx: &C, read: F) -> S + pub fn read_with(&self, cx: &C, read: F) -> S where C: ReadModelWith, F: FnOnce(&T, &AppContext) -> S, @@ -4381,7 +4386,6 @@ impl ModelHandle { } }), cx.subscribe(self, { - let tx = tx.clone(); move |_, _, _| { tx.unbounded_send(()).ok(); } @@ -5258,6 +5262,7 @@ pub enum Subscription { ReleaseObservation { id: usize, entity_id: usize, + #[allow(clippy::type_complexity)] observations: Option>>>>, }, @@ -5407,7 +5412,7 @@ impl Drop for Subscription { } Subscription::ActionObservation { id, observations } => { if let Some(observations) = observations.as_ref().and_then(Weak::upgrade) { - observations.lock().remove(&id); + observations.lock().remove(id); } } Subscription::WindowActivationObservation { @@ -5465,6 +5470,7 @@ lazy_static! { #[derive(Default)] pub struct LeakDetector { next_handle_id: usize, + #[allow(clippy::type_complexity)] handle_backtraces: HashMap< usize, ( @@ -5502,11 +5508,9 @@ impl LeakDetector { pub fn assert_dropped(&mut self, entity_id: usize) { if let Some((type_name, backtraces)) = self.handle_backtraces.get_mut(&entity_id) { - for trace in backtraces.values_mut() { - if let Some(trace) = trace { - trace.resolve(); - eprintln!("{:?}", crate::util::CwdBacktrace(trace)); - } + for trace in backtraces.values_mut().flatten() { + trace.resolve(); + eprintln!("{:?}", crate::util::CwdBacktrace(trace)); } let hint = if *LEAK_BACKTRACE { @@ -5534,11 +5538,9 @@ impl LeakDetector { type_name.unwrap_or("entity"), id ); - for trace in backtraces.values_mut() { - if let Some(trace) = trace { - trace.resolve(); - eprintln!("{:?}", crate::util::CwdBacktrace(trace)); - } + for trace in backtraces.values_mut().flatten() { + trace.resolve(); + eprintln!("{:?}", crate::util::CwdBacktrace(trace)); } found_leaks = true; } @@ -6586,7 +6588,7 @@ mod tests { let subscription = subscription.clone(); move |_, _, e, _| { subscription.borrow_mut().take(); - events.borrow_mut().push(e.clone()); + events.borrow_mut().push(*e); } })); }); @@ -7158,8 +7160,8 @@ mod tests { let model = cx.add_model(|_| Counter(0)); - let condition1 = model.condition(&cx, |model, _| model.0 == 2); - let condition2 = model.condition(&cx, |model, _| model.0 == 3); + let condition1 = model.condition(cx, |model, _| model.0 == 2); + let condition2 = model.condition(cx, |model, _| model.0 == 3); smol::pin!(condition1, condition2); model.update(cx, |model, cx| model.inc(cx)); @@ -7186,7 +7188,7 @@ mod tests { } let model = cx.add_model(|_| Model); - model.condition(&cx, |_, _| false).await; + model.condition(cx, |_, _| false).await; } #[crate::test(self)] @@ -7199,7 +7201,7 @@ mod tests { } let model = cx.add_model(|_| Model); - let condition = model.condition(&cx, |_, _| false); + let condition = model.condition(cx, |_, _| false); cx.update(|_| drop(model)); condition.await; } @@ -7231,8 +7233,8 @@ mod tests { let (_, view) = cx.add_window(|_| Counter(0)); - let condition1 = view.condition(&cx, |view, _| view.0 == 2); - let condition2 = view.condition(&cx, |view, _| view.0 == 3); + let condition1 = view.condition(cx, |view, _| view.0 == 2); + let condition2 = view.condition(cx, |view, _| view.0 == 3); smol::pin!(condition1, condition2); view.update(cx, |view, cx| view.inc(cx)); @@ -7268,7 +7270,7 @@ mod tests { } let (_, view) = cx.add_window(|_| View); - view.condition(&cx, |_, _| false).await; + view.condition(cx, |_, _| false).await; } #[crate::test(self)] @@ -7293,7 +7295,7 @@ mod tests { let (_, root_view) = cx.add_window(|_| View); let view = cx.add_view(&root_view, |_| View); - let condition = view.condition(&cx, |_, _| false); + let condition = view.condition(cx, |_, _| false); cx.update(|_| drop(view)); condition.await; } diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 7a0da8dad9..8fb7bcb278 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -389,9 +389,9 @@ impl ElementBox { } } -impl Into for ElementBox { - fn into(self) -> ElementRc { - self.0 +impl From for ElementRc { + fn from(val: ElementBox) -> Self { + val.0 } } diff --git a/crates/gpui/src/elements/empty.rs b/crates/gpui/src/elements/empty.rs index 9a67115c23..a7c2fc1d60 100644 --- a/crates/gpui/src/elements/empty.rs +++ b/crates/gpui/src/elements/empty.rs @@ -11,13 +11,14 @@ use crate::{ }; use crate::{Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint}; +#[derive(Default)] pub struct Empty { collapsed: bool, } impl Empty { pub fn new() -> Self { - Self { collapsed: false } + Self::default() } pub fn collapsed(mut self) -> Self { diff --git a/crates/gpui/src/elements/expanded.rs b/crates/gpui/src/elements/expanded.rs index e8803affab..d77bbdbfb9 100644 --- a/crates/gpui/src/elements/expanded.rs +++ b/crates/gpui/src/elements/expanded.rs @@ -24,13 +24,13 @@ impl Expanded { } } - pub fn to_full_width(mut self) -> Self { + pub fn full_width(mut self) -> Self { self.full_width = true; self.full_height = false; self } - pub fn to_full_height(mut self) -> Self { + pub fn full_height(mut self) -> Self { self.full_width = false; self.full_height = true; self diff --git a/crates/gpui/src/elements/image.rs b/crates/gpui/src/elements/image.rs index dff46804e7..e0387e39bb 100644 --- a/crates/gpui/src/elements/image.rs +++ b/crates/gpui/src/elements/image.rs @@ -53,8 +53,8 @@ impl Element for Image { _: &mut LayoutContext, ) -> (Vector2F, Self::LayoutState) { let desired_size = vec2f( - self.style.width.unwrap_or(constraint.max.x()), - self.style.height.unwrap_or(constraint.max.y()), + self.style.width.unwrap_or_else(|| constraint.max.x()), + self.style.height.unwrap_or_else(|| constraint.max.y()), ); let size = constrain_size_preserving_aspect_ratio( constraint.constrain(desired_size), diff --git a/crates/gpui/src/elements/list.rs b/crates/gpui/src/elements/list.rs index 2b44918e43..e0ca47b598 100644 --- a/crates/gpui/src/elements/list.rs +++ b/crates/gpui/src/elements/list.rs @@ -33,6 +33,7 @@ struct StateInner { logical_scroll_top: Option, orientation: Orientation, overdraw: f32, + #[allow(clippy::type_complexity)] scroll_handler: Option, &mut EventContext)>>, } @@ -311,19 +312,17 @@ impl Element for List { drop(cursor); state.items = new_items; - match event { - Event::ScrollWheel(ScrollWheelEvent { - position, - delta, - precise, - }) => { - if bounds.contains_point(*position) { - if state.scroll(scroll_top, bounds.height(), *delta, *precise, cx) { - handled = true; - } - } + if let Event::ScrollWheel(ScrollWheelEvent { + position, + delta, + precise, + }) = event + { + if bounds.contains_point(*position) + && state.scroll(scroll_top, bounds.height(), *delta, *precise, cx) + { + handled = true; } - _ => {} } handled diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 0cdbe12304..7ad43c47de 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -129,7 +129,7 @@ impl Element for MouseEventHandler { cx.scene.push_mouse_region(MouseRegion::from_handlers( cx.current_view_id(), - Some(self.discriminant.clone()), + Some(self.discriminant), hit_bounds, self.handlers.clone(), )); diff --git a/crates/gpui/src/elements/overlay.rs b/crates/gpui/src/elements/overlay.rs index bf2ef59579..d81c939061 100644 --- a/crates/gpui/src/elements/overlay.rs +++ b/crates/gpui/src/elements/overlay.rs @@ -74,7 +74,7 @@ impl Element for Overlay { size: &mut Self::LayoutState, cx: &mut PaintContext, ) { - let mut bounds = RectF::new(self.abs_position.unwrap_or(bounds.origin()), *size); + let mut bounds = RectF::new(self.abs_position.unwrap_or_else(|| bounds.origin()), *size); cx.scene.push_stacking_context(None); if self.hoverable { diff --git a/crates/gpui/src/elements/stack.rs b/crates/gpui/src/elements/stack.rs index 992a8922a7..5de53ff9e7 100644 --- a/crates/gpui/src/elements/stack.rs +++ b/crates/gpui/src/elements/stack.rs @@ -8,15 +8,14 @@ use crate::{ SizeConstraint, }; +#[derive(Default)] pub struct Stack { children: Vec, } impl Stack { pub fn new() -> Self { - Stack { - children: Vec::new(), - } + Self::default() } } diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index 580240e3fd..92e38894c1 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -100,7 +100,7 @@ impl Element for Text { chunks, &self.style, cx.text_layout_cache, - &cx.font_cache, + cx.font_cache, usize::MAX, self.text.matches('\n').count() + 1, ); diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index 2ab4e91538..bf9a0a4e30 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -45,6 +45,7 @@ pub struct LayoutState { pub struct UniformList { state: UniformListState, item_count: usize, + #[allow(clippy::type_complexity)] append_items: Box, &mut Vec, &mut LayoutContext)>, padding_top: f32, padding_bottom: f32, @@ -310,19 +311,17 @@ impl Element for UniformList { handled = item.dispatch_event(event, cx) || handled; } - match event { - Event::ScrollWheel(ScrollWheelEvent { - position, - delta, - precise, - }) => { - if bounds.contains_point(*position) { - if self.scroll(*position, *delta, *precise, layout.scroll_max, cx) { - handled = true; - } - } + if let Event::ScrollWheel(ScrollWheelEvent { + position, + delta, + precise, + }) = event + { + if bounds.contains_point(*position) + && self.scroll(*position, *delta, *precise, layout.scroll_max, cx) + { + handled = true; } - _ => {} } handled diff --git a/crates/gpui/src/executor.rs b/crates/gpui/src/executor.rs index 7c2ba44c44..539d582e5b 100644 --- a/crates/gpui/src/executor.rs +++ b/crates/gpui/src/executor.rs @@ -332,7 +332,7 @@ impl Deterministic { pub fn now(&self) -> std::time::Instant { let state = self.state.lock(); - state.now.clone() + state.now } pub fn advance_clock(&self, duration: Duration) { @@ -681,6 +681,12 @@ impl Background { } } +impl Default for Background { + fn default() -> Self { + Self::new() + } +} + pub struct Scope<'a> { executor: Arc, futures: Vec + Send + 'static>>>, diff --git a/crates/gpui/src/font_cache.rs b/crates/gpui/src/font_cache.rs index 52acb2bcf3..3631cbe724 100644 --- a/crates/gpui/src/font_cache.rs +++ b/crates/gpui/src/font_cache.rs @@ -117,7 +117,7 @@ impl FontCache { .font_selections .entry(family_id) .or_default() - .insert(properties.clone(), font_id); + .insert(*properties, font_id); Ok(font_id) } } @@ -257,10 +257,10 @@ mod tests { let arial = fonts.load_family(&["Arial"]).unwrap(); let arial_regular = fonts.select_font(arial, &Properties::new()).unwrap(); let arial_italic = fonts - .select_font(arial, &Properties::new().style(Style::Italic)) + .select_font(arial, Properties::new().style(Style::Italic)) .unwrap(); let arial_bold = fonts - .select_font(arial, &Properties::new().weight(Weight::BOLD)) + .select_font(arial, Properties::new().weight(Weight::BOLD)) .unwrap(); assert_ne!(arial_regular, arial_italic); assert_ne!(arial_regular, arial_bold); diff --git a/crates/gpui/src/fonts.rs b/crates/gpui/src/fonts.rs index 6308f68289..5c49ddcf61 100644 --- a/crates/gpui/src/fonts.rs +++ b/crates/gpui/src/fonts.rs @@ -332,8 +332,7 @@ impl<'de> Deserialize<'de> for TextStyle { where D: serde::Deserializer<'de>, { - Ok(Self::from_json(TextStyleJson::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(e))?) + Self::from_json(TextStyleJson::deserialize(deserializer)?).map_err(de::Error::custom) } } diff --git a/crates/gpui/src/geometry.rs b/crates/gpui/src/geometry.rs index 705184fa6b..fb93c26b0f 100644 --- a/crates/gpui/src/geometry.rs +++ b/crates/gpui/src/geometry.rs @@ -19,6 +19,12 @@ enum PathVertexKind { Quadratic, } +impl Default for PathBuilder { + fn default() -> Self { + PathBuilder::new() + } +} + impl PathBuilder { pub fn new() -> Self { Self { @@ -58,10 +64,7 @@ impl PathBuilder { pub fn build(mut self, color: Color, clip_bounds: Option) -> Path { if let Some(clip_bounds) = clip_bounds { - self.bounds = self - .bounds - .intersection(clip_bounds) - .unwrap_or(RectF::default()); + self.bounds = self.bounds.intersection(clip_bounds).unwrap_or_default(); } Path { bounds: self.bounds, diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index d32344b0db..c408c98960 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -202,7 +202,7 @@ impl Keymap { for (ix, binding) in bindings.iter().enumerate() { binding_indices_by_action_type .entry(binding.action.as_any().type_id()) - .or_insert_with(|| SmallVec::new()) + .or_insert_with(SmallVec::new) .push(ix); } Self { @@ -211,10 +211,7 @@ impl Keymap { } } - fn bindings_for_action_type<'a>( - &'a self, - action_type: TypeId, - ) -> impl Iterator { + fn bindings_for_action_type(&self, action_type: TypeId) -> impl Iterator { self.binding_indices_by_action_type .get(&action_type) .map(SmallVec::as_slice) @@ -253,7 +250,7 @@ impl Binding { let keystrokes = keystrokes .split_whitespace() - .map(|key| Keystroke::parse(key)) + .map(Keystroke::parse) .collect::>()?; Ok(Self { @@ -281,7 +278,7 @@ impl Keystroke { let mut function = false; let mut key = None; - let mut components = source.split("-").peekable(); + let mut components = source.split('-').peekable(); while let Some(component) = components.next() { match component { "ctrl" => ctrl = true, @@ -379,12 +376,12 @@ impl ContextPredicate { let kind = node.kind(); match kind { - "source" => Self::from_node(node.child(0).ok_or(anyhow!(parse_error))?, source), + "source" => Self::from_node(node.child(0).ok_or_else(|| anyhow!(parse_error))?, source), "identifier" => Ok(Self::Identifier(node.utf8_text(source)?.into())), "not" => { let child = Self::from_node( node.child_by_field_name("expression") - .ok_or(anyhow!(parse_error))?, + .ok_or_else(|| anyhow!(parse_error))?, source, )?; Ok(Self::Not(Box::new(child))) @@ -392,12 +389,12 @@ impl ContextPredicate { "and" | "or" => { let left = Box::new(Self::from_node( node.child_by_field_name("left") - .ok_or(anyhow!(parse_error))?, + .ok_or_else(|| anyhow!(parse_error))?, source, )?); let right = Box::new(Self::from_node( node.child_by_field_name("right") - .ok_or(anyhow!(parse_error))?, + .ok_or_else(|| anyhow!(parse_error))?, source, )?); if kind == "and" { @@ -409,12 +406,12 @@ impl ContextPredicate { "equal" | "not_equal" => { let left = node .child_by_field_name("left") - .ok_or(anyhow!(parse_error))? + .ok_or_else(|| anyhow!(parse_error))? .utf8_text(source)? .into(); let right = node .child_by_field_name("right") - .ok_or(anyhow!(parse_error))? + .ok_or_else(|| anyhow!(parse_error))? .utf8_text(source)? .into(); if kind == "equal" { @@ -425,7 +422,7 @@ impl ContextPredicate { } "parenthesized" => Self::from_node( node.child_by_field_name("expression") - .ok_or(anyhow!(parse_error))?, + .ok_or_else(|| anyhow!(parse_error))?, source, ), _ => Err(anyhow!(parse_error)), @@ -604,7 +601,7 @@ mod tests { Ok(()) } - fn downcast<'a, A: Action>(action: &'a Option>) -> Option<&'a A> { + fn downcast(action: &Option>) -> Option<&A> { action .as_ref() .and_then(|action| action.as_any().downcast_ref()) diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index df7727ee89..b5fcfe8f0d 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -74,7 +74,7 @@ pub(crate) trait ForegroundPlatform { fn on_quit(&self, callback: Box); fn on_event(&self, callback: Box bool>); fn on_open_urls(&self, callback: Box)>); - fn run(&self, on_finish_launching: Box ()>); + fn run(&self, on_finish_launching: Box); fn on_menu_command(&self, callback: Box); fn on_validate_menu_command(&self, callback: Box bool>); diff --git a/crates/gpui/src/platform/mac/event.rs b/crates/gpui/src/platform/mac/event.rs index 5aedc63b2e..a53e009589 100644 --- a/crates/gpui/src/platform/mac/event.rs +++ b/crates/gpui/src/platform/mac/event.rs @@ -223,7 +223,7 @@ unsafe fn parse_keystroke(native_event: id) -> Keystroke { let cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask); let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask) && first_char.map_or(true, |ch| { - ch < NSUpArrowFunctionKey || ch > NSModeSwitchFunctionKey + !(NSUpArrowFunctionKey..=NSModeSwitchFunctionKey).contains(&ch) }); #[allow(non_upper_case_globals)] diff --git a/crates/gpui/src/platform/mac/fonts.rs b/crates/gpui/src/platform/mac/fonts.rs index 5a08cacf09..f39d548049 100644 --- a/crates/gpui/src/platform/mac/fonts.rs +++ b/crates/gpui/src/platform/mac/fonts.rs @@ -53,6 +53,12 @@ impl FontSystem { } } +impl Default for FontSystem { + fn default() -> Self { + Self::new() + } +} + impl platform::FontSystem for FontSystem { fn add_fonts(&self, fonts: &[Arc>]) -> anyhow::Result<()> { self.0.write().add_fonts(fonts) @@ -402,7 +408,7 @@ impl FontSystemState { fn wrap_line(&self, text: &str, font_id: FontId, font_size: f32, width: f32) -> Vec { let mut string = CFMutableAttributedString::new(); string.replace_str(&CFString::new(text), CFRange::init(0, 0)); - let cf_range = CFRange::init(0 as isize, text.encode_utf16().count() as isize); + let cf_range = CFRange::init(0, text.encode_utf16().count() as isize); let font = &self.fonts[font_id.0]; unsafe { string.set_attribute( @@ -505,14 +511,14 @@ mod tests { }; let menlo_italic = RunStyle { font_id: fonts - .select_font(&menlo, &Properties::new().style(Style::Italic)) + .select_font(&menlo, Properties::new().style(Style::Italic)) .unwrap(), color: Default::default(), underline: Default::default(), }; let menlo_bold = RunStyle { font_id: fonts - .select_font(&menlo, &Properties::new().weight(Weight::BOLD)) + .select_font(&menlo, Properties::new().weight(Weight::BOLD)) .unwrap(), color: Default::default(), underline: Default::default(), @@ -599,7 +605,7 @@ mod tests { let name = format!("/Users/as-cii/Desktop/twog-{}.png", i); let path = Path::new(&name); let file = File::create(path).unwrap(); - let ref mut w = BufWriter::new(file); + let w = &mut BufWriter::new(file); let mut encoder = png::Encoder::new(w, bounds.width() as u32, bounds.height() as u32); encoder.set_color(png::ColorType::Grayscale); diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 365e747825..113653478a 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -50,7 +50,7 @@ use time::UtcOffset; #[allow(non_upper_case_globals)] const NSUTF8StringEncoding: NSUInteger = 4; -const MAC_PLATFORM_IVAR: &'static str = "platform"; +const MAC_PLATFORM_IVAR: &str = "platform"; static mut APP_CLASS: *const Class = ptr::null(); static mut APP_DELEGATE_CLASS: *const Class = ptr::null(); @@ -118,7 +118,7 @@ pub struct MacForegroundPlatformState { validate_menu_command: Option bool>>, will_open_menu: Option>, open_urls: Option)>>, - finish_launching: Option ()>>, + finish_launching: Option>, menu_actions: Vec>, } @@ -277,7 +277,7 @@ impl platform::ForegroundPlatform for MacForegroundPlatform { self.0.borrow_mut().open_urls = Some(callback); } - fn run(&self, on_finish_launching: Box ()>) { + fn run(&self, on_finish_launching: Box) { self.0.borrow_mut().finish_launching = Some(on_finish_launching); unsafe { @@ -533,7 +533,7 @@ impl platform::Platform for MacPlatform { fn read_from_clipboard(&self) -> Option { unsafe { if let Some(text_bytes) = self.read_from_pasteboard(NSPasteboardTypeString) { - let text = String::from_utf8_lossy(&text_bytes).to_string(); + let text = String::from_utf8_lossy(text_bytes).to_string(); let hash_bytes = self .read_from_pasteboard(self.text_hash_pasteboard_type) .and_then(|bytes| bytes.try_into().ok()) diff --git a/crates/gpui/src/platform/mac/renderer.rs b/crates/gpui/src/platform/mac/renderer.rs index 6b95fd6271..8fdbda15e8 100644 --- a/crates/gpui/src/platform/mac/renderer.rs +++ b/crates/gpui/src/platform/mac/renderer.rs @@ -14,8 +14,7 @@ use metal::{MTLPixelFormat, MTLResourceOptions, NSRange}; use shaders::ToFloat2 as _; use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, sync::Arc, vec}; -const SHADERS_METALLIB: &'static [u8] = - include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib")); +const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib")); const INSTANCE_BUFFER_SIZE: usize = 8192 * 1024; // This is an arbitrary decision. There's probably a more optimal value. pub struct Renderer { @@ -385,10 +384,10 @@ impl Renderer { drawable_size: Vector2F, command_encoder: &metal::RenderCommandEncoderRef, ) { - let clip_bounds = (layer.clip_bounds().unwrap_or(RectF::new( - vec2f(0., 0.), - drawable_size / scene.scale_factor(), - )) * scene.scale_factor()) + let clip_bounds = (layer + .clip_bounds() + .unwrap_or_else(|| RectF::new(vec2f(0., 0.), drawable_size / scene.scale_factor())) + * scene.scale_factor()) .round(); command_encoder.set_scissor_rect(metal::MTLScissorRect { x: clip_bounds.origin_x() as NSUInteger, @@ -438,8 +437,7 @@ impl Renderer { ); let buffer_contents = unsafe { - (self.instances.contents() as *mut u8).offset(*offset as isize) - as *mut shaders::GPUIShadow + (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIShadow }; for (ix, shadow) in shadows.iter().enumerate() { let shape_bounds = shadow.bounds * scale_factor; @@ -451,7 +449,7 @@ impl Renderer { color: shadow.color.to_uchar4(), }; unsafe { - *(buffer_contents.offset(ix as isize)) = shader_shadow; + *(buffer_contents.add(ix)) = shader_shadow; } } @@ -503,8 +501,7 @@ impl Renderer { ); let buffer_contents = unsafe { - (self.instances.contents() as *mut u8).offset(*offset as isize) - as *mut shaders::GPUIQuad + (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIQuad }; for (ix, quad) in quads.iter().enumerate() { let bounds = quad.bounds * scale_factor; @@ -514,7 +511,7 @@ impl Renderer { size: bounds.size().round().to_float2(), background_color: quad .background - .unwrap_or(Color::transparent_black()) + .unwrap_or_else(Color::transparent_black) .to_uchar4(), border_top: border_width * (quad.border.top as usize as f32), border_right: border_width * (quad.border.right as usize as f32), @@ -524,7 +521,7 @@ impl Renderer { corner_radius: quad.corner_radius * scale_factor, }; unsafe { - *(buffer_contents.offset(ix as isize)) = shader_quad; + *(buffer_contents.add(ix)) = shader_quad; } } @@ -641,9 +638,8 @@ impl Renderer { ); unsafe { - let buffer_contents = (self.instances.contents() as *mut u8) - .offset(*offset as isize) - as *mut shaders::GPUISprite; + let buffer_contents = + (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUISprite; std::ptr::copy_nonoverlapping(sprites.as_ptr(), buffer_contents, sprites.len()); } @@ -757,9 +753,8 @@ impl Renderer { ); unsafe { - let buffer_contents = (self.instances.contents() as *mut u8) - .offset(*offset as isize) - as *mut shaders::GPUIImage; + let buffer_contents = + (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIImage; std::ptr::copy_nonoverlapping(images.as_ptr(), buffer_contents, images.len()); } @@ -821,10 +816,9 @@ impl Renderer { } unsafe { - let buffer_contents = (self.instances.contents() as *mut u8) - .offset(*offset as isize) - as *mut shaders::GPUISprite; - *buffer_contents.offset(atlas_sprite_count as isize) = sprite.shader_data; + let buffer_contents = + (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUISprite; + *buffer_contents.add(atlas_sprite_count) = sprite.shader_data; } atlas_sprite_count += 1; @@ -917,8 +911,7 @@ impl Renderer { ); let buffer_contents = unsafe { - (self.instances.contents() as *mut u8).offset(*offset as isize) - as *mut shaders::GPUIUnderline + (self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIUnderline }; for (ix, underline) in underlines.iter().enumerate() { let origin = underline.origin * scale_factor; @@ -935,7 +928,7 @@ impl Renderer { squiggly: underline.squiggly as u8, }; unsafe { - *(buffer_contents.offset(ix as isize)) = shader_underline; + *(buffer_contents.add(ix)) = shader_underline; } } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 568356e938..cda7ce5257 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -48,7 +48,7 @@ use std::{ time::Duration, }; -const WINDOW_STATE_IVAR: &'static str = "windowState"; +const WINDOW_STATE_IVAR: &str = "windowState"; static mut WINDOW_CLASS: *const Class = ptr::null(); static mut VIEW_CLASS: *const Class = ptr::null(); @@ -72,7 +72,7 @@ impl NSRange { self.location != NSNotFound as NSUInteger } - fn to_range(&self) -> Option> { + fn to_range(self) -> Option> { if self.is_valid() { let start = self.location as usize; let end = start + self.length as usize; @@ -513,7 +513,7 @@ impl platform::Window for Window { }; let _: () = msg_send![alert, setAlertStyle: alert_style]; let _: () = msg_send![alert, setMessageText: ns_string(msg)]; - for (ix, answer) in answers.into_iter().enumerate() { + for (ix, answer) in answers.iter().enumerate() { let button: id = msg_send![alert, addButtonWithTitle: ns_string(answer)]; let _: () = msg_send![button, setTag: ix as NSInteger]; } @@ -721,14 +721,14 @@ extern "C" fn yes(_: &Object, _: Sel) -> BOOL { extern "C" fn dealloc_window(this: &Object, _: Sel) { unsafe { drop_window_state(this); - let () = msg_send![super(this, class!(NSWindow)), dealloc]; + let _: () = msg_send![super(this, class!(NSWindow)), dealloc]; } } extern "C" fn dealloc_view(this: &Object, _: Sel) { unsafe { drop_window_state(this); - let () = msg_send![super(this, class!(NSView)), dealloc]; + let _: () = msg_send![super(this, class!(NSView)), dealloc]; } } @@ -912,7 +912,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) { extern "C" fn send_event(this: &Object, _: Sel, native_event: id) { unsafe { - let () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event]; + let _: () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event]; get_window_state(this).borrow_mut().performed_key_equivalent = false; } } @@ -991,7 +991,7 @@ extern "C" fn close_window(this: &Object, _: Sel) { callback(); } - let () = msg_send![super(this, class!(NSWindow)), close]; + let _: () = msg_send![super(this, class!(NSWindow)), close]; } } @@ -1157,17 +1157,22 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS .flatten() .is_some(); - if is_composing || text.chars().count() > 1 || pending_key_down.is_none() { - with_input_handler(this, |input_handler| { - input_handler.replace_text_in_range(replacement_range, text) - }); - } else { - let mut pending_key_down = pending_key_down.unwrap(); - pending_key_down.1 = Some(InsertText { - replacement_range, - text: text.to_string(), - }); - window_state.borrow_mut().pending_key_down = Some(pending_key_down); + match pending_key_down { + None | Some(_) if is_composing || text.chars().count() > 1 => { + with_input_handler(this, |input_handler| { + input_handler.replace_text_in_range(replacement_range, text) + }); + } + + Some(mut pending_key_down) => { + pending_key_down.1 = Some(InsertText { + replacement_range, + text: text.to_string(), + }); + window_state.borrow_mut().pending_key_down = Some(pending_key_down); + } + + _ => unreachable!(), } } } diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index 3eb9b1e88e..f75cff78e8 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -74,7 +74,7 @@ impl super::ForegroundPlatform for ForegroundPlatform { fn on_open_urls(&self, _: Box)>) {} - fn run(&self, _on_finish_launching: Box ()>) { + fn run(&self, _on_finish_launching: Box) { unimplemented!() } diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 9cba57810b..1556572816 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -89,8 +89,8 @@ impl Presenter { ) { cx.start_frame(); for view_id in &invalidation.removed { - invalidation.updated.remove(&view_id); - self.rendered_views.remove(&view_id); + invalidation.updated.remove(view_id); + self.rendered_views.remove(view_id); } for view_id in &invalidation.updated { self.rendered_views.insert( @@ -285,7 +285,7 @@ impl Presenter { { dragged_region = Some(( clicked_region.clone(), - MouseRegionEvent::Drag(*prev_drag_position, e.clone()), + MouseRegionEvent::Drag(*prev_drag_position, *e), )); *prev_drag_position = *position; } @@ -366,7 +366,7 @@ impl Presenter { }, ) = event { - if let None = pressed_button { + if pressed_button.is_none() { let mut style_to_assign = CursorStyle::Arrow; for region in self.cursor_regions.iter().rev() { if region.bounds.contains_point(*position) { @@ -385,23 +385,17 @@ impl Presenter { if let Some(region_id) = region.id() { if !self.hovered_region_ids.contains(®ion_id) { invalidated_views.push(region.view_id); - hover_regions.push(( - region.clone(), - MouseRegionEvent::Hover(true, e.clone()), - )); + hover_regions + .push((region.clone(), MouseRegionEvent::Hover(true, *e))); self.hovered_region_ids.insert(region_id); } } - } else { - if let Some(region_id) = region.id() { - if self.hovered_region_ids.contains(®ion_id) { - invalidated_views.push(region.view_id); - hover_regions.push(( - region.clone(), - MouseRegionEvent::Hover(false, e.clone()), - )); - self.hovered_region_ids.remove(®ion_id); - } + } else if let Some(region_id) = region.id() { + if self.hovered_region_ids.contains(®ion_id) { + invalidated_views.push(region.view_id); + hover_regions + .push((region.clone(), MouseRegionEvent::Hover(false, *e))); + self.hovered_region_ids.remove(®ion_id); } } } @@ -625,7 +619,7 @@ impl<'a> PaintContext<'a> { #[inline] pub fn paint_layer(&mut self, clip_bounds: Option, f: F) where - F: FnOnce(&mut Self) -> (), + F: FnOnce(&mut Self), { self.scene.push_layer(clip_bounds); f(self); diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs index d3d788c466..704567450a 100644 --- a/crates/gpui/src/scene/mouse_region.rs +++ b/crates/gpui/src/scene/mouse_region.rs @@ -107,6 +107,7 @@ pub struct MouseRegionId { #[derive(Clone, Default)] pub struct HandlerSet { + #[allow(clippy::type_complexity)] pub set: HashMap< (Discriminant, Option), Rc, @@ -115,6 +116,7 @@ pub struct HandlerSet { impl HandlerSet { pub fn handle_all() -> Self { + #[allow(clippy::type_complexity)] let mut set: HashMap< (Discriminant, Option), Rc, diff --git a/crates/gpui/src/text_layout.rs b/crates/gpui/src/text_layout.rs index 571f932e52..8fd10a6018 100644 --- a/crates/gpui/src/text_layout.rs +++ b/crates/gpui/src/text_layout.rs @@ -66,7 +66,7 @@ impl TextLayoutCache { let mut curr_frame = RwLockUpgradableReadGuard::upgrade(curr_frame); if let Some((key, layout)) = self.prev_frame.lock().remove_entry(key) { curr_frame.insert(key, layout.clone()); - Line::new(layout.clone(), runs) + Line::new(layout, runs) } else { let layout = Arc::new(self.fonts.layout_line(text, font_size, runs)); let key = CacheKeyValue { @@ -81,7 +81,7 @@ impl TextLayoutCache { } trait CacheKey { - fn key<'a>(&'a self) -> CacheKeyRef<'a>; + fn key(&self) -> CacheKeyRef; } impl<'a> PartialEq for (dyn CacheKey + 'a) { @@ -98,7 +98,7 @@ impl<'a> Hash for (dyn CacheKey + 'a) { } } -#[derive(Eq, PartialEq)] +#[derive(Eq)] struct CacheKeyValue { text: String, font_size: OrderedFloat, @@ -106,15 +106,21 @@ struct CacheKeyValue { } impl CacheKey for CacheKeyValue { - fn key<'a>(&'a self) -> CacheKeyRef<'a> { + fn key(&self) -> CacheKeyRef { CacheKeyRef { - text: &self.text.as_str(), + text: self.text.as_str(), font_size: self.font_size, runs: self.runs.as_slice(), } } } +impl PartialEq for CacheKeyValue { + fn eq(&self, other: &Self) -> bool { + self.key().eq(&other.key()) + } +} + impl Hash for CacheKeyValue { fn hash(&self, state: &mut H) { self.key().hash(state); @@ -135,7 +141,7 @@ struct CacheKeyRef<'a> { } impl<'a> CacheKey for CacheKeyRef<'a> { - fn key<'b>(&'b self) -> CacheKeyRef<'b> { + fn key(&self) -> CacheKeyRef { *self } } @@ -242,6 +248,10 @@ impl Line { self.layout.len } + pub fn is_empty(&self) -> bool { + self.layout.len == 0 + } + pub fn index_for_x(&self, x: f32) -> Option { if x >= self.layout.width { None @@ -300,7 +310,7 @@ impl Line { ), Underline { color: Some(run_underline.color.unwrap_or(*run_color)), - thickness: run_underline.thickness.into(), + thickness: run_underline.thickness, squiggly: run_underline.squiggly, }, )); @@ -484,7 +494,7 @@ impl LineWrapper { let mut prev_c = '\0'; let mut char_indices = line.char_indices(); iter::from_fn(move || { - while let Some((ix, c)) = char_indices.next() { + for (ix, c) in char_indices.by_ref() { if c == '\n' { continue; } @@ -746,7 +756,7 @@ mod tests { let mut wrapper = LineWrapper::new(font_id, 16., font_system); assert_eq!( wrapper - .wrap_shaped_line(&text, &line, 72.0) + .wrap_shaped_line(text, &line, 72.0) .collect::>(), &[ ShapedBoundary { diff --git a/crates/gpui_macros/src/gpui_macros.rs b/crates/gpui_macros/src/gpui_macros.rs index 7ec8b4fb7c..a60d385e8f 100644 --- a/crates/gpui_macros/src/gpui_macros.rs +++ b/crates/gpui_macros/src/gpui_macros.rs @@ -25,7 +25,7 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream { NestedMeta::Meta(Meta::NameValue(meta)) => { let key_name = meta.path.get_ident().map(|i| i.to_string()); let result = (|| { - match key_name.as_ref().map(String::as_str) { + match key_name.as_deref() { Some("retries") => max_retries = parse_int(&meta.lit)?, Some("iterations") => num_iterations = parse_int(&meta.lit)?, Some("seed") => starting_seed = parse_int(&meta.lit)?, diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 2f458b04c9..52ad88f092 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -737,9 +737,7 @@ impl Buffer { this.parsing_in_background = false; this.did_finish_parsing(new_tree, parsed_version, cx); - if parse_again && this.reparse(cx) { - return; - } + if parse_again && this.reparse(cx) {} }); }) .detach(); @@ -933,10 +931,12 @@ impl Buffer { indent_sizes.entry(row).or_insert_with(|| { let mut size = snapshot.indent_size_for_line(row); if size.kind == new_indent.kind { - if delta > 0 { - size.len = size.len + delta as u32; - } else if delta < 0 { - size.len = size.len.saturating_sub(-delta as u32); + match delta.cmp(&0) { + Ordering::Greater => size.len += delta as u32, + Ordering::Less => { + size.len = size.len.saturating_sub(-delta as u32) + } + Ordering::Equal => {} } } size @@ -961,7 +961,7 @@ impl Buffer { let edits: Vec<_> = indent_sizes .into_iter() .filter_map(|(row, indent_size)| { - let current_size = indent_size_for_line(&self, row); + let current_size = indent_size_for_line(self, row); Self::edit_for_indent_size_adjustment(row, current_size, indent_size) }) .collect(); @@ -978,21 +978,23 @@ impl Buffer { return None; } - if new_size.len > current_size.len { - let point = Point::new(row, 0); - Some(( - point..point, - iter::repeat(new_size.char()) - .take((new_size.len - current_size.len) as usize) - .collect::(), - )) - } else if new_size.len < current_size.len { - Some(( + match new_size.len.cmp(¤t_size.len) { + Ordering::Greater => { + let point = Point::new(row, 0); + Some(( + point..point, + iter::repeat(new_size.char()) + .take((new_size.len - current_size.len) as usize) + .collect::(), + )) + } + + Ordering::Less => Some(( Point::new(row, 0)..Point::new(row, current_size.len - new_size.len), String::new(), - )) - } else { - None + )), + + Ordering::Equal => None, } } @@ -1599,7 +1601,7 @@ impl Deref for Buffer { impl BufferSnapshot { pub fn indent_size_for_line(&self, row: u32) -> IndentSize { - indent_size_for_line(&self, row) + indent_size_for_line(self, row) } pub fn single_indent_size(&self, cx: &AppContext) -> IndentSize { @@ -1643,10 +1645,10 @@ impl BufferSnapshot { result } - fn suggest_autoindents<'a>( - &'a self, + fn suggest_autoindents( + &self, row_range: Range, - ) -> Option> + 'a> { + ) -> Option> + '_> { let language = self.language.as_ref()?; let grammar = language.grammar.as_ref()?; let config = &language.config; @@ -1675,7 +1677,7 @@ impl BufferSnapshot { start.get_or_insert(Point::from_ts_point(capture.node.start_position())); end.get_or_insert(Point::from_ts_point(capture.node.end_position())); } else if Some(capture.index) == end_capture_ix { - end = Some(Point::from_ts_point(capture.node.start_position().into())); + end = Some(Point::from_ts_point(capture.node.start_position())); } } @@ -1733,15 +1735,17 @@ impl BufferSnapshot { let mut outdent_to_row = u32::MAX; while let Some((indent_row, delta)) = indent_changes.peek() { - if *indent_row == row { - match delta { + match indent_row.cmp(&row) { + Ordering::Equal => match delta { Ordering::Less => outdent_from_prev_row = true, Ordering::Greater => indent_from_prev_row = true, _ => {} - } - } else if *indent_row > row { - break; + }, + + Ordering::Greater => break, + Ordering::Less => {} } + indent_changes.next(); } @@ -1805,11 +1809,7 @@ impl BufferSnapshot { None } - pub fn chunks<'a, T: ToOffset>( - &'a self, - range: Range, - language_aware: bool, - ) -> BufferChunks<'a> { + pub fn chunks(&self, range: Range, language_aware: bool) -> BufferChunks { let range = range.start.to_offset(self)..range.end.to_offset(self); let mut tree = None; @@ -1843,7 +1843,7 @@ impl BufferSnapshot { ) } - pub fn for_each_line<'a>(&'a self, range: Range, mut callback: impl FnMut(u32, &str)) { + pub fn for_each_line(&self, range: Range, mut callback: impl FnMut(u32, &str)) { let mut line = String::new(); let mut row = range.start.row; for chunk in self @@ -1969,7 +1969,7 @@ impl BufferSnapshot { position: T, theme: Option<&SyntaxTheme>, ) -> Option>> { - let position = position.to_offset(&self); + let position = position.to_offset(self); let mut items = self.outline_items_containing(position.saturating_sub(1)..position + 1, theme)?; let mut prev_depth = None; @@ -2050,7 +2050,7 @@ impl BufferSnapshot { let mut offset = range.start; chunks.seek(offset); - while let Some(mut chunk) = chunks.next() { + for mut chunk in chunks.by_ref() { if chunk.text.len() > range.end - offset { chunk.text = &chunk.text[0..(range.end - offset)]; offset = range.end; @@ -2105,7 +2105,7 @@ impl BufferSnapshot { let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1; let mut cursor = QueryCursorHandle::new(); let matches = cursor.set_byte_range(range).matches( - &brackets_query, + brackets_query, tree.root_node(), TextProvider(self.as_rope()), ); @@ -2120,17 +2120,17 @@ impl BufferSnapshot { .min_by_key(|(open_range, close_range)| close_range.end - open_range.start) } - pub fn remote_selections_in_range<'a>( - &'a self, + #[allow(clippy::type_complexity)] + pub fn remote_selections_in_range( + &self, range: Range, - ) -> impl 'a - + Iterator< + ) -> impl Iterator< Item = ( ReplicaId, bool, - impl 'a + Iterator>, + impl Iterator> + '_, ), - > { + > + '_ { self.remote_selections .iter() .filter(|(replica_id, set)| { @@ -2165,8 +2165,7 @@ impl BufferSnapshot { T: 'a + Clone + ToOffset, O: 'a + FromAnchor, { - self.diagnostics - .range(search_range.clone(), self, true, reversed) + self.diagnostics.range(search_range, self, true, reversed) } pub fn diagnostic_groups(&self) -> Vec> { @@ -2469,10 +2468,7 @@ impl<'a> Iterator for BufferChunks<'a> { impl QueryCursorHandle { pub(crate) fn new() -> Self { - let mut cursor = QUERY_CURSORS - .lock() - .pop() - .unwrap_or_else(|| QueryCursor::new()); + let mut cursor = QUERY_CURSORS.lock().pop().unwrap_or_else(QueryCursor::new); cursor.set_match_limit(64); QueryCursorHandle(Some(cursor)) } @@ -2614,7 +2610,7 @@ pub fn contiguous_ranges( values: impl Iterator, max_len: usize, ) -> impl Iterator> { - let mut values = values.into_iter(); + let mut values = values; let mut current_range: Option> = None; std::iter::from_fn(move || loop { if let Some(value) = values.next() { diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index 51c921e61c..b52327cac0 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -8,7 +8,7 @@ use std::{ use sum_tree::{self, Bias, SumTree}; use text::{Anchor, FromAnchor, PointUtf16, ToOffset}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct DiagnosticSet { diagnostics: SumTree>, } @@ -167,24 +167,15 @@ impl DiagnosticSet { .map(|entry| entry.resolve(buffer)) } } - -impl Default for DiagnosticSet { - fn default() -> Self { - Self { - diagnostics: Default::default(), - } - } -} - impl sum_tree::Item for DiagnosticEntry { type Summary = Summary; fn summary(&self) -> Self::Summary { Summary { - start: self.range.start.clone(), - end: self.range.end.clone(), - min_start: self.range.start.clone(), - max_end: self.range.end.clone(), + start: self.range.start, + end: self.range.end, + min_start: self.range.start, + max_end: self.range.end, count: 1, } } @@ -217,13 +208,13 @@ impl sum_tree::Summary for Summary { fn add_summary(&mut self, other: &Self, buffer: &Self::Context) { if other.min_start.cmp(&self.min_start, buffer).is_lt() { - self.min_start = other.min_start.clone(); + self.min_start = other.min_start; } if other.max_end.cmp(&self.max_end, buffer).is_gt() { - self.max_end = other.max_end.clone(); + self.max_end = other.max_end; } - self.start = other.start.clone(); - self.end = other.end.clone(); + self.start = other.start; + self.end = other.end; self.count += other.count; } } diff --git a/crates/language/src/highlight_map.rs b/crates/language/src/highlight_map.rs index 36ed286bea..ddb4dead79 100644 --- a/crates/language/src/highlight_map.rs +++ b/crates/language/src/highlight_map.rs @@ -56,10 +56,7 @@ impl HighlightId { } pub fn style(&self, theme: &SyntaxTheme) -> Option { - theme - .highlights - .get(self.0 as usize) - .map(|entry| entry.1.clone()) + theme.highlights.get(self.0 as usize).map(|entry| entry.1) } #[cfg(any(test, feature = "test-support"))] diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 331c8c3987..fbcc983df9 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -308,6 +308,7 @@ pub struct LanguageRegistry { lsp_binary_statuses_tx: async_broadcast::Sender<(Arc, LanguageServerBinaryStatus)>, lsp_binary_statuses_rx: async_broadcast::Receiver<(Arc, LanguageServerBinaryStatus)>, login_shell_env_loaded: Shared>, + #[allow(clippy::type_complexity)] lsp_binary_paths: Mutex< HashMap< LanguageServerName, @@ -342,7 +343,7 @@ impl LanguageRegistry { if let Some(theme) = self.theme.read().clone() { language.set_theme(&theme.editor.syntax); } - self.languages.write().push(language.clone()); + self.languages.write().push(language); *self.subscription.write().0.borrow_mut() = (); } @@ -409,7 +410,7 @@ impl LanguageRegistry { ) -> Option>> { #[cfg(any(test, feature = "test-support"))] if language.fake_adapter.is_some() { - let language = language.clone(); + let language = language; return Some(cx.spawn(|cx| async move { let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap(); let (server, mut fake_server) = lsp::LanguageServer::fake( @@ -474,7 +475,7 @@ impl LanguageRegistry { let server = lsp::LanguageServer::new( server_id, &server_binary_path, - &server_args, + server_args, &root_path, cx, )?; diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 4dca2f855d..047cef3ab6 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -408,10 +408,12 @@ pub async fn deserialize_completion( Ok(Completion { old_range: old_start..old_end, new_text: completion.new_text, - label: label.unwrap_or(CodeLabel::plain( - lsp_completion.label.clone(), - lsp_completion.filter_text.as_deref(), - )), + label: label.unwrap_or_else(|| { + CodeLabel::plain( + lsp_completion.label.clone(), + lsp_completion.filter_text.as_deref(), + ) + }), lsp_completion, }) } @@ -465,7 +467,7 @@ pub fn deserialize_transaction(transaction: proto::Transaction) -> Result buffer1_ops.borrow_mut().push(op), - event @ _ => buffer_1_events.borrow_mut().push(event), + event => buffer_1_events.borrow_mut().push(event), }) .detach(); let buffer_2_events = buffer_2_events.clone(); @@ -190,7 +190,7 @@ async fn test_apply_diff(cx: &mut gpui::TestAppContext) { buffer.update(cx, |buffer, cx| { buffer.apply_diff(diff, cx).unwrap(); assert_eq!(buffer.text(), text); - assert_eq!(anchor.to_point(&buffer), Point::new(2, 3)); + assert_eq!(anchor.to_point(buffer), Point::new(2, 3)); }); let text = "a\n1\n\nccc\ndd2dd\nffffff\n"; @@ -198,7 +198,7 @@ async fn test_apply_diff(cx: &mut gpui::TestAppContext) { buffer.update(cx, |buffer, cx| { buffer.apply_diff(diff, cx).unwrap(); assert_eq!(buffer.text(), text); - assert_eq!(anchor.to_point(&buffer), Point::new(4, 4)); + assert_eq!(anchor.to_point(buffer), Point::new(4, 4)); }); } @@ -209,11 +209,9 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx)); // Wait for the initial text to parse - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; assert_eq!( - get_tree_sexp(&buffer, &cx), + get_tree_sexp(&buffer, cx), concat!( "(source_file (function_item name: (identifier) ", "parameters: (parameters) ", @@ -230,11 +228,11 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { buffer.update(cx, |buf, cx| { buf.start_transaction(); - let offset = buf.text().find(")").unwrap(); + let offset = buf.text().find(')').unwrap(); buf.edit([(offset..offset, "b: C")], None, cx); assert!(!buf.is_parsing()); - let offset = buf.text().find("}").unwrap(); + let offset = buf.text().find('}').unwrap(); buf.edit([(offset..offset, " d; ")], None, cx); assert!(!buf.is_parsing()); @@ -242,11 +240,9 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { assert_eq!(buf.text(), "fn a(b: C) { d; }"); assert!(buf.is_parsing()); }); - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; assert_eq!( - get_tree_sexp(&buffer, &cx), + get_tree_sexp(&buffer, cx), concat!( "(source_file (function_item name: (identifier) ", "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ", @@ -259,13 +255,13 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { // * turn field expression into a method call // * add a turbofish to the method call buffer.update(cx, |buf, cx| { - let offset = buf.text().find(";").unwrap(); + let offset = buf.text().find(';').unwrap(); buf.edit([(offset..offset, ".e")], None, cx); assert_eq!(buf.text(), "fn a(b: C) { d.e; }"); assert!(buf.is_parsing()); }); buffer.update(cx, |buf, cx| { - let offset = buf.text().find(";").unwrap(); + let offset = buf.text().find(';').unwrap(); buf.edit([(offset..offset, "(f)")], None, cx); assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }"); assert!(buf.is_parsing()); @@ -276,11 +272,9 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { assert_eq!(buf.text(), "fn a(b: C) { d.e::(f); }"); assert!(buf.is_parsing()); }); - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; assert_eq!( - get_tree_sexp(&buffer, &cx), + get_tree_sexp(&buffer, cx), concat!( "(source_file (function_item name: (identifier) ", "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ", @@ -297,11 +291,9 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { assert_eq!(buf.text(), "fn a() {}"); assert!(buf.is_parsing()); }); - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; assert_eq!( - get_tree_sexp(&buffer, &cx), + get_tree_sexp(&buffer, cx), concat!( "(source_file (function_item name: (identifier) ", "parameters: (parameters) ", @@ -314,11 +306,9 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { assert_eq!(buf.text(), "fn a(b: C) { d.e::(f); }"); assert!(buf.is_parsing()); }); - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; assert_eq!( - get_tree_sexp(&buffer, &cx), + get_tree_sexp(&buffer, cx), concat!( "(source_file (function_item name: (identifier) ", "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ", @@ -340,21 +330,17 @@ async fn test_resetting_language(cx: &mut gpui::TestAppContext) { }); // Wait for the initial text to parse - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; assert_eq!( - get_tree_sexp(&buffer, &cx), + get_tree_sexp(&buffer, cx), "(source_file (expression_statement (block)))" ); buffer.update(cx, |buffer, cx| { buffer.set_language(Some(Arc::new(json_lang())), cx) }); - buffer - .condition(&cx, |buffer, _| !buffer.is_parsing()) - .await; - assert_eq!(get_tree_sexp(&buffer, &cx), "(document (object))"); + buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await; + assert_eq!(get_tree_sexp(&buffer, cx), "(document (object))"); } #[gpui::test] @@ -417,7 +403,7 @@ async fn test_outline(cx: &mut gpui::TestAppContext) { // Without space, we only match on names assert_eq!( - search(&outline, "oon", &cx).await, + search(&outline, "oon", cx).await, &[ ("mod module", vec![]), // included as the parent of a match ("enum LoginState", vec![]), // included as the parent of a match @@ -427,18 +413,18 @@ async fn test_outline(cx: &mut gpui::TestAppContext) { ); assert_eq!( - search(&outline, "dp p", &cx).await, + search(&outline, "dp p", cx).await, &[ ("impl Drop for Person", vec![5, 8, 9, 14]), ("fn drop", vec![]), ] ); assert_eq!( - search(&outline, "dpn", &cx).await, + search(&outline, "dpn", cx).await, &[("impl Drop for Person", vec![5, 14, 19])] ); assert_eq!( - search(&outline, "impl ", &cx).await, + search(&outline, "impl ", cx).await, &[ ("impl Eq for Person", vec![0, 1, 2, 3, 4]), ("impl Drop for Person", vec![0, 1, 2, 3, 4]), @@ -530,9 +516,9 @@ async fn test_symbols_containing(cx: &mut gpui::TestAppContext) { ] ); - fn symbols_containing<'a>( + fn symbols_containing( position: Point, - snapshot: &'a BufferSnapshot, + snapshot: &BufferSnapshot, ) -> Vec<(String, Range)> { snapshot .symbols_containing(position, None) @@ -799,7 +785,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut Muta Ok(()) } " - .replace("|", "") // included in the string to preserve trailing whites + .replace('|', "") // included in the string to preserve trailing whites .unindent() ); @@ -971,7 +957,7 @@ fn test_autoindent_block_mode(cx: &mut MutableAppContext) { buffer.undo(cx); buffer.edit([(Point::new(2, 0)..Point::new(2, 0), " ")], None, cx); buffer.edit( - [(Point::new(2, 8)..Point::new(2, 8), inserted_text.clone())], + [(Point::new(2, 8)..Point::new(2, 8), inserted_text)], Some(AutoindentMode::Block { original_indent_columns: vec![0], }), @@ -1098,7 +1084,7 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) { if let Event::Operation(op) = event { network .borrow_mut() - .broadcast(buffer.replica_id(), vec![proto::serialize_operation(&op)]); + .broadcast(buffer.replica_id(), vec![proto::serialize_operation(op)]); } }) .detach(); @@ -1202,7 +1188,7 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) { if let Event::Operation(op) = event { network.borrow_mut().broadcast( buffer.replica_id(), - vec![proto::serialize_operation(&op)], + vec![proto::serialize_operation(op)], ); } }) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 5c8916e34e..95ef299c72 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -27,8 +27,8 @@ use std::{ use std::{path::Path, process::Stdio}; use util::{ResultExt, TryFutureExt}; -const JSON_RPC_VERSION: &'static str = "2.0"; -const CONTENT_LEN_HEADER: &'static str = "Content-Length: "; +const JSON_RPC_VERSION: &str = "2.0"; +const CONTENT_LEN_HEADER: &str = "Content-Length: "; type NotificationHandler = Box, &str, AsyncAppContext)>; type ResponseHandler = Box)>; @@ -42,6 +42,7 @@ pub struct LanguageServer { notification_handlers: Arc>>, response_handlers: Arc>>, executor: Arc, + #[allow(clippy::type_complexity)] io_tasks: Mutex>, Task>)>>, output_done_rx: Mutex>, root_path: PathBuf, @@ -112,7 +113,7 @@ impl LanguageServer { let working_dir = if root_path.is_dir() { root_path } else { - root_path.parent().unwrap_or(Path::new("/")) + root_path.parent().unwrap_or_else(|| Path::new("/")) }; let mut server = process::Command::new(binary_path) .current_dir(working_dir) @@ -251,7 +252,7 @@ impl LanguageServer { capabilities: Default::default(), next_id: Default::default(), outbound_tx, - executor: cx.background().clone(), + executor: cx.background(), io_tasks: Mutex::new(Some((input_task, output_task))), output_done_rx: Mutex::new(Some(output_done_rx)), root_path: root_path.to_path_buf(), @@ -641,7 +642,7 @@ impl LanguageServer { stdin_reader, None, Path::new("/"), - cx.clone(), + cx, move |msg| { notifications_tx .try_send((msg.method.to_string(), msg.params.get().to_string())) @@ -651,7 +652,7 @@ impl LanguageServer { notifications_rx, }; fake.handle_request::({ - let capabilities = capabilities.clone(); + let capabilities = capabilities; move |_, _| { let capabilities = capabilities.clone(); let name = name.clone(); @@ -662,7 +663,6 @@ impl LanguageServer { name, ..Default::default() }), - ..Default::default() }) } } @@ -697,7 +697,7 @@ impl FakeLanguageServer { loop { let (method, params) = self.notifications_rx.next().await?; - if &method == T::METHOD { + if method == T::METHOD { return Some(serde_json::from_str::(¶ms).unwrap()); } else { log::info!("skipping message in fake language server {:?}", params); diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 414a48ed10..f814276306 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -115,8 +115,8 @@ impl OutlineView { self.active_editor.update(cx, |active_editor, cx| { let snapshot = active_editor.snapshot(cx).display_snapshot; let buffer_snapshot = &snapshot.buffer_snapshot; - let start = outline_item.range.start.to_point(&buffer_snapshot); - let end = outline_item.range.end.to_point(&buffer_snapshot); + let start = outline_item.range.start.to_point(buffer_snapshot); + let end = outline_item.range.end.to_point(buffer_snapshot); let display_rows = start.to_display_point(&snapshot).row() ..end.to_display_point(&snapshot).row() + 1; active_editor.highlight_rows(Some(display_rows)); @@ -183,8 +183,8 @@ impl PickerDelegate for OutlineView { .map(|(ix, item)| { let range = item.range.to_offset(&buffer); let distance_to_closest_endpoint = cmp::min( - (range.start as isize - cursor_offset as isize).abs() as usize, - (range.end as isize - cursor_offset as isize).abs() as usize, + (range.start as isize - cursor_offset as isize).abs(), + (range.end as isize - cursor_offset as isize).abs(), ); let depth = if range.contains(&cursor_offset) { Some(item.depth) diff --git a/crates/plugin/src/lib.rs b/crates/plugin/src/lib.rs index bcb5b770dc..079b96fba8 100644 --- a/crates/plugin/src/lib.rs +++ b/crates/plugin/src/lib.rs @@ -29,7 +29,7 @@ impl __Buffer { pub extern "C" fn __alloc_buffer(len: u32) -> u32 { let vec = vec![0; len as usize]; let buffer = unsafe { __Buffer::from_vec(vec) }; - return buffer.ptr; + buffer.ptr } /// Frees a given buffer, requires the size. diff --git a/crates/plugin_runtime/build.rs b/crates/plugin_runtime/build.rs index 0614659b5e..d253064103 100644 --- a/crates/plugin_runtime/build.rs +++ b/crates/plugin_runtime/build.rs @@ -17,8 +17,7 @@ fn main() { // Clear out and recreate the plugin bin directory let _ = std::fs::remove_dir_all(base.join("bin")); - let _ = - std::fs::create_dir_all(base.join("bin")).expect("Could not make plugins bin directory"); + std::fs::create_dir_all(base.join("bin")).expect("Could not make plugins bin directory"); // Compile the plugins using the same profile as the current Zed build let (profile_flags, profile_target) = match std::env::var("PROFILE").unwrap().as_str() { @@ -43,7 +42,7 @@ fn main() { // Get the target architecture for pre-cross-compilation of plugins // and create and engine with the appropriate config - let target_triple = std::env::var("TARGET").unwrap().to_string(); + let target_triple = std::env::var("TARGET").unwrap(); println!("cargo:rerun-if-env-changed=TARGET"); let engine = create_default_engine(&target_triple); @@ -77,7 +76,7 @@ fn create_default_engine(target_triple: &str) -> Engine { let mut config = Config::default(); config .target(target_triple) - .expect(&format!("Could not set target to `{}`", target_triple)); + .unwrap_or_else(|_| panic!("Could not set target to `{}`", target_triple)); config.async_support(true); config.consume_fuel(true); Engine::new(&config).expect("Could not create precompilation engine") diff --git a/crates/plugin_runtime/src/lib.rs b/crates/plugin_runtime/src/lib.rs index 8665a108c9..177092a529 100644 --- a/crates/plugin_runtime/src/lib.rs +++ b/crates/plugin_runtime/src/lib.rs @@ -69,13 +69,13 @@ mod tests { let unsorted = vec![1, 3, 4, 2, 5]; let sorted = vec![1, 2, 3, 4, 5]; - assert_eq!(runtime.call(&plugin.noop, ()).await.unwrap(), ()); + runtime.call(&plugin.noop, ()).await.unwrap(); assert_eq!(runtime.call(&plugin.constant, ()).await.unwrap(), 27); assert_eq!(runtime.call(&plugin.identity, 58).await.unwrap(), 58); assert_eq!(runtime.call(&plugin.add, (3, 4)).await.unwrap(), 7); assert_eq!(runtime.call(&plugin.swap, (1, 2)).await.unwrap(), (2, 1)); assert_eq!(runtime.call(&plugin.sort, unsorted).await.unwrap(), sorted); - assert_eq!(runtime.call(&plugin.print, "Hi!".into()).await.unwrap(), ()); + runtime.call(&plugin.print, "Hi!".into()).await.unwrap(); assert_eq!(runtime.call(&plugin.and_back, 1).await.unwrap(), 8); assert_eq!(runtime.call(&plugin.imports, 1).await.unwrap(), 8); assert_eq!(runtime.call(&plugin.half_async, 4).await.unwrap(), 2); diff --git a/crates/plugin_runtime/src/plugin.rs b/crates/plugin_runtime/src/plugin.rs index 2748a3f3f7..bfcb024faa 100644 --- a/crates/plugin_runtime/src/plugin.rs +++ b/crates/plugin_runtime/src/plugin.rs @@ -135,7 +135,7 @@ impl PluginBuilder { // TODO: use try block once avaliable let result: Result<(WasiBuffer, Memory, _), Trap> = (|| { // grab a handle to the memory - let mut plugin_memory = match caller.get_export("memory") { + let plugin_memory = match caller.get_export("memory") { Some(Extern::Memory(mem)) => mem, _ => return Err(Trap::new("Could not grab slice of plugin memory"))?, }; @@ -144,9 +144,9 @@ impl PluginBuilder { // get the args passed from Guest let args = - Plugin::buffer_to_bytes(&mut plugin_memory, caller.as_context(), &buffer)?; + Plugin::buffer_to_bytes(&plugin_memory, caller.as_context(), &buffer)?; - let args: A = Plugin::deserialize_to_type(&args)?; + let args: A = Plugin::deserialize_to_type(args)?; // Call the Host-side function let result = function(args); @@ -214,7 +214,7 @@ impl PluginBuilder { // TODO: use try block once avaliable let result: Result<(WasiBuffer, Memory, Vec), Trap> = (|| { // grab a handle to the memory - let mut plugin_memory = match caller.get_export("memory") { + let plugin_memory = match caller.get_export("memory") { Some(Extern::Memory(mem)) => mem, _ => return Err(Trap::new("Could not grab slice of plugin memory"))?, }; @@ -222,7 +222,7 @@ impl PluginBuilder { let buffer = WasiBuffer::from_u64(packed_buffer); // get the args passed from Guest - let args = Plugin::buffer_to_type(&mut plugin_memory, &mut caller, &buffer)?; + let args = Plugin::buffer_to_type(&plugin_memory, &mut caller, &buffer)?; // Call the Host-side function let result: R = function(args); @@ -258,7 +258,7 @@ impl PluginBuilder { /// Initializes a [`Plugin`] from a given compiled Wasm module. /// Both binary (`.wasm`) and text (`.wat`) module formats are supported. - pub async fn init<'a>(self, binary: PluginBinary<'a>) -> Result { + pub async fn init(self, binary: PluginBinary<'_>) -> Result { Plugin::init(binary, self).await } } @@ -324,7 +324,7 @@ impl Plugin { println!(); } - async fn init<'a>(binary: PluginBinary<'a>, plugin: PluginBuilder) -> Result { + async fn init(binary: PluginBinary<'_>, plugin: PluginBuilder) -> Result { // initialize the WebAssembly System Interface context let engine = plugin.engine; let mut linker = plugin.linker; @@ -576,7 +576,7 @@ impl Plugin { .await?; Self::buffer_to_type( - &mut plugin_memory, + &plugin_memory, &mut self.store, &WasiBuffer::from_u64(result_buffer), ) diff --git a/crates/project/src/fs.rs b/crates/project/src/fs.rs index 0084402b85..f2d62fae87 100644 --- a/crates/project/src/fs.rs +++ b/crates/project/src/fs.rs @@ -460,7 +460,7 @@ impl FakeFs { } } Null => { - self.create_dir(&path).await.unwrap(); + self.create_dir(path).await.unwrap(); } String(contents) => { self.insert_file(&path, contents).await; diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 4d679ec9cb..7737a4df9e 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1027,7 +1027,7 @@ impl LspCommand for GetHover { lsp::HoverContents::Array(marked_strings) => { let content: Vec = marked_strings .into_iter() - .filter_map(|marked_string| HoverBlock::try_new(marked_string)) + .filter_map(HoverBlock::try_new) .collect(); if content.is_empty() { None @@ -1049,9 +1049,7 @@ impl LspCommand for GetHover { } Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(new_language))) => { if !current_text.is_empty() { - let text = std::mem::replace(&mut current_text, String::new()) - .trim() - .to_string(); + let text = std::mem::take(&mut current_text).trim().to_string(); contents.push(HoverBlock { text, language }); } @@ -1067,9 +1065,7 @@ impl LspCommand for GetHover { | Event::End(Tag::BlockQuote) | Event::HardBreak => { if !current_text.is_empty() { - let text = std::mem::replace(&mut current_text, String::new()) - .trim() - .to_string(); + let text = std::mem::take(&mut current_text).trim().to_string(); contents.push(HoverBlock { text, language }); } language = None; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 6488afd303..31d18f4fa8 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -114,10 +114,12 @@ pub struct Project { _subscriptions: Vec, opened_buffer: (Rc>>, watch::Receiver<()>), shared_buffers: HashMap>, + #[allow(clippy::type_complexity)] loading_buffers: HashMap< ProjectPath, postage::watch::Receiver, Arc>>>, >, + #[allow(clippy::type_complexity)] loading_local_worktrees: HashMap, Shared, Arc>>>>, opened_buffers: HashMap, @@ -993,7 +995,7 @@ impl Project { .iter() .filter_map(|worktree| { worktree - .upgrade(&cx) + .upgrade(cx) .map(|worktree| worktree.read(cx).as_local().unwrap().metadata_proto()) }) .collect() @@ -1080,7 +1082,7 @@ impl Project { self.worktrees .iter() .filter_map(|worktree| { - let worktree = worktree.upgrade(&cx)?.read(cx); + let worktree = worktree.upgrade(cx)?.read(cx); if worktree.is_visible() { Some(format!( "project-path-online:{}", @@ -1121,7 +1123,7 @@ impl Project { } pub fn contains_paths(&self, paths: &[PathBuf], cx: &AppContext) -> bool { - paths.iter().all(|path| self.contains_path(&path, cx)) + paths.iter().all(|path| self.contains_path(path, cx)) } pub fn contains_path(&self, path: &Path, cx: &AppContext) -> bool { @@ -1395,11 +1397,8 @@ impl Project { } for open_buffer in self.opened_buffers.values_mut() { - match open_buffer { - OpenBuffer::Strong(buffer) => { - *open_buffer = OpenBuffer::Weak(buffer.downgrade()); - } - _ => {} + if let OpenBuffer::Strong(buffer) = open_buffer { + *open_buffer = OpenBuffer::Weak(buffer.downgrade()); } } @@ -1493,7 +1492,7 @@ impl Project { let buffer = cx.add_model(|cx| { Buffer::new(self.replica_id(), text, cx) - .with_language(language.unwrap_or(language::PLAIN_TEXT.clone()), cx) + .with_language(language.unwrap_or_else(|| language::PLAIN_TEXT.clone()), cx) }); self.register_buffer(&buffer, cx)?; Ok(buffer) @@ -1791,7 +1790,7 @@ impl Project { server .notify::( lsp::DidCloseTextDocumentParams { - text_document: lsp::TextDocumentIdentifier::new(uri.clone()), + text_document: lsp::TextDocumentIdentifier::new(uri), }, ) .log_err(); @@ -1825,7 +1824,7 @@ impl Project { language_server = self .language_server_ids .get(&(worktree_id, adapter.name.clone())) - .and_then(|id| self.language_servers.get(&id)) + .and_then(|id| self.language_servers.get(id)) .and_then(|server_state| { if let LanguageServerState::Running { server, .. } = server_state { Some(server.clone()) @@ -1838,7 +1837,7 @@ impl Project { if let Some(local_worktree) = file.worktree.read(cx).as_local() { if let Some(diagnostics) = local_worktree.diagnostics_for_path(file.path()) { - self.update_buffer_diagnostics(&buffer_handle, diagnostics, None, cx) + self.update_buffer_diagnostics(buffer_handle, diagnostics, None, cx) .log_err(); } } @@ -1853,8 +1852,7 @@ impl Project { 0, initial_snapshot.text(), ), - } - .clone(), + }, ) .log_err(); buffer_handle.update(cx, |buffer, cx| { @@ -1864,7 +1862,7 @@ impl Project { .completion_provider .as_ref() .and_then(|provider| provider.trigger_characters.clone()) - .unwrap_or(Vec::new()), + .unwrap_or_default(), cx, ) }); @@ -1910,7 +1908,7 @@ impl Project { let request = self.client.request(proto::UpdateBuffer { project_id, buffer_id: buffer.read(cx).remote_id(), - operations: vec![language::proto::serialize_operation(&operation)], + operations: vec![language::proto::serialize_operation(operation)], }); cx.background().spawn(request).detach_and_log_err(cx); } else if let Some(project_id) = self.remote_id() { @@ -2014,7 +2012,7 @@ impl Project { .filter_map(move |((language_server_worktree_id, _), id)| { if *language_server_worktree_id == worktree_id { if let Some(LanguageServerState::Running { adapter, server }) = - self.language_servers.get(&id) + self.language_servers.get(id) { return Some((adapter, server)); } @@ -2151,7 +2149,7 @@ impl Project { let this = this.downgrade(); let adapter = adapter.clone(); move |mut params, cx| { - let this = this.clone(); + let this = this; let adapter = adapter.clone(); cx.spawn(|mut cx| async move { adapter.process_diagnostics(&mut params).await; @@ -2371,7 +2369,7 @@ impl Project { .and_then(|provider| { provider.trigger_characters.clone() }) - .unwrap_or(Vec::new()), + .unwrap_or_default(), cx, ) }); @@ -2502,10 +2500,8 @@ impl Project { .cloned() { for orphaned_worktree in orphaned_worktrees { - this.language_server_ids.insert( - (orphaned_worktree, server_name.clone()), - new_server_id.clone(), - ); + this.language_server_ids + .insert((orphaned_worktree, server_name.clone()), new_server_id); } } }); @@ -2528,9 +2524,7 @@ impl Project { return; } }; - let progress = match progress.value { - lsp::ProgressParamsValue::WorkDone(value) => value, - }; + let lsp::ProgressParamsValue::WorkDone(progress) = progress.value; let language_server_status = if let Some(status) = self.language_server_statuses.get_mut(&server_id) { status @@ -2543,7 +2537,7 @@ impl Project { } let is_disk_based_diagnostics_progress = - Some(token.as_ref()) == disk_based_diagnostics_progress_token.as_ref().map(|x| &**x); + Some(token.as_ref()) == disk_based_diagnostics_progress_token.as_deref(); match progress { lsp::WorkDoneProgress::Begin(report) => { @@ -2796,7 +2790,7 @@ impl Project { } else { let group_id = post_inc(&mut self.next_diagnostic_group_id); let is_disk_based = - source.map_or(false, |source| disk_based_sources.contains(&source)); + source.map_or(false, |source| disk_based_sources.contains(source)); sources_by_group_id.insert(group_id, source); primary_diagnostic_group_ids @@ -3194,7 +3188,7 @@ impl Project { if let Some(lsp_edits) = lsp_edits { let edits = this .update(cx, |this, cx| { - this.edits_from_lsp(&buffer, lsp_edits, None, cx) + this.edits_from_lsp(buffer, lsp_edits, None, cx) }) .await?; buffer.update(cx, |buffer, cx| { @@ -3366,7 +3360,7 @@ impl Project { if let Some((worktree, rel_path)) = this.find_local_worktree(&abs_path, cx) { - worktree_id = (&worktree.read(cx)).id(); + worktree_id = worktree.read(cx).id(); path = rel_path; } else { path = relativize_path(&worktree_abs_path, &abs_path); @@ -3613,7 +3607,7 @@ impl Project { .clone(); ( snapshot.anchor_before(start)..snapshot.anchor_after(end), - text.clone(), + text, ) } Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => { @@ -3791,7 +3785,7 @@ impl Project { let lsp_range = range_to_lsp(range.to_point_utf16(buffer)); cx.foreground().spawn(async move { - if !lang_server.capabilities().code_action_provider.is_some() { + if lang_server.capabilities().code_action_provider.is_none() { return Ok(Default::default()); } @@ -4120,6 +4114,7 @@ impl Project { ) } + #[allow(clippy::type_complexity)] pub fn search( &self, query: SearchQuery, @@ -4341,7 +4336,7 @@ impl Project { ) { let lsp_params = request.to_lsp(&file.abs_path(cx), cx); return cx.spawn(|this, cx| async move { - if !request.check_capabilities(&language_server.capabilities()) { + if !request.check_capabilities(language_server.capabilities()) { return Ok(Default::default()); } @@ -4375,7 +4370,7 @@ impl Project { ) -> Task, PathBuf)>> { let abs_path = abs_path.as_ref(); if let Some((tree, relative_path)) = self.find_local_worktree(abs_path, cx) { - Task::ready(Ok((tree.clone(), relative_path.into()))) + Task::ready(Ok((tree, relative_path))) } else { let worktree = self.create_local_worktree(abs_path, visible, cx); cx.foreground() @@ -4455,7 +4450,7 @@ impl Project { Ok(worktree) } - .map_err(|err| Arc::new(err)) + .map_err(Arc::new) }) .shared() }) @@ -4487,9 +4482,9 @@ impl Project { } fn add_worktree(&mut self, worktree: &ModelHandle, cx: &mut ModelContext) { - cx.observe(&worktree, |_, _, cx| cx.notify()).detach(); + cx.observe(worktree, |_, _, cx| cx.notify()).detach(); if worktree.read(cx).is_local() { - cx.subscribe(&worktree, |this, worktree, _, cx| { + cx.subscribe(worktree, |this, worktree, _, cx| { this.update_local_worktree_buffers(worktree, cx); }) .detach(); @@ -4508,7 +4503,7 @@ impl Project { } self.metadata_changed(true, cx); - cx.observe_release(&worktree, |this, worktree, cx| { + cx.observe_release(worktree, |this, worktree, cx| { this.remove_worktree(worktree.id(), cx); cx.notify(); }) @@ -4610,9 +4605,9 @@ impl Project { } } - pub fn language_servers_running_disk_based_diagnostics<'a>( - &'a self, - ) -> impl 'a + Iterator { + pub fn language_servers_running_disk_based_diagnostics( + &self, + ) -> impl Iterator + '_ { self.language_server_statuses .iter() .filter_map(|(id, status)| { @@ -4762,7 +4757,7 @@ impl Project { .remove(&peer_id) .ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))? .replica_id; - for (_, buffer) in &this.opened_buffers { + for buffer in this.opened_buffers.values() { if let Some(buffer) = buffer.upgrade(cx) { buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx)); } @@ -5088,7 +5083,7 @@ impl Project { let ops = payload .operations .into_iter() - .map(|op| language::proto::deserialize_operation(op)) + .map(language::proto::deserialize_operation) .collect::, _>>()?; let is_remote = this.is_remote(); match this.opened_buffers.entry(buffer_id) { @@ -5125,7 +5120,7 @@ impl Project { let worktree = this .worktree_for_id(WorktreeId::from_proto(file.worktree_id), cx) .ok_or_else(|| anyhow!("no such worktree"))?; - let file = File::from_proto(file, worktree.clone(), cx)?; + let file = File::from_proto(file, worktree, cx)?; let buffer = this .opened_buffers .get_mut(&buffer_id) @@ -5791,6 +5786,7 @@ impl Project { }) } + #[allow(clippy::type_complexity)] fn edits_from_lsp( &mut self, buffer: &ModelHandle, @@ -5837,7 +5833,7 @@ impl Project { new_text.push('\n'); } range.end = next_range.end; - new_text.push_str(&next_text); + new_text.push_str(next_text); lsp_edits.next(); } @@ -5872,7 +5868,7 @@ impl Project { ChangeTag::Insert => { if moved_since_edit { let anchor = snapshot.anchor_after(offset); - edits.push((anchor.clone()..anchor, value.to_string())); + edits.push((anchor..anchor, value.to_string())); } else { edits.last_mut().unwrap().1.push_str(value); } @@ -5882,7 +5878,7 @@ impl Project { } } else if range.end == range.start { let anchor = snapshot.anchor_after(range.start); - edits.push((anchor.clone()..anchor, new_text)); + edits.push((anchor..anchor, new_text)); } else { let edit_start = snapshot.anchor_after(range.start); let edit_end = snapshot.anchor_before(range.end); @@ -5944,7 +5940,7 @@ impl Project { if let Some(server_id) = self.language_server_ids.get(&key) { if let Some(LanguageServerState::Running { adapter, server }) = - self.language_servers.get(&server_id) + self.language_servers.get(server_id) { return Some((adapter, server)); } diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 3dc4e9359f..ceb5d033a7 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -499,7 +499,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { }); buffer_a.read_with(cx, |buffer, _| { - let chunks = chunks_with_diagnostics(&buffer, 0..buffer.len()); + let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); assert_eq!( chunks .iter() @@ -513,7 +513,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { ); }); buffer_b.read_with(cx, |buffer, _| { - let chunks = chunks_with_diagnostics(&buffer, 0..buffer.len()); + let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); assert_eq!( chunks .iter() @@ -579,7 +579,7 @@ async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { .await .unwrap(); buffer.read_with(cx, |buffer, _| { - let chunks = chunks_with_diagnostics(&buffer, 0..buffer.len()); + let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); assert_eq!( chunks .iter() @@ -1262,7 +1262,7 @@ async fn test_empty_diagnostic_ranges(cx: &mut gpui::TestAppContext) { // At the end of a line, an empty range is extended backward to include // the preceding character. buffer.read_with(cx, |buffer, _| { - let chunks = chunks_with_diagnostics(&buffer, 0..buffer.len()); + let chunks = chunks_with_diagnostics(buffer, 0..buffer.len()); assert_eq!( chunks .iter() @@ -1511,7 +1511,7 @@ async fn test_edits_from_lsp_with_edits_on_adjacent_lines(cx: &mut gpui::TestApp .into_iter() .map(|(range, text)| { ( - range.start.to_point(&buffer)..range.end.to_point(&buffer), + range.start.to_point(buffer)..range.end.to_point(buffer), text, ) }) @@ -1614,7 +1614,7 @@ async fn test_invalid_edits_from_lsp(cx: &mut gpui::TestAppContext) { .into_iter() .map(|(range, text)| { ( - range.start.to_point(&buffer)..range.end.to_point(&buffer), + range.start.to_point(buffer)..range.end.to_point(buffer), text, ) }) @@ -2139,7 +2139,7 @@ async fn test_rescan_and_remote_updates( let tree = project.worktrees(cx).next().unwrap(); tree.read(cx) .entry_for_path(path) - .expect(&format!("no entry for path {}", path)) + .unwrap_or_else(|| panic!("no entry for path {}", path)) .id }) }; @@ -2149,9 +2149,9 @@ async fn test_rescan_and_remote_updates( let buffer4 = buffer_for_path("b/c/file4", cx).await; let buffer5 = buffer_for_path("b/c/file5", cx).await; - let file2_id = id_for_path("a/file2", &cx); - let file3_id = id_for_path("a/file3", &cx); - let file4_id = id_for_path("b/c/file4", &cx); + let file2_id = id_for_path("a/file2", cx); + let file3_id = id_for_path("a/file3", cx); + let file4_id = id_for_path("b/c/file4", cx); // Create a remote copy of this worktree. let tree = project.read_with(cx, |project, cx| project.worktrees(cx).next().unwrap()); @@ -2183,12 +2183,12 @@ async fn test_rescan_and_remote_updates( }); // Rename and delete files and directories. - tree.flush_fs_events(&cx).await; + tree.flush_fs_events(cx).await; std::fs::rename(dir.path().join("a/file3"), dir.path().join("b/c/file3")).unwrap(); std::fs::remove_file(dir.path().join("b/c/file5")).unwrap(); std::fs::rename(dir.path().join("b/c"), dir.path().join("d")).unwrap(); std::fs::rename(dir.path().join("a/file2"), dir.path().join("a/file2.new")).unwrap(); - tree.flush_fs_events(&cx).await; + tree.flush_fs_events(cx).await; let expected_paths = vec![ "a", @@ -2209,9 +2209,9 @@ async fn test_rescan_and_remote_updates( expected_paths ); - assert_eq!(id_for_path("a/file2.new", &cx), file2_id); - assert_eq!(id_for_path("d/file3", &cx), file3_id); - assert_eq!(id_for_path("d/file4", &cx), file4_id); + assert_eq!(id_for_path("a/file2.new", cx), file2_id); + assert_eq!(id_for_path("d/file3", cx), file3_id); + assert_eq!(id_for_path("d/file4", cx), file4_id); assert_eq!( buffer2.read(app).file().unwrap().path().as_ref(), @@ -2689,7 +2689,7 @@ async fn test_grouped_diagnostics(cx: &mut gpui::TestAppContext) { message: "error 2 hint 2".to_string(), related_information: Some(vec![lsp::DiagnosticRelatedInformation { location: lsp::Location { - uri: buffer_uri.clone(), + uri: buffer_uri, range: lsp::Range::new(lsp::Position::new(2, 8), lsp::Position::new(2, 17)), }, message: "original diagnostic".to_string(), diff --git a/crates/project/src/search.rs b/crates/project/src/search.rs index 58fa04eeb2..b526ab0c18 100644 --- a/crates/project/src/search.rs +++ b/crates/project/src/search.rs @@ -53,7 +53,7 @@ impl SearchQuery { query = word_query } - let multiline = query.contains("\n") || query.contains("\\n"); + let multiline = query.contains('\n') || query.contains("\\n"); let regex = RegexBuilder::new(&query) .case_insensitive(!case_sensitive) .multi_line(multiline) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 203b512d9b..3888e1ea36 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -57,6 +57,7 @@ lazy_static! { #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] pub struct WorktreeId(usize); +#[allow(clippy::large_enum_variant)] pub enum Worktree { Local(LocalWorktree), Remote(RemoteWorktree), @@ -157,7 +158,7 @@ impl Worktree { cx: &mut AsyncAppContext, ) -> Result> { let (tree, scan_states_tx) = - LocalWorktree::new(client, path, visible, fs.clone(), next_entry_id, cx).await?; + LocalWorktree::create(client, path, visible, fs.clone(), next_entry_id, cx).await?; tree.update(cx, |tree, cx| { let tree = tree.as_local_mut().unwrap(); let abs_path = tree.abs_path().clone(); @@ -229,7 +230,7 @@ impl Worktree { cx.spawn(|mut cx| { let this = worktree_handle.downgrade(); async move { - while let Some(_) = snapshot_updated_rx.recv().await { + while (snapshot_updated_rx.recv().await).is_some() { if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| { this.poll_snapshot(cx); @@ -322,15 +323,15 @@ impl Worktree { } } - pub fn diagnostic_summaries<'a>( - &'a self, - ) -> impl Iterator, DiagnosticSummary)> + 'a { + pub fn diagnostic_summaries( + &self, + ) -> impl Iterator, DiagnosticSummary)> + '_ { match self { Worktree::Local(worktree) => &worktree.diagnostic_summaries, Worktree::Remote(worktree) => &worktree.diagnostic_summaries, } .iter() - .map(|(path, summary)| (path.0.clone(), summary.clone())) + .map(|(path, summary)| (path.0.clone(), *summary)) } fn poll_snapshot(&mut self, cx: &mut ModelContext) { @@ -342,7 +343,7 @@ impl Worktree { } impl LocalWorktree { - async fn new( + async fn create( client: Arc, path: impl Into>, visible: bool, @@ -386,7 +387,7 @@ impl LocalWorktree { }; if let Some(metadata) = metadata { let entry = Entry::new( - path.into(), + path, &metadata, &snapshot.next_entry_id, snapshot.root_char_bag, @@ -651,7 +652,7 @@ impl LocalWorktree { let abs_path = self.absolutize(&entry.path); let delete = cx.background().spawn({ let fs = self.fs.clone(); - let abs_path = abs_path.clone(); + let abs_path = abs_path; async move { if entry.is_file() { fs.remove_file(&abs_path, Default::default()).await @@ -848,7 +849,7 @@ impl LocalWorktree { let rpc = self.client.clone(); let worktree_id = cx.model_id() as u64; let maintain_remote_snapshot = cx.background().spawn({ - let rpc = rpc.clone(); + let rpc = rpc; let diagnostic_summaries = self.diagnostic_summaries.clone(); async move { let mut prev_snapshot = match snapshots_rx.recv().await { @@ -1002,10 +1003,9 @@ impl RemoteWorktree { warning_count: summary.warning_count as usize, }; if summary.is_empty() { - self.diagnostic_summaries.remove(&PathKey(path.clone())); + self.diagnostic_summaries.remove(&PathKey(path)); } else { - self.diagnostic_summaries - .insert(PathKey(path.clone()), summary); + self.diagnostic_summaries.insert(PathKey(path), summary); } } @@ -1513,7 +1513,7 @@ impl LocalSnapshot { let mut ignore_stack = IgnoreStack::none(); for (parent_abs_path, ignore) in new_ignores.into_iter().rev() { - if ignore_stack.is_abs_path_ignored(&parent_abs_path, true) { + if ignore_stack.is_abs_path_ignored(parent_abs_path, true) { ignore_stack = IgnoreStack::all(); break; } else if let Some(ignore) = ignore { @@ -1530,8 +1530,8 @@ impl LocalSnapshot { } async fn build_gitignore(abs_path: &Path, fs: &dyn Fs) -> Result { - let contents = fs.load(&abs_path).await?; - let parent = abs_path.parent().unwrap_or(Path::new("/")); + let contents = fs.load(abs_path).await?; + let parent = abs_path.parent().unwrap_or_else(|| Path::new("/")); let mut builder = GitignoreBuilder::new(parent); for line in contents.lines() { builder.add_line(Some(abs_path.into()), line)?; @@ -1769,7 +1769,7 @@ impl language::LocalFile for File { .send(proto::BufferReloaded { project_id, buffer_id, - version: serialize_version(&version), + version: serialize_version(version), mtime: Some(mtime.into()), fingerprint, line_ending: serialize_line_ending(line_ending) as i32, @@ -2285,7 +2285,7 @@ impl BackgroundScanner { snapshot.scan_id += 1; for event in &events { if let Ok(path) = event.path.strip_prefix(&root_canonical_path) { - snapshot.remove_path(&path); + snapshot.remove_path(path); } } @@ -2528,13 +2528,13 @@ impl WorktreeHandle for ModelHandle { fs.create_file(&root_path.join(filename), Default::default()) .await .unwrap(); - tree.condition(&cx, |tree, _| tree.entry_for_path(filename).is_some()) + tree.condition(cx, |tree, _| tree.entry_for_path(filename).is_some()) .await; fs.remove_file(&root_path.join(filename), Default::default()) .await .unwrap(); - tree.condition(&cx, |tree, _| tree.entry_for_path(filename).is_none()) + tree.condition(cx, |tree, _| tree.entry_for_path(filename).is_none()) .await; cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) @@ -2726,7 +2726,7 @@ impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry { let kind = if entry.is_dir { EntryKind::Dir } else { - let mut char_bag = root_char_bag.clone(); + let mut char_bag = *root_char_bag; char_bag.extend( String::from_utf8_lossy(&entry.path) .chars() @@ -2738,7 +2738,7 @@ impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry { Ok(Entry { id: ProjectEntryId::from_proto(entry.id), kind, - path: path.clone(), + path, inode: entry.inode, mtime: mtime.into(), is_symlink: entry.is_symlink, @@ -2955,7 +2955,7 @@ mod tests { .unwrap(); cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; - tree.flush_fs_events(&cx).await; + tree.flush_fs_events(cx).await; cx.read(|cx| { let tree = tree.read(cx); assert!( @@ -2979,7 +2979,7 @@ mod tests { std::fs::write(dir.join("tracked-dir/tracked-file2"), "").unwrap(); std::fs::write(dir.join("tracked-dir/ancestor-ignored-file2"), "").unwrap(); std::fs::write(dir.join("ignored-dir/ignored-file2"), "").unwrap(); - tree.flush_fs_events(&cx).await; + tree.flush_fs_events(cx).await; cx.read(|cx| { let tree = tree.read(cx); assert!( @@ -3026,7 +3026,7 @@ mod tests { .unwrap(); cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; - tree.flush_fs_events(&cx).await; + tree.flush_fs_events(cx).await; tree.update(cx, |tree, cx| { tree.as_local().unwrap().write_file( @@ -3052,8 +3052,8 @@ mod tests { tree.read_with(cx, |tree, _| { let tracked = tree.entry_for_path("tracked-dir/file.txt").unwrap(); let ignored = tree.entry_for_path("ignored-dir/file.txt").unwrap(); - assert_eq!(tracked.is_ignored, false); - assert_eq!(ignored.is_ignored, true); + assert!(!tracked.is_ignored); + assert!(ignored.is_ignored); }); } @@ -3226,9 +3226,9 @@ mod tests { let mut ignore_contents = String::new(); for path_to_ignore in files_to_ignore.chain(dirs_to_ignore) { - write!( + writeln!( ignore_contents, - "{}\n", + "{}", path_to_ignore .strip_prefix(&ignore_dir_path)? .to_str() @@ -3363,7 +3363,7 @@ mod tests { .collect::>(); assert_eq!(dfs_paths_via_traversal, dfs_paths_via_iter); - for (ignore_parent_abs_path, _) in &self.ignores_by_parent_abs_path { + for ignore_parent_abs_path in self.ignores_by_parent_abs_path.keys() { let ignore_parent_path = ignore_parent_abs_path.strip_prefix(&self.abs_path).unwrap(); assert!(self.entry_for_path(&ignore_parent_path).is_some()); @@ -3389,7 +3389,7 @@ mod tests { paths.push((entry.path.as_ref(), entry.inode, entry.is_ignored)); } } - paths.sort_by(|a, b| a.0.cmp(&b.0)); + paths.sort_by(|a, b| a.0.cmp(b.0)); paths } } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 0a32a8427b..f077520d72 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -186,15 +186,14 @@ impl ProjectPanel { }); cx.observe_focus(&filename_editor, |this, _, is_focused, cx| { - if !is_focused { - if this + if !is_focused + && this .edit_state .as_ref() .map_or(false, |state| state.processing_filename.is_none()) - { - this.edit_state = None; - this.update_visible_entries(None, cx); - } + { + this.edit_state = None; + this.update_visible_entries(None, cx); } }) .detach(); @@ -209,7 +208,7 @@ impl ProjectPanel { edit_state: None, filename_editor, clipboard_entry: None, - context_menu: cx.add_view(|cx| ContextMenu::new(cx)), + context_menu: cx.add_view(ContextMenu::new), }; this.update_visible_entries(None, cx); this @@ -380,13 +379,11 @@ impl ProjectPanel { self.index_for_selection(selection).unwrap_or_default(); if entry_ix > 0 { entry_ix -= 1; + } else if worktree_ix > 0 { + worktree_ix -= 1; + entry_ix = self.visible_entries[worktree_ix].1.len() - 1; } else { - if worktree_ix > 0 { - worktree_ix -= 1; - entry_ix = self.visible_entries[worktree_ix].1.len() - 1; - } else { - return; - } + return; } let (worktree_id, worktree_entries) = &self.visible_entries[worktree_ix]; @@ -734,17 +731,15 @@ impl ProjectPanel { self.clipboard_entry.take(); if clipboard_entry.is_cut() { - self.project - .update(cx, |project, cx| { - project.rename_entry(clipboard_entry.entry_id(), new_path, cx) - }) - .map(|task| task.detach_and_log_err(cx)); - } else { - self.project - .update(cx, |project, cx| { - project.copy_entry(clipboard_entry.entry_id(), new_path, cx) - }) - .map(|task| task.detach_and_log_err(cx)); + if let Some(task) = self.project.update(cx, |project, cx| { + project.rename_entry(clipboard_entry.entry_id(), new_path, cx) + }) { + task.detach_and_log_err(cx) + } + } else if let Some(task) = self.project.update(cx, |project, cx| { + project.copy_entry(clipboard_entry.entry_id(), new_path, cx) + }) { + task.detach_and_log_err(cx) } } None @@ -760,10 +755,9 @@ impl ProjectPanel { } fn index_for_selection(&self, selection: Selection) -> Option<(usize, usize, usize)> { - let mut worktree_index = 0; let mut entry_index = 0; let mut visible_entries_index = 0; - for (worktree_id, worktree_entries) in &self.visible_entries { + for (worktree_index, (worktree_id, worktree_entries)) in self.visible_entries.iter().enumerate() { if *worktree_id == selection.worktree_id { for entry in worktree_entries { if entry.id == selection.entry_id { @@ -777,7 +771,6 @@ impl ProjectPanel { } else { visible_entries_index += worktree_entries.len(); } - worktree_index += 1; } None } @@ -849,10 +842,10 @@ impl ProjectPanel { is_ignored: false, }); } - if expanded_dir_ids.binary_search(&entry.id).is_err() { - if entry_iter.advance_to_sibling() { - continue; - } + if expanded_dir_ids.binary_search(&entry.id).is_err() + && entry_iter.advance_to_sibling() + { + continue; } entry_iter.advance(); } @@ -982,7 +975,7 @@ impl ProjectPanel { if let Some(processing_filename) = &edit_state.processing_filename { details.is_processing = true; details.filename.clear(); - details.filename.push_str(&processing_filename); + details.filename.push_str(processing_filename); } else { if edit_state.is_new_entry { details.filename.clear(); @@ -1116,7 +1109,7 @@ impl View for ProjectPanel { cx, move |this, range, items, cx| { let theme = cx.global::().theme.clone(); - this.for_each_visible_entry(range.clone(), cx, |id, details, cx| { + this.for_each_visible_entry(range, cx, |id, details, cx| { items.push(Self::render_entry( id, details, diff --git a/crates/rpc/src/conn.rs b/crates/rpc/src/conn.rs index dfb09a0913..450e36782e 100644 --- a/crates/rpc/src/conn.rs +++ b/crates/rpc/src/conn.rs @@ -50,6 +50,7 @@ impl Connection { killed, ); + #[allow(clippy::type_complexity)] fn channel( killed: Arc, executor: Arc, @@ -76,9 +77,7 @@ impl Connection { // Writes to a half-open TCP connection will error. if killed.load(SeqCst) { - std::io::Result::Err( - Error::new(ErrorKind::Other, "connection lost").into(), - )?; + std::io::Result::Err(Error::new(ErrorKind::Other, "connection lost"))?; } Ok(msg) @@ -87,7 +86,7 @@ impl Connection { }); let rx = rx.then({ - let killed = killed.clone(); + let killed = killed; let executor = Arc::downgrade(&executor); move |msg| { let killed = killed.clone(); diff --git a/crates/rpc/src/peer.rs b/crates/rpc/src/peer.rs index a22dcfe39e..6c1c4f01da 100644 --- a/crates/rpc/src/peer.rs +++ b/crates/rpc/src/peer.rs @@ -94,6 +94,7 @@ pub struct ConnectionState { #[serde(skip)] outgoing_tx: mpsc::UnboundedSender, next_message_id: Arc, + #[allow(clippy::type_complexity)] #[serde(skip)] response_channels: Arc)>>>>>, @@ -139,7 +140,7 @@ impl Peer { let connection_id = ConnectionId(self.next_connection_id.fetch_add(1, SeqCst)); let connection_state = ConnectionState { - outgoing_tx: outgoing_tx.clone(), + outgoing_tx, next_message_id: Default::default(), response_channels: Arc::new(Mutex::new(Some(Default::default()))), }; diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 8cd5ca36fb..8cd65d34f1 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -265,7 +265,9 @@ entity_messages!( entity_messages!(channel_id, ChannelMessageSent); -const MAX_BUFFER_LEN: usize = 1 * 1024 * 1024; +const KIB: usize = 1024; +const MIB: usize = KIB * 1024; +const MAX_BUFFER_LEN: usize = MIB; /// A stream of protobuf messages. pub struct MessageStream { @@ -273,6 +275,7 @@ pub struct MessageStream { encoding_buffer: Vec, } +#[allow(clippy::large_enum_variant)] #[derive(Debug)] pub enum Message { Envelope(Envelope), @@ -309,7 +312,7 @@ where self.encoding_buffer.reserve(message.encoded_len()); message .encode(&mut self.encoding_buffer) - .map_err(|err| io::Error::from(err))?; + .map_err(io::Error::from)?; let buffer = zstd::stream::encode_all(self.encoding_buffer.as_slice(), COMPRESSION_LEVEL) .unwrap(); @@ -360,10 +363,10 @@ where } } -impl Into for Timestamp { - fn into(self) -> SystemTime { +impl From for SystemTime { + fn from(val: Timestamp) -> Self { UNIX_EPOCH - .checked_add(Duration::new(self.seconds, self.nanos)) + .checked_add(Duration::new(val.seconds, val.nanos)) .unwrap() } } @@ -451,7 +454,7 @@ mod tests { .unwrap(); assert!(sink.encoding_buffer.capacity() <= MAX_BUFFER_LEN); - let mut stream = MessageStream::new(rx.map(|msg| anyhow::Ok(msg))); + let mut stream = MessageStream::new(rx.map(anyhow::Ok)); stream.read().await.unwrap(); assert!(stream.encoding_buffer.capacity() <= MAX_BUFFER_LEN); stream.read().await.unwrap(); diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index bc6f37202d..742d2acb64 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -216,7 +216,7 @@ impl BufferSearchBar { fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext) { self.dismissed = true; - for (editor, _) in &self.editors_with_matches { + for editor in self.editors_with_matches.keys() { if let Some(editor) = editor.upgrade(cx) { editor.update(cx, |editor, cx| { editor.clear_background_highlights::(cx) @@ -450,14 +450,11 @@ impl BufferSearchBar { event: &editor::Event, cx: &mut ViewContext, ) { - match event { - editor::Event::BufferEdited { .. } => { - self.query_contains_error = false; - self.clear_matches(cx); - self.update_matches(true, cx); - cx.notify(); - } - _ => {} + if let editor::Event::BufferEdited { .. } = event { + self.query_contains_error = false; + self.clear_matches(cx); + self.update_matches(true, cx); + cx.notify(); } } @@ -586,7 +583,7 @@ impl BufferSearchBar { let ranges = self.editors_with_matches.get(&editor.downgrade())?; let editor = editor.read(cx); active_match_index( - &ranges, + ranges, &editor.selections.newest_anchor().head(), &editor.buffer().read(cx).snapshot(cx), ) @@ -610,7 +607,7 @@ mod tests { #[gpui::test] async fn test_search_simple(cx: &mut TestAppContext) { let fonts = cx.font_cache(); - let mut theme = gpui::fonts::with_font_cache(fonts.clone(), || theme::Theme::default()); + let mut theme = gpui::fonts::with_font_cache(fonts.clone(), theme::Theme::default); theme.search.match_background = Color::red(); cx.update(|cx| { let mut settings = Settings::test(cx); @@ -649,7 +646,7 @@ mod tests { search_bar.update(cx, |search_bar, cx| { search_bar.set_query("us", cx); }); - editor.next_notification(&cx).await; + editor.next_notification(cx).await; editor.update(cx, |editor, cx| { assert_eq!( editor.all_background_highlights(cx), @@ -670,7 +667,7 @@ mod tests { search_bar.update(cx, |search_bar, cx| { search_bar.toggle_search_option(SearchOption::CaseSensitive, cx); }); - editor.next_notification(&cx).await; + editor.next_notification(cx).await; editor.update(cx, |editor, cx| { assert_eq!( editor.all_background_highlights(cx), @@ -686,7 +683,7 @@ mod tests { search_bar.update(cx, |search_bar, cx| { search_bar.set_query("or", cx); }); - editor.next_notification(&cx).await; + editor.next_notification(cx).await; editor.update(cx, |editor, cx| { assert_eq!( editor.all_background_highlights(cx), @@ -727,7 +724,7 @@ mod tests { search_bar.update(cx, |search_bar, cx| { search_bar.toggle_search_option(SearchOption::WholeWord, cx); }); - editor.next_notification(&cx).await; + editor.next_notification(cx).await; editor.update(cx, |editor, cx| { assert_eq!( editor.all_background_highlights(cx), diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 475923d6ef..0b30a0bd36 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -367,7 +367,7 @@ impl ProjectSearchView { }); // Subcribe to query_editor in order to reraise editor events for workspace item activation purposes cx.subscribe(&query_editor, |_, _, event, cx| { - cx.emit(ViewEvent::EditorEvent(event.clone())) + cx.emit(ViewEvent::EditorEvent(*event)) }) .detach(); @@ -384,7 +384,7 @@ impl ProjectSearchView { this.update_match_index(cx); } // Reraise editor events for workspace item activation purposes - cx.emit(ViewEvent::EditorEvent(event.clone())); + cx.emit(ViewEvent::EditorEvent(*event)); }) .detach(); @@ -567,6 +567,12 @@ impl ProjectSearchView { } } +impl Default for ProjectSearchBar { + fn default() -> Self { + Self::new() + } +} + impl ProjectSearchBar { pub fn new() -> Self { Self { @@ -903,7 +909,7 @@ mod tests { #[gpui::test] async fn test_project_search(cx: &mut TestAppContext) { let fonts = cx.font_cache(); - let mut theme = gpui::fonts::with_font_cache(fonts.clone(), || theme::Theme::default()); + let mut theme = gpui::fonts::with_font_cache(fonts.clone(), theme::Theme::default); theme.search.match_background = Color::red(); cx.update(|cx| { let mut settings = Settings::test(cx); @@ -933,7 +939,7 @@ mod tests { .update(cx, |query_editor, cx| query_editor.set_text("TWO", cx)); search_view.search(cx); }); - search_view.next_notification(&cx).await; + search_view.next_notification(cx).await; search_view.update(cx, |search_view, cx| { assert_eq!( search_view diff --git a/crates/search/src/search.rs b/crates/search/src/search.rs index 5d6014eaeb..a975ab0666 100644 --- a/crates/search/src/search.rs +++ b/crates/search/src/search.rs @@ -66,9 +66,9 @@ pub(crate) fn active_match_index( None } else { match ranges.binary_search_by(|probe| { - if probe.end.cmp(&cursor, &*buffer).is_lt() { + if probe.end.cmp(cursor, &*buffer).is_lt() { Ordering::Less - } else if probe.start.cmp(&cursor, &*buffer).is_gt() { + } else if probe.start.cmp(cursor, &*buffer).is_gt() { Ordering::Greater } else { Ordering::Equal @@ -86,7 +86,7 @@ pub(crate) fn match_index_for_direction( direction: Direction, buffer: &MultiBufferSnapshot, ) -> usize { - if ranges[index].start.cmp(&cursor, &buffer).is_gt() { + if ranges[index].start.cmp(cursor, buffer).is_gt() { if direction == Direction::Prev { if index == 0 { index = ranges.len() - 1; @@ -94,7 +94,7 @@ pub(crate) fn match_index_for_direction( index -= 1; } } - } else if ranges[index].end.cmp(&cursor, &buffer).is_lt() { + } else if ranges[index].end.cmp(cursor, buffer).is_lt() { if direction == Direction::Next { index = 0; } diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index 99cf81c6ba..c1d5db32bb 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -49,37 +49,37 @@ impl KeymapFileContent { pub fn load(asset_path: &str, cx: &mut MutableAppContext) -> Result<()> { let content = Assets::get(asset_path).unwrap().data; let content_str = std::str::from_utf8(content.as_ref()).unwrap(); - Ok(parse_json_with_comments::(content_str)?.add(cx)?) + parse_json_with_comments::(content_str)?.add_to_cx(cx) } - pub fn add(self, cx: &mut MutableAppContext) -> Result<()> { + pub fn add_to_cx(self, cx: &mut MutableAppContext) -> Result<()> { for KeymapBlock { context, bindings } in self.0 { - cx.add_bindings( - bindings - .into_iter() - .map(|(keystroke, action)| { - let action = action.0.get(); + let bindings = bindings + .into_iter() + .map(|(keystroke, action)| { + let action = action.0.get(); - // This is a workaround for a limitation in serde: serde-rs/json#497 - // We want to deserialize the action data as a `RawValue` so that we can - // deserialize the action itself dynamically directly from the JSON - // string. But `RawValue` currently does not work inside of an untagged enum. - let action = if action.starts_with('[') { - let ActionWithData(name, data) = serde_json::from_str(action)?; - cx.deserialize_action(&name, Some(data.get())) - } else { - let name = serde_json::from_str(action)?; - cx.deserialize_action(name, None) - } - .with_context(|| { - format!( + // This is a workaround for a limitation in serde: serde-rs/json#497 + // We want to deserialize the action data as a `RawValue` so that we can + // deserialize the action itself dynamically directly from the JSON + // string. But `RawValue` currently does not work inside of an untagged enum. + let action = if action.starts_with('[') { + let ActionWithData(name, data) = serde_json::from_str(action)?; + cx.deserialize_action(&name, Some(data.get())) + } else { + let name = serde_json::from_str(action)?; + cx.deserialize_action(name, None) + } + .with_context(|| { + format!( "invalid binding value for keystroke {keystroke}, context {context:?}" ) - })?; - Binding::load(&keystroke, action, context.as_deref()) - }) - .collect::>>()?, - ) + })?; + Binding::load(&keystroke, action, context.as_deref()) + }) + .collect::>>()?; + + cx.add_bindings(bindings); } Ok(()) } @@ -98,7 +98,7 @@ pub fn keymap_file_json_schema(action_names: &[&'static str]) -> serde_json::Val instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))), enum_values: Some( action_names - .into_iter() + .iter() .map(|name| Value::String(name.to_string())) .collect(), ), diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index fc5384cb3e..ce1fa09d99 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -200,7 +200,7 @@ impl Settings { } } if let Some(value) = &data.theme { - if let Some(theme) = theme_registry.get(&value.to_string()).log_err() { + if let Some(theme) = theme_registry.get(value).log_err() { self.theme = theme; } } @@ -301,7 +301,7 @@ impl Settings { language_overrides: Default::default(), lsp: Default::default(), projects_online_by_default: true, - theme: gpui::fonts::with_font_cache(cx.font_cache().clone(), || Default::default()), + theme: gpui::fonts::with_font_cache(cx.font_cache().clone(), Default::default), } } @@ -309,7 +309,7 @@ impl Settings { pub fn test_async(cx: &mut gpui::TestAppContext) { cx.update(|cx| { let settings = Self::test(cx); - cx.set_global(settings.clone()); + cx.set_global(settings); }); } } @@ -327,12 +327,7 @@ pub fn settings_file_json_schema( // Create a schema for a theme name. let theme_name_schema = SchemaObject { instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))), - enum_values: Some( - theme_names - .into_iter() - .map(|name| Value::String(name)) - .collect(), - ), + enum_values: Some(theme_names.into_iter().map(Value::String).collect()), ..Default::default() }; diff --git a/crates/snippet/src/snippet.rs b/crates/snippet/src/snippet.rs index 8f4ca82c05..808701569a 100644 --- a/crates/snippet/src/snippet.rs +++ b/crates/snippet/src/snippet.rs @@ -78,22 +78,22 @@ fn parse_tabstop<'a>( ) -> Result<&'a str> { let tabstop_start = text.len(); let tabstop_index; - if source.chars().next() == Some('{') { + if source.starts_with('{') { let (index, rest) = parse_int(&source[1..])?; tabstop_index = index; source = rest; - if source.chars().next() == Some(':') { + if source.starts_with(':') { source = parse_snippet(&source[1..], true, text, tabstops)?; } - if source.chars().next() == Some('}') { + if source.starts_with('}') { source = &source[1..]; } else { return Err(anyhow!("expected a closing brace")); } } else { - let (index, rest) = parse_int(&source)?; + let (index, rest) = parse_int(source)?; tabstop_index = index; source = rest; } diff --git a/crates/sum_tree/src/cursor.rs b/crates/sum_tree/src/cursor.rs index 39848ea56d..09f253d432 100644 --- a/crates/sum_tree/src/cursor.rs +++ b/crates/sum_tree/src/cursor.rs @@ -160,7 +160,7 @@ where let mut descending = false; while !self.stack.is_empty() { - if let Some(StackEntry { position, .. }) = self.stack.iter().rev().skip(1).next() { + if let Some(StackEntry { position, .. }) = self.stack.iter().rev().nth(1) { self.position = position.clone(); } else { self.position = D::default(); @@ -224,7 +224,7 @@ where self.did_seek = true; } - while self.stack.len() > 0 { + while !self.stack.is_empty() { let new_subtree = { let entry = self.stack.last_mut().unwrap(); match entry.tree.0.as_ref() { @@ -409,7 +409,7 @@ where .zip(&child_summaries[entry.index..]) { let mut child_end = self.position.clone(); - child_end.add_summary(&child_summary, cx); + child_end.add_summary(child_summary, cx); let comparison = target.cmp(&child_end, cx); if comparison == Ordering::Greater @@ -503,7 +503,7 @@ impl<'a, T: Item> Iterator for Iter<'a, T> { descend = true; } - while self.stack.len() > 0 { + while !self.stack.is_empty() { let new_subtree = { let entry = self.stack.last_mut().unwrap(); match entry.tree.0.as_ref() { diff --git a/crates/sum_tree/src/sum_tree.rs b/crates/sum_tree/src/sum_tree.rs index efd5c43480..fdfd5d9de2 100644 --- a/crates/sum_tree/src/sum_tree.rs +++ b/crates/sum_tree/src/sum_tree.rs @@ -304,7 +304,7 @@ impl SumTree { } pub fn push_tree(&mut self, other: Self, cx: &::Context) { - if !other.0.is_leaf() || other.0.items().len() > 0 { + if !other.0.is_leaf() || !other.0.items().is_empty() { if self.0.height() < other.0.height() { for tree in other.0.child_trees() { self.push_tree(tree.clone(), cx); @@ -610,10 +610,7 @@ pub enum Node { impl Node { fn is_leaf(&self) -> bool { - match self { - Node::Leaf { .. } => true, - _ => false, - } + matches!(self, Node::Leaf { .. }) } fn height(&self) -> u8 { @@ -786,8 +783,7 @@ mod tests { while item_ix < expected_filtered_items.len() { log::info!("filter_cursor, item_ix: {}", item_ix); let actual_item = filter_cursor.item().unwrap(); - let (reference_index, reference_item) = - expected_filtered_items[item_ix].clone(); + let (reference_index, reference_item) = expected_filtered_items[item_ix]; assert_eq!(actual_item, &reference_item); assert_eq!(filter_cursor.start().0, reference_index); log::info!("next"); diff --git a/crates/sum_tree/src/tree_map.rs b/crates/sum_tree/src/tree_map.rs index 5218d2b4db..8672ca398f 100644 --- a/crates/sum_tree/src/tree_map.rs +++ b/crates/sum_tree/src/tree_map.rs @@ -73,7 +73,7 @@ impl TreeMap { removed } - pub fn iter<'a>(&'a self) -> impl 'a + Iterator { + pub fn iter(&self) -> impl Iterator + '_ { self.0.iter().map(|entry| (&entry.key, &entry.value)) } } @@ -162,7 +162,7 @@ where self.0.get(key).is_some() } - pub fn iter<'a>(&'a self) -> impl 'a + Iterator { + pub fn iter(&self) -> impl Iterator + '_ { self.0.iter().map(|(k, _)| k) } } diff --git a/crates/terminal/src/connected_el.rs b/crates/terminal/src/connected_el.rs index a68280a7c7..ab08efc1b3 100644 --- a/crates/terminal/src/connected_el.rs +++ b/crates/terminal/src/connected_el.rs @@ -190,7 +190,7 @@ impl RelativeHighlightedRange { let end_x = origin.x() + self.range.end as f32 * layout.size.cell_width + layout.size.cell_width; - return HighlightedRangeLine { start_x, end_x }; + HighlightedRangeLine { start_x, end_x } } } @@ -273,7 +273,7 @@ impl TerminalEl { cur_rect = cur_rect.take().map(|rect| rect.extend()); } else { cur_alac_color = Some(bg); - if let Some(_) = cur_rect { + if cur_rect.is_some() { rects.push(cur_rect.take().unwrap()); } cur_rect = Some(LayoutRect::new( @@ -402,7 +402,7 @@ impl TerminalEl { RunStyle { color: fg, - font_id: font_id, + font_id, underline, } } @@ -416,9 +416,9 @@ impl TerminalEl { display_offset: usize, cx: &mut PaintContext, ) { - let mouse_down_connection = self.terminal.clone(); - let click_connection = self.terminal.clone(); - let drag_connection = self.terminal.clone(); + let mouse_down_connection = self.terminal; + let click_connection = self.terminal; + let drag_connection = self.terminal; cx.scene.push_mouse_region( MouseRegion::new(view_id, None, visible_bounds) .on_down( @@ -500,7 +500,7 @@ impl TerminalEl { .terminal_overrides .font_family .as_ref() - .or_else(|| settings.terminal_defaults.font_family.as_ref()) + .or(settings.terminal_defaults.font_family.as_ref()) .and_then(|family_name| font_cache.load_family(&[family_name]).log_err()) .unwrap_or(settings.buffer_font_family); @@ -581,7 +581,7 @@ impl Element for TerminalEl { //Setup layout information let terminal_theme = settings.theme.terminal.clone(); //TODO: Try to minimize this clone. - let text_style = TerminalEl::make_text_style(font_cache, &settings); + let text_style = TerminalEl::make_text_style(font_cache, settings); let selection_color = settings.theme.editor.selection.selection; let dimensions = { let line_height = font_cache.line_height(text_style.font_size); @@ -590,9 +590,9 @@ impl Element for TerminalEl { }; let background_color = if self.modal { - terminal_theme.colors.modal_background.clone() + terminal_theme.colors.modal_background } else { - terminal_theme.colors.background.clone() + terminal_theme.colors.background }; let (cells, selection, cursor, display_offset, cursor_text) = self @@ -614,17 +614,17 @@ impl Element for TerminalEl { // && !ic.flags.contains(Flags::INVERSE)) // }) .map(|ic| IndexedCell { - point: ic.point.clone(), + point: ic.point, cell: ic.cell.clone(), }), ); ( cells, - content.selection.clone(), - content.cursor.clone(), - content.display_offset.clone(), - cursor_text.clone(), + content.selection, + content.cursor, + content.display_offset, + cursor_text, ) }) }); @@ -666,7 +666,7 @@ impl Element for TerminalEl { dimensions.line_height, terminal_theme.colors.cursor, CursorShape::Block, - Some(cursor_text.clone()), + Some(cursor_text), ) }, ) @@ -721,7 +721,7 @@ impl Element for TerminalEl { }); for rect in &layout.rects { - rect.paint(origin, &layout, cx) + rect.paint(origin, layout, cx) } }); @@ -786,11 +786,11 @@ impl Element for TerminalEl { let vertical_scroll = (delta.y() / layout.size.line_height) * ALACRITTY_SCROLL_MULTIPLIER; - self.terminal.upgrade(cx.app).map(|terminal| { + if let Some(terminal) = self.terminal.upgrade(cx.app) { terminal.update(cx.app, |term, _| { term.scroll(Scroll::Delta(vertical_scroll.round() as i32)) }); - }); + } cx.notify(); }) diff --git a/crates/terminal/src/connected_view.rs b/crates/terminal/src/connected_view.rs index ed9b994e75..1da8aad610 100644 --- a/crates/terminal/src/connected_view.rs +++ b/crates/terminal/src/connected_view.rs @@ -82,7 +82,7 @@ impl ConnectedView { has_new_content: true, has_bell: false, modal, - context_menu: cx.add_view(|cx| ContextMenu::new(cx)), + context_menu: cx.add_view(ContextMenu::new), } } @@ -127,9 +127,9 @@ impl ConnectedView { ///Attempt to paste the clipboard into the terminal fn paste(&mut self, _: &Paste, cx: &mut ViewContext) { - cx.read_from_clipboard().map(|item| { + if let Some(item) = cx.read_from_clipboard() { self.terminal.read(cx).paste(item.text()); - }); + } } ///Synthesize the keyboard event corresponding to 'up' diff --git a/crates/terminal/src/mappings/colors.rs b/crates/terminal/src/mappings/colors.rs index 1a425ebaed..9359be79ff 100644 --- a/crates/terminal/src/mappings/colors.rs +++ b/crates/terminal/src/mappings/colors.rs @@ -110,7 +110,7 @@ pub fn get_color_at_index(index: &usize, colors: &TerminalColors) -> Color { /// ///This function does the reverse, calculating the r, g, and b components from a given index. fn rgb_for_index(i: &u8) -> (u8, u8, u8) { - debug_assert!(i >= &16 && i <= &231); + debug_assert!((&16..=&231).contains(&i)); let i = i - 16; let r = (i - (i % 36)) / 36; let g = ((i % 36) - (i % 6)) / 6; diff --git a/crates/terminal/src/mappings/keys.rs b/crates/terminal/src/mappings/keys.rs index 215bfe1ad9..e07a324998 100644 --- a/crates/terminal/src/mappings/keys.rs +++ b/crates/terminal/src/mappings/keys.rs @@ -48,7 +48,7 @@ pub fn might_convert(keystroke: &Keystroke) -> bool { } pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode) -> Option { - let modifiers = Modifiers::new(&keystroke); + let modifiers = Modifiers::new(keystroke); // Manual Bindings including modifiers let manual_esc_str = match (keystroke.key.as_ref(), &modifiers) { @@ -204,7 +204,7 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode) -> Option { // Automated bindings applying modifiers if modifiers.any() { - let modifier_code = modifier_code(&keystroke); + let modifier_code = modifier_code(keystroke); let modified_esc_str = match keystroke.key.as_ref() { "up" => Some(format!("\x1b[1;{}A", modifier_code)), "down" => Some(format!("\x1b[1;{}B", modifier_code)), diff --git a/crates/terminal/src/modal.rs b/crates/terminal/src/modal.rs index 322f26ea3c..936a4091b6 100644 --- a/crates/terminal/src/modal.rs +++ b/crates/terminal/src/modal.rs @@ -58,9 +58,7 @@ pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewCon let terminal_handle = connected.read(cx).handle(); // Set the global immediately if terminal construction was successful, // in case the user opens the command palette - cx.set_global::>(Some(StoredTerminal( - terminal_handle.clone(), - ))); + cx.set_global::>(Some(StoredTerminal(terminal_handle))); } } } diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index b54685c458..f31c07423e 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -137,13 +137,13 @@ impl Default for TerminalSize { } } -impl Into for TerminalSize { - fn into(self) -> WindowSize { +impl From for WindowSize { + fn from(val: TerminalSize) -> Self { WindowSize { - num_lines: self.num_lines() as u16, - num_cols: self.num_columns() as u16, - cell_width: self.cell_width() as u16, - cell_height: self.line_height() as u16, + num_lines: val.num_lines() as u16, + num_cols: val.num_columns() as u16, + cell_width: val.cell_width() as u16, + cell_height: val.line_height() as u16, } } } @@ -269,7 +269,7 @@ impl TerminalBuilder { } }; - let mut env = env.unwrap_or_else(|| HashMap::new()); + let mut env = env.unwrap_or_default(); //TODO: Properly set the current locale, env.insert("LC_ALL".to_string(), "en_US.UTF-8".to_string()); @@ -293,7 +293,7 @@ impl TerminalBuilder { let term = Arc::new(FairMutex::new(term)); //Setup the pty... - let pty = match tty::new(&pty_config, initial_size.clone().into(), None) { + let pty = match tty::new(&pty_config, initial_size.into(), None) { Ok(pty) => pty, Err(error) => { bail!(TerminalError { @@ -321,7 +321,7 @@ impl TerminalBuilder { //And connect them together let event_loop = EventLoop::new( term.clone(), - ZedListener(events_tx.clone()), + ZedListener(events_tx), pty, pty_config.hold, false, @@ -379,7 +379,7 @@ impl TerminalBuilder { } } - if events.len() == 0 { + if events.is_empty() { smol::future::yield_now().await; break 'outer; } else { @@ -459,11 +459,11 @@ impl Terminal { AlacTermEvent::ClipboardLoad(_, format) => self.notify_pty(format( &cx.read_from_clipboard() .map(|ci| ci.text().to_string()) - .unwrap_or("".to_string()), + .unwrap_or_else(|| "".to_string()), )), AlacTermEvent::PtyWrite(out) => self.notify_pty(out.clone()), AlacTermEvent::TextAreaSizeRequest(format) => { - self.notify_pty(format(self.cur_size.clone().into())) + self.notify_pty(format(self.cur_size.into())) } AlacTermEvent::CursorBlinkingChange => { //TODO whatever state we need to set to get the cursor blinking @@ -500,24 +500,19 @@ impl Terminal { ) { // TODO: Handle is_self_focused in subscription on terminal view match event { - InternalEvent::TermEvent(term_event) => match term_event { - //Needs to lock - AlacTermEvent::ColorRequest(index, format) => { + InternalEvent::TermEvent(term_event) => { + if let AlacTermEvent::ColorRequest(index, format) = term_event { let color = term.colors()[*index].unwrap_or_else(|| { let term_style = &cx.global::().theme.terminal; to_alac_rgb(get_color_at_index(index, &term_style.colors)) }); self.notify_pty(format(color)) } - _ => {} //Other events are handled in the event loop - }, + } InternalEvent::Resize(new_size) => { - self.cur_size = new_size.clone(); + self.cur_size = *new_size; - self.pty_tx - .0 - .send(Msg::Resize(new_size.clone().into())) - .ok(); + self.pty_tx.0.send(Msg::Resize((*new_size).into())).ok(); term.resize(*new_size); } @@ -553,7 +548,7 @@ impl Terminal { ///Resize the terminal and the PTY. pub fn set_size(&mut self, new_size: TerminalSize) { - self.events.push(InternalEvent::Resize(new_size.into())) + self.events.push(InternalEvent::Resize(new_size)) } pub fn clear(&mut self) { @@ -574,7 +569,7 @@ impl Terminal { pub fn paste(&self, text: &str) { if self.last_mode.contains(TermMode::BRACKETED_PASTE) { self.notify_pty("\x1b[200~".to_string()); - self.notify_pty(text.replace('\x1b', "").to_string()); + self.notify_pty(text.replace('\x1b', "")); self.notify_pty("\x1b[201~".to_string()); } else { self.notify_pty(text.replace("\r\n", "\r").replace('\n', "\r")); @@ -597,7 +592,7 @@ impl Terminal { } // self.utilization = Self::estimate_utilization(term.take_last_processed_bytes()); - self.last_mode = term.mode().clone(); + self.last_mode = *term.mode(); let content = term.renderable_content(); @@ -668,7 +663,7 @@ mod tests { mod alacritty_unix { use alacritty_terminal::config::Program; use gpui::anyhow::{bail, Result}; - use libc; + use std::ffi::CStr; use std::mem::MaybeUninit; use std::ptr; diff --git a/crates/terminal/src/terminal_view.rs b/crates/terminal/src/terminal_view.rs index 1b4544a3dc..ed63217178 100644 --- a/crates/terminal/src/terminal_view.rs +++ b/crates/terminal/src/terminal_view.rs @@ -99,7 +99,7 @@ impl TerminalView { Ok(terminal) => { let terminal = cx.add_model(|cx| terminal.subscribe(cx)); let view = cx.add_view(|cx| ConnectedView::from_terminal(terminal, modal, cx)); - cx.subscribe(&view, |_this, _content, event, cx| cx.emit(event.clone())) + cx.subscribe(&view, |_this, _content, event, cx| cx.emit(*event)) .detach(); TerminalContent::Connected(view) } @@ -206,7 +206,7 @@ impl View for ErrorView { ) .with_child(Text::new(program_text, style.clone()).contained().boxed()) .with_child(Text::new(directory_text, style.clone()).contained().boxed()) - .with_child(Text::new(error_text, style.clone()).contained().boxed()) + .with_child(Text::new(error_text, style).contained().boxed()) .aligned() .boxed() } @@ -333,7 +333,7 @@ pub fn get_working_directory( .filter(|dir| dir.is_dir()) } }; - res.or_else(|| home_dir()) + res.or_else(home_dir) } ///Get's the first project's home directory, or the home directory diff --git a/crates/text/src/anchor.rs b/crates/text/src/anchor.rs index 36781bd331..dca95ce5d5 100644 --- a/crates/text/src/anchor.rs +++ b/crates/text/src/anchor.rs @@ -33,7 +33,7 @@ impl Anchor { } else { buffer .fragment_id_for_anchor(self) - .cmp(&buffer.fragment_id_for_anchor(other)) + .cmp(buffer.fragment_id_for_anchor(other)) }; fragment_id_comparison @@ -43,17 +43,17 @@ impl Anchor { pub fn min(&self, other: &Self, buffer: &BufferSnapshot) -> Self { if self.cmp(other, buffer).is_le() { - self.clone() + *self } else { - other.clone() + *other } } pub fn max(&self, other: &Self, buffer: &BufferSnapshot) -> Self { if self.cmp(other, buffer).is_ge() { - self.clone() + *self } else { - other.clone() + *other } } @@ -67,7 +67,7 @@ impl Anchor { pub fn bias_left(&self, buffer: &BufferSnapshot) -> Anchor { if self.bias == Bias::Left { - self.clone() + *self } else { buffer.anchor_before(self) } @@ -75,13 +75,13 @@ impl Anchor { pub fn bias_right(&self, buffer: &BufferSnapshot) -> Anchor { if self.bias == Bias::Right { - self.clone() + *self } else { buffer.anchor_after(self) } } - pub fn summary<'a, D>(&self, content: &'a BufferSnapshot) -> D + pub fn summary(&self, content: &BufferSnapshot) -> D where D: TextDimension, { @@ -100,7 +100,7 @@ where T: ToOffset, { fn to_offset(&self, snapshot: &BufferSnapshot) -> Range { - self.start.to_offset(snapshot)..self.end.to_offset(&snapshot) + self.start.to_offset(snapshot)..self.end.to_offset(snapshot) } fn to_point(&self, snapshot: &BufferSnapshot) -> Range { @@ -122,7 +122,7 @@ impl AnchorRangeExt for Range { fn cmp(&self, other: &Range, buffer: &BufferSnapshot) -> Result { Ok(match self.start.cmp(&other.start, buffer) { Ordering::Equal => other.end.cmp(&self.end, buffer), - ord @ _ => ord, + ord => ord, }) } } diff --git a/crates/text/src/locator.rs b/crates/text/src/locator.rs index f98f050339..9d38a51df0 100644 --- a/crates/text/src/locator.rs +++ b/crates/text/src/locator.rs @@ -41,6 +41,10 @@ impl Locator { pub fn len(&self) -> usize { self.0.len() } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Default for Locator { diff --git a/crates/text/src/operation_queue.rs b/crates/text/src/operation_queue.rs index a3f5b9b6bd..063f050665 100644 --- a/crates/text/src/operation_queue.rs +++ b/crates/text/src/operation_queue.rs @@ -26,6 +26,12 @@ impl OperationKey { } } +impl Default for OperationQueue { + fn default() -> Self { + OperationQueue::new() + } +} + impl OperationQueue { pub fn new() -> Self { OperationQueue(SumTree::new()) @@ -35,6 +41,10 @@ impl OperationQueue { self.0.summary().len } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn insert(&mut self, mut ops: Vec) { ops.sort_by_key(|op| op.lamport_timestamp()); ops.dedup_by_key(|op| op.lamport_timestamp()); diff --git a/crates/text/src/patch.rs b/crates/text/src/patch.rs index 63e69f45a7..f10acbc2d3 100644 --- a/crates/text/src/patch.rs +++ b/crates/text/src/patch.rs @@ -548,7 +548,7 @@ mod tests { let composed = patches[0].compose(&patches[1]); log::info!("composed patch: {:?}", &composed); - let mut actual_chars = initial_chars.clone(); + let mut actual_chars = initial_chars; for edit in composed.0 { actual_chars.splice( edit.new.start as usize..edit.new.start as usize + edit.old.len(), @@ -570,7 +570,7 @@ mod tests { apply_patch(&mut expected, &old, &inserted); apply_patch(&mut expected, &new, &inserted); - let mut actual = original.clone(); + let mut actual = original; apply_patch(&mut actual, &composed, &expected); assert_eq!( actual.into_iter().collect::(), diff --git a/crates/text/src/point.rs b/crates/text/src/point.rs index 9eded9f443..4be01dfdac 100644 --- a/crates/text/src/point.rs +++ b/crates/text/src/point.rs @@ -23,7 +23,7 @@ impl Point { Point::new(0, 0) } - pub fn from_str(s: &str) -> Self { + pub fn parse_str(s: &str) -> Self { let mut point = Self::zero(); for (row, line) in s.split('\n').enumerate() { point.row = row as u32; diff --git a/crates/text/src/rope.rs b/crates/text/src/rope.rs index 012b7fdd66..d35ac46f45 100644 --- a/crates/text/src/rope.rs +++ b/crates/text/src/rope.rs @@ -123,6 +123,10 @@ impl Rope { self.chunks.extent(&()) } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn max_point(&self) -> Point { self.chunks.extent(&()) } @@ -152,7 +156,7 @@ impl Rope { Bytes::new(self, range) } - pub fn chunks<'a>(&'a self) -> Chunks<'a> { + pub fn chunks(&self) -> Chunks { self.chunks_in_range(0..self.len()) } @@ -896,7 +900,7 @@ impl sum_tree::Summary for TextSummary { } } -impl<'a> std::ops::Add for TextSummary { +impl std::ops::Add for TextSummary { type Output = Self; fn add(mut self, rhs: Self) -> Self::Output { @@ -946,7 +950,7 @@ pub trait TextDimension: 'static + for<'a> Dimension<'a, ChunkSummary> { fn add_assign(&mut self, other: &Self); } -impl<'a, D1: TextDimension, D2: TextDimension> TextDimension for (D1, D2) { +impl TextDimension for (D1, D2) { fn from_text_summary(summary: &TextSummary) -> Self { ( D1::from_text_summary(summary), diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 33d02acf5a..ae91478f89 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -42,7 +42,7 @@ fn test_random_edits(mut rng: StdRng) { let mut reference_string = RandomCharIter::new(&mut rng) .take(reference_string_len) .collect::(); - let mut buffer = Buffer::new(0, 0, reference_string.clone().into()); + let mut buffer = Buffer::new(0, 0, reference_string.clone()); LineEnding::normalize(&mut reference_string); buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200)); @@ -56,7 +56,7 @@ fn test_random_edits(mut rng: StdRng) { for _i in 0..operations { let (edits, _) = buffer.randomly_edit(&mut rng, 5); for (old_range, new_text) in edits.iter().rev() { - reference_string.replace_range(old_range.clone(), &new_text); + reference_string.replace_range(old_range.clone(), new_text); } assert_eq!(buffer.text(), reference_string); @@ -677,9 +677,9 @@ fn test_concurrent_edits() { buffer1.apply_op(buf2_op.clone()).unwrap(); buffer1.apply_op(buf3_op.clone()).unwrap(); buffer2.apply_op(buf1_op.clone()).unwrap(); - buffer2.apply_op(buf3_op.clone()).unwrap(); - buffer3.apply_op(buf1_op.clone()).unwrap(); - buffer3.apply_op(buf2_op.clone()).unwrap(); + buffer2.apply_op(buf3_op).unwrap(); + buffer3.apply_op(buf1_op).unwrap(); + buffer3.apply_op(buf2_op).unwrap(); assert_eq!(buffer1.text(), "a12c34e56"); assert_eq!(buffer2.text(), "a12c34e56"); @@ -704,7 +704,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) { let mut network = Network::new(rng.clone()); for i in 0..peers { - let mut buffer = Buffer::new(i as ReplicaId, 0, base_text.clone().into()); + let mut buffer = Buffer::new(i as ReplicaId, 0, base_text.clone()); buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200)); buffers.push(buffer); replica_ids.push(i as u16); diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 7da77b22ff..ff78f4a14b 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -530,7 +530,7 @@ impl Buffer { let mut version = clock::Global::new(); let visible_text = Rope::from(history.base_text.as_ref()); - if visible_text.len() > 0 { + if !visible_text.is_empty() { let insertion_timestamp = InsertionTimestamp { replica_id: 0, local: 1, @@ -860,7 +860,7 @@ impl Buffer { return; } - let edits = ranges.into_iter().zip(new_text.into_iter()); + let edits = ranges.iter().zip(new_text.iter()); let mut edits_patch = Patch::default(); let mut insertion_slices = Vec::new(); let cx = Some(version.clone()); @@ -1242,6 +1242,7 @@ impl Buffer { } } + #[allow(clippy::needless_collect)] pub fn undo_to_transaction(&mut self, transaction_id: TransactionId) -> Vec { let transactions = self .history @@ -1249,6 +1250,7 @@ impl Buffer { .iter() .map(|entry| entry.transaction.clone()) .collect::>(); + transactions .into_iter() .map(|transaction| self.undo_or_redo(transaction).unwrap()) @@ -1270,6 +1272,7 @@ impl Buffer { } } + #[allow(clippy::needless_collect)] pub fn redo_to_transaction(&mut self, transaction_id: TransactionId) -> Vec { let transactions = self .history @@ -1277,6 +1280,7 @@ impl Buffer { .iter() .map(|entry| entry.transaction.clone()) .collect::>(); + transactions .into_iter() .map(|transaction| self.undo_or_redo(transaction).unwrap()) @@ -1293,7 +1297,7 @@ impl Buffer { id: self.local_clock.tick(), version: self.version(), counts, - transaction_version: transaction.start.clone(), + transaction_version: transaction.start, }; self.apply_undo(&undo)?; let operation = Operation::Undo { @@ -1490,6 +1494,7 @@ impl Buffer { start..end } + #[allow(clippy::type_complexity)] pub fn randomly_edit( &mut self, rng: &mut T, @@ -1574,6 +1579,10 @@ impl BufferSnapshot { self.visible_text.len() } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn chars(&self) -> impl Iterator + '_ { self.chars_at(0) } @@ -1609,8 +1618,8 @@ impl BufferSnapshot { .filter(|&len| { let left = self .chars_for_range(offset - len..offset) - .flat_map(|c| char::to_lowercase(c)); - let right = needle[..len].chars().flat_map(|c| char::to_lowercase(c)); + .flat_map(char::to_lowercase); + let right = needle[..len].chars().flat_map(char::to_lowercase); left.eq(right) }) .last() @@ -1684,15 +1693,12 @@ impl BufferSnapshot { &self.version } - pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator + 'a { + pub fn chars_at(&self, position: T) -> impl Iterator + '_ { let offset = position.to_offset(self); self.visible_text.chars_at(offset) } - pub fn reversed_chars_at<'a, T: ToOffset>( - &'a self, - position: T, - ) -> impl Iterator + 'a { + pub fn reversed_chars_at(&self, position: T) -> impl Iterator + '_ { let offset = position.to_offset(self); self.visible_text.reversed_chars_at(offset) } @@ -1702,13 +1708,13 @@ impl BufferSnapshot { self.visible_text.reversed_chunks_in_range(range) } - pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range) -> rope::Bytes<'a> { + pub fn bytes_in_range(&self, range: Range) -> rope::Bytes<'_> { let start = range.start.to_offset(self); let end = range.end.to_offset(self); self.visible_text.bytes_in_range(start..end) } - pub fn text_for_range<'a, T: ToOffset>(&'a self, range: Range) -> Chunks<'a> { + pub fn text_for_range(&self, range: Range) -> Chunks<'_> { let start = range.start.to_offset(self); let end = range.end.to_offset(self); self.visible_text.chunks_in_range(start..end) @@ -1729,7 +1735,7 @@ impl BufferSnapshot { .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none()) } - pub fn text_summary_for_range<'a, D, O: ToOffset>(&'a self, range: Range) -> D + pub fn text_summary_for_range(&self, range: Range) -> D where D: TextDimension, { @@ -1788,7 +1794,7 @@ impl BufferSnapshot { }) } - fn summary_for_anchor<'a, D>(&'a self, anchor: &Anchor) -> D + fn summary_for_anchor(&self, anchor: &Anchor) -> D where D: TextDimension, { @@ -2048,7 +2054,7 @@ impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator fo break; } - if !fragment.was_visible(&self.since, &self.undos) && fragment.visible { + if !fragment.was_visible(self.since, self.undos) && fragment.visible { let mut visible_end = cursor.end(&None).visible; if fragment.id == *self.range.end.0 { visible_end = cmp::min( @@ -2070,7 +2076,7 @@ impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator fo } self.new_end = new_end; - } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible { + } else if fragment.was_visible(self.since, self.undos) && !fragment.visible { let mut deleted_end = cursor.end(&None).deleted; if fragment.id == *self.range.end.0 { deleted_end = cmp::min( @@ -2354,10 +2360,7 @@ impl Operation { } pub fn is_edit(&self) -> bool { - match self { - Operation::Edit { .. } => true, - _ => false, - } + matches!(self, Operation::Edit { .. }) } } @@ -2423,7 +2426,7 @@ impl LineEnding { } pub trait ToOffset { - fn to_offset<'a>(&self, snapshot: &BufferSnapshot) -> usize; + fn to_offset(&self, snapshot: &BufferSnapshot) -> usize; } impl ToOffset for Point { @@ -2464,7 +2467,7 @@ impl<'a, T: ToOffset> ToOffset for &'a T { } pub trait ToPoint { - fn to_point<'a>(&self, snapshot: &BufferSnapshot) -> Point; + fn to_point(&self, snapshot: &BufferSnapshot) -> Point; } impl ToPoint for Anchor { @@ -2492,7 +2495,7 @@ impl ToPoint for Point { } pub trait ToPointUtf16 { - fn to_point_utf16<'a>(&self, snapshot: &BufferSnapshot) -> PointUtf16; + fn to_point_utf16(&self, snapshot: &BufferSnapshot) -> PointUtf16; } impl ToPointUtf16 for Anchor { @@ -2520,7 +2523,7 @@ impl ToPointUtf16 for Point { } pub trait ToOffsetUtf16 { - fn to_offset_utf16<'a>(&self, snapshot: &BufferSnapshot) -> OffsetUtf16; + fn to_offset_utf16(&self, snapshot: &BufferSnapshot) -> OffsetUtf16; } impl ToOffsetUtf16 for Anchor { diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index dcda882168..d09e3b298d 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -44,7 +44,7 @@ impl ThemeSelector { theme_names.sort_unstable_by(|a, b| { a.ends_with("dark") .cmp(&b.ends_with("dark")) - .then_with(|| a.cmp(&b)) + .then_with(|| a.cmp(b)) }); let matches = theme_names .iter() diff --git a/crates/util/src/lib.rs b/crates/util/src/lib.rs index 0616b2a75e..9b65074615 100644 --- a/crates/util/src/lib.rs +++ b/crates/util/src/lib.rs @@ -128,7 +128,9 @@ struct Defer(Option); impl Drop for Defer { fn drop(&mut self) { - self.0.take().map(|f| f()); + if let Some(f) = self.0.take() { + f() + } } } diff --git a/crates/util/src/test/marked_text.rs b/crates/util/src/test/marked_text.rs index b5b68c22c9..c2aaca3831 100644 --- a/crates/util/src/test/marked_text.rs +++ b/crates/util/src/test/marked_text.rs @@ -195,19 +195,19 @@ pub fn generate_marked_text( match range.start.cmp(&range.end) { Ordering::Less => { marked_text.insert_str(range.end, "ˇ»"); - marked_text.insert_str(range.start, "«"); + marked_text.insert(range.start, '«'); } Ordering::Equal => { - marked_text.insert_str(range.start, "ˇ"); + marked_text.insert(range.start, 'ˇ'); } Ordering::Greater => { - marked_text.insert_str(range.start, "»"); + marked_text.insert(range.start, '»'); marked_text.insert_str(range.end, "«ˇ"); } } } else { - marked_text.insert_str(range.end, "»"); - marked_text.insert_str(range.start, "«"); + marked_text.insert(range.end, '»'); + marked_text.insert(range.start, '«'); } } marked_text diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index d9e4bf084c..b4667278ba 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -126,10 +126,10 @@ fn motion(motion: Motion, cx: &mut MutableAppContext) { impl Motion { pub fn linewise(self) -> bool { use Motion::*; - match self { - Down | Up | StartOfDocument | EndOfDocument | CurrentLine => true, - _ => false, - } + matches!( + self, + Down | Up | StartOfDocument | EndOfDocument | CurrentLine + ) } pub fn inclusive(self) -> bool { @@ -282,8 +282,7 @@ fn next_word_end( // we have backtraced already if !map .chars_at(point) - .skip(1) - .next() + .nth(1) .map(|c| c == '\n') .unwrap_or(true) { diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 508477ea46..db5583b4ce 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -254,7 +254,7 @@ fn paste(_: &mut Workspace, _: &Paste, cx: &mut ViewContext) { } // Drop selection at the start of the next line let selection_point = Point::new(point.row + 1, 0); - new_selections.push(selection.map(|_| selection_point.clone())); + new_selections.push(selection.map(|_| selection_point)); point } else { let mut point = selection.end; diff --git a/crates/vim/src/normal/change.rs b/crates/vim/src/normal/change.rs index 1a7b934a31..8695c9668b 100644 --- a/crates/vim/src/normal/change.rs +++ b/crates/vim/src/normal/change.rs @@ -28,7 +28,7 @@ pub fn change_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) { }); }); copy_selections_content(editor, motion.linewise(), cx); - editor.insert(&"", cx); + editor.insert("", cx); }); }); vim.switch_mode(Mode::Insert, false, cx) @@ -67,7 +67,7 @@ fn change_word( }); }); copy_selections_content(editor, false, cx); - editor.insert(&"", cx); + editor.insert("", cx); }); }); vim.switch_mode(Mode::Insert, false, cx); diff --git a/crates/vim/src/normal/delete.rs b/crates/vim/src/normal/delete.rs index c639e604dc..b2e228bdb1 100644 --- a/crates/vim/src/normal/delete.rs +++ b/crates/vim/src/normal/delete.rs @@ -16,7 +16,7 @@ pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) { }); }); copy_selections_content(editor, motion.linewise(), cx); - editor.insert(&"", cx); + editor.insert("", cx); // Fixup cursor position after the deletion editor.set_clip_at_line_ends(true, cx); diff --git a/crates/vim/src/state.rs b/crates/vim/src/state.rs index e36cb7203d..e556048ea8 100644 --- a/crates/vim/src/state.rs +++ b/crates/vim/src/state.rs @@ -54,10 +54,7 @@ impl VimState { } pub fn clip_at_line_end(&self) -> bool { - match self.mode { - Mode::Insert | Mode::Visual { .. } => false, - _ => true, - } + !matches!(self.mode, Mode::Insert | Mode::Visual { .. }) } pub fn empty_selections_only(&self) -> bool { @@ -99,6 +96,6 @@ impl Operator { context .map - .insert("vim_operator".to_string(), operator_context.to_string()); + .insert("vim_operator".to_string(), operator_context); } } diff --git a/crates/vim/src/vim_test_context.rs b/crates/vim/src/vim_test_context.rs index dff0aaf375..2be2eb8d6f 100644 --- a/crates/vim/src/vim_test_context.rs +++ b/crates/vim/src/vim_test_context.rs @@ -45,7 +45,7 @@ impl<'a> VimTestContext<'a> { workspace.update(cx, |workspace, cx| { workspace.active_pane().update(cx, |pane, cx| { pane.toolbar().update(cx, |toolbar, cx| { - let buffer_search_bar = cx.add_view(|cx| BufferSearchBar::new(cx)); + let buffer_search_bar = cx.add_view(BufferSearchBar::new); toolbar.add_item(buffer_search_bar, cx); let project_search_bar = cx.add_view(|_| ProjectSearchBar::new()); toolbar.add_item(project_search_bar, cx); diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index 3f7b9c0683..d468393027 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -103,7 +103,7 @@ pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext let new_position = if linewise { edits.push((range.start..range.start, "\n")); - let mut new_position = range.start.clone(); + let mut new_position = range.start; new_position.column = 0; new_position.row += 1; new_position } else { - range.start.clone() + range.start }; - new_selections.push(selection.map(|_| new_position.clone())); + new_selections.push(selection.map(|_| new_position)); if linewise && to_insert.ends_with('\n') { edits.push(( diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 4a96699dee..34108eef5e 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -189,7 +189,7 @@ pub struct NavigationEntry { impl Pane { pub fn new(cx: &mut ViewContext) -> Self { let handle = cx.weak_handle(); - let context_menu = cx.add_view(|cx| ContextMenu::new(cx)); + let context_menu = cx.add_view(ContextMenu::new); Self { items: Vec::new(), is_active: true, @@ -389,7 +389,7 @@ impl Pane { let existing_item = pane.update(cx, |pane, cx| { for (ix, item) in pane.items.iter().enumerate() { if item.project_path(cx).is_some() - && item.project_entry_ids(cx).as_slice() == &[project_entry_id] + && item.project_entry_ids(cx).as_slice() == [project_entry_id] { let item = item.boxed_clone(); pane.activate_item(ix, true, focus_item, true, cx); @@ -450,7 +450,7 @@ impl Pane { self.items.iter() } - pub fn items_of_type<'a, T: View>(&'a self) -> impl 'a + Iterator> { + pub fn items_of_type(&self) -> impl '_ + Iterator> { self.items .iter() .filter_map(|item| item.to_any().downcast()) @@ -466,7 +466,7 @@ impl Pane { cx: &AppContext, ) -> Option> { self.items.iter().find_map(|item| { - if item.is_singleton(cx) && item.project_entry_ids(cx).as_slice() == &[entry_id] { + if item.is_singleton(cx) && item.project_entry_ids(cx).as_slice() == [entry_id] { Some(item.boxed_clone()) } else { None @@ -532,7 +532,7 @@ impl Pane { let mut index = self.active_item_index; if index > 0 { index -= 1; - } else if self.items.len() > 0 { + } else if !self.items.is_empty() { index = self.items.len() - 1; } self.activate_item(index, true, true, false, cx); @@ -653,7 +653,7 @@ impl Pane { { let other_project_entry_ids = item.project_entry_ids(cx); project_entry_ids - .retain(|id| !other_project_entry_ids.contains(&id)); + .retain(|id| !other_project_entry_ids.contains(id)); } } }); @@ -662,12 +662,11 @@ impl Pane { .any(|id| saved_project_entry_ids.insert(*id)) }; - if should_save { - if !Self::save_item(project.clone(), &pane, item_ix, &item, true, &mut cx) + if should_save + && !Self::save_item(project.clone(), &pane, item_ix, &*item, true, &mut cx) .await? - { - break; - } + { + break; } // Remove the item from the pane. @@ -728,14 +727,13 @@ impl Pane { project: ModelHandle, pane: &ViewHandle, item_ix: usize, - item: &Box, + item: &dyn ItemHandle, should_prompt_for_save: bool, cx: &mut AsyncAppContext, ) -> Result { - const CONFLICT_MESSAGE: &'static str = + const CONFLICT_MESSAGE: &str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; - const DIRTY_MESSAGE: &'static str = - "This file contains unsaved edits. Do you want to save it?"; + const DIRTY_MESSAGE: &str = "This file contains unsaved edits. Do you want to save it?"; let (has_conflict, is_dirty, can_save, is_singleton) = cx.read(|cx| { ( @@ -765,7 +763,7 @@ impl Pane { matches!( cx.global::().autosave, Autosave::OnFocusChange | Autosave::OnWindowChange - ) && Self::can_autosave_item(item.as_ref(), cx) + ) && Self::can_autosave_item(&*item, cx) }); let should_save = if should_prompt_for_save && !will_autosave { let mut answer = pane.update(cx, |pane, cx| { @@ -794,7 +792,7 @@ impl Pane { let worktree = project.visible_worktrees(cx).next()?; Some(worktree.read(cx).as_local()?.abs_path().to_path_buf()) }) - .unwrap_or(Path::new("").into()); + .unwrap_or_else(|| Path::new("").into()); let mut abs_path = cx.update(|cx| cx.prompt_for_new_path(&start_abs_path)); if let Some(abs_path) = abs_path.next().await.flatten() { diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 025d561f61..0ed7ed111b 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -50,7 +50,7 @@ impl PaneGroup { } } - pub(crate) fn render<'a>( + pub(crate) fn render( &self, theme: &Theme, follower_states: &FollowerStatesByLeader, diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index b7ed8140c9..6749de36a9 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -38,7 +38,7 @@ where } fn is_focused(&self, cx: &AppContext) -> bool { - ViewHandle::is_focused(&self, cx) || self.read(cx).contains_focused_view(cx) + ViewHandle::is_focused(self, cx) || self.read(cx).contains_focused_view(cx) } fn to_any(&self) -> AnyViewHandle { @@ -46,9 +46,9 @@ where } } -impl Into for &dyn SidebarItemHandle { - fn into(self) -> AnyViewHandle { - self.to_any() +impl From<&dyn SidebarItemHandle> for AnyViewHandle { + fn from(val: &dyn SidebarItemHandle) -> Self { + val.to_any() } } @@ -284,11 +284,14 @@ impl View for SidebarButtons { Side::Left => theme.group_left, Side::Right => theme.group_right, }; + + #[allow(clippy::needless_collect)] let items = sidebar .items .iter() .map(|item| (item.icon_path, item.tooltip.clone(), item.view.clone())) .collect::>(); + Flex::row() .with_children(items.into_iter().enumerate().map( |(ix, (icon_path, tooltip, item_view))| { diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index ca44cf7c27..f055168075 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -126,8 +126,8 @@ impl StatusItemViewHandle for ViewHandle { } } -impl Into for &dyn StatusItemViewHandle { - fn into(self) -> AnyViewHandle { - self.to_any() +impl From<&dyn StatusItemViewHandle> for AnyViewHandle { + fn from(val: &dyn StatusItemViewHandle) -> Self { + val.to_any() } } diff --git a/crates/workspace/src/toolbar.rs b/crates/workspace/src/toolbar.rs index f2a3fff6c4..24edbd673e 100644 --- a/crates/workspace/src/toolbar.rs +++ b/crates/workspace/src/toolbar.rs @@ -133,12 +133,10 @@ impl View for Toolbar { .with_child(nav_button( "icons/arrow_right_16.svg", button_style, - tooltip_style.clone(), + tooltip_style, enable_go_forward, spacing, - super::GoForward { - pane: Some(pane.clone()), - }, + super::GoForward { pane: Some(pane) }, super::GoForward { pane: None }, "Go Forward", cx, @@ -156,6 +154,7 @@ impl View for Toolbar { } } +#[allow(clippy::too_many_arguments)] fn nav_button( svg_path: &'static str, style: theme::Interactive, @@ -280,8 +279,8 @@ impl ToolbarItemViewHandle for ViewHandle { } } -impl Into for &dyn ToolbarItemViewHandle { - fn into(self) -> AnyViewHandle { - self.to_any() +impl From<&dyn ToolbarItemViewHandle> for AnyViewHandle { + fn from(val: &dyn ToolbarItemViewHandle) -> Self { + val.to_any() } } diff --git a/crates/workspace/src/waiting_room.rs b/crates/workspace/src/waiting_room.rs index e5d765d4d5..e05e0fb5ff 100644 --- a/crates/workspace/src/waiting_room.rs +++ b/crates/workspace/src/waiting_room.rs @@ -116,7 +116,7 @@ impl WaitingRoom { workspace }); } - Err(error @ _) => { + Err(error) => { let login = &contact.user.github_login; let message = match error { project::JoinProjectError::HostDeclined => { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 0d4ced4293..1137098d16 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -588,7 +588,9 @@ impl ItemHandle for ViewHandle { if T::is_edit_event(event) { if let Autosave::AfterDelay { milliseconds } = cx.global::().autosave { - let prev_autosave = pending_autosave.take().unwrap_or(Task::ready(Some(()))); + let prev_autosave = pending_autosave + .take() + .unwrap_or_else(|| Task::ready(Some(()))); let (cancel_tx, mut cancel_rx) = oneshot::channel::<()>(); let prev_cancel_tx = mem::replace(&mut cancel_pending_autosave, cancel_tx); let project = workspace.project.downgrade(); @@ -695,9 +697,9 @@ impl ItemHandle for ViewHandle { } } -impl Into for Box { - fn into(self) -> AnyViewHandle { - self.to_any() +impl From> for AnyViewHandle { + fn from(val: Box) -> Self { + val.to_any() } } @@ -742,9 +744,9 @@ impl NotificationHandle for ViewHandle { } } -impl Into for &dyn NotificationHandle { - fn into(self) -> AnyViewHandle { - self.to_any() +impl From<&dyn NotificationHandle> for AnyViewHandle { + fn from(val: &dyn NotificationHandle) -> Self { + val.to_any() } } @@ -769,7 +771,7 @@ impl AppState { user_store, project_store, initialize_workspace: |_, _, _| {}, - build_window_options: || Default::default(), + build_window_options: Default::default, }) } } @@ -848,7 +850,7 @@ impl Workspace { }) .detach(); - let pane = cx.add_view(|cx| Pane::new(cx)); + let pane = cx.add_view(Pane::new); let pane_id = pane.id(); cx.subscribe(&pane, move |this, _, event, cx| { this.handle_pane_event(pane_id, event, cx) @@ -860,8 +862,8 @@ impl Workspace { let fs = project.read(cx).fs().clone(); let user_store = project.read(cx).user_store(); let client = project.read(cx).client(); - let mut current_user = user_store.read(cx).watch_current_user().clone(); - let mut connection_status = client.status().clone(); + let mut current_user = user_store.read(cx).watch_current_user(); + let mut connection_status = client.status(); let _observe_current_user = cx.spawn_weak(|this, mut cx| async move { current_user.recv().await; connection_status.recv().await; @@ -1073,7 +1075,7 @@ impl Workspace { project.clone(), &pane, ix, - &item, + &*item, should_prompt_to_save, &mut cx, ) @@ -1088,6 +1090,7 @@ impl Workspace { }) } + #[allow(clippy::type_complexity)] pub fn open_paths( &mut self, mut abs_paths: Vec, @@ -1150,10 +1153,8 @@ impl Workspace { let results = this .update(&mut cx, |this, cx| this.open_paths(paths, true, cx)) .await; - for result in results { - if let Some(result) = result { - result.log_err(); - } + for result in results.into_iter().flatten() { + result.log_err(); } } }) @@ -1316,7 +1317,7 @@ impl Workspace { if let Some(item) = self.active_item(cx) { if !force_name_change && item.can_save(cx) { if item.has_conflict(cx.as_ref()) { - const CONFLICT_MESSAGE: &'static str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; + const CONFLICT_MESSAGE: &str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; let mut answer = cx.prompt( PromptLevel::Warning, @@ -1424,7 +1425,7 @@ impl Workspace { } fn add_pane(&mut self, cx: &mut ViewContext) -> ViewHandle { - let pane = cx.add_view(|cx| Pane::new(cx)); + let pane = cx.add_view(Pane::new); let pane_id = pane.id(); cx.subscribe(&pane, move |this, _, event, cx| { this.handle_pane_event(pane_id, event, cx) @@ -1519,11 +1520,9 @@ impl Workspace { pub fn activate_item(&mut self, item: &dyn ItemHandle, cx: &mut ViewContext) -> bool { let result = self.panes.iter().find_map(|pane| { - if let Some(ix) = pane.read(cx).index_for_item(item) { - Some((pane.clone(), ix)) - } else { - None - } + pane.read(cx) + .index_for_item(item) + .map(|ix| (pane.clone(), ix)) }); if let Some((pane, ix)) = result { pane.update(cx, |pane, cx| pane.activate_item(ix, true, true, false, cx)); @@ -1749,7 +1748,7 @@ impl Workspace { let collaborators = self.project.read(cx).collaborators(); let next_leader_id = if let Some(leader_id) = self.leader_for_pane(&self.active_pane) { let mut collaborators = collaborators.keys().copied(); - while let Some(peer_id) = collaborators.next() { + for peer_id in collaborators.by_ref() { if peer_id == leader_id { break; } @@ -1779,7 +1778,7 @@ impl Workspace { ) -> Option { for (leader_id, states_by_pane) in &mut self.follower_states_by_leader { let leader_id = *leader_id; - if let Some(state) = states_by_pane.remove(&pane) { + if let Some(state) = states_by_pane.remove(pane) { for (_, item) in state.items_by_leader_view_id { if let FollowerItem::Loaded(item) = item { item.set_leader_replica_id(None, cx); @@ -2253,7 +2252,6 @@ impl Workspace { .values() .map(|b| b.0) .collect::>() - .clone() }); let mut item_tasks_by_pane = HashMap::default(); @@ -2367,13 +2365,11 @@ impl Workspace { fn leader_updated(&mut self, leader_id: PeerId, cx: &mut ViewContext) -> Option<()> { let mut items_to_add = Vec::new(); for (pane, state) in self.follower_states_by_leader.get(&leader_id)? { - if let Some(active_item) = state + if let Some(FollowerItem::Loaded(item)) = state .active_view_id .and_then(|id| state.items_by_leader_view_id.get(&id)) { - if let FollowerItem::Loaded(item) = active_item { - items_to_add.push((pane.clone(), item.boxed_clone())); - } + items_to_add.push((pane.clone(), item.boxed_clone())); } } @@ -2626,6 +2622,7 @@ pub fn activate_workspace_for_project( None } +#[allow(clippy::type_complexity)] pub fn open_paths( abs_paths: &[PathBuf], app_state: &Arc, @@ -2914,7 +2911,7 @@ mod tests { let item1 = cx.add_view(&workspace, |_| TestItem::new()); workspace.update(cx, |w, cx| w.add_item(Box::new(item1.clone()), cx)); let task = workspace.update(cx, |w, cx| w.prepare_to_close(cx)); - assert_eq!(task.await.unwrap(), true); + assert!(task.await.unwrap()); // When there are dirty untitled items, prompt to save each one. If the user // cancels any prompt, then abort. @@ -2938,7 +2935,7 @@ mod tests { cx.simulate_prompt_answer(window_id, 2 /* cancel */); cx.foreground().run_until_parked(); assert!(!cx.has_pending_prompt(window_id)); - assert_eq!(task.await.unwrap(), false); + assert!(!task.await.unwrap()); } #[gpui::test] @@ -3396,7 +3393,7 @@ mod tests { impl Item for TestItem { fn tab_description<'a>(&'a self, detail: usize, _: &'a AppContext) -> Option> { self.tab_descriptions.as_ref().and_then(|descriptions| { - let description = *descriptions.get(detail).or(descriptions.last())?; + let description = *descriptions.get(detail).or_else(|| descriptions.last())?; Some(description.into()) }) } @@ -3452,7 +3449,7 @@ mod tests { } fn can_save(&self, _: &AppContext) -> bool { - self.project_entry_ids.len() > 0 + !self.project_entry_ids.is_empty() } fn save( diff --git a/crates/zed/src/feedback.rs b/crates/zed/src/feedback.rs index f4b67a12bd..18f8c04b4a 100644 --- a/crates/zed/src/feedback.rs +++ b/crates/zed/src/feedback.rs @@ -7,8 +7,7 @@ use gpui::{ use settings::Settings; use workspace::StatusItemView; -pub const NEW_ISSUE_URL: &'static str = - "https://github.com/zed-industries/feedback/issues/new/choose"; +pub const NEW_ISSUE_URL: &str = "https://github.com/zed-industries/feedback/issues/new/choose"; pub struct FeedbackLink; diff --git a/crates/zed/src/languages/c.rs b/crates/zed/src/languages/c.rs index a4db4b9a75..6aa750f6a0 100644 --- a/crates/zed/src/languages/c.rs +++ b/crates/zed/src/languages/c.rs @@ -116,7 +116,7 @@ impl super::LspAdapter for CLspAdapter { ) -> Option { let label = completion .label - .strip_prefix("•") + .strip_prefix('•') .unwrap_or(&completion.label) .trim(); diff --git a/crates/zed/src/languages/go.rs b/crates/zed/src/languages/go.rs index 3fa47428c9..729d39b513 100644 --- a/crates/zed/src/languages/go.rs +++ b/crates/zed/src/languages/go.rs @@ -72,7 +72,7 @@ impl super::LspAdapter for GoLspAdapter { } } } else if let Some(path) = this.cached_server_binary(container_dir.clone()).await { - return Ok(path.to_path_buf()); + return Ok(path); } let gobin_dir = container_dir.join("gobin"); @@ -122,7 +122,7 @@ impl super::LspAdapter for GoLspAdapter { } if let Some(path) = last_binary_path { - Ok(path.to_path_buf()) + Ok(path) } else { Err(anyhow!("no cached binary")) } @@ -141,7 +141,7 @@ impl super::LspAdapter for GoLspAdapter { // Gopls returns nested fields and methods as completions. // To syntax highlight these, combine their final component // with their detail. - let name_offset = label.rfind(".").unwrap_or(0); + let name_offset = label.rfind('.').unwrap_or(0); match completion.kind.zip(completion.detail.as_ref()) { Some((lsp::CompletionItemKind::MODULE, detail)) => { diff --git a/crates/zed/src/languages/python.rs b/crates/zed/src/languages/python.rs index 801c7c96f9..274fc3216c 100644 --- a/crates/zed/src/languages/python.rs +++ b/crates/zed/src/languages/python.rs @@ -206,7 +206,7 @@ mod tests { ); // dedent the closing paren if it is shifted to the beginning of the line - let argument_ix = buffer.text().find("1").unwrap(); + let argument_ix = buffer.text().find('1').unwrap(); buffer.edit( [(argument_ix..argument_ix + 1, "")], Some(AutoindentMode::EachLine), diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index 199a7f22ae..85a1bd6400 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -65,7 +65,7 @@ impl LspAdapter for TypeScriptLspAdapter { ("typescript", versions.typescript_version.as_str()), ( "typescript-language-server", - &versions.server_version.as_str(), + versions.server_version.as_str(), ), ], &version_dir, diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index ed718272d8..aa2f0b7ada 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -29,7 +29,7 @@ use serde_json::json; use settings::{self, KeymapFileContent, Settings, SettingsFileContent}; use smol::process::Command; use std::{env, ffi::OsStr, fs, panic, path::PathBuf, sync::Arc, thread, time::Duration}; -use terminal; + use theme::ThemeRegistry; use util::{ResultExt, TryFutureExt}; use workspace::{self, AppState, NewFile, OpenPaths}; @@ -54,7 +54,7 @@ fn main() { let db = app.background().spawn(async move { project::Db::open(&*zed::paths::DB) .log_err() - .unwrap_or(project::Db::null()) + .unwrap_or_else(project::Db::null) }); load_embedded_fonts(&app); @@ -182,10 +182,8 @@ fn main() { if client::IMPERSONATE_LOGIN.is_some() { client.authenticate_and_connect(false, &cx).await?; } - } else { - if client.has_keychain_credentials(&cx) { - client.authenticate_and_connect(true, &cx).await?; - } + } else if client.has_keychain_credentials(&cx) { + client.authenticate_and_connect(true, &cx).await?; } Ok::<_, anyhow::Error>(()) }) @@ -222,7 +220,9 @@ fn init_logger() { let level = LevelFilter::Info; // Prevent log file from becoming too large. - const MAX_LOG_BYTES: u64 = 1 * 1024 * 1024; + const KIB: u64 = 1024; + const MIB: u64 = 1024 * KIB; + const MAX_LOG_BYTES: u64 = MIB; if fs::metadata(&*zed::paths::LOG).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES) { let _ = fs::rename(&*zed::paths::LOG, &*zed::paths::OLD_LOG); @@ -406,7 +406,7 @@ fn load_embedded_fonts(app: &App) { for font_path in &font_paths { scope.spawn(async { let font_path = &*font_path; - let font_bytes = Assets.load(&font_path).unwrap().to_vec(); + let font_bytes = Assets.load(font_path).unwrap().to_vec(); embedded_fonts.lock().push(Arc::from(font_bytes)); }); } @@ -426,7 +426,7 @@ async fn watch_themes( let mut events = fs .watch("styles/src".as_ref(), Duration::from_millis(100)) .await; - while let Some(_) = events.next().await { + while (events.next().await).is_some() { let output = Command::new("npm") .current_dir("styles") .args(["run", "build-themes"]) diff --git a/crates/zed/src/settings_file.rs b/crates/zed/src/settings_file.rs index b8cdde8b2f..14c9f63e95 100644 --- a/crates/zed/src/settings_file.rs +++ b/crates/zed/src/settings_file.rs @@ -42,11 +42,11 @@ where ///Loads the given watched JSON file. In the special case that the file is ///empty (ignoring whitespace) or is not a file, this will return T::default() async fn load(fs: Arc, path: &Path) -> Option { - if !fs.is_file(&path).await { + if !fs.is_file(path).await { return Some(T::default()); } - fs.load(&path).await.log_err().and_then(|data| { + fs.load(path).await.log_err().and_then(|data| { if data.trim().is_empty() { Some(T::default()) } else { @@ -74,7 +74,7 @@ pub fn watch_settings_file( pub fn keymap_updated(content: KeymapFileContent, cx: &mut MutableAppContext) { cx.clear_bindings(); settings::KeymapFileContent::load_defaults(cx); - content.add(cx).log_err(); + content.add_to_cx(cx).log_err(); } pub fn settings_updated( @@ -84,7 +84,7 @@ pub fn settings_updated( cx: &mut MutableAppContext, ) { let mut settings = defaults.clone(); - settings.set_user_settings(content, theme_registry, &cx.font_cache()); + settings.set_user_settings(content, theme_registry, cx.font_cache()); cx.set_global(settings); cx.refresh_windows(); } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 78d642120e..3a5dd18c1c 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -143,7 +143,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { cx.add_action({ let app_state = app_state.clone(); move |_: &mut Workspace, _: &OpenKeymap, cx: &mut ViewContext| { - open_config_file(&paths::KEYMAP, app_state.clone(), cx, || Default::default()); + open_config_file(&paths::KEYMAP, app_state.clone(), cx, Default::default); } }); cx.add_action({ @@ -222,7 +222,7 @@ pub fn initialize_workspace( pane.toolbar().update(cx, |toolbar, cx| { let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(project.clone())); toolbar.add_item(breadcrumbs, cx); - let buffer_search_bar = cx.add_view(|cx| BufferSearchBar::new(cx)); + let buffer_search_bar = cx.add_view(BufferSearchBar::new); toolbar.add_item(buffer_search_bar, cx); let project_search_bar = cx.add_view(|_| ProjectSearchBar::new()); toolbar.add_item(project_search_bar, cx); @@ -273,7 +273,7 @@ pub fn initialize_workspace( sidebar.add_item( "icons/folder_tree_16.svg", "Project Panel".to_string(), - project_panel.into(), + project_panel, cx, ) }); @@ -281,7 +281,7 @@ pub fn initialize_workspace( sidebar.add_item( "icons/user_group_16.svg", "Contacts Panel".to_string(), - contact_panel.into(), + contact_panel, cx, ) }); @@ -487,7 +487,7 @@ fn open_bundled_config_file( title: &str, cx: &mut ViewContext, ) { - workspace.with_local_workspace(cx, app_state.clone(), |workspace, cx| { + workspace.with_local_workspace(cx, app_state, |workspace, cx| { let project = workspace.project().clone(); let buffer = project.update(cx, |project, cx| { let text = Assets::get(asset_path).unwrap().data; @@ -1005,7 +1005,7 @@ mod tests { .insert_file("/root/a.txt", "changed".to_string()) .await; editor - .condition(&cx, |editor, cx| editor.has_conflict(cx)) + .condition(cx, |editor, cx| editor.has_conflict(cx)) .await; cx.read(|cx| assert!(editor.is_dirty(cx))); @@ -1072,7 +1072,7 @@ mod tests { // Edit the file and save it again. This time, there is no filename prompt. editor.update(cx, |editor, cx| { editor.handle_input(" there", cx); - assert_eq!(editor.is_dirty(cx.as_ref()), true); + assert!(editor.is_dirty(cx.as_ref())); }); let save_task = workspace.update(cx, |workspace, cx| workspace.save_active_item(false, cx)); save_task.await.unwrap(); @@ -1570,30 +1570,20 @@ mod tests { // Reopen all the closed items, ensuring they are reopened in the same order // in which they were closed. - workspace - .update(cx, |workspace, cx| Pane::reopen_closed_item(workspace, cx)) - .await; + workspace.update(cx, Pane::reopen_closed_item).await; assert_eq!(active_path(&workspace, cx), Some(file3.clone())); - workspace - .update(cx, |workspace, cx| Pane::reopen_closed_item(workspace, cx)) - .await; + workspace.update(cx, Pane::reopen_closed_item).await; assert_eq!(active_path(&workspace, cx), Some(file2.clone())); - workspace - .update(cx, |workspace, cx| Pane::reopen_closed_item(workspace, cx)) - .await; + workspace.update(cx, Pane::reopen_closed_item).await; assert_eq!(active_path(&workspace, cx), Some(file4.clone())); - workspace - .update(cx, |workspace, cx| Pane::reopen_closed_item(workspace, cx)) - .await; + workspace.update(cx, Pane::reopen_closed_item).await; assert_eq!(active_path(&workspace, cx), Some(file1.clone())); // Reopening past the last closed item is a no-op. - workspace - .update(cx, |workspace, cx| Pane::reopen_closed_item(workspace, cx)) - .await; + workspace.update(cx, Pane::reopen_closed_item).await; assert_eq!(active_path(&workspace, cx), Some(file1.clone())); // Reopening closed items doesn't interfere with navigation history. From 9aa3f2d7772ddd84ca3550d5f0ccd74f45249d54 Mon Sep 17 00:00:00 2001 From: K Simmons Date: Wed, 10 Aug 2022 16:49:17 -0700 Subject: [PATCH 23/27] clippy fixes for focus change --- crates/collab/src/rpc.rs | 2 +- crates/language/src/buffer.rs | 9 ++++----- crates/workspace/src/workspace.rs | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 6346e15830..4164424a2b 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -1711,7 +1711,7 @@ impl Server { Ok(()) } - pub(crate) async fn store(&self) -> StoreGuard { + pub(crate) async fn store(&self) -> StoreGuard<'_> { #[cfg(test)] tokio::task::yield_now().await; let guard = self.store.lock().await; diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 52ad88f092..c8180e0a8f 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -442,12 +442,11 @@ impl Buffer { } fn build(buffer: TextBuffer, file: Option>) -> Self { - let saved_mtime; - if let Some(file) = file.as_ref() { - saved_mtime = file.mtime(); + let saved_mtime = if let Some(file) = file.as_ref() { + file.mtime() } else { - saved_mtime = UNIX_EPOCH; - } + UNIX_EPOCH + }; Self { saved_mtime, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 1137098d16..40934f4ed7 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -703,9 +703,9 @@ impl From> for AnyViewHandle { } } -impl Into for &Box { - fn into(self) -> AnyViewHandle { - self.to_any() +impl From<&Box> for AnyViewHandle { + fn from(val: &Box) -> Self { + val.to_any() } } From c74d10809e7055126567bcd1003813038ba6f7a1 Mon Sep 17 00:00:00 2001 From: K Simmons Date: Wed, 10 Aug 2022 17:01:13 -0700 Subject: [PATCH 24/27] Testing with allow flags --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e54324c8c9..e8e5e6f7b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,9 @@ jobs: clean: false - name: Run clippy - run: cargo clippy --workspace -- -D warnings - + run: | + cargo clippy --workspace -- -D warnings -Aclippy::reversed_empty_ranges -Aclippy::missing_safety_doc -Aclippy::let_unit_value + - name: Run tests run: cargo test --workspace --no-fail-fast From 073bd767f247161285d38b3628dafd48e6549986 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 10 Aug 2022 17:50:44 -0700 Subject: [PATCH 25/27] Fixed build errors in json_language --- .cargo/config.toml | 1 + .github/workflows/.ci.yml.swp | Bin 12288 -> 0 bytes plugins/json_language/src/lib.rs | 23 ++++++++++------------- 3 files changed, 11 insertions(+), 13 deletions(-) delete mode 100644 .github/workflows/.ci.yml.swp diff --git a/.cargo/config.toml b/.cargo/config.toml index 4dddb54d24..cf5c88d091 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,6 @@ [target.'cfg(all())'] rustflags = [ + "-Dwarnings", "-Aclippy::reversed_empty_ranges", "-Aclippy::missing_safety_doc", "-Aclippy::let_unit_value", diff --git a/.github/workflows/.ci.yml.swp b/.github/workflows/.ci.yml.swp deleted file mode 100644 index 063ded33eec61c5c7dd50a9cea1af60dc3d6edfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmYc?2=nw+u+TGNU|?VnU|`5{{gU)Rav~pZDFZ`pW_Ds_P9jJKFZP9~E7tW*Om@o8 z&(?L!EYi!#PfpB1)m8^JP`{ukKPxr4q*%WyHAP=9J+maEG)ccazbHE`C%?Q{KRHvc zG8auRs!5}~(GVC70n$T&m%-S`&;X=QSxHerSSS?49L1v{Fd71*Aut*OqaiRF0;3@? z8UmvsFd70QBm_zd7#Zpr7#NtK{>_BajA%5JJ4%g)z-S1JhQMeDjE2By2#kinXb6mk zz-S1JhQMeDjE2By2n@jxNK9d1IK|As(8UUw|A+PezwT*)z{bGvgO!2d9xDUGX;ub?eXNl9>IB8v5KMEUP96<`(GWln z0R=d4_YCm}b&3!1_jdKOQc$U`RwzzQE=nya)hWi>(w&5{uGPOZ1CUb5awFQ}v@#Q}j}D(~;Dr z6eXsWpy@8pEXhDvoS6o7ZAoHLNpW~)NrnbwZI@nAYMPFMdQoaxv3^Nnda-_)x+b#o z^AdAYtrS8Fa`F>X6cP&x6p~8wQgTuiO7az;?or50gELDKVb0Q3C@luLy*NLuq@XCj zpjbaKxg;|`Pd7b77pl>r%#Z=e69tJS8ASLM;vn=e!0uaw7Zq%6p`Of0O-w1)&rQtC zQ%CkE#I+DN7VDRS{i~Z;RFavNm|WseW(0Mpt^&kOSmF8I~6ekyD7L@2i!jb`!RA5Fs7o{eaq#}hicD-eZIhiSmC8@e)sYS(^`FT)N z6coseYMAw5P;(Vv=E4nDP)N>6P0X`WNK4EqMkG_zphpeI$W|4V7MGM3 zK(m)ZVoHiad17&{v5{_hVsR$iRs{u2brlw7@n$Bvi3J5Ysk$kNMdg`@@W-Y;F|jB) zgP?}e0#Jl16qh6>7h=p8kIE0gl1J;r>A`(6Rzrvf)vP$U#^Xg$BC@ z`8oQ!5;P5_5Mi3HqqBc-yt8Xih^L#Uvtx)W4yWN(hsP{b_h1+S(}`4Y>q1LCa3Cru z=qePa=A`Ln>pTRJ#=-@qyzjIk6}`Um>Y9 zGbcqsS2rm$uUJ7>H!&wiH!U@>q_iltSOIJ}$U>NzAf?IqIXQ_*3Q3uHiA9;I#b7mH z0#uG58C;TDT%w?>3o4b03lfu46?Ap;@^#Y^Gjnv)5}_#qVRleyo&rb*#5|Bu*vw4M z$t)o;yCFkcB z_fsv9g!}>^QiCl(e)UZ8u20o(e8b3rcfx;)_xXOH+$WAY}l^?Mh`( erJ!~dLKxI402_yDLUD!_1E>UHfMj)NPX++@EoJfm diff --git a/plugins/json_language/src/lib.rs b/plugins/json_language/src/lib.rs index 1503f9f8b2..b3c70da7a1 100644 --- a/plugins/json_language/src/lib.rs +++ b/plugins/json_language/src/lib.rs @@ -1,13 +1,12 @@ +use std::{fs, path::PathBuf}; + use plugin::prelude::*; use serde::Deserialize; -use std::fs; -use std::path::PathBuf; #[import] fn command(string: &str) -> Option>; -const BIN_PATH: &'static str = - "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; +const BIN_PATH: &str = "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; #[export] pub fn name() -> &'static str { @@ -51,13 +50,11 @@ pub fn fetch_server_binary(container_dir: PathBuf, version: String) -> Result Result Option { let mut last_version_dir = None; - let mut entries = fs::read_dir(&container_dir).ok()?; + let entries = fs::read_dir(&container_dir).ok()?; - while let Some(entry) = entries.next() { + for entry in entries { let entry = entry.ok()?; if entry.file_type().ok()?.is_dir() { last_version_dir = Some(entry.path()); From 42c01c5b1011f1fdf8621db9827978e6d6d68a1f Mon Sep 17 00:00:00 2001 From: K Simmons Date: Thu, 11 Aug 2022 11:35:11 -0700 Subject: [PATCH 26/27] minor rustfmt fix --- crates/gpui/src/presenter.rs | 8 ++++---- crates/project_panel/src/project_panel.rs | 4 +++- styles/package-lock.json | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 1556572816..023e013d13 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -491,24 +491,24 @@ impl<'a> LayoutContext<'a> { if layout_parent != app_parent { panic!( "View {} was laid out with parent {} when it was constructed with parent {}", - print_error(view_id), + print_error(view_id), print_error(*layout_parent), print_error(*app_parent)) } } (None, Some(ParentId::View(app_parent))) => panic!( "View {} was laid out without a parent when it was constructed with parent {}", - print_error(view_id), + print_error(view_id), print_error(*app_parent) ), (Some(layout_parent), Some(ParentId::Root)) => panic!( "View {} was laid out with parent {} when it was constructed as a window root", - print_error(view_id), + print_error(view_id), print_error(*layout_parent), ), (_, None) => panic!( "View {} did not have a registered parent in the app context", - print_error(view_id), + print_error(view_id), ), _ => {} } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index f077520d72..702c750ea2 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -757,7 +757,9 @@ impl ProjectPanel { fn index_for_selection(&self, selection: Selection) -> Option<(usize, usize, usize)> { let mut entry_index = 0; let mut visible_entries_index = 0; - for (worktree_index, (worktree_id, worktree_entries)) in self.visible_entries.iter().enumerate() { + for (worktree_index, (worktree_id, worktree_entries)) in + self.visible_entries.iter().enumerate() + { if *worktree_id == selection.worktree_id { for entry in worktree_entries { if entry.id == selection.entry_id { diff --git a/styles/package-lock.json b/styles/package-lock.json index 5499f1852c..582f1c8496 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "styles", "version": "1.0.0", "license": "ISC", "dependencies": { From 8cf2ae3b6b8f552d7f53812eb7af86949b9eebaa Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 11 Aug 2022 11:46:54 -0700 Subject: [PATCH 27/27] Removed clippy from default settings --- assets/settings/default.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 9cf915d1a6..43b4be512f 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -154,13 +154,13 @@ //rust-analyzer //typescript-language-server //vscode-json-languageserver - "rust_analyzer": { - //These initialization options are merged into Zed's defaults - "initialization_options": { - "checkOnSave": { - "command": "clippy" - } - } - } + // "rust_analyzer": { + // //These initialization options are merged into Zed's defaults + // "initialization_options": { + // "checkOnSave": { + // "command": "clippy" + // } + // } + // } } }