chore: add pedantic workspace lints (#90)
Add [workspace.lints.rust] and wire each member crate up with [lints] workspace = true: unsafe_code = "deny" (forbid would break the Android JNI build) single_use_lifetimes = "warn" trivial_casts = "warn" unused_lifetimes = "warn" unused_qualifications = "warn" variant_size_differences = "warn" unexpected_cfgs = "warn" unsafe_code is "deny" rather than the issue's "forbid" so the three Android JNI FFI modules (android_keystore, android_clipboard, safe_area) can opt back in with a scoped #![allow(unsafe_code)] — forbid cannot be locally overridden. Pure crates carry no unsafe and stay clean. Clean up the warnings the new lints surface: - 150ish unused_qualifications removed via `cargo fix` (purely syntactic redundant-path-prefix removals). - table_plugin: the TABLE_COLOUR import was #[cfg(test)]-gated while the camera clear-colour used the fully-qualified path; unqualifying it left a non-test build with no import. Made the import unconditional instead. - assets/sources: the `as &[u8]` casts in embed_*_svg! coerce each fixed-size &[u8; N] to a uniform slice so the tuples fit the &[(&str, &[u8])] arrays — load-bearing, so scoped #[allow(trivial_casts)]. Workspace clippy -D warnings and the full test suite pass. Android build not compiled here (needs the NDK; built separately per CLAUDE.md §15) — the deny + scoped-allow keeps the JNI unsafe blocks legal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -483,7 +483,7 @@ impl Plugin for CardPlugin {
|
||||
update_stock_empty_indicator.after(GameMutation),
|
||||
update_stock_count_badge
|
||||
.after(GameMutation)
|
||||
.run_if(resource_changed::<crate::GameStateResource>),
|
||||
.run_if(resource_changed::<GameStateResource>),
|
||||
collect_resize_events.after(LayoutSystem::UpdateOnResize),
|
||||
snap_cards_on_window_resize.after(collect_resize_events),
|
||||
),
|
||||
@@ -2431,7 +2431,7 @@ fn update_tableau_fan_frac(
|
||||
.into_iter()
|
||||
.map(|tableau| {
|
||||
game.0
|
||||
.pile(solitaire_core::KlondikePile::Tableau(tableau))
|
||||
.pile(KlondikePile::Tableau(tableau))
|
||||
.into_iter()
|
||||
.filter(|(_, face_up)| *face_up)
|
||||
.count()
|
||||
@@ -2566,7 +2566,7 @@ mod tests {
|
||||
#[test]
|
||||
fn card_positions_includes_all_52_cards_at_game_start() {
|
||||
// At game start waste is empty, so all 52 cards are across stock + tableau.
|
||||
let g = GameState::new(42, solitaire_core::DrawStockConfig::DrawOne);
|
||||
let g = GameState::new(42, DrawStockConfig::DrawOne);
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
assert_eq!(positions.len(), 52);
|
||||
@@ -2580,7 +2580,7 @@ mod tests {
|
||||
for _ in 0..3 {
|
||||
let _ = g.draw();
|
||||
}
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
g.waste_cards().iter().map(|c| c.0.clone()).collect();
|
||||
assert_eq!(waste_ids.len(), 3);
|
||||
|
||||
@@ -2624,7 +2624,7 @@ mod tests {
|
||||
"need at least 3 waste cards for this test"
|
||||
);
|
||||
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
waste_pile.iter().map(|c| c.0.clone()).collect();
|
||||
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
@@ -2677,7 +2677,7 @@ mod tests {
|
||||
let count = waste_pile.len();
|
||||
assert!(count >= 2, "need at least 2 waste cards");
|
||||
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
waste_pile.iter().map(|c| c.0.clone()).collect();
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
@@ -2715,7 +2715,7 @@ mod tests {
|
||||
for _ in 0..3 {
|
||||
let _ = g.draw();
|
||||
}
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
g.waste_cards().iter().map(|c| c.0.clone()).collect();
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
@@ -2740,7 +2740,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn card_positions_tableau_cards_are_fanned_downward() {
|
||||
let g = GameState::new(42, solitaire_core::DrawStockConfig::DrawOne);
|
||||
let g = GameState::new(42, DrawStockConfig::DrawOne);
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
|
||||
@@ -3083,7 +3083,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn facedown_cards_use_tighter_fan_than_uniform_faceup_fan() {
|
||||
let g = GameState::new(42, solitaire_core::DrawStockConfig::DrawOne);
|
||||
let g = GameState::new(42, DrawStockConfig::DrawOne);
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
|
||||
@@ -3153,7 +3153,7 @@ mod tests {
|
||||
|
||||
fn fire_window_resize(app: &mut App, width: f32, height: f32) {
|
||||
// Any Entity will do — the snap system reads only width/height.
|
||||
let window = bevy::ecs::entity::Entity::from_raw_u32(0)
|
||||
let window = Entity::from_raw_u32(0)
|
||||
.expect("Entity::from_raw_u32(0) is a valid placeholder");
|
||||
app.world_mut().write_message(WindowResized {
|
||||
window,
|
||||
@@ -3171,9 +3171,9 @@ mod tests {
|
||||
// entity IDs must remain alive.
|
||||
let mut app = app();
|
||||
|
||||
let labels_before: std::collections::HashSet<bevy::prelude::Entity> = app
|
||||
let labels_before: HashSet<Entity> = app
|
||||
.world_mut()
|
||||
.query_filtered::<bevy::prelude::Entity, With<CardLabel>>()
|
||||
.query_filtered::<Entity, With<CardLabel>>()
|
||||
.iter(app.world())
|
||||
.collect();
|
||||
assert!(
|
||||
@@ -3184,9 +3184,9 @@ mod tests {
|
||||
fire_window_resize(&mut app, 1024.0, 768.0);
|
||||
advance_past_resize_throttle(&mut app);
|
||||
|
||||
let labels_after: std::collections::HashSet<bevy::prelude::Entity> = app
|
||||
let labels_after: HashSet<Entity> = app
|
||||
.world_mut()
|
||||
.query_filtered::<bevy::prelude::Entity, With<CardLabel>>()
|
||||
.query_filtered::<Entity, With<CardLabel>>()
|
||||
.iter(app.world())
|
||||
.collect();
|
||||
|
||||
@@ -3336,9 +3336,9 @@ mod tests {
|
||||
|
||||
// Each shadow's parent must be a CardEntity, so the child relation
|
||||
// is wired correctly.
|
||||
let cards: HashSet<bevy::prelude::Entity> = app
|
||||
let cards: HashSet<Entity> = app
|
||||
.world_mut()
|
||||
.query_filtered::<bevy::prelude::Entity, With<CardEntity>>()
|
||||
.query_filtered::<Entity, With<CardEntity>>()
|
||||
.iter(app.world())
|
||||
.collect();
|
||||
let mut q = app
|
||||
@@ -3423,7 +3423,7 @@ mod tests {
|
||||
let card_entity = {
|
||||
let mut q = app
|
||||
.world_mut()
|
||||
.query::<(bevy::prelude::Entity, &CardEntity)>();
|
||||
.query::<(Entity, &CardEntity)>();
|
||||
q.iter(app.world())
|
||||
.find(|(_, c)| c.card == *card)
|
||||
.map(|(e, _)| e)
|
||||
@@ -3533,7 +3533,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn stock_card_count_helper_reads_zero_for_empty_stock() {
|
||||
let g = GameState::new(42, solitaire_core::DrawStockConfig::DrawOne);
|
||||
let g = GameState::new(42, DrawStockConfig::DrawOne);
|
||||
let mut g_empty_stock = g.clone();
|
||||
g_empty_stock.set_test_stock_cards(Vec::new());
|
||||
assert_eq!(stock_card_count(&g_empty_stock), 0);
|
||||
@@ -3553,9 +3553,9 @@ mod tests {
|
||||
// Allocate five different strong handles by passing each a
|
||||
// distinct dummy `Image`. We never render these; we only
|
||||
// compare ids.
|
||||
let mut images = bevy::asset::Assets::<bevy::image::Image>::default();
|
||||
let backs: [Handle<bevy::image::Image>; 5] =
|
||||
std::array::from_fn(|_| images.add(bevy::image::Image::default()));
|
||||
let mut images = Assets::<Image>::default();
|
||||
let backs: [Handle<Image>; 5] =
|
||||
std::array::from_fn(|_| images.add(Image::default()));
|
||||
CardImageSet {
|
||||
faces: std::array::from_fn(|_| std::array::from_fn(|_| Handle::default())),
|
||||
backs,
|
||||
@@ -3569,8 +3569,8 @@ mod tests {
|
||||
// card must render with the theme's back regardless of which
|
||||
// legacy back the player picked in Settings.
|
||||
let mut set = image_set_with_distinct_back_handles();
|
||||
let mut images = bevy::asset::Assets::<bevy::image::Image>::default();
|
||||
let theme_back: Handle<bevy::image::Image> = images.add(bevy::image::Image::default());
|
||||
let mut images = Assets::<Image>::default();
|
||||
let theme_back: Handle<Image> = images.add(Image::default());
|
||||
set.theme_back = Some(theme_back.clone());
|
||||
|
||||
let face_down = make_card(Suit::Spades, Rank::Ace);
|
||||
@@ -3634,8 +3634,8 @@ mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut set = image_set_with_distinct_back_handles();
|
||||
let mut images = bevy::asset::Assets::<bevy::image::Image>::default();
|
||||
let theme_back: Handle<bevy::image::Image> = images.add(bevy::image::Image::default());
|
||||
let mut images = Assets::<Image>::default();
|
||||
let theme_back: Handle<Image> = images.add(Image::default());
|
||||
|
||||
let theme = CardTheme {
|
||||
meta: ThemeMeta {
|
||||
@@ -3645,7 +3645,7 @@ mod tests {
|
||||
version: "0".into(),
|
||||
card_aspect: (2, 3),
|
||||
},
|
||||
faces: HashMap::<CardKey, Handle<bevy::image::Image>>::new(),
|
||||
faces: HashMap::<CardKey, Handle<Image>>::new(),
|
||||
back: theme_back.clone(),
|
||||
};
|
||||
|
||||
@@ -3813,7 +3813,7 @@ mod tests {
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
g.waste_cards().iter().map(|c| c.0.clone()).collect();
|
||||
|
||||
let mut waste_zs: Vec<f32> = positions
|
||||
@@ -3863,7 +3863,7 @@ mod tests {
|
||||
|
||||
let stock_x = layout.pile_positions[&KlondikePile::Stock].x;
|
||||
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
g.waste_cards().iter().map(|c| c.0.clone()).collect();
|
||||
|
||||
let mut waste_positions: Vec<_> = card_positions(&g, &layout)
|
||||
@@ -3893,7 +3893,7 @@ mod tests {
|
||||
let layout = crate::layout::compute_layout(Vec2::new(1280.0, 800.0), 0.0, 0.0, true);
|
||||
let positions = card_positions(&g, &layout);
|
||||
|
||||
let waste_ids: std::collections::HashSet<Card> =
|
||||
let waste_ids: HashSet<Card> =
|
||||
g.waste_cards().iter().map(|c| c.0.clone()).collect();
|
||||
|
||||
let mut waste_zs: Vec<f32> = positions
|
||||
|
||||
Reference in New Issue
Block a user