diff --git a/.github/actions/check_style/action.yml b/.github/actions/check_style/action.yml index 25020e4e4c5399026c1ab32622903a3779ba86b2..74bb871bf58fe222c150754c88440d1667b0aef1 100644 --- a/.github/actions/check_style/action.yml +++ b/.github/actions/check_style/action.yml @@ -15,6 +15,7 @@ runs: # will have more fixes & suppression for the standard lint set run: | cargo clippy --workspace --all-features --all-targets -- -A clippy::all -D clippy::dbg_macro -D clippy::todo + cargo clippy -p gpui - name: Find modified migrations shell: bash -euxo pipefail {0} diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 7b349d92568e72b9b4929655e93dd1683636964e..dfecffb80a26461cc16d40489213988494229672 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -25,13 +25,12 @@ use crate::{ use anyhow::{anyhow, Result}; use collections::{FxHashMap, FxHashSet, VecDeque}; use futures::{channel::oneshot, future::LocalBoxFuture, Future}; -use parking_lot::Mutex; + use slotmap::SlotMap; use std::{ any::{type_name, TypeId}, cell::{Ref, RefCell, RefMut}, marker::PhantomData, - mem, ops::{Deref, DerefMut}, path::{Path, PathBuf}, rc::{Rc, Weak}, @@ -109,6 +108,7 @@ pub struct App(Rc); /// configured, you'll start the app with `App::run`. impl App { /// Builds an app with the given asset source. + #[allow(clippy::new_without_default)] pub fn new() -> Self { Self(AppContext::new( current_platform(), @@ -224,7 +224,7 @@ pub struct AppContext { pub(crate) entities: EntityMap, pub(crate) new_view_observers: SubscriberSet, pub(crate) windows: SlotMap>, - pub(crate) keymap: Arc>, + pub(crate) keymap: Rc>, pub(crate) global_action_listeners: FxHashMap>>, pending_effects: VecDeque, @@ -242,6 +242,7 @@ pub struct AppContext { } impl AppContext { + #[allow(clippy::new_ret_no_self)] pub(crate) fn new( platform: Rc, asset_source: Arc, @@ -285,7 +286,7 @@ impl AppContext { entities, new_view_observers: SubscriberSet::new(), windows: SlotMap::with_key(), - keymap: Arc::new(Mutex::new(Keymap::default())), + keymap: Rc::new(RefCell::new(Keymap::default())), global_action_listeners: FxHashMap::default(), pending_effects: VecDeque::new(), pending_notifications: FxHashSet::default(), @@ -763,7 +764,7 @@ impl AppContext { /// so it can be held across `await` points. pub fn to_async(&self) -> AsyncAppContext { AsyncAppContext { - app: unsafe { mem::transmute(self.this.clone()) }, + app: self.this.clone(), background_executor: self.background_executor.clone(), foreground_executor: self.foreground_executor.clone(), } @@ -996,13 +997,13 @@ impl AppContext { /// Register key bindings. pub fn bind_keys(&mut self, bindings: impl IntoIterator) { - self.keymap.lock().add_bindings(bindings); + self.keymap.borrow_mut().add_bindings(bindings); self.pending_effects.push_back(Effect::Refresh); } /// Clear all key bindings in the app. pub fn clear_key_bindings(&mut self) { - self.keymap.lock().clear(); + self.keymap.borrow_mut().clear(); self.pending_effects.push_back(Effect::Refresh); } @@ -1106,7 +1107,7 @@ impl AppContext { /// Sets the menu bar for this application. This will replace any existing menu bar. pub fn set_menus(&mut self, menus: Vec) { - self.platform.set_menus(menus, &self.keymap.lock()); + self.platform.set_menus(menus, &self.keymap.borrow()); } /// Dispatch an action to the currently active window or global action handler diff --git a/crates/gpui/src/app/entity_map.rs b/crates/gpui/src/app/entity_map.rs index db5d844d17c173bbc0541d49aaf5f67e70f139a0..6383cdad7b5efba1859f34fc4ce16c11520d4576 100644 --- a/crates/gpui/src/app/entity_map.rs +++ b/crates/gpui/src/app/entity_map.rs @@ -242,7 +242,7 @@ impl Clone for AnyModel { assert_ne!(prev_count, 0, "Detected over-release of a model."); } - let this = Self { + Self { entity_id: self.entity_id, entity_type: self.entity_type, entity_map: self.entity_map.clone(), @@ -254,8 +254,7 @@ impl Clone for AnyModel { .write() .leak_detector .handle_created(self.entity_id), - }; - this + } } } diff --git a/crates/gpui/src/color.rs b/crates/gpui/src/color.rs index e76c31d6f15db5a7690aab3bafd0b950f79e2824..dadc3d5ad301ba3cd2145215bb7909701fd9ed27 100644 --- a/crates/gpui/src/color.rs +++ b/crates/gpui/src/color.rs @@ -203,20 +203,16 @@ impl PartialEq for Hsla { impl PartialOrd for Hsla { fn partial_cmp(&self, other: &Self) -> Option { - // SAFETY: The total ordering relies on this always being Some() - Some( - self.h - .total_cmp(&other.h) - .then(self.s.total_cmp(&other.s)) - .then(self.l.total_cmp(&other.l).then(self.a.total_cmp(&other.a))), - ) + Some(self.cmp(other)) } } impl Ord for Hsla { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - // SAFETY: The partial comparison is a total comparison - unsafe { self.partial_cmp(other).unwrap_unchecked() } + self.h + .total_cmp(&other.h) + .then(self.s.total_cmp(&other.s)) + .then(self.l.total_cmp(&other.l).then(self.a.total_cmp(&other.a))) } } diff --git a/crates/gpui/src/element.rs b/crates/gpui/src/element.rs index cd5e6ea9dcd2af407e1de2cfa2f6f25e3e6c392c..4dbc7be652d3acf73bc90e3c709039fb79223074 100644 --- a/crates/gpui/src/element.rs +++ b/crates/gpui/src/element.rs @@ -133,9 +133,7 @@ pub trait Render: 'static + Sized { } impl Render for () { - fn render(&mut self, _cx: &mut ViewContext) -> impl IntoElement { - () - } + fn render(&mut self, _cx: &mut ViewContext) -> impl IntoElement {} } /// You can derive [`IntoElement`] on any type that implements this trait. diff --git a/crates/gpui/src/elements/div.rs b/crates/gpui/src/elements/div.rs index b1d936546b91f0387bfacf907d309a78d79d4a44..7ccdf8c2bf04891d9084b2170dc926874143a563 100644 --- a/crates/gpui/src/elements/div.rs +++ b/crates/gpui/src/elements/div.rs @@ -1008,10 +1008,9 @@ pub(crate) type ActionListener = Box Div { #[cfg(debug_assertions)] - let interactivity = { - let mut interactivity = Interactivity::default(); - interactivity.location = Some(*core::panic::Location::caller()); - interactivity + let interactivity = Interactivity { + location: Some(*core::panic::Location::caller()), + ..Default::default() }; #[cfg(not(debug_assertions))] diff --git a/crates/gpui/src/elements/overlay.rs b/crates/gpui/src/elements/overlay.rs index 61c34bd9385f6580feb3930dd3b3ea4b1494e919..9db75b75ba0d8138d75fd4a9aa90071e15689a10 100644 --- a/crates/gpui/src/elements/overlay.rs +++ b/crates/gpui/src/elements/overlay.rs @@ -222,7 +222,7 @@ impl OverlayPositionMode { ) -> (Point, Bounds) { match self { OverlayPositionMode::Window => { - let anchor_position = anchor_position.unwrap_or_else(|| bounds.origin); + let anchor_position = anchor_position.unwrap_or(bounds.origin); let bounds = anchor_corner.get_bounds(anchor_position, size); (anchor_position, bounds) } diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index 108e669f7550a2e6387641aaa4c1dae6e59f6313..ce32b993a5592732f763712b84fa33f24e2738f4 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -181,7 +181,7 @@ impl Element for UniformList { let shared_scroll_offset = element_state .interactive .scroll_offset - .get_or_insert_with(|| Rc::default()) + .get_or_insert_with(Rc::default) .clone(); let item_height = self.measure_item(Some(padded_bounds.size.width), cx).height; diff --git a/crates/gpui/src/geometry.rs b/crates/gpui/src/geometry.rs index d986f26be4475a72b0da8b75de8b3847e3fce588..dd826b68f541c98c88d364156dafc641bdbc8afa 100644 --- a/crates/gpui/src/geometry.rs +++ b/crates/gpui/src/geometry.rs @@ -1,3 +1,7 @@ +//! The GPUI geometry module is a collection of types and traits that +//! can be used to describe common units, concepts, and the relationships +//! between them. + use core::fmt::Debug; use derive_more::{Add, AddAssign, Div, DivAssign, Mul, Neg, Sub, SubAssign}; use refineable::Refineable; @@ -8,13 +12,17 @@ use std::{ ops::{Add, Div, Mul, MulAssign, Sub}, }; +/// An axis along which a measurement can be made. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Axis { + /// The y axis, or up and down Vertical, + /// The x axis, or left and right Horizontal, } impl Axis { + /// Swap this axis to the opposite axis. pub fn invert(&self) -> Self { match self { Axis::Vertical => Axis::Horizontal, @@ -23,11 +31,15 @@ impl Axis { } } +/// A trait for accessing the given unit along a certain axis. pub trait Along { + /// The unit associated with this type type Unit; + /// Returns the unit along the given axis. fn along(&self, axis: Axis) -> Self::Unit; + /// Applies the given function to the unit along the given axis and returns a new value. fn apply_along(&self, axis: Axis, f: impl FnOnce(Self::Unit) -> Self::Unit) -> Self; } @@ -47,7 +59,9 @@ pub trait Along { #[refineable(Debug)] #[repr(C)] pub struct Point { + /// The x coordinate of the point. pub x: T, + /// The y coordinate of the point. pub y: T, } @@ -334,7 +348,9 @@ impl Clone for Point { #[refineable(Debug)] #[repr(C)] pub struct Size { + /// The width component of the size. pub width: T, + /// The height component of the size. pub height: T, } @@ -640,7 +656,9 @@ impl Size { #[refineable(Debug)] #[repr(C)] pub struct Bounds { + /// The origin point of this area. pub origin: Point, + /// The size of the rectangle. pub size: Size, } @@ -1192,9 +1210,13 @@ impl Copy for Bounds {} #[refineable(Debug)] #[repr(C)] pub struct Edges { + /// The size of the top edge. pub top: T, + /// The size of the right edge. pub right: T, + /// The size of the bottom edge. pub bottom: T, + /// The size of the left edge. pub left: T, } @@ -1600,9 +1622,13 @@ impl From for Edges { #[refineable(Debug)] #[repr(C)] pub struct Corners { + /// The value associated with the top left corner. pub top_left: T, + /// The value associated with the top right corner. pub top_right: T, + /// The value associated with the bottom right corner. pub bottom_right: T, + /// The value associated with the bottom left corner. pub bottom_left: T, } @@ -2020,13 +2046,13 @@ impl Eq for Pixels {} impl PartialOrd for Pixels { fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) + Some(self.cmp(other)) } } impl Ord for Pixels { fn cmp(&self, other: &Self) -> cmp::Ordering { - self.partial_cmp(other).unwrap() + self.0.total_cmp(&other.0) } } diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 929e9ebfb4f262088e90e7ab5b99477a9933d998..8ecfd8ad6d834ac8c6577e2f724e22719e15e36e 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -26,6 +26,9 @@ //! TODO!(docs): Wrap up with a conclusion and links to other places? Zed / GPUI website? //! Discord for chatting about it? Other tutorials or references? +#![deny(missing_docs)] +#![allow(clippy::type_complexity)] + #[macro_use] mod action; mod app; diff --git a/crates/gpui/src/interactive.rs b/crates/gpui/src/interactive.rs index 4faa92ce043ae32e6e795b296daeb9ad281475f1..1bc32717c4b7702ca37ee413092d13e12fc6114f 100644 --- a/crates/gpui/src/interactive.rs +++ b/crates/gpui/src/interactive.rs @@ -343,7 +343,7 @@ impl ExternalPaths { impl Render for ExternalPaths { fn render(&mut self, _: &mut ViewContext) -> impl IntoElement { - () // Intentionally left empty because the platform will render icons for the dragged files + // Intentionally left empty because the platform will render icons for the dragged files } } diff --git a/crates/gpui/src/key_dispatch.rs b/crates/gpui/src/key_dispatch.rs index dd5a7ab84e25e267012de5e9dfb216404b8dfa7d..b4de09e36c58e6b32bacac0e0b90d160f3de0195 100644 --- a/crates/gpui/src/key_dispatch.rs +++ b/crates/gpui/src/key_dispatch.rs @@ -54,13 +54,12 @@ use crate::{ KeyContext, Keymap, KeymatchResult, Keystroke, KeystrokeMatcher, WindowContext, }; use collections::FxHashMap; -use parking_lot::Mutex; use smallvec::{smallvec, SmallVec}; use std::{ any::{Any, TypeId}, + cell::RefCell, mem, rc::Rc, - sync::Arc, }; #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] @@ -73,7 +72,7 @@ pub(crate) struct DispatchTree { focusable_node_ids: FxHashMap, view_node_ids: FxHashMap, keystroke_matchers: FxHashMap, KeystrokeMatcher>, - keymap: Arc>, + keymap: Rc>, action_registry: Rc, } @@ -96,7 +95,7 @@ pub(crate) struct DispatchActionListener { } impl DispatchTree { - pub fn new(keymap: Arc>, action_registry: Rc) -> Self { + pub fn new(keymap: Rc>, action_registry: Rc) -> Self { Self { node_stack: Vec::new(), context_stack: Vec::new(), @@ -307,7 +306,7 @@ impl DispatchTree { action: &dyn Action, context_stack: &Vec, ) -> Vec { - let keymap = self.keymap.lock(); + let keymap = self.keymap.borrow(); keymap .bindings_for_action(action) .filter(|binding| { @@ -440,9 +439,7 @@ impl DispatchTree { #[cfg(test)] mod tests { - use std::{rc::Rc, sync::Arc}; - - use parking_lot::Mutex; + use std::{cell::RefCell, rc::Rc}; use crate::{Action, ActionRegistry, DispatchTree, KeyBinding, KeyContext, Keymap}; @@ -496,7 +493,7 @@ mod tests { registry.load_action::(); - let keymap = Arc::new(Mutex::new(keymap)); + let keymap = Rc::new(RefCell::new(keymap)); let tree = DispatchTree::new(keymap, Rc::new(registry)); diff --git a/crates/gpui/src/keymap/keymap.rs b/crates/gpui/src/keymap.rs similarity index 97% rename from crates/gpui/src/keymap/keymap.rs rename to crates/gpui/src/keymap.rs index 2eefbb841ee5be0b499e7b32aaf28aa7da36a072..45e0ebbe951fe4a260cf869787e24322a47b1bd0 100644 --- a/crates/gpui/src/keymap/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -1,4 +1,12 @@ -use crate::{Action, KeyBinding, KeyBindingContextPredicate, KeyContext, Keystroke, NoAction}; +mod binding; +mod context; +mod matcher; + +pub use binding::*; +pub use context::*; +pub(crate) use matcher::*; + +use crate::{Action, Keystroke, NoAction}; use collections::HashSet; use smallvec::SmallVec; use std::{ diff --git a/crates/gpui/src/keymap/context.rs b/crates/gpui/src/keymap/context.rs index 05ef67ba2bc9d260215fc0df89a8a6e3039450f5..6c22fa9fd69bfacf650e549d786ebfc0cb83de21 100644 --- a/crates/gpui/src/keymap/context.rs +++ b/crates/gpui/src/keymap/context.rs @@ -267,8 +267,8 @@ impl KeyBindingContextPredicate { '(' => { source = skip_whitespace(&source[1..]); let (predicate, rest) = Self::parse_expr(source, 0)?; - if rest.starts_with(')') { - source = skip_whitespace(&rest[1..]); + if let Some(stripped) = rest.strip_prefix(')') { + source = skip_whitespace(stripped); Ok((predicate, source)) } else { Err(anyhow!("expected a ')'")) diff --git a/crates/gpui/src/keymap/matcher.rs b/crates/gpui/src/keymap/matcher.rs index 09ba281a0d7ebc1e032100eb9463f32767afa403..c2dec94a5134d0f5879776f4cf56e2e776437ec1 100644 --- a/crates/gpui/src/keymap/matcher.rs +++ b/crates/gpui/src/keymap/matcher.rs @@ -1,11 +1,10 @@ use crate::{KeyBinding, KeyContext, Keymap, KeymapVersion, Keystroke}; -use parking_lot::Mutex; use smallvec::SmallVec; -use std::sync::Arc; +use std::{cell::RefCell, rc::Rc}; pub(crate) struct KeystrokeMatcher { pending_keystrokes: Vec, - keymap: Arc>, + keymap: Rc>, keymap_version: KeymapVersion, } @@ -15,8 +14,8 @@ pub struct KeymatchResult { } impl KeystrokeMatcher { - pub fn new(keymap: Arc>) -> Self { - let keymap_version = keymap.lock().version(); + pub fn new(keymap: Rc>) -> Self { + let keymap_version = keymap.borrow().version(); Self { pending_keystrokes: Vec::new(), keymap_version, @@ -42,7 +41,8 @@ impl KeystrokeMatcher { keystroke: &Keystroke, context_stack: &[KeyContext], ) -> KeymatchResult { - let keymap = self.keymap.lock(); + let keymap = self.keymap.borrow(); + // Clear pending keystrokes if the keymap has changed since the last matched keystroke. if keymap.version() != self.keymap_version { self.keymap_version = keymap.version(); @@ -72,7 +72,7 @@ impl KeystrokeMatcher { } } - if bindings.len() == 0 && pending_key.is_none() && self.pending_keystrokes.len() > 0 { + if bindings.is_empty() && pending_key.is_none() && !self.pending_keystrokes.is_empty() { drop(keymap); self.pending_keystrokes.remove(0); return self.match_keystroke(keystroke, context_stack); diff --git a/crates/gpui/src/keymap/mod.rs b/crates/gpui/src/keymap/mod.rs deleted file mode 100644 index 6f1a018322b1a7f55349af70729860b9d85bde60..0000000000000000000000000000000000000000 --- a/crates/gpui/src/keymap/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod binding; -mod context; -mod keymap; -mod matcher; - -pub use binding::*; -pub use context::*; -pub use keymap::*; -pub(crate) use matcher::*; diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index e623742740259f62db547b6b2c4791cec15051ca..900b17bb2c565a80b4095090478b3d2a06c8423a 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -397,7 +397,7 @@ impl PlatformInputHandler { let Some(range) = self.handler.selected_text_range(cx) else { return; }; - self.handler.replace_text_in_range(Some(range), &input, cx); + self.handler.replace_text_in_range(Some(range), input, cx); } } diff --git a/crates/gpui/src/platform/mac/text_system.rs b/crates/gpui/src/platform/mac/text_system.rs index 21fe3c70a8a8787056fd3409c837af76a70427cf..e8c8b45311e628fe96549fca5a4f9a10b399473e 100644 --- a/crates/gpui/src/platform/mac/text_system.rs +++ b/crates/gpui/src/platform/mac/text_system.rs @@ -143,7 +143,7 @@ impl PlatformTextSystem for MacTextSystem { fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { Ok(self.0.read().fonts[font_id.0] - .typographic_bounds(glyph_id.into())? + .typographic_bounds(glyph_id.0)? .into()) } @@ -221,11 +221,11 @@ impl MacTextSystemState { } fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { - Ok(self.fonts[font_id.0].advance(glyph_id.into())?.into()) + Ok(self.fonts[font_id.0].advance(glyph_id.0)?.into()) } fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option { - self.fonts[font_id.0].glyph_for_char(ch).map(Into::into) + self.fonts[font_id.0].glyph_for_char(ch).map(GlyphId) } fn id_for_native_font(&mut self, requested_font: CTFont) -> FontId { @@ -259,7 +259,7 @@ impl MacTextSystemState { let scale = Transform2F::from_scale(params.scale_factor); Ok(font .raster_bounds( - params.glyph_id.into(), + params.glyph_id.0, params.font_size.into(), scale, HintingOptions::None, @@ -334,7 +334,7 @@ impl MacTextSystemState { .native_font() .clone_with_font_size(f32::from(params.font_size) as CGFloat) .draw_glyphs( - &[u32::from(params.glyph_id) as CGGlyph], + &[params.glyph_id.0 as CGGlyph], &[CGPoint::new( (subpixel_shift.x / params.scale_factor) as CGFloat, (subpixel_shift.y / params.scale_factor) as CGFloat, @@ -419,7 +419,7 @@ impl MacTextSystemState { let glyph_utf16_ix = usize::try_from(*glyph_utf16_ix).unwrap(); ix_converter.advance_to_utf16_ix(glyph_utf16_ix); glyphs.push(ShapedGlyph { - id: (*glyph_id).into(), + id: GlyphId(*glyph_id as u32), position: point(position.x as f32, position.y as f32).map(px), index: ix_converter.utf8_ix, is_emoji: self.is_emoji(font_id), @@ -651,7 +651,7 @@ mod lenient_font_attributes { #[cfg(test)] mod tests { - use crate::{font, px, FontRun, MacTextSystem, PlatformTextSystem}; + use crate::{font, px, FontRun, GlyphId, MacTextSystem, PlatformTextSystem}; #[test] fn test_wrap_line() { @@ -690,8 +690,8 @@ mod tests { assert_eq!(layout.len, line.len()); assert_eq!(layout.runs.len(), 1); assert_eq!(layout.runs[0].glyphs.len(), 2); - assert_eq!(layout.runs[0].glyphs[0].id, 68u32.into()); // a - // There's no glyph for \u{feff} - assert_eq!(layout.runs[0].glyphs[1].id, 69u32.into()); // b + assert_eq!(layout.runs[0].glyphs[0].id, GlyphId(68u32)); // a + // There's no glyph for \u{feff} + assert_eq!(layout.runs[0].glyphs[1].id, GlyphId(69u32)); // b } } diff --git a/crates/gpui/src/style.rs b/crates/gpui/src/style.rs index e1d82adea8751a8f0baf60c40dac4efbec993b1b..a12bb6df12836390855c6dfd6da078481425fabc 100644 --- a/crates/gpui/src/style.rs +++ b/crates/gpui/src/style.rs @@ -7,7 +7,7 @@ use crate::{ SizeRefinement, Styled, TextRun, }; use collections::HashSet; -use refineable::{Cascade, Refineable}; +use refineable::Refineable; use smallvec::SmallVec; pub use taffy::style::{ AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent, @@ -15,10 +15,12 @@ pub use taffy::style::{ }; #[cfg(debug_assertions)] +/// Use this struct for interfacing with the 'debug_below' styling from your own elements. +/// If a parent element has this style set on it, then this struct will be set as a global in +/// GPUI. pub struct DebugBelow; -pub type StyleCascade = Cascade