From 5237c6bfac9c9d37e704d3ea3153a1902593b81b Mon Sep 17 00:00:00 2001 From: kirillDevPro <113171057+kirillDevPro@users.noreply.github.com> Date: Sat, 26 Sep 2026 17:58:49 +0200 Subject: [PATCH 1/5] chore(clippy): allow three workspace lints Clippy is about to become a merge gate. too_many_arguments and type_complexity describe API shape, not defects, and `!(a < b)` is deliberate NaN handling that must not be rewritten to `>=`. Each crate inherits the table with `[lints] workspace = true`. --- Cargo.toml | 11 +++++++++++ crates/moon-chart/Cargo.toml | 3 +++ crates/moon-core/Cargo.toml | 3 +++ crates/moon-ui-gpui/Cargo.toml | 3 +++ 4 files changed, 20 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 9cde5226d..7959190fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,3 +43,14 @@ opt-level = 2 [patch.crates-io] async-process = { git = "https://github.com/zed-industries/async-process.git", rev = "0b6d6713570af61806e1e5cb40e0f757cb93fd9d" } async-task = { git = "https://github.com/smol-rs/async-task.git", rev = "b4486cd71e4e94fbda54ce6302444de14f4d190e" } + +# Clippy is a merge gate (`cargo clippy --workspace --all-targets -- -D warnings`). +# These three stay allowed: fixing them is a refactor or would rewrite deliberate +# numeric comparisons, not a bugfix. Every crate opts in with `[lints] workspace = true`. +[workspace.lints.clippy] +# Constructors and draw helpers take one argument per field on purpose. +too_many_arguments = "allow" +# Nested results and iterators name the data; a typedef would only rename them. +type_complexity = "allow" +# `!(a < b)` is deliberate NaN handling. Never rewrite it to `a >= b`. +neg_cmp_op_on_partial_ord = "allow" diff --git a/crates/moon-chart/Cargo.toml b/crates/moon-chart/Cargo.toml index 9e51feadb..28d89ddcb 100644 --- a/crates/moon-chart/Cargo.toml +++ b/crates/moon-chart/Cargo.toml @@ -15,3 +15,6 @@ moon-core = { path = "../moon-core" } # Only for #[derive(Pod/Zeroable)] on instance types and ChartUniform. wgpu is no longer used: # the wgpu chart engine was removed with the egui binary; own-pass DX11 (chartdx) does the rendering. bytemuck = { version = "1", features = ["derive"] } + +[lints] +workspace = true diff --git a/crates/moon-core/Cargo.toml b/crates/moon-core/Cargo.toml index b261dd278..58d754b9e 100644 --- a/crates/moon-core/Cargo.toml +++ b/crates/moon-core/Cargo.toml @@ -119,3 +119,6 @@ windows-sys = { version = "0.61", features = [ # Descriptor count on Exhausted log lines: `fcntl(F_GETFD)` is a kernel query # that allocates no descriptor, so the probe still answers at the open-file cliff. libc = "0.2" + +[lints] +workspace = true diff --git a/crates/moon-ui-gpui/Cargo.toml b/crates/moon-ui-gpui/Cargo.toml index e377fa020..ccc0154fa 100644 --- a/crates/moon-ui-gpui/Cargo.toml +++ b/crates/moon-ui-gpui/Cargo.toml @@ -167,3 +167,6 @@ core-graphics = "0.24" # test build only and never the shipped binary. MoonUI's own `moon-ui-components` declares it the # same way. gpui = { package = "moon-gpui", git = "https://github.com/Moonbot-Tech/MoonUI", branch = "master", features = ["test-support"] } + +[lints] +workspace = true From fe34efc7ab72a02e6e2cf9941e48cc02cb211063 Mon Sep 17 00:00:00 2001 From: kirillDevPro <113171057+kirillDevPro@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:09:09 +0200 Subject: [PATCH 2/5] chore(clippy): apply machine-applicable fixes cargo clippy --fix rewrote the suggestions it marks as safe: needless borrows, unit lets, map_or forms, and nested ifs as let chains. Comparisons and NaN handling are untouched. One collapsible_match suggestion does not compile and stays for a targeted allow. --- crates/moon-chart/src/container.rs | 2 +- crates/moon-chart/src/view.rs | 2 +- crates/moon-core/examples/db_read_timing.rs | 2 +- crates/moon-core/src/backup_store.rs | 2 +- crates/moon-core/src/backups.rs | 2 +- crates/moon-core/src/config/layout.rs | 4 +- crates/moon-core/src/config/migrate.rs | 2 +- .../src/config/moonbot_import/schema_v7.rs | 2 +- crates/moon-core/src/crowd/standing/tests.rs | 2 +- crates/moon-core/src/db/analytics/groups.rs | 4 +- .../src/db/analytics/summary_stream.rs | 6 +- crates/moon-core/src/db/analytics/tests.rs | 4 +- .../moon-core/src/db/analytics/time_zone.rs | 4 +- crates/moon-core/src/db/report_axis.rs | 2 +- crates/moon-core/src/db/report_read/tests.rs | 2 +- crates/moon-core/src/db/tests.rs | 4 +- crates/moon-core/src/db/tuner/time/tests.rs | 4 +- crates/moon-core/src/db/valuation/health.rs | 2 +- crates/moon-core/src/db/valuation/mod.rs | 10 +- crates/moon-core/src/db/valuation/provider.rs | 12 +- crates/moon-core/src/feed/live/mod.rs | 9 +- crates/moon-core/src/market/candles.rs | 4 +- crates/moon-core/src/market/kline_cache.rs | 2 +- .../moon-core/src/market/kline_cache/tests.rs | 2 +- crates/moon-core/src/market/source/history.rs | 36 +++-- crates/moon-core/src/market/source/read.rs | 2 +- .../src/market/trade_replay/rest/okx/tests.rs | 2 +- crates/moon-core/src/strat_db/stats.rs | 4 +- crates/moon-core/src/telegram/init_data.rs | 2 +- crates/moon-core/src/telegram/report/tests.rs | 7 +- crates/moon-core/src/telegram/web.rs | 2 +- crates/moon-core/src/update/discovery.rs | 14 +- crates/moon-ui-gpui/build.rs | 11 +- crates/moon-ui-gpui/src/analytics/bg.rs | 4 +- crates/moon-ui-gpui/src/analytics/bg/tests.rs | 4 +- .../src/analytics/calendar/day.rs | 9 +- .../src/analytics/calendar/mod.rs | 16 +-- crates/moon-ui-gpui/src/analytics/mod.rs | 15 +- .../src/analytics/profit_monitor/mod.rs | 6 +- crates/moon-ui-gpui/src/analytics/render.rs | 8 +- .../src/analytics/summary/charts.rs | 10 +- .../src/analytics/summary/cumulative.rs | 2 +- .../moon-ui-gpui/src/analytics/summary/mod.rs | 2 +- crates/moon-ui-gpui/src/analytics/toolbar.rs | 4 +- .../src/analytics/tuner/coins/load.rs | 2 +- .../src/analytics/tuner/coins/save.rs | 10 +- .../moon-ui-gpui/src/analytics/tuner/save.rs | 58 ++++---- crates/moon-ui-gpui/src/backend/figures.rs | 22 +-- crates/moon-ui-gpui/src/backend/mod.rs | 49 ++++--- crates/moon-ui-gpui/src/backend/telegram.rs | 21 +-- .../moon-ui-gpui/src/chart_tabs/add_stack.rs | 35 +++-- .../src/chart_tabs/apply_all/tests.rs | 2 +- crates/moon-ui-gpui/src/chart_tabs/custom.rs | 16 +-- .../src/chart_tabs/detached_host/mod.rs | 24 ++-- .../src/chart_tabs/detached_host/render.rs | 30 ++-- .../moon-ui-gpui/src/chart_tabs/main_stack.rs | 10 +- crates/moon-ui-gpui/src/chart_tabs/mod.rs | 46 +++--- crates/moon-ui-gpui/src/chartdx/base.rs | 7 +- crates/moon-ui-gpui/src/chartdx/combo.rs | 18 +-- .../moon-ui-gpui/src/chartdx/combo/tests.rs | 2 +- .../src/chartdx/data_state/market.rs | 13 +- .../src/chartdx/data_state/orders.rs | 72 +++++----- .../src/chartdx/data_state/state.rs | 4 +- crates/moon-ui-gpui/src/chartdx/orderbook.rs | 7 +- crates/moon-ui-gpui/src/chartdx/pane.rs | 6 +- .../moon-ui-gpui/src/chartdx/render_state.rs | 12 +- .../moon-ui-gpui/src/chartdx/text/prepare.rs | 136 +++++++++--------- crates/moon-ui-gpui/src/design.rs | 2 +- .../src/diagnostics/debug_window.rs | 11 +- .../src/firetest/stages/order_cancel.rs | 32 ++--- .../moon-ui-gpui/src/firetest/stages/perf.rs | 8 +- crates/moon-ui-gpui/src/firetest/storm/win.rs | 2 +- .../moon-ui-gpui/src/media/exchange_logos.rs | 2 +- crates/moon-ui-gpui/src/media/sound.rs | 2 +- .../src/panels/alerts/controls.rs | 4 +- crates/moon-ui-gpui/src/panels/assets/mod.rs | 14 +- .../src/panels/assets/spot_order.rs | 5 +- .../moon-ui-gpui/src/panels/assets/table.rs | 52 +++---- .../moon-ui-gpui/src/panels/assets/window.rs | 9 +- crates/moon-ui-gpui/src/panels/chart/mod.rs | 16 +-- .../moon-ui-gpui/src/panels/chart/render.rs | 10 +- .../src/panels/chart/render_input.rs | 21 ++- crates/moon-ui-gpui/src/panels/chart/trade.rs | 4 +- crates/moon-ui-gpui/src/panels/chart/warn.rs | 8 +- .../src/panels/core_status/mod.rs | 13 +- .../src/panels/core_status/server_view.rs | 71 +++++---- .../panels/core_status/time_offset/tests.rs | 2 +- crates/moon-ui-gpui/src/panels/detects/mod.rs | 4 +- .../moon-ui-gpui/src/panels/log/controls.rs | 2 +- crates/moon-ui-gpui/src/panels/log/render.rs | 2 +- .../src/panels/orders/controls.rs | 4 +- .../moon-ui-gpui/src/panels/report/actions.rs | 6 +- .../src/panels/report/controls.rs | 4 +- .../moon-ui-gpui/src/panels/report/export.rs | 10 +- .../moon-ui-gpui/src/panels/report/query.rs | 4 +- .../moon-ui-gpui/src/panels/report/state.rs | 4 +- .../moon-ui-gpui/src/panels/report/totals.rs | 82 +++++------ .../src/persistence/chart_persist.rs | 40 ++---- .../src/persistence/dock_persist.rs | 8 +- crates/moon-ui-gpui/src/screener/view.rs | 19 ++- crates/moon-ui-gpui/src/settings/badges.rs | 60 ++++---- crates/moon-ui-gpui/src/settings/common.rs | 16 +-- .../src/settings/connections/mod.rs | 27 ++-- .../src/settings/connections/tab.rs | 22 +-- .../src/settings/connections/table.rs | 68 ++++----- crates/moon-ui-gpui/src/settings/general.rs | 16 +-- .../moon-ui-gpui/src/settings/hotkeys/tab.rs | 10 +- .../src/settings/import_preview.rs | 12 +- crates/moon-ui-gpui/src/settings/mod.rs | 19 ++- crates/moon-ui-gpui/src/settings/storage.rs | 6 +- crates/moon-ui-gpui/src/settings/telegram.rs | 10 +- crates/moon-ui-gpui/src/shell/actions.rs | 6 +- .../src/shell/core_settings_popup/widgets.rs | 8 +- crates/moon-ui-gpui/src/shell/init.rs | 68 ++++----- crates/moon-ui-gpui/src/shell/ticker.rs | 2 +- crates/moon-ui-gpui/src/shell/workspace.rs | 16 +-- crates/moon-ui-gpui/src/startup/boot.rs | 10 +- .../src/startup/strategy_filters_migration.rs | 8 +- crates/moon-ui-gpui/src/strategies/actions.rs | 10 +- crates/moon-ui-gpui/src/strategies/fields.rs | 8 +- .../src/strategies/full_params.rs | 10 +- .../src/strategies/param_entries.rs | 16 +-- crates/moon-ui-gpui/src/strategies/params.rs | 48 +++---- .../moon-ui-gpui/src/strategies/sections.rs | 6 +- .../moon-ui-gpui/src/strategies/tree/dnd.rs | 4 +- .../src/strategies/tree/ops/tests.rs | 4 +- .../moon-ui-gpui/src/strategies/versions.rs | 33 +++-- crates/moon-ui-gpui/src/trade_window/mod.rs | 2 +- .../moon-ui-gpui/src/window/group_window.rs | 9 +- crates/moon-ui-gpui/src/window/windowing.rs | 20 ++- crates/moon-ui-gpui/src/workspace/tests.rs | 2 +- .../tests/theme_contract/chart.rs | 2 +- .../tests/theme_contract/shell.rs | 2 +- .../tests/theme_contract/strategies.rs | 27 ++-- 134 files changed, 924 insertions(+), 993 deletions(-) diff --git a/crates/moon-chart/src/container.rs b/crates/moon-chart/src/container.rs index 9ae490549..3a47c1d4d 100644 --- a/crates/moon-chart/src/container.rs +++ b/crates/moon-chart/src/container.rs @@ -39,7 +39,7 @@ impl PaneSource { PaneSource::Manual => None, // Lazy on purpose: the eager form still computes the infinity this keeps out. PaneSource::AddToChart { born_ms, ttl_ms } => { - ttl_ms.is_finite().then(|| born_ms + ttl_ms) + ttl_ms.is_finite().then_some(born_ms + ttl_ms) } } } diff --git a/crates/moon-chart/src/view.rs b/crates/moon-chart/src/view.rs index 9c9f0672a..6d311beff 100644 --- a/crates/moon-chart/src/view.rs +++ b/crates/moon-chart/src/view.rs @@ -552,7 +552,7 @@ impl ChartView { let area_delta = area_w - self.last_phase_area_w; // Every shrink matters for the six-hour lower bound; sub-pixel growth can safely retain // the previous scale because it only increases the visible history. - let area_changed = area_delta < 0.0 || area_delta >= 0.5; + let area_changed = !(0.0..0.5).contains(&area_delta); let present_changed = (present_hz - self.last_phase_present_hz).abs() >= 0.5; let phase_changed = area_changed || present_changed; if phase_changed || self.x_init_pending { diff --git a/crates/moon-core/examples/db_read_timing.rs b/crates/moon-core/examples/db_read_timing.rs index 552e0cc00..9374748c1 100644 --- a/crates/moon-core/examples/db_read_timing.rs +++ b/crates/moon-core/examples/db_read_timing.rs @@ -342,7 +342,7 @@ fn dump_all(period_name: &str, from: i64, to: i64, pool: &Pool) { let monitor = moon_core::db::analytics::profit_monitor(&q(ProfitMetric::Quote)); println!("{period_name}|profit_monitor|{monitor:?}"); - if let Some(conn) = moon_core::db::open_reader().ok() { + if let Ok(conn) = moon_core::db::open_reader() { if let Ok(snap) = moon_core::db::read_snapshot(&conn) { let filter = ReportFilter::default(); if let Ok(cores) = moon_core::db::distinct_cores(&snap) { diff --git a/crates/moon-core/src/backup_store.rs b/crates/moon-core/src/backup_store.rs index e56e05aa9..3e985fdfa 100644 --- a/crates/moon-core/src/backup_store.rs +++ b/crates/moon-core/src/backup_store.rs @@ -193,7 +193,7 @@ impl<'a> SnapshotStore<'a> { return false; }; let mut found = Vec::::new(); - while let Some(entry) = entries.next() { + for entry in entries.by_ref() { let Ok(entry) = entry else { return false; }; diff --git a/crates/moon-core/src/backups.rs b/crates/moon-core/src/backups.rs index 8e68a8db7..580418ce5 100644 --- a/crates/moon-core/src/backups.rs +++ b/crates/moon-core/src/backups.rs @@ -264,7 +264,7 @@ fn launch_settings_job() { "settings", &SETTINGS_JOB_ACTIVE, false, - |now_ms| crate::config::backup_due_at(now_ms), + crate::config::backup_due_at, ); } diff --git a/crates/moon-core/src/config/layout.rs b/crates/moon-core/src/config/layout.rs index 92d54d29c..ddd965cee 100644 --- a/crates/moon-core/src/config/layout.rs +++ b/crates/moon-core/src/config/layout.rs @@ -2203,7 +2203,7 @@ impl WindowLayout { |_| false, ); let moved = match self.kind_defaults_mut(kind) { - Some(d) => std::mem::replace(&mut d.candle_view, Some(value)) != Some(value), + Some(d) => d.candle_view.replace(value) != Some(value), None => std::mem::replace(&mut self.candle_view, value) != value, }; split || moved @@ -2221,7 +2221,7 @@ impl WindowLayout { |_| false, ); let moved = match self.kind_defaults_mut(kind) { - Some(d) => std::mem::replace(&mut d.chart_graphics, Some(value)) != Some(value), + Some(d) => d.chart_graphics.replace(value) != Some(value), None => std::mem::replace(&mut self.chart_graphics, value) != value, }; split || moved diff --git a/crates/moon-core/src/config/migrate.rs b/crates/moon-core/src/config/migrate.rs index 322ac81e8..8a3beef28 100644 --- a/crates/moon-core/src/config/migrate.rs +++ b/crates/moon-core/src/config/migrate.rs @@ -51,7 +51,7 @@ fn config_from_legacy_enc(plain: &[u8], uid_floor: Option) -> anyhow::Resul groups: Vec, } - let old: Old = toml::from_str(std::str::from_utf8(&plain)?)?; + let old: Old = toml::from_str(std::str::from_utf8(plain)?)?; let servers = old .servers .into_iter() diff --git a/crates/moon-core/src/config/moonbot_import/schema_v7.rs b/crates/moon-core/src/config/moonbot_import/schema_v7.rs index 4c6b5f7be..9f9554509 100644 --- a/crates/moon-core/src/config/moonbot_import/schema_v7.rs +++ b/crates/moon-core/src/config/moonbot_import/schema_v7.rs @@ -237,7 +237,7 @@ pub fn parse_payload(payload: &[u8]) -> Result { } match kind { // Signals/Trading/Visual must be present, but their contents are skipped. - 1 | 2 | 3 => {} + 1..=3 => {} 4 => theme = Some(parse_theme(sub)?), 5 => ini = Some(parse_ini(sub)?), 6 => ui = Some(parse_ui(sub)?), diff --git a/crates/moon-core/src/crowd/standing/tests.rs b/crates/moon-core/src/crowd/standing/tests.rs index 8606e3e9d..2195b44f4 100644 --- a/crates/moon-core/src/crowd/standing/tests.rs +++ b/crates/moon-core/src/crowd/standing/tests.rs @@ -21,7 +21,7 @@ fn a_row_carries_both_sides_of_the_minute() { #[test] fn the_loud_come_first() { - let mut rows = vec![ + let mut rows = [ Standing::live("BTC", &stat(10.0, 5.0)), Standing::live("ETH", &stat(100.0, 5.0)), ]; diff --git a/crates/moon-core/src/db/analytics/groups.rs b/crates/moon-core/src/db/analytics/groups.rs index 95f662c92..fdf8a7720 100644 --- a/crates/moon-core/src/db/analytics/groups.rs +++ b/crates/moon-core/src/db/analytics/groups.rs @@ -237,8 +237,8 @@ pub(in crate::db) fn coin_groups_from_source( q: &Query, src: &str, ) -> ReadResult> { - let raw_src = raw_source(conn, &q)?; - groups(conn, &src, raw_src.as_deref(), &q, false, false) + let raw_src = raw_source(conn, q)?; + groups(conn, src, raw_src.as_deref(), q, false, false) } /// Build the lens-neutral source used by raw-profit and average-order enrichments. diff --git a/crates/moon-core/src/db/analytics/summary_stream.rs b/crates/moon-core/src/db/analytics/summary_stream.rs index 24ad4172f..47653398a 100644 --- a/crates/moon-core/src/db/analytics/summary_stream.rs +++ b/crates/moon-core/src/db/analytics/summary_stream.rs @@ -136,11 +136,7 @@ impl GroupAccumulator { self.worst = Some(self.worst.map_or(value, |worst| worst.min(value))); } if let Some(name) = &row.core_name { - if self - .core_name - .as_ref() - .map_or(true, |current| name > current) - { + if self.core_name.as_ref().is_none_or(|current| name > current) { self.core_name = Some(name.clone()); } } diff --git a/crates/moon-core/src/db/analytics/tests.rs b/crates/moon-core/src/db/analytics/tests.rs index 2195aa540..790755451 100644 --- a/crates/moon-core/src/db/analytics/tests.rs +++ b/crates/moon-core/src/db/analytics/tests.rs @@ -312,7 +312,7 @@ fn one_current_stream_preserves_every_summary_field() { profit: 6.0, raw_profit: 6.0, avg_order: 100.0, - quote: quote.clone(), + quote, wins: 1, pf: 2.5, best: 10.0, @@ -1096,7 +1096,7 @@ fn corrupt_replica_surfaces_error_not_empty() { let res = summary_on(&conn, &wide, false, false); assert!( - !matches!(res, Ok(_)), + !res.is_ok(), "ошибка чтения не должна превращаться в успешный — в том числе \ пустой или частичный — период: это и есть чинимый баг" ); diff --git a/crates/moon-core/src/db/analytics/time_zone.rs b/crates/moon-core/src/db/analytics/time_zone.rs index 6e97fe145..e44b90d49 100644 --- a/crates/moon-core/src/db/analytics/time_zone.rs +++ b/crates/moon-core/src/db/analytics/time_zone.rs @@ -86,11 +86,11 @@ pub(crate) fn install(conn: &Connection, axis: &ReportAxis) -> rusqlite::Result< // by two conversions cancelling. conn.create_scalar_function("mt_core_minute_of_day", 1, flags, move |ctx| { let secs = ctx.get::(0)?; - Ok(crate::util::display_time::minute_of_day(secs, chrono_tz::UTC).unwrap_or(0) as i64) + Ok(crate::util::display_time::minute_of_day(secs, chrono_tz::UTC).unwrap_or(0)) })?; conn.create_scalar_function("mt_core_minute_of_week", 1, flags, move |ctx| { let secs = ctx.get::(0)?; - Ok(crate::util::display_time::minute_of_week(secs, chrono_tz::UTC).unwrap_or(0) as i64) + Ok(crate::util::display_time::minute_of_week(secs, chrono_tz::UTC).unwrap_or(0)) })?; Ok(()) diff --git a/crates/moon-core/src/db/report_axis.rs b/crates/moon-core/src/db/report_axis.rs index a4657dd88..2eee1fb3f 100644 --- a/crates/moon-core/src/db/report_axis.rs +++ b/crates/moon-core/src/db/report_axis.rs @@ -410,7 +410,7 @@ impl ReportAxis { /// the honest signal that the uncorrected single-branch predicate is still correct. pub fn measured_groups(&self, at: i64) -> Vec<(i32, Vec)> { let mut by_offset: HashMap> = HashMap::new(); - for (&core_uid, _) in self.segments.iter() { + for &core_uid in self.segments.keys() { if let Some(offset) = self.offset_secs(core_uid, at) { by_offset.entry(offset).or_default().push(core_uid); } diff --git a/crates/moon-core/src/db/report_read/tests.rs b/crates/moon-core/src/db/report_read/tests.rs index c6db9dd46..b817a384e 100644 --- a/crates/moon-core/src/db/report_read/tests.rs +++ b/crates/moon-core/src/db/report_read/tests.rs @@ -2807,7 +2807,7 @@ fn chart_history_preserves_optional_millisecond_columns_and_legacy_rows() { thread_local! { static CHART_HISTORY_SQL: std::cell::RefCell> = - std::cell::RefCell::new(Vec::new()); + const { std::cell::RefCell::new(Vec::new()) }; } /// Keep expanded chart-history SELECTs so the test can `EXPLAIN` the statement the function prepared. diff --git a/crates/moon-core/src/db/tests.rs b/crates/moon-core/src/db/tests.rs index e22a175cd..b85bf6af9 100644 --- a/crates/moon-core/src/db/tests.rs +++ b/crates/moon-core/src/db/tests.rs @@ -1110,7 +1110,7 @@ fn corrupt_replica_fails_report_query_instead_of_truncating() { let res = query_reports(&conn, &filter, "closedate", true, 5_000); assert!( - !matches!(res, Ok(_)), + !res.is_ok(), "сбой чтения обязан вернуть ошибку, а не частичную/пустую таблицу: \ такой файл экспорта неотличим от полного" ); @@ -1158,7 +1158,7 @@ fn corrupt_replica_fails_report_totals_instead_of_zeroing() { let res = query_totals(&conn, &filter); assert!( - !matches!(res, Ok(_)), + !res.is_ok(), "сбой агрегата обязан вернуть ошибку, а не (0.0, 0)" ); diff --git a/crates/moon-core/src/db/tuner/time/tests.rs b/crates/moon-core/src/db/tuner/time/tests.rs index 54e1d5a4d..6643368dc 100644 --- a/crates/moon-core/src/db/tuner/time/tests.rs +++ b/crates/moon-core/src/db/tuner/time/tests.rs @@ -166,8 +166,8 @@ fn suggest_time_never_worse_than_base() { .iter() .filter(|&&(wd, mn, _)| { s.week_span - .map_or(true, |(f, t)| span_ok(wd * 1440 + mn, f as i64, t as i64)) - && s.tod.map_or(true, |tw| match tw { + .is_none_or(|(f, t)| span_ok(wd * 1440 + mn, f as i64, t as i64)) + && s.tod.is_none_or(|tw| match tw { TimeWindow::Day(f, t) => span_ok(mn, f as i64, t as i64), TimeWindow::Hour(f, t) => span_ok(mn % 60, f as i64, t as i64), }) diff --git a/crates/moon-core/src/db/valuation/health.rs b/crates/moon-core/src/db/valuation/health.rs index 6ae8c126a..a2194589c 100644 --- a/crates/moon-core/src/db/valuation/health.rs +++ b/crates/moon-core/src/db/valuation/health.rs @@ -460,7 +460,7 @@ fn retry_delay(consecutive_failures: u32) -> Duration { /// Returns: /// `true` for the first few attempts and then periodically. const fn should_log(attempt: u32) -> bool { - matches!(attempt, 1 | 2 | 3 | 5 | 10) || (attempt > 10 && attempt % 20 == 0) + matches!(attempt, 1 | 2 | 3 | 5 | 10) || (attempt > 10 && attempt.is_multiple_of(20)) } /// Emit one failing-run line in the shape every stage shares. diff --git a/crates/moon-core/src/db/valuation/mod.rs b/crates/moon-core/src/db/valuation/mod.rs index 3813f3bd9..e8c180ed0 100644 --- a/crates/moon-core/src/db/valuation/mod.rs +++ b/crates/moon-core/src/db/valuation/mod.rs @@ -1132,10 +1132,10 @@ fn retire_live_family(files: &[PathBuf; 3], pending: &Path) -> std::io::Result<( } for path in files { if path.try_exists()? { - return Err(std::io::Error::new( - std::io::ErrorKind::Other, - format!("live valuation member remains: {}", path.display()), - )); + return Err(std::io::Error::other(format!( + "live valuation member remains: {}", + path.display() + ))); } } Ok(()) @@ -1388,7 +1388,7 @@ fn attach_store(conn: &Connection, path: &Path) -> ReadResult { let _lifecycle = CACHE_LIFECYCLE .read() .unwrap_or_else(|poisoned| poisoned.into_inner()); - match std::fs::metadata(&path) { + match std::fs::metadata(path) { Ok(_) => {} Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(false), Err(error) => { diff --git a/crates/moon-core/src/db/valuation/provider.rs b/crates/moon-core/src/db/valuation/provider.rs index 367d11d9a..dc6751848 100644 --- a/crates/moon-core/src/db/valuation/provider.rs +++ b/crates/moon-core/src/db/valuation/provider.rs @@ -146,9 +146,9 @@ impl HttpSpotRateSource { .get("https://data-api.binance.vision/api/v3/klines") .query("symbol", symbol) .query("interval", "1m") - .query("startTime", &start_ms.to_string()) - .query("endTime", &end_ms.to_string()) - .query("limit", &limit.to_string()) + .query("startTime", start_ms.to_string()) + .query("endTime", end_ms.to_string()) + .query("limit", limit.to_string()) .call() .map_err(classify_http_error)?; let status = response.status().as_u16(); @@ -182,9 +182,9 @@ impl HttpSpotRateSource { .query("category", "spot") .query("symbol", symbol) .query("interval", "1") - .query("start", &start_ms.to_string()) - .query("end", &end_ms.to_string()) - .query("limit", &limit.to_string()) + .query("start", start_ms.to_string()) + .query("end", end_ms.to_string()) + .query("limit", limit.to_string()) .call() .map_err(classify_http_error)?; let status = response.status().as_u16(); diff --git a/crates/moon-core/src/feed/live/mod.rs b/crates/moon-core/src/feed/live/mod.rs index a97a85e1d..751567eaa 100644 --- a/crates/moon-core/src/feed/live/mod.rs +++ b/crates/moon-core/src/feed/live/mod.rs @@ -2701,11 +2701,10 @@ pub(super) fn run( // Do NOT copy market data here. The feed only signals that the provider has a fresh // read-model snapshot; the visible chart pulls the markets it needs itself. - if !dirty_markets.is_empty() { - if tx.send(FeedMsg::MarketDataChanged(dirty_markets)).is_err() { - let _ = client.disconnect(); - return Ok(()); - } + if !dirty_markets.is_empty() && tx.send(FeedMsg::MarketDataChanged(dirty_markets)).is_err() + { + let _ = client.disconnect(); + return Ok(()); } force_market_sample = false; diff --git a/crates/moon-core/src/market/candles.rs b/crates/moon-core/src/market/candles.rs index e25fcf7f3..018b5bfe4 100644 --- a/crates/moon-core/src/market/candles.rs +++ b/crates/moon-core/src/market/candles.rs @@ -1321,9 +1321,7 @@ impl CandleSeries { // Buckets from here on are ours to accumulate into; earlier ones keep a base candle whose // volume is already complete. See `push_trades`. self.live_from = local - .iter() - .skip(usize::from(skip_partial_first)) - .next() + .get(usize::from(skip_partial_first)) .map_or(f64::INFINITY, |c| c.t_open_ms); local.clear(); diff --git a/crates/moon-core/src/market/kline_cache.rs b/crates/moon-core/src/market/kline_cache.rs index 5e1b20c18..53df65e79 100644 --- a/crates/moon-core/src/market/kline_cache.rs +++ b/crates/moon-core/src/market/kline_cache.rs @@ -697,7 +697,7 @@ fn upsert_one( } } for r in day_rows { - merged.insert((r.t_open_ms as i64 - day_start) as u32, r.clone()); + merged.insert((r.t_open_ms as i64 - day_start) as u32, *r); } let blob = pack_rows_v2(merged.values(), day_start); conn.execute( diff --git a/crates/moon-core/src/market/kline_cache/tests.rs b/crates/moon-core/src/market/kline_cache/tests.rs index bcdb63a4c..60b32bc82 100644 --- a/crates/moon-core/src/market/kline_cache/tests.rs +++ b/crates/moon-core/src/market/kline_cache/tests.rs @@ -202,7 +202,7 @@ fn retention_removes_expired_rows_from_both_cache_tables() { #[test] fn pack_unpack_roundtrip() { let day_start = 19_000i64 * DAY_MS; - let rows = vec![ + let rows = [ candle(day_start as f64, 5.0), candle((day_start + 60_000) as f64, 6.0), ]; diff --git a/crates/moon-core/src/market/source/history.rs b/crates/moon-core/src/market/source/history.rs index 9c195691e..5e7537090 100644 --- a/crates/moon-core/src/market/source/history.rs +++ b/crates/moon-core/src/market/source/history.rs @@ -446,7 +446,7 @@ impl MarketDataSource { let zone_unbounded = candle_params.is_some_and(|cp| { cp.trades_from_rel_ms == crate::market::candles::TRADES_FROM_UNBOUNDED }); - let display_trades = candle_params.map_or(true, |cp| cp.trades_from_rel_ms.is_finite()); + let display_trades = candle_params.is_none_or(|cp| cp.trades_from_rel_ms.is_finite()); let trades_from_rel = if zone_unbounded { crate::market::candles::TRADES_FROM_UNBOUNDED } else { @@ -718,15 +718,14 @@ impl MarketDataSource { subscribed: false, }, ); - if !entry.subscribed || entry.kind_min != deep_kind_min { - if client + if (!entry.subscribed || entry.kind_min != deep_kind_min) + && client .streams() .subscribe_candles([market], deep_kind) .is_ok() - { - entry.subscribed = true; - entry.kind_min = deep_kind_min; - } + { + entry.subscribed = true; + entry.kind_min = deep_kind_min; } entry.last_want = now_i; } @@ -783,7 +782,7 @@ impl MarketDataSource { let native_kind = deep_history_kind(native_kind_min); let have_native = snapshot .tf_candles(market, native_kind) - .map_or(false, |r| !r.is_empty()); + .is_some_and(|r| !r.is_empty()); let cache_covers = cursor.cache_rows_kind == native_kind_min && cursor.cache_rows.len() >= 30; if !have_native && !cache_covers { @@ -865,7 +864,7 @@ impl MarketDataSource { crate::market::candles::bucket_open_ms(now_unix_ms, base_tf_native_ms); let deep_stale = rows .and_then(|r| r.last()) - .map_or(true, |r| (r.unix_millis() as f64) < cur_bucket_ms); + .is_none_or(|r| (r.unix_millis() as f64) < cur_bucket_ms); let kind_changed = cursor.last_deep_kind != Some(deep_kind); let retry_delay = Duration::from_secs(cursor.deep_retry_delay_s.max(HISTORY_RETRY_MIN_S) as u64); @@ -873,7 +872,7 @@ impl MarketDataSource { && (kind_changed || cursor .last_deep_request - .map_or(true, |t| t.elapsed() > retry_delay)) + .is_none_or(|t| t.elapsed() > retry_delay)) { cursor.last_deep_request = Some(Instant::now()); cursor.last_deep_kind = Some(deep_kind); @@ -1069,19 +1068,18 @@ impl MarketDataSource { times.last().copied().unwrap_or(i64::MIN); cursor.cache_written_len = times.len(); } - (Some(_), None) => { + (Some(_), None) // The provider exchange identity is unavailable, so the cache cannot // address these rows. Make this visible in the log once per panel. Keep // the real signature unchanged, but use the initial marker to suppress // repeated logging. - if cursor.cache_written_sig == 0 { + if cursor.cache_written_sig == 0 => { cursor.cache_written_sig = 1; log::warn!( "kline cache: провайдер {provider} без ExchangeId — \ ряды {market} не кэшируются" ); } - } _ => {} } } @@ -1236,10 +1234,10 @@ impl MarketDataSource { .unwrap_or(0.0); let warn_due = cursor .last_gap_diag - .map_or(true, |t| t.elapsed() > Duration::from_secs(30)); + .is_none_or(|t| t.elapsed() > Duration::from_secs(30)); let scan_due = cursor .last_gap_scan - .map_or(true, |t| t.elapsed() > Duration::from_secs(30)); + .is_none_or(|t| t.elapsed() > Duration::from_secs(30)); // Detect gaps inside the sequence where the next candle begins after the previous // one ends. This is where the scroll-to-history then return-to-live gap was hidden. let mut max_hole = 0.0f64; @@ -1546,7 +1544,7 @@ pub(crate) fn deep_writeback_start( if !same_key || since_full >= DEEP_FULL_WRITEBACK_EVERY || written_last == i64::MIN - || times.first().map_or(true, |f| *f < written_first) + || times.first().is_none_or(|f| *f < written_first) || times.len() < written_len { 0 @@ -1679,9 +1677,9 @@ pub(crate) fn poll_cache_prefix( cursor.cache_want_from = Some(want_from); // A read that did not happen must not be remembered as a completed one; retry it, but no more // often than every `CACHE_RETRY_MS` so a busy worker is not asked again on every frame. - let retry_due = cursor.cache_retry_at.map_or(true, |t| { - t.elapsed() >= Duration::from_millis(CACHE_RETRY_MS) - }); + let retry_due = cursor + .cache_retry_at + .is_none_or(|t| t.elapsed() >= Duration::from_millis(CACHE_RETRY_MS)); if cursor.cache_pending.is_some() || !retry_due { return; } diff --git a/crates/moon-core/src/market/source/read.rs b/crates/moon-core/src/market/source/read.rs index 7df82fae3..6ca57d8fc 100644 --- a/crates/moon-core/src/market/source/read.rs +++ b/crates/moon-core/src/market/source/read.rs @@ -662,7 +662,7 @@ impl MarketDataSource { out.mark = m .price .mark_price_found - .then(|| m.price.mark_price) + .then_some(m.price.mark_price) .and_then(positive); out.price_step = positive(m.price.chart_price_step); out.vol_24h = positive(m.volume); diff --git a/crates/moon-core/src/market/trade_replay/rest/okx/tests.rs b/crates/moon-core/src/market/trade_replay/rest/okx/tests.rs index ce261092f..86ddc72c0 100644 --- a/crates/moon-core/src/market/trade_replay/rest/okx/tests.rs +++ b/crates/moon-core/src/market/trade_replay/rest/okx/tests.rs @@ -66,7 +66,7 @@ fn okx_uses_the_market_specific_base_volume_cell() { let spot = parse_klines(&fixture("spot"), SPOT_VOLUME_CELL).expect("spot fixture parses"); let swap = parse_klines(&fixture("swap"), SWAP_VOLUME_CELL).expect("swap fixture parses"); - assert!((spot[0].volume - 10.030_456_94).abs() < 0.000_01); + assert!((spot[0].volume - 10.030_457).abs() < 0.000_01); assert!((swap[0].volume - 144.84).abs() < 0.001); assert!( swap[0].volume < 1_000.0, diff --git a/crates/moon-core/src/strat_db/stats.rs b/crates/moon-core/src/strat_db/stats.rs index 54638621f..af8208ba2 100644 --- a/crates/moon-core/src/strat_db/stats.rs +++ b/crates/moon-core/src/strat_db/stats.rs @@ -417,7 +417,7 @@ pub fn deleted_heads() -> Vec { )) else { return Vec::new(); }; - stmt.query_map([], |r| head_from_row(r)) + stmt.query_map([], head_from_row) .map(|rows| rows.flatten().collect()) .unwrap_or_default() } @@ -446,7 +446,7 @@ pub fn head_row(core_uid: u64, strategy_id: i64) -> Option { conn.query_row( &format!("SELECT {HEAD_COLS} FROM strategies WHERE core_uid=?1 AND strategy_id=?2"), rusqlite::params![core_uid as i64, strategy_id], - |r| head_from_row(r), + head_from_row, ) .optional() .ok() diff --git a/crates/moon-core/src/telegram/init_data.rs b/crates/moon-core/src/telegram/init_data.rs index fe926a8e2..9fe4e2b95 100644 --- a/crates/moon-core/src/telegram/init_data.rs +++ b/crates/moon-core/src/telegram/init_data.rs @@ -241,7 +241,7 @@ pub fn authorize_paired_identity( authorized_chat_ids: &[i64], ) -> Result { let chat_id = signed.pairing_chat_id(); - if authorized_chat_ids.iter().any(|id| *id == chat_id) { + if authorized_chat_ids.contains(&chat_id) { Ok(chat_id) } else { Err(InitDataError::Unpaired) diff --git a/crates/moon-core/src/telegram/report/tests.rs b/crates/moon-core/src/telegram/report/tests.rs index ad578e947..c1c232d76 100644 --- a/crates/moon-core/src/telegram/report/tests.rs +++ b/crates/moon-core/src/telegram/report/tests.rs @@ -25,11 +25,10 @@ fn callback_exchange_list_flag_defaults_to_collapsed() { let mut request = ReportRequest::new(Period::Today, false); assert!(!request.exchanges_open); assert_eq!(request.callback(), "r:e:t:0"); - assert_eq!( - ReportRequest::parse_callback("r:e:t:0") + assert!( + !ReportRequest::parse_callback("r:e:t:0") .unwrap() - .exchanges_open, - false + .exchanges_open ); request.exchanges_open = true; assert_eq!(request.callback(), "r:ek:t:0"); diff --git a/crates/moon-core/src/telegram/web.rs b/crates/moon-core/src/telegram/web.rs index 437b8e5de..7009c396f 100644 --- a/crates/moon-core/src/telegram/web.rs +++ b/crates/moon-core/src/telegram/web.rs @@ -254,7 +254,7 @@ impl App { ) && request.uri().path().starts_with("/api/") { status_response(StatusCode::NOT_FOUND, "not_found") - } else if request.method() != &Method::GET { + } else if request.method() != Method::GET { status_response(StatusCode::METHOD_NOT_ALLOWED, "method") } else { status_response(StatusCode::NOT_FOUND, "not_found") diff --git a/crates/moon-core/src/update/discovery.rs b/crates/moon-core/src/update/discovery.rs index fdef0eebb..310d1e778 100644 --- a/crates/moon-core/src/update/discovery.rs +++ b/crates/moon-core/src/update/discovery.rs @@ -195,14 +195,12 @@ impl ReleaseDiscovery { let page_two_due = staged[1].is_none() || first_changed || now_unix >= self.page_two_refresh_at; - if page_two_due && first_low { - if first_changed || staged[1].is_none() { - return Err(DiscoveryError::new( - DiscoveryRetry::RateLimited, - defer_until, - anyhow!("GitHub release scan deferred before its required second page"), - )); - } + if page_two_due && first_low && (first_changed || staged[1].is_none()) { + return Err(DiscoveryError::new( + DiscoveryRetry::RateLimited, + defer_until, + anyhow!("GitHub release scan deferred before its required second page"), + )); } let mut next_page_two_refresh_at = self.page_two_refresh_at; if page_two_due && !first_low { diff --git a/crates/moon-ui-gpui/build.rs b/crates/moon-ui-gpui/build.rs index b6f4c185b..e503a3496 100644 --- a/crates/moon-ui-gpui/build.rs +++ b/crates/moon-ui-gpui/build.rs @@ -69,15 +69,14 @@ fn embed_group_icons() -> std::io::Result<()> { let mut ids: Vec = Vec::new(); for entry in std::fs::read_dir(dir)? { let path = entry?.path(); - if path.extension().and_then(|s| s.to_str()) == Some("png") { - if let Some(id) = path + if path.extension().and_then(|s| s.to_str()) == Some("png") + && let Some(id) = path .file_stem() .and_then(|s| s.to_str()) .and_then(|s| s.parse::().ok()) - { - ids.push(id); - max_id = max_id.max(id); - } + { + ids.push(id); + max_id = max_id.max(id); } } let mut present = vec![false; max_id + 1]; diff --git a/crates/moon-ui-gpui/src/analytics/bg.rs b/crates/moon-ui-gpui/src/analytics/bg.rs index 8774b3eeb..e60f36137 100644 --- a/crates/moon-ui-gpui/src/analytics/bg.rs +++ b/crates/moon-ui-gpui/src/analytics/bg.rs @@ -203,7 +203,7 @@ impl AnalyticsView { } cx.spawn(async move |this, cx| { let result = cx.background_spawn(async move { db() }).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.db_ops = this.db_ops.saturating_sub(1); store(this, result, cx); @@ -243,7 +243,7 @@ impl AnalyticsView { let result = cx .background_spawn(async move { with_read_cancellation(worker_cancellation, db) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.latest_reads.finish(&cancellation); this.db_ops = this.db_ops.saturating_sub(1); diff --git a/crates/moon-ui-gpui/src/analytics/bg/tests.rs b/crates/moon-ui-gpui/src/analytics/bg/tests.rs index 5b4c70d86..d2fa3c622 100644 --- a/crates/moon-ui-gpui/src/analytics/bg/tests.rs +++ b/crates/moon-ui-gpui/src/analytics/bg/tests.rs @@ -62,8 +62,8 @@ fn stale_completion_preserves_newer_lane_owner() { fn dropping_the_registry_cancels_detached_requests() { let token = { let mut reads = LatestReads::default(); - let token = reads.replace(&[ReadLane::Summary]); - token + + reads.replace(&[ReadLane::Summary]) }; assert!(token.is_cancelled()); diff --git a/crates/moon-ui-gpui/src/analytics/calendar/day.rs b/crates/moon-ui-gpui/src/analytics/calendar/day.rs index b2fd9a7c9..3cb914bae 100644 --- a/crates/moon-ui-gpui/src/analytics/calendar/day.rs +++ b/crates/moon-ui-gpui/src/analytics/calendar/day.rs @@ -193,12 +193,11 @@ impl AnalyticsView { for h in 0..24usize { if let Some(c) = hour_start(d, h as u32, self.bound_zone()).and_then(|start| map.get(&start)) + && c.has_activity() { - if c.has_activity() { - hour_max = hour_max.max(c.totals.profit.abs()); - hour_sum[h] += c.totals.profit; - hour_cnt[h] += 1; - } + hour_max = hour_max.max(c.totals.profit.abs()); + hour_sum[h] += c.totals.profit; + hour_cnt[h] += 1; } } let next = next_day(d, self.bound_zone()); diff --git a/crates/moon-ui-gpui/src/analytics/calendar/mod.rs b/crates/moon-ui-gpui/src/analytics/calendar/mod.rs index a40ad13e1..270c7ab7d 100644 --- a/crates/moon-ui-gpui/src/analytics/calendar/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/calendar/mod.rs @@ -480,14 +480,14 @@ impl AnalyticsView { .into_any_element(); } }; - if self.cal_mode == CalMode::Month { - if let Err(note) = self.cal_prev.view(|_| false) { - return v_flex() - .size_full() - .child(self.cal_nav(p, cx)) - .child(note_el("analytics-calendar-prev-read", note, 18.0, p, cx)) - .into_any_element(); - } + if self.cal_mode == CalMode::Month + && let Err(note) = self.cal_prev.view(|_| false) + { + return v_flex() + .size_full() + .child(self.cal_nav(p, cx)) + .child(note_el("analytics-calendar-prev-read", note, 18.0, p, cx)) + .into_any_element(); }; // Frame: the nav bar (like Summary's period bar) + the mode's content. let content = match self.cal_mode { diff --git a/crates/moon-ui-gpui/src/analytics/mod.rs b/crates/moon-ui-gpui/src/analytics/mod.rs index c4ac9c131..7f28e1cbd 100644 --- a/crates/moon-ui-gpui/src/analytics/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/mod.rs @@ -1353,7 +1353,7 @@ impl AnalyticsView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(wait).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.report_refresh.timer_fired(); this.schedule_report_refresh(cx); @@ -1446,7 +1446,7 @@ impl AnalyticsView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(wait).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.core_refresh_timer_armed = false; if !this.core_refresh_needed { @@ -1617,7 +1617,7 @@ impl AnalyticsView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(BUSY_OVERLAY_DELAY).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { // Detached timers outlive their batches, so match the captured start time // before repainting; a later batch has its own delay and timer. @@ -2344,13 +2344,12 @@ pub fn open( owner_display: Option, cx: &mut App, ) { - if let Some(handle) = backend.read(cx).analytics_window { - if handle + if let Some(handle) = backend.read(cx).analytics_window + && handle .update(cx, |_, window, _| window.activate_window()) .is_ok() - { - return; - } + { + return; } let saved = backend.read(cx).layout.analytics_window; let bounds = saved.map_or( diff --git a/crates/moon-ui-gpui/src/analytics/profit_monitor/mod.rs b/crates/moon-ui-gpui/src/analytics/profit_monitor/mod.rs index 1cf647cb5..d8aaff7e9 100644 --- a/crates/moon-ui-gpui/src/analytics/profit_monitor/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/profit_monitor/mod.rs @@ -628,7 +628,7 @@ impl ProfitMonitorView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(wait).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { if this.clock_timer_generation != generation { return; @@ -751,7 +751,7 @@ impl ProfitMonitorView { moon_core::db::analytics::profit_monitor_snapshot(&query) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.db_active = false; if this.seq == request { @@ -842,7 +842,7 @@ impl ProfitMonitorView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(wait).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.refresh.timer_fired(); this.schedule_refresh(cx); diff --git a/crates/moon-ui-gpui/src/analytics/render.rs b/crates/moon-ui-gpui/src/analytics/render.rs index 1f5c0ba15..3c90733e1 100644 --- a/crates/moon-ui-gpui/src/analytics/render.rs +++ b/crates/moon-ui-gpui/src/analytics/render.rs @@ -252,14 +252,14 @@ fn quote_split_note( if coverage.unavailable_orders > 0 { text.push_str(" · "); text.push_str( - &t!( + t!( mode.key( "analytics.quote_valuation_unavailable", "report.valuation_current_unavailable" ), n = coverage.unavailable_orders ) - .to_string(), + .as_ref(), ); } // Without this the ratio above simply stops moving, which reads as a slow backfill @@ -268,13 +268,13 @@ fn quote_split_note( if let Some(facts) = stalled { text.push_str(" · "); text.push_str( - &t!( + t!( "analytics.quote_valuation_stalled", stage = facts.stage, kind = facts.kind, minutes = facts.minutes ) - .to_string(), + .as_ref(), ); } text diff --git a/crates/moon-ui-gpui/src/analytics/summary/charts.rs b/crates/moon-ui-gpui/src/analytics/summary/charts.rs index 95cb1d3cb..a5090d2cd 100644 --- a/crates/moon-ui-gpui/src/analytics/summary/charts.rs +++ b/crates/moon-ui-gpui/src/analytics/summary/charts.rs @@ -364,11 +364,11 @@ pub(super) fn distinct_core_colors( let mut out = vec![None; configured.len()]; let mut taken: Vec = Vec::with_capacity(configured.len()); for &i in &order { - if let Some(c) = configured[i].1.map(rgb) { - if !taken.iter().any(|&t| too_close(t, c)) { - taken.push(c); - out[i] = Some(c); - } + if let Some(c) = configured[i].1.map(rgb) + && !taken.iter().any(|&t| too_close(t, c)) + { + taken.push(c); + out[i] = Some(c); } } // Mid-shade first (index 2 of `SHADES`, the saturated one the picker leads with), then the diff --git a/crates/moon-ui-gpui/src/analytics/summary/cumulative.rs b/crates/moon-ui-gpui/src/analytics/summary/cumulative.rs index bc270bc48..f613b759a 100644 --- a/crates/moon-ui-gpui/src/analytics/summary/cumulative.rs +++ b/crates/moon-ui-gpui/src/analytics/summary/cumulative.rs @@ -91,7 +91,7 @@ pub(super) fn core_legend( let text_w = |s: &str| design::mono_caption_text_width(cx, s, 400.0); // Always keep room for the tail: a row that packs to the last pixel and then discovers it // must say "+3 more" has nowhere to put it. - let tail_w = text_w(&t!("analytics.popup_more", n = order.len()).to_string()) + gap; + let tail_w = text_w(t!("analytics.popup_more", n = order.len()).as_ref()) + gap; let mut used = 0.0; let mut shown = 0usize; for &ci in &order { diff --git a/crates/moon-ui-gpui/src/analytics/summary/mod.rs b/crates/moon-ui-gpui/src/analytics/summary/mod.rs index 0f713f549..41b9d6a73 100644 --- a/crates/moon-ui-gpui/src/analytics/summary/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/summary/mod.rs @@ -447,7 +447,7 @@ impl AnalyticsView { /// Row of KPI tiles with deltas against the previous period. fn kpi_row(&self, d: &Summary, p: MoonPalette, cx: &Context) -> impl IntoElement { let (cur, prev) = (&d.cur, &d.prev); - let profit_el = colored_value(p, cur.profit, format!("{}", fmt_signed(cur.profit))); + let profit_el = colored_value(p, cur.profit, fmt_signed(cur.profit).to_string()); let dd_el = div() .text_color(moon(p.orange)) .child(format!( diff --git a/crates/moon-ui-gpui/src/analytics/toolbar.rs b/crates/moon-ui-gpui/src/analytics/toolbar.rs index 363a8eaf1..6d3fc981c 100644 --- a/crates/moon-ui-gpui/src/analytics/toolbar.rs +++ b/crates/moon-ui-gpui/src/analytics/toolbar.rs @@ -739,7 +739,7 @@ impl AnalyticsView { crate::controls::core_combo( "an-core", &cores, - &venues, + venues, &selected, crate::controls::CoreAllRowMode::ImplicitOnly, all_label, @@ -915,7 +915,7 @@ impl AnalyticsView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(wait).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.integrity_poll_armed = false; cx.notify(); diff --git a/crates/moon-ui-gpui/src/analytics/tuner/coins/load.rs b/crates/moon-ui-gpui/src/analytics/tuner/coins/load.rs index 4b54c1f29..5bd753c68 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/coins/load.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/coins/load.rs @@ -308,7 +308,7 @@ impl AnalyticsView { self.coins.kpi_task = Some(cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(KPI_DEBOUNCE).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { // A later edit landed during the wait — that one owns the recompute. if this.coins.kpi_seq == req { diff --git a/crates/moon-ui-gpui/src/analytics/tuner/coins/save.rs b/crates/moon-ui-gpui/src/analytics/tuner/coins/save.rs index 06f6bcfe6..a20b04c37 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/coins/save.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/coins/save.rs @@ -169,7 +169,7 @@ impl AnalyticsView { (targets, live, unresolved) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { 'completion: { let now: Vec<(i64, Option)> = this @@ -245,11 +245,9 @@ impl AnalyticsView { let empties = per_target.iter().any(|v| { v.iter().any(|(k, val)| k == key && val.trim().is_empty()) }); - if empties { - if let Some(Some(note)) = notes.get_mut(i) { - note.push_str(" · "); - note.push_str(&t!("analytics.tuner.save_clears")); - } + if empties && let Some(Some(note)) = notes.get_mut(i) { + note.push_str(" · "); + note.push_str(&t!("analytics.tuner.save_clears")); } } let mut warns = Vec::new(); diff --git a/crates/moon-ui-gpui/src/analytics/tuner/save.rs b/crates/moon-ui-gpui/src/analytics/tuner/save.rs index 58bbb4e9f..bc62fe11e 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/save.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/save.rs @@ -326,10 +326,10 @@ impl AnalyticsView { } // In Classic, a missing target core applies the copy to every core containing the // strategy; Auto rejects that legacy aggregate target before reaching this loop. - if let Some(tc) = target_core { - if cid != tc { - continue; - } + if let Some(tc) = target_core + && cid != tc + { + continue; } let Some(row) = cd.strategies.iter().find(|r| r.id == sid) else { continue; @@ -807,32 +807,32 @@ impl AnalyticsView { }; let mut list = v_flex().w_full().gap_0(); // Copy dialog: the editable name of the new strategy as the first row. - if dlg.copy { - if let Some(input) = self.tuner.inputs.get("copy-name") { - list = list.child( - h_flex() - .w_full() - .px(design::ui_px(cx, 10.0)) - .py(design::ui_px(cx, 5.0)) - .gap(design::ui_px(cx, 8.0)) - .items_center() - .child( - div() - .flex_none() - .font_family(design::ui_font()) - .text_size(design::t_caption(cx)) - .text_color(moon(p.text_muted)) - .child(t!("analytics.tuner.copy_name_lbl").to_string()), - ) - .child( - div().flex_1().min_w_0().child( - MoonInput::new("tun-copy-name") - .state(input) - .size(design::INPUT_SIZE), - ), + if dlg.copy + && let Some(input) = self.tuner.inputs.get("copy-name") + { + list = list.child( + h_flex() + .w_full() + .px(design::ui_px(cx, 10.0)) + .py(design::ui_px(cx, 5.0)) + .gap(design::ui_px(cx, 8.0)) + .items_center() + .child( + div() + .flex_none() + .font_family(design::ui_font()) + .text_size(design::t_caption(cx)) + .text_color(moon(p.text_muted)) + .child(t!("analytics.tuner.copy_name_lbl").to_string()), + ) + .child( + div().flex_1().min_w_0().child( + MoonInput::new("tun-copy-name") + .state(input) + .size(design::INPUT_SIZE), ), - ); - } + ), + ); } // Bulk: name the strategies that will be written — some may be filtered out of the list, // and the count-only title would otherwise let a hidden target be written unseen. diff --git a/crates/moon-ui-gpui/src/backend/figures.rs b/crates/moon-ui-gpui/src/backend/figures.rs index 89dccc0b1..295b039e0 100644 --- a/crates/moon-ui-gpui/src/backend/figures.rs +++ b/crates/moon-ui-gpui/src/backend/figures.rs @@ -220,11 +220,11 @@ impl Backend { /// Sets the core's default Alerts-strategy ID. A changed value marks the configuration for the /// coordination loop's routine save; an unknown core or unchanged value is ignored. pub(crate) fn set_alert_def_strategy(&mut self, core: CoreId, strategy_id: u64) { - if let Some(s) = self.config.servers.iter_mut().find(|s| s.id == core) { - if s.default_alert_strategy != strategy_id { - s.default_alert_strategy = strategy_id; - self.config_dirty = true; - } + if let Some(s) = self.config.servers.iter_mut().find(|s| s.id == core) + && s.default_alert_strategy != strategy_id + { + s.default_alert_strategy = strategy_id; + self.config_dirty = true; } } @@ -344,12 +344,12 @@ impl Backend { /// is cleared even if the figure was already absent; command-send errors are ignored. pub(crate) fn remove_figure(&mut self, core: CoreId, market: &str, id: u64) { let removed = self.figures.borrow_mut().remove(core, market, id); - if let Some(fig) = removed { - if fig.alert { - let _ = self - .session - .chart_alert_delete(core, market.to_string(), id); - } + if let Some(fig) = removed + && fig.alert + { + let _ = self + .session + .chart_alert_delete(core, market.to_string(), id); } if self .fig_selected diff --git a/crates/moon-ui-gpui/src/backend/mod.rs b/crates/moon-ui-gpui/src/backend/mod.rs index 168ef6691..0e76f2d0f 100644 --- a/crates/moon-ui-gpui/src/backend/mod.rs +++ b/crates/moon-ui-gpui/src/backend/mod.rs @@ -420,7 +420,7 @@ impl Backend { &self, group: &str, ) -> Option<&(CoreId, String)> { - (self.current_open_main_group().as_deref() == Some(group)) + (self.current_open_main_group() == Some(group)) .then_some(()) .and(self.open_main_request.pending_target()) } @@ -433,7 +433,7 @@ impl Backend { /// Returns: /// Request revision when the pending core currently belongs to `group`, otherwise zero. pub(crate) fn pending_open_main_revision_for_group(&self, group: &str) -> u64 { - if self.current_open_main_group().as_deref() == Some(group) { + if self.current_open_main_group() == Some(group) { self.open_main_request.revision() } else { 0 @@ -1792,12 +1792,11 @@ impl Backend { /// /// `force` recomputes immediately when sorting changes the first core. pub(crate) fn refresh_header_ticker_default(&mut self, force: bool) { - if !force { - if let Some((core, _)) = &self.header_ticker_default { - if self.session.sessions().iter().any(|s| s.id == *core) { - return; - } - } + if !force + && let Some((core, _)) = &self.header_ticker_default + && self.session.sessions().iter().any(|s| s.id == *core) + { + return; } let now = Instant::now(); if !force @@ -1829,12 +1828,11 @@ impl Backend { /// otherwise the precomputed default cache is returned. Rendering neither searches markets nor /// mutates the backend. pub(crate) fn header_ticker(&self) -> Option<(CoreId, String)> { - if let Some(sel) = &self.layout.header_ticker { - if let Some(core) = self.core_of_uid(sel.core_uid) { - if self.session.sessions().iter().any(|s| s.id == core) { - return Some((core, sel.market.clone())); - } - } + if let Some(sel) = &self.layout.header_ticker + && let Some(core) = self.core_of_uid(sel.core_uid) + && self.session.sessions().iter().any(|s| s.id == core) + { + return Some((core, sel.market.clone())); } self.header_ticker_default .as_ref() @@ -2232,16 +2230,15 @@ impl Backend { } fn chart_text_market_for(&self, core: CoreId) -> Option { - if let Some(last) = self.chart_text_last.get(&core) { - if self + if let Some(last) = self.chart_text_last.get(&core) + && self .chart_text_refs .get(&(core, last.clone())) .copied() .unwrap_or(0) > 0 - { - return Some(last.clone()); - } + { + return Some(last.clone()); } self.chart_text_refs .iter() @@ -2323,7 +2320,8 @@ impl Backend { let mut want: Vec<(CoreId, String)> = self .chart_orderbook_refs .iter() - .filter_map(|((core, market), count)| (*count > 0).then(|| (*core, market.clone()))) + .filter(|&((_core, _market), count)| *count > 0) + .map(|((core, market), _count)| (*core, market.clone())) .collect(); want.sort_unstable_by(|a, b| a.0.cmp(&b.0).then_with(|| a.1.cmp(&b.1))); if self.desired_orderbook != want { @@ -2336,7 +2334,8 @@ impl Backend { let mut desired: Vec<(CoreId, String)> = self .chart_market_refs .iter() - .filter_map(|((core, market), count)| (*count > 0).then(|| (*core, market.clone()))) + .filter(|&((_core, _market), count)| *count > 0) + .map(|((core, market), _count)| (*core, market.clone())) .collect(); desired.sort_unstable_by(|a, b| a.0.cmp(&b.0).then_with(|| a.1.cmp(&b.1))); if self.desired != desired { @@ -2454,10 +2453,10 @@ impl Backend { // trimming — `warn_last_prune_ms == 0` fires it on the first tick. if now_ms - self.warn_last_prune_ms >= WARN_PRUNE_INTERVAL_MS { self.warn_last_prune_ms = now_ms; - if let Some(store) = self.warn_store.as_ref() { - if let Err(err) = store.prune_slices(now_ms - WARN_SLICE_RETENTION_MS) { - log::warn!("core warning slice prune failed: {err}"); - } + if let Some(store) = self.warn_store.as_ref() + && let Err(err) = store.prune_slices(now_ms - WARN_SLICE_RETENTION_MS) + { + log::warn!("core warning slice prune failed: {err}"); } } // Persist each closed episode plus its full topology (collect the follow-up re-captures into a diff --git a/crates/moon-ui-gpui/src/backend/telegram.rs b/crates/moon-ui-gpui/src/backend/telegram.rs index c52afbfc7..53bc0c18b 100644 --- a/crates/moon-ui-gpui/src/backend/telegram.rs +++ b/crates/moon-ui-gpui/src/backend/telegram.rs @@ -198,12 +198,12 @@ impl Backend { if self.telegram.service.is_none() { return; } - if self.telegram.configuration_pending { - if let Some(service) = self.telegram.service.as_ref() { - let configured = service.configure(&self.config.telegram); - let localized = service.set_labels(telegram_labels()); - self.telegram.configuration_pending = !configured || !localized; - } + if self.telegram.configuration_pending + && let Some(service) = self.telegram.service.as_ref() + { + let configured = service.configure(&self.config.telegram); + let localized = service.set_labels(telegram_labels()); + self.telegram.configuration_pending = !configured || !localized; } let mut changed = false; for _ in 0..64 { @@ -228,10 +228,11 @@ impl Backend { let saved = candidate.save_telegram().is_ok(); if saved { self.config = candidate; - if newly_paired && let Some(preview) = self.preview.as_mut() { - if !preview.telegram.authorized_chat_ids.contains(&chat_id) { - preview.telegram.authorized_chat_ids.push(chat_id); - } + if newly_paired + && let Some(preview) = self.preview.as_mut() + && !preview.telegram.authorized_chat_ids.contains(&chat_id) + { + preview.telegram.authorized_chat_ids.push(chat_id); } if let Some(service) = self.telegram.service.as_ref() { self.telegram.configuration_pending |= diff --git a/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs b/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs index 9d9d57404..0c5dd9fae 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs @@ -656,20 +656,21 @@ impl AddChartStack { // In COMPRESS mode, automatic AddToChart tabs place a new chart in the FIRST retained empty // slot without moving or resizing neighbors. Custom tabs set `hold_vacated = false` and do // not use this path. - if compress && self.hold_vacated { - if let Some(i) = self.charts.iter().position(|e| e.vacated) { - self.charts[i].core = core; - self.charts[i].market = market.to_string(); - self.charts[i].arrived_at = Instant::now(); - self.charts[i].vacated = false; - self.charts[i].owner = owner; - self.touch_count_change(); // A chart reused an empty slot; reset the debounce. - self.flash_arrival(i, cx); - let panel = self.charts[i].panel.clone(); - Self::show_market_with_history(&panel, core, market, ttl_ms, cx); - cx.notify(); - return; - } + if compress + && self.hold_vacated + && let Some(i) = self.charts.iter().position(|e| e.vacated) + { + self.charts[i].core = core; + self.charts[i].market = market.to_string(); + self.charts[i].arrived_at = Instant::now(); + self.charts[i].vacated = false; + self.charts[i].owner = owner; + self.touch_count_change(); // A chart reused an empty slot; reset the debounce. + self.flash_arrival(i, cx); + let panel = self.charts[i].panel.clone(); + Self::show_market_with_history(&panel, core, market, ttl_ms, cx); + cx.notify(); + return; } // Append a new chart; render sorting raises pinned charts in FIT-stretch mode. @@ -964,10 +965,8 @@ impl AddChartStack { for e in &self.charts { e.panel.update(cx, |p, pcx| { p.set_default_x_ppm(ppm); - if apply { - if let Some(v) = ppm { - p.apply_x_ppm(v, pcx); - } + if apply && let Some(v) = ppm { + p.apply_x_ppm(v, pcx); } }); } diff --git a/crates/moon-ui-gpui/src/chart_tabs/apply_all/tests.rs b/crates/moon-ui-gpui/src/chart_tabs/apply_all/tests.rs index 02d63d842..55cd75b14 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/apply_all/tests.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/apply_all/tests.rs @@ -82,7 +82,7 @@ fn an_empty_target_set_addresses_nothing() { /// to store a value that has nowhere to be stored — and cannot perform a press another popup armed. #[test] fn only_values_that_have_a_default_can_become_one() { - let storable = vec![StackSetting::CandleView(CandleViewCfg::default())]; + let storable = [StackSetting::CandleView(CandleViewCfg::default())]; assert!(storable.iter().all(|v| v.global_slot().is_some())); let layout = layout_values( &loud_snapshot(), diff --git a/crates/moon-ui-gpui/src/chart_tabs/custom.rs b/crates/moon-ui-gpui/src/chart_tabs/custom.rs index be6f21e9c..996d88f3c 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/custom.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/custom.rs @@ -651,7 +651,7 @@ impl ChartTabs { specs .iter() .find(|s| s.matches(&self.group, num, bucket)) - .map_or(true, |s| { + .is_none_or(|s| { s.custom_coins.as_deref() != Some(coins.as_slice()) || s.compare_anchor != anchor || s.compare_orderbook_only != broom @@ -669,12 +669,12 @@ impl ChartTabs { /// Re-persist the active custom tab's tickers after its composition changes. pub(super) fn persist_custom_active(&mut self, cx: &mut Context) { - if let Tab::Custom(n, b) = self.active.clone() { - if let Some(stack) = self.add_stack(n, &b) { - let coins = stack.read(cx).coins(cx); - let label = self.custom_label(n); - self.persist_custom(cx, n, &b, &coins, &label); - } + if let Tab::Custom(n, b) = self.active.clone() + && let Some(stack) = self.add_stack(n, &b) + { + let coins = stack.read(cx).coins(cx); + let label = self.custom_label(n); + self.persist_custom(cx, n, &b, &coins, &label); } } @@ -867,7 +867,7 @@ impl ChartTabs { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(Duration::from_secs(5)).await; - let _ = cx.update(|cx| { + cx.update(|cx| { this.update(cx, |this, cx| { // Is the timer still current, with the tab still inactive in the strip? let still = this.custom_gate_gen.get(&n) == Some(&want_gen) diff --git a/crates/moon-ui-gpui/src/chart_tabs/detached_host/mod.rs b/crates/moon-ui-gpui/src/chart_tabs/detached_host/mod.rs index e7a7a6c84..afd444c5d 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/detached_host/mod.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/detached_host/mod.rs @@ -218,7 +218,7 @@ impl DetachedChartHost { // Restore this detached panel's saved per-tab display settings from charts.json. let (group2, num2, bucket2) = (group.clone(), num, bucket.clone()); let saved = backend.read(cx).chart_specs.iter().find_map(|s| { - s.matches(&group2, num2, &bucket2).then(|| { + s.matches(&group2, num2, &bucket2).then_some({ ( s.layout_mode, s.layout_height_fit, @@ -555,7 +555,8 @@ impl DetachedChartHost { cx: &mut Context, ) -> bool { use crate::hotkeys::HotkeyAction; - let handled = match action { + + match action { // Resolved against THIS window's own hover trail, exactly as in the group window: a // detached host owns a stack rather than a single chart, so it names no panel either. HotkeyAction::ChartShot => { @@ -629,8 +630,7 @@ impl DetachedChartHost { crate::hotkeys::apply(other, b, bcx, &self.group, target.clone(), active_core) }) } - }; - handled + } } /// Return whether this window is a detached Custom tab whose spec has `custom_coins`. @@ -739,16 +739,14 @@ impl DetachedChartHost { .chart_specs .iter_mut() .find(|s| s.matches(&group, num, &bucket)) - { - if s.custom_coins.as_deref() != Some(coins.as_slice()) + && (s.custom_coins.as_deref() != Some(coins.as_slice()) || s.compare_anchor != anchor - || s.compare_orderbook_only != broom - { - s.custom_coins = Some(coins); - s.compare_anchor = anchor; - s.compare_orderbook_only = broom; - b.chart_specs_dirty = true; - } + || s.compare_orderbook_only != broom) + { + s.custom_coins = Some(coins); + s.compare_anchor = anchor; + s.compare_orderbook_only = broom; + b.chart_specs_dirty = true; } }); } diff --git a/crates/moon-ui-gpui/src/chart_tabs/detached_host/render.rs b/crates/moon-ui-gpui/src/chart_tabs/detached_host/render.rs index 52e6da64d..1362e1943 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/detached_host/render.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/detached_host/render.rs @@ -45,21 +45,21 @@ impl Render for DetachedChartHost { }; if rev != self.last_x_sync_rev { self.last_x_sync_rev = rev; - if let Some((handle, ppm)) = req { - if handle == window.window_handle() { - self.panel - .update(cx, |s, c| s.set_x_ppm(Some(ppm), true, c)); - let backend = self.backend.clone(); - let (num, bucket) = (self.num, self.bucket.clone()); - common::upsert_spec( - &backend, - &self.group.clone(), - num, - &bucket, - cx, - move |s| s.x_ppm = Some(ppm), - ); - } + if let Some((handle, ppm)) = req + && handle == window.window_handle() + { + self.panel + .update(cx, |s, c| s.set_x_ppm(Some(ppm), true, c)); + let backend = self.backend.clone(); + let (num, bucket) = (self.num, self.bucket.clone()); + common::upsert_spec( + &backend, + &self.group.clone(), + num, + &bucket, + cx, + move |s| s.x_ppm = Some(ppm), + ); } } } diff --git a/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs b/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs index aa615bba3..0203625d8 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/main_stack.rs @@ -912,10 +912,8 @@ impl MainChartStack { for e in &self.charts { e.panel.update(cx, |p, pcx| { p.set_default_x_ppm(ppm); - if apply { - if let Some(v) = ppm { - p.apply_x_ppm(v, pcx); - } + if apply && let Some(v) = ppm { + p.apply_x_ppm(v, pcx); } }); } @@ -1716,11 +1714,11 @@ impl Render for MainChartStack { }; // The body flexes into whatever the row leaves, so the chart loses exactly the row's // height and nothing has to subtract it by hand. - return v_flex() + v_flex() .size_full() .child(tab_row) .child(div().flex_1().w_full().min_h(px(0.0)).child(body)) - .into_any_element(); + .into_any_element() } } diff --git a/crates/moon-ui-gpui/src/chart_tabs/mod.rs b/crates/moon-ui-gpui/src/chart_tabs/mod.rs index c1d3a12a1..d3b40ca0c 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/mod.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/mod.rs @@ -573,10 +573,10 @@ impl ChartTabs { // active, so an edit relayed while an AddToChart tab is shown would be written into // that tab's spec. It cannot be relayed later either — the edit belongs to the chart it // was made on — so it is taken and dropped rather than held. - if let Some(cfg) = main.update(cx, |stack, _| stack.take_pending_labels()) { - if matches!(this.active, Tab::Main) { - this.apply_labels(cfg, cx); - } + if let Some(cfg) = main.update(cx, |stack, _| stack.take_pending_labels()) + && matches!(this.active, Tab::Main) + { + this.apply_labels(cfg, cx); } // Main owns focus changes, while ChartTabs owns the visible anchor-aware group target. this.sync_main_chart_target(cx); @@ -1035,10 +1035,10 @@ impl ChartTabs { fn main_chart_target(&self, cx: &App) -> Option<(CoreId, String)> { // A locked comparison anchor acts like Main fullscreen for trading: its `(core, market)` // becomes the group target for F1-F6, S1-S6, and cancel-buy hotkeys. - if let Some(stack) = self.active_stack() { - if let Some(anchor) = stack.read(cx).compare_anchor() { - return Some(anchor); - } + if let Some(stack) = self.active_stack() + && let Some(anchor) = stack.read(cx).compare_anchor() + { + return Some(anchor); } self.main.read(cx).active_target(cx) } @@ -1067,10 +1067,9 @@ impl ChartTabs { // Only the ACTIVE tab's edit is taken, and only it is persisted here. A DETACHED // stack carries this observer too and is never active — its edits belong to the // window's own host, which relays them itself, so taking one here would swallow it. - if is_active { - if let Some(cfg) = stack.update(cx, |stack, _| stack.take_pending_labels()) { - this.apply_labels(cfg, cx); - } + if is_active && let Some(cfg) = stack.update(cx, |stack, _| stack.take_pending_labels()) + { + this.apply_labels(cfg, cx); } if is_active { this.sync_main_chart_target(cx); @@ -1183,12 +1182,11 @@ impl ChartTabs { } fn sync_seen_for_active(&mut self, cx: &App) { - if let Tab::Add(n, c) = self.active.clone() { - if let Some((_, _, panel)) = self.add.iter().find(|(num, cc, _)| *num == n && *cc == c) - { - let cnt = panel.read(cx).pane_count(cx); - self.seen.insert((n, c), cnt); - } + if let Tab::Add(n, c) = self.active.clone() + && let Some((_, _, panel)) = self.add.iter().find(|(num, cc, _)| *num == n && *cc == c) + { + let cnt = panel.read(cx).pane_count(cx); + self.seen.insert((n, c), cnt); } } @@ -1397,12 +1395,12 @@ fn chart_pane_label( // of the raw 100000-series number; `custom_coins` in the spec identifies it. { let specs = &backend.read(cx).chart_specs; - if let Some(s) = specs.iter().find(|s| s.matches(group, n, bucket)) { - if s.custom_coins.is_some() { - return s.custom_label.clone().unwrap_or_else(|| { - t!("chart.tab.custom", n = n - CUSTOM_NUM_BASE + 1).to_string() - }); - } + if let Some(s) = specs.iter().find(|s| s.matches(group, n, bucket)) + && s.custom_coins.is_some() + { + return s.custom_label.clone().unwrap_or_else(|| { + t!("chart.tab.custom", n = n - CUSTOM_NUM_BASE + 1).to_string() + }); } } let mut label = if group.is_empty() { diff --git a/crates/moon-ui-gpui/src/chartdx/base.rs b/crates/moon-ui-gpui/src/chartdx/base.rs index 3e4e6f262..30bf8abde 100644 --- a/crates/moon-ui-gpui/src/chartdx/base.rs +++ b/crates/moon-ui-gpui/src/chartdx/base.rs @@ -79,9 +79,10 @@ impl BaseCache { anyhow::bail!("chart base cache cannot rebuild zero-sized target"); } let generation = gpu.device_generation(); - let recreate = self.tex.as_ref().map_or(true, |tex| { - tex.w != w || tex.h != h || tex.generation != generation - }); + let recreate = self + .tex + .as_ref() + .is_none_or(|tex| tex.w != w || tex.h != h || tex.generation != generation); if recreate { self.tex = Some(Self::create_tex(device, w, h, generation)); } diff --git a/crates/moon-ui-gpui/src/chartdx/combo.rs b/crates/moon-ui-gpui/src/chartdx/combo.rs index 822f3309c..ea631685a 100644 --- a/crates/moon-ui-gpui/src/chartdx/combo.rs +++ b/crates/moon-ui-gpui/src/chartdx/combo.rs @@ -432,12 +432,14 @@ impl ComboLayer { let v_margin = combo_v_margin_px(bh); let tex_h_total = tex_h + 2 * v_margin as u32; let band_px = volume_band_px(bh); - if self.tex.as_ref().map_or(true, |c| { - c.key.tex_w != tex_w || c.key.tex_h_total != tex_h_total - }) { + if self + .tex + .as_ref() + .is_none_or(|c| c.key.tex_w != tex_w || c.key.tex_h_total != tex_h_total) + { self.tex = Some(Self::create_tex(device, tex_w, tex_h_total, v_margin)); } - if self.vol_tex.as_ref().map_or(true, |c| { + if self.vol_tex.as_ref().is_none_or(|c| { c.key.tex_w != tex_w || c.key.band_px != band_px || c.key.chart_h != tex_h }) { self.vol_tex = Some(Self::create_vol_tex(device, tex_w, band_px, tex_h)); @@ -1071,10 +1073,10 @@ impl ComboLayer { tex_w_bits: tex_w.to_bits(), time_to_px_bits: time_to_px.to_bits(), }; - if let Some((cached_key, cached)) = self.volume_window_cache { - if cached_key == key { - return cached; - } + if let Some((cached_key, cached)) = self.volume_window_cache + && cached_key == key + { + return cached; } let time_left = bake_t0 - 2.0 / time_to_px; let time_right = bake_t0 + (tex_w + 2.0) / time_to_px; diff --git a/crates/moon-ui-gpui/src/chartdx/combo/tests.rs b/crates/moon-ui-gpui/src/chartdx/combo/tests.rs index 4740d1a6a..3884908e2 100644 --- a/crates/moon-ui-gpui/src/chartdx/combo/tests.rs +++ b/crates/moon-ui-gpui/src/chartdx/combo/tests.rs @@ -433,7 +433,7 @@ fn new_row_in_span_damages_without_eviction() { cross(30.0, 0, 1.0), ]); let old = logical_ring(&layer); - assert!(old.len() + 1 <= 8, "fixture must not evict"); + assert!(old.len() < 8, "fixture must not evict"); assert!( damage_of(&layer, &[cross(120.0, 0, 4.0)], cross_span, volume_span), "a new row inside the volume span must damage without eviction" diff --git a/crates/moon-ui-gpui/src/chartdx/data_state/market.rs b/crates/moon-ui-gpui/src/chartdx/data_state/market.rs index ef112db18..450bc4343 100644 --- a/crates/moon-ui-gpui/src/chartdx/data_state/market.rs +++ b/crates/moon-ui-gpui/src/chartdx/data_state/market.rs @@ -923,10 +923,7 @@ impl ChartDataState { // core streams some, and the hide-candles zone below refuses to blank a bucket // that has no crosses to replace it. Re-stamped on every full range read; an // incremental drain returns just the live edge, so it only fills a NaN (below). - pr.combo_left_rel = history - .combo_left_rel_ms - .map(|v| v as f32) - .unwrap_or(f32::NAN); + pr.combo_left_rel = history.combo_left_rel_ms.map(|v| v).unwrap_or(f32::NAN); // Restart the pan budget from the reset that ACTUALLY happened, whatever raised // it. Stamping back where the decision was made would also credit a frame whose // read returned nothing, and would miss the capacity-driven re-read that resets @@ -953,10 +950,10 @@ impl ChartDataState { // NaN — with filled candles that paints candle bodies over crosses of the same // colour, and nothing re-stamps it until the next reset. Close the NaN from // the drain; a later reset re-stamps it anyway. - if pr.combo_left_rel.is_nan() { - if let Some(left) = history.combo_left_rel_ms { - pr.combo_left_rel = left; - } + if pr.combo_left_rel.is_nan() + && let Some(left) = history.combo_left_rel_ms + { + pr.combo_left_rel = left; } pr.gpu_prepare_dirty = true; pixels_changed |= damage; diff --git a/crates/moon-ui-gpui/src/chartdx/data_state/orders.rs b/crates/moon-ui-gpui/src/chartdx/data_state/orders.rs index 67c96205b..315da5bc3 100644 --- a/crates/moon-ui-gpui/src/chartdx/data_state/orders.rs +++ b/crates/moon-ui-gpui/src/chartdx/data_state/orders.rs @@ -79,16 +79,18 @@ impl ChartDataState { // Which venues have a core behind them, for the column's dimming. Read ONCE for the sync, // like the caption gates beside it: it is a property of the connected cores, not of a pane, // and a walk per pane would repeat it for every chart in a stack. - let arb_reachable: Vec<(u8, String)> = labels_cfg - .any_drawn(|f| f == ChartLabelField::ArbColumn) - .then(|| { - session - .core_venues() - .values() - .map(|venue| (venue.id.code, venue.dex.clone())) - .collect() - }) - .unwrap_or_default(); + let arb_reachable: Vec<(u8, String)> = + if labels_cfg.any_drawn(|f| f == ChartLabelField::ArbColumn) { + { + session + .core_venues() + .values() + .map(|venue| (venue.id.code, venue.dex.clone())) + .collect() + } + } else { + Default::default() + }; // The LATEST detect this core fired, which is a live event. Same argument as the position // captions above. let wants_detect_cfg = !frozen @@ -238,7 +240,7 @@ impl ChartDataState { // The fill arrow goes too, as in the live chart's archived pass below: the frozen // store draws only in the lines style now (`frozen_store_drawn`), where the exit // line starting at the fill already says the entry filled. - let frozen_graphics = frozen.then(|| moon_core::config::ChartGraphicsCfg { + let frozen_graphics = frozen.then_some(moon_core::config::ChartGraphicsCfg { hide_closed_sell_line: false, hide_entry_fill_arrow: true, ..self.chart_graphics @@ -735,18 +737,18 @@ fn build_order_labels( notional: None, }); } - if let Some(bp) = buy { - if bp > 0.0 { - let pct = signed_pct(sp, bp, short); - push( - LineKind::Sell, - sp, - with_tag(fmt_pct(pct)), - short, - pct_color(theme, pct), - PRIO_SELL_PCT, - ); - } + if let Some(bp) = buy + && bp > 0.0 + { + let pct = signed_pct(sp, bp, short); + push( + LineKind::Sell, + sp, + with_tag(fmt_pct(pct)), + short, + pct_color(theme, pct), + PRIO_SELL_PCT, + ); } let remaining = o.exit_size(); if remaining > 0.0 && sp > 0.0 { @@ -766,18 +768,18 @@ fn build_order_labels( } // Show stop percentage from the buy price above the line for shorts and below for longs. // The primary label bypasses YTextFill, matching the Delphi stop-loss label block. - if let (Some(stp), Some(bp)) = (stop, buy) { - if bp > 0.0 { - let pct = signed_pct(stp, bp, short); - push( - LineKind::Stop, - stp, - with_tag(fmt_pct(pct)), - short, - pct_color(theme, pct), - PRIO_STOP_PCT, - ); - } + if let (Some(stp), Some(bp)) = (stop, buy) + && bp > 0.0 + { + let pct = signed_pct(stp, bp, short); + push( + LineKind::Stop, + stp, + with_tag(fmt_pct(pct)), + short, + pct_color(theme, pct), + PRIO_STOP_PCT, + ); } } } diff --git a/crates/moon-ui-gpui/src/chartdx/data_state/state.rs b/crates/moon-ui-gpui/src/chartdx/data_state/state.rs index 8387adc08..62f2e0c58 100644 --- a/crates/moon-ui-gpui/src/chartdx/data_state/state.rs +++ b/crates/moon-ui-gpui/src/chartdx/data_state/state.rs @@ -328,8 +328,8 @@ impl ChartDataState { let mut sig = 0xcbf29ce484222325; sig = mix_sig(sig, core); - sig = mix_sig(sig, str_sig(&market)); - if let Some(revs) = source.market_revisions(core, &market) { + sig = mix_sig(sig, str_sig(market)); + if let Some(revs) = source.market_revisions(core, market) { // Every revision this market has, including the chart archive. The inner gate in // `market.rs` deliberately mixes a SUBSET by hand; this one wants the lot, so it asks // for the lot rather than re-listing the fields and drifting from them. diff --git a/crates/moon-ui-gpui/src/chartdx/orderbook.rs b/crates/moon-ui-gpui/src/chartdx/orderbook.rs index 8ea4bb7a7..329f6e26e 100644 --- a/crates/moon-ui-gpui/src/chartdx/orderbook.rs +++ b/crates/moon-ui-gpui/src/chartdx/orderbook.rs @@ -220,9 +220,10 @@ impl OrderBookLayer { let tex_w = bw.round().max(1.0) as u32; let v_margin = book_v_margin_px(bh); let tex_h_total = bh.round().max(1.0) as u32 + 2 * v_margin as u32; - let need_new = self.tex.as_ref().map_or(true, |t| { - t.tex_w != tex_w || t.key.tex_h_total != tex_h_total - }); + let need_new = self + .tex + .as_ref() + .is_none_or(|t| t.tex_w != tex_w || t.key.tex_h_total != tex_h_total); if need_new { self.tex = Some(Self::create_tex(device, tex_w, tex_h_total, v_margin)); } diff --git a/crates/moon-ui-gpui/src/chartdx/pane.rs b/crates/moon-ui-gpui/src/chartdx/pane.rs index 07d3cda93..eeac3daf4 100644 --- a/crates/moon-ui-gpui/src/chartdx/pane.rs +++ b/crates/moon-ui-gpui/src/chartdx/pane.rs @@ -193,10 +193,8 @@ impl Container { .pane .as_ref() .is_some_and(|p| !p.pinned && p.source.deadline_ms().is_some_and(|d| now_ms >= d)); - if remove { - if let Some(p) = self.pane.take() { - return vec![(p.core, p.market)]; - } + if remove && let Some(p) = self.pane.take() { + return vec![(p.core, p.market)]; } Vec::new() } diff --git a/crates/moon-ui-gpui/src/chartdx/render_state.rs b/crates/moon-ui-gpui/src/chartdx/render_state.rs index 1d8f8f28b..80feec578 100644 --- a/crates/moon-ui-gpui/src/chartdx/render_state.rs +++ b/crates/moon-ui-gpui/src/chartdx/render_state.rs @@ -757,12 +757,12 @@ impl RenderState { // normal path: the shot restores the caption itself as soon as it has its picture, and this // only fires when that chain never completed. Leaving it armed would keep the EXCHANGE on // the user's own screen, where the core name belongs. - if let Some(deadline) = self.shot_caption_until { - if now >= deadline { - self.shot_caption_until = None; - self.shot_caption_frames = 0; - wants_present = true; - } + if let Some(deadline) = self.shot_caption_until + && now >= deadline + { + self.shot_caption_until = None; + self.shot_caption_frames = 0; + wants_present = true; } // Preserve independent reasons to update the camera before adding an overlay-only present. let camera_present = wants_present; diff --git a/crates/moon-ui-gpui/src/chartdx/text/prepare.rs b/crates/moon-ui-gpui/src/chartdx/text/prepare.rs index 3382030ec..01a4786f3 100644 --- a/crates/moon-ui-gpui/src/chartdx/text/prepare.rs +++ b/crates/moon-ui-gpui/src/chartdx/text/prepare.rs @@ -115,54 +115,52 @@ impl RenderState { } else { 0.0 }; - if band_on { - if let Some(stats) = volume_stats { - let band = volume_band_h; - // The band is LINEAR and its second line sits at the ratio itself, mirroring - // the sides shader exactly. - let avg_frac = volume_style.m[3].clamp(0.0, 1.0); - // Moonbot's `Ind. Pos`: the scale is a bracket whose stem the shader stands - // at the same offset this reads, and each label prints to the RIGHT of the - // tick at its level — on either side, so the right-hand bracket's labels run - // into the margin, exactly as the reference prints them. - let bracket_x = plot_left - + moon_chart::volume_bars::scale_bracket_offset(plot_w, volume_scale_right); - let label_x = bracket_x - + moon_chart::volume_bars::VOLUME_SCALE_TICK_PX - + moon_chart::volume_bars::VOLUME_SCALE_LABEL_GAP_PX; - let label_ax = 0.0; - for (frac, value) in [(1.0f32, stats.max), (avg_frac, stats.avg)] { - // Too close to the band floor to read: skip rather than overprint. The - // room a label needs follows its own line height, so the larger, bolder - // scale face cannot start hanging past the plot's bottom edge unnoticed. - if !super::volume_scale_label_fits(band, frac) { - continue; - } - // The room a label has is what lies between its tick and the plot's - // right edge — the right-hand bracket leaves it the margin only. - let Some(label) = super::volume_scale_label( - value, - &self.panes[idx].quote, - plot_right - label_x, - |text| { - super::measure_sized_text_run( - &mut self.text_runs, - self.text_run_cursor, - ctx, - text, - VOLUME_SCALE_FONT_SIZE, - VOLUME_SCALE_LINE_H, - VOLUME_SCALE_WEIGHT, - ) - .width - .as_f32() - }, - ) else { - continue; - }; - let y = plot_bottom - band * frac; - self.draw_volume_scale_text(ctx, &label, label_x, y, label_ax, 0.5, ink)?; + if band_on && let Some(stats) = volume_stats { + let band = volume_band_h; + // The band is LINEAR and its second line sits at the ratio itself, mirroring + // the sides shader exactly. + let avg_frac = volume_style.m[3].clamp(0.0, 1.0); + // Moonbot's `Ind. Pos`: the scale is a bracket whose stem the shader stands + // at the same offset this reads, and each label prints to the RIGHT of the + // tick at its level — on either side, so the right-hand bracket's labels run + // into the margin, exactly as the reference prints them. + let bracket_x = plot_left + + moon_chart::volume_bars::scale_bracket_offset(plot_w, volume_scale_right); + let label_x = bracket_x + + moon_chart::volume_bars::VOLUME_SCALE_TICK_PX + + moon_chart::volume_bars::VOLUME_SCALE_LABEL_GAP_PX; + let label_ax = 0.0; + for (frac, value) in [(1.0f32, stats.max), (avg_frac, stats.avg)] { + // Too close to the band floor to read: skip rather than overprint. The + // room a label needs follows its own line height, so the larger, bolder + // scale face cannot start hanging past the plot's bottom edge unnoticed. + if !super::volume_scale_label_fits(band, frac) { + continue; } + // The room a label has is what lies between its tick and the plot's + // right edge — the right-hand bracket leaves it the margin only. + let Some(label) = super::volume_scale_label( + value, + &self.panes[idx].quote, + plot_right - label_x, + |text| { + super::measure_sized_text_run( + &mut self.text_runs, + self.text_run_cursor, + ctx, + text, + VOLUME_SCALE_FONT_SIZE, + VOLUME_SCALE_LINE_H, + VOLUME_SCALE_WEIGHT, + ) + .width + .as_f32() + }, + ) else { + continue; + }; + let y = plot_bottom - band * frac; + self.draw_volume_scale_text(ctx, &label, label_x, y, label_ax, 0.5, ink)?; } } // Horizontal volumes: the zone's corner caption names the time window and the price @@ -930,28 +928,28 @@ impl RenderState { } // Draw the cursor's percentage deviation from the nearest book side right of // the separator, below the line. - if let Some(r) = cursor_ref { - if r > 0.0 { - let pct = (cursor_price - r) / r * 100.0; - let m = self.draw_label_text( - ctx, - &fmt_pct(pct), - right_x, - cy_log + gap, - 0.0, - 0.0, - cur_col, - )?; - placed.push(PlacedLabel { - x: right_x, - y: cy_log + gap, - ax: 0.0, - ay: 0.0, - w: m.width.as_f32(), - h: m.line_height.as_f32(), - solid: true, - }); - } + if let Some(r) = cursor_ref + && r > 0.0 + { + let pct = (cursor_price - r) / r * 100.0; + let m = self.draw_label_text( + ctx, + &fmt_pct(pct), + right_x, + cy_log + gap, + 0.0, + 0.0, + cur_col, + )?; + placed.push(PlacedLabel { + x: right_x, + y: cy_log + gap, + ax: 0.0, + ay: 0.0, + w: m.width.as_f32(), + h: m.line_height.as_f32(), + solid: true, + }); } } } else { diff --git a/crates/moon-ui-gpui/src/design.rs b/crates/moon-ui-gpui/src/design.rs index b24e522e0..5e6b86cb9 100644 --- a/crates/moon-ui-gpui/src/design.rs +++ b/crates/moon-ui-gpui/src/design.rs @@ -1161,7 +1161,7 @@ impl<'a> MonoBodyTextMeasurer<'a> { pub(crate) fn new(cx: &'a App) -> Self { let tokens = MoonTheme::active_tokens(cx); let size = px(tokens.font(base_text(cx))); - let family = SharedString::from(tokens.font_family(true)); + let family = tokens.font_family(true); let text_system = cx.text_system(); let mut fonts = HashMap::with_capacity(2); for weight in [FontWeight::NORMAL, FontWeight::SEMIBOLD] { diff --git a/crates/moon-ui-gpui/src/diagnostics/debug_window.rs b/crates/moon-ui-gpui/src/diagnostics/debug_window.rs index e0fa738b5..98485aa0f 100644 --- a/crates/moon-ui-gpui/src/diagnostics/debug_window.rs +++ b/crates/moon-ui-gpui/src/diagnostics/debug_window.rs @@ -434,13 +434,12 @@ pub(crate) fn open_debug_perf_window( group: String, owner: Option, ) { - if let Some(handle) = backend.read(cx).debug_window { - if handle + if let Some(handle) = backend.read(cx).debug_window + && handle .update(cx, |_, window, _| window.activate_window()) .is_ok() - { - return; - } + { + return; } let opts = windowing::debug_window_options( @@ -527,7 +526,7 @@ pub(crate) fn debug_chart_target(b: &Backend) -> Option<(CoreId, String)> { pub(crate) fn spawn_debug_chart_windows(cx: &mut App, backend: Entity) { let Some((core, group, market, epoch, theme, owner)) = ({ let b = backend.read(cx); - debug_chart_target(&b).map(|(core, market)| { + debug_chart_target(b).map(|(core, market)| { let group = b .session .sessions() diff --git a/crates/moon-ui-gpui/src/firetest/stages/order_cancel.rs b/crates/moon-ui-gpui/src/firetest/stages/order_cancel.rs index 774a325f5..53273bde2 100644 --- a/crates/moon-ui-gpui/src/firetest/stages/order_cancel.rs +++ b/crates/moon-ui-gpui/src/firetest/stages/order_cancel.rs @@ -255,23 +255,21 @@ impl Runtime { run.cancel_submit_ms.unwrap_or_default(), ); } - if run.closed_store_ms.is_none() { - if let Some(state) = core.order_lines.order_state(uid) { - if let (Some(closed_store_ms), Some(closed_rev)) = - (state.closed_store_ms, state.closed_rev) - { - let closed_ms_i64 = closed_store_ms.round() as i64; - run.closed_store_ms = Some(closed_ms_i64); - run.closed_order_lines_rev = Some(closed_rev); - run.closed_reason = state.closed_reason; - firetest_info(&format!( - "[firetest] order_cancel_lag closed uid={uid} order_lines_rev={} reason={:?} cancel_to_order_lines_ms={}", - closed_rev, - state.closed_reason, - closed_ms_i64 - run.cancel_submit_ms.unwrap_or(closed_ms_i64) - )); - } - } + if run.closed_store_ms.is_none() + && let Some(state) = core.order_lines.order_state(uid) + && let (Some(closed_store_ms), Some(closed_rev)) = + (state.closed_store_ms, state.closed_rev) + { + let closed_ms_i64 = closed_store_ms.round() as i64; + run.closed_store_ms = Some(closed_ms_i64); + run.closed_order_lines_rev = Some(closed_rev); + run.closed_reason = state.closed_reason; + firetest_info(&format!( + "[firetest] order_cancel_lag closed uid={uid} order_lines_rev={} reason={:?} cancel_to_order_lines_ms={}", + closed_rev, + state.closed_reason, + closed_ms_i64 - run.cancel_submit_ms.unwrap_or(closed_ms_i64) + )); } let Some(closed_rev) = run.closed_order_lines_rev else { self.wait_log("order_cancel_lag waiting for cancelled order snapshot"); diff --git a/crates/moon-ui-gpui/src/firetest/stages/perf.rs b/crates/moon-ui-gpui/src/firetest/stages/perf.rs index 73a79c084..d123fe434 100644 --- a/crates/moon-ui-gpui/src/firetest/stages/perf.rs +++ b/crates/moon-ui-gpui/src/firetest/stages/perf.rs @@ -114,10 +114,10 @@ impl Runtime { return 0; } let mut applied = 0usize; - if let Some(chart) = backend.live_chart_consumers().into_iter().next() { - if chart.set_firetest_text_labels(count) { - applied += 1; - } + if let Some(chart) = backend.live_chart_consumers().into_iter().next() + && chart.set_firetest_text_labels(count) + { + applied += 1; } firetest_info(&format!( "[firetest] text overlay labels={count} applied_to={applied}" diff --git a/crates/moon-ui-gpui/src/firetest/storm/win.rs b/crates/moon-ui-gpui/src/firetest/storm/win.rs index 67cc9e430..c7a22ec3d 100644 --- a/crates/moon-ui-gpui/src/firetest/storm/win.rs +++ b/crates/moon-ui-gpui/src/firetest/storm/win.rs @@ -92,7 +92,7 @@ pub(in crate::firetest) fn start_mouse_storm( let elapsed = start.elapsed(); if target > elapsed { std::thread::sleep(target - elapsed); - } else if sent % 128 == 0 { + } else if sent.is_multiple_of(128) { std::thread::yield_now(); } } diff --git a/crates/moon-ui-gpui/src/media/exchange_logos.rs b/crates/moon-ui-gpui/src/media/exchange_logos.rs index fe14997ce..08a8e7876 100644 --- a/crates/moon-ui-gpui/src/media/exchange_logos.rs +++ b/crates/moon-ui-gpui/src/media/exchange_logos.rs @@ -132,7 +132,7 @@ pub(crate) fn prewarm() { /// Returns: /// Nothing; concurrent callers block until the winning initializer completes. fn prewarm_once(gate: &OnceLock<()>, warm: impl FnOnce()) { - gate.get_or_init(|| warm()); + gate.get_or_init(warm); } #[cfg(test)] diff --git a/crates/moon-ui-gpui/src/media/sound.rs b/crates/moon-ui-gpui/src/media/sound.rs index da44b60e7..40ae52fad 100644 --- a/crates/moon-ui-gpui/src/media/sound.rs +++ b/crates/moon-ui-gpui/src/media/sound.rs @@ -50,7 +50,7 @@ pub(crate) fn rescan(cx: &mut App, done: impl FnOnce(&mut App) + 'static) { let catalog = cx .background_spawn(async move { sources::scan(&dir) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { install(catalog); done(cx); }); diff --git a/crates/moon-ui-gpui/src/panels/alerts/controls.rs b/crates/moon-ui-gpui/src/panels/alerts/controls.rs index afb6d1bb4..819ea9ea9 100644 --- a/crates/moon-ui-gpui/src/panels/alerts/controls.rs +++ b/crates/moon-ui-gpui/src/panels/alerts/controls.rs @@ -91,7 +91,7 @@ impl AlertsPanel { &cores, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, - &t!("alerts.all_cores").to_string(), + t!("alerts.all_cores").as_ref(), &|n| t!("alerts.cores_n", n = n).to_string(), ) .label @@ -118,7 +118,7 @@ impl AlertsPanel { crate::controls::core_combo( "alerts-cores", &cores, - &venues, + venues, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, t!("alerts.all_cores").to_string(), diff --git a/crates/moon-ui-gpui/src/panels/assets/mod.rs b/crates/moon-ui-gpui/src/panels/assets/mod.rs index 308b646cd..5a35f1adb 100644 --- a/crates/moon-ui-gpui/src/panels/assets/mod.rs +++ b/crates/moon-ui-gpui/src/panels/assets/mod.rs @@ -560,14 +560,12 @@ impl AssetsView { { return Some(core); } - if workspace_owned { - if let Some(scope) = scope.as_ref() { - let ids = scope.ids(); - return self - .overview_wallet_pick - .filter(|core| ids.contains(core)) - .or_else(|| ids.first().copied()); - } + if workspace_owned && let Some(scope) = scope.as_ref() { + let ids = scope.ids(); + return self + .overview_wallet_pick + .filter(|core| ids.contains(core)) + .or_else(|| ids.first().copied()); } None } diff --git a/crates/moon-ui-gpui/src/panels/assets/spot_order.rs b/crates/moon-ui-gpui/src/panels/assets/spot_order.rs index 3480c059c..165b98b08 100644 --- a/crates/moon-ui-gpui/src/panels/assets/spot_order.rs +++ b/crates/moon-ui-gpui/src/panels/assets/spot_order.rs @@ -116,9 +116,8 @@ fn live_order_on_market(backend: &Backend, core: CoreId, market: &str) -> Option let orders = &store.core(core)?.orders; let on_market = || orders.iter().filter(|o| o.market == market); on_market() - .filter(|o| crate::panels::orders::executed(o)) - .last() - .or_else(|| on_market().last()) + .rfind(|o| crate::panels::orders::executed(o)) + .or_else(|| on_market().next_back()) .map(|o| o.uid) } diff --git a/crates/moon-ui-gpui/src/panels/assets/table.rs b/crates/moon-ui-gpui/src/panels/assets/table.rs index 6c527726d..b56e78573 100644 --- a/crates/moon-ui-gpui/src/panels/assets/table.rs +++ b/crates/moon-ui-gpui/src/panels/assets/table.rs @@ -261,7 +261,7 @@ impl AssetsView { cores, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, - &t!("assets.all_cores").to_string(), + t!("assets.all_cores").as_ref(), &|n| t!("assets.cores_n", n = n).to_string(), ) .label @@ -282,7 +282,7 @@ impl AssetsView { crate::controls::core_combo( "assets-core", cores, - &venues, + venues, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, t!("assets.all_cores").to_string(), @@ -452,32 +452,32 @@ impl AssetsView { .child(super::balances::figure(Some(agg), p, cx)), ) .on_click(cx.listener(move |this, _, window, cx| { - if let AssetsScope::Group(_) = &this.scope { - if let Some(scope) = this.effective_scope(this.backend.read(cx)) { - if scope.is_auto_core() { - // A selected Auto core pins the wallet host to the rail. - return; - } - if scope.is_workspace_owned() { - // Auto Overview: pick a transfer host without touching the rail or - // Classic's retained `selected_core`. - if this.overview_wallet_pick != Some(cid) { - this.overview_wallet_pick = Some(cid); - if let Err(error) = - this.backend.read(cx).session.refresh_transfer_assets(cid) - { - log::warn!("assets refresh failed for core {cid}: {error}"); - window.push_notification( - MoonNotification::error(error.to_string()), - cx, - ); - } - let backend = this.backend.clone(); - this.rebuild_cache(backend.read(cx)); - cx.notify(); + if let AssetsScope::Group(_) = &this.scope + && let Some(scope) = this.effective_scope(this.backend.read(cx)) + { + if scope.is_auto_core() { + // A selected Auto core pins the wallet host to the rail. + return; + } + if scope.is_workspace_owned() { + // Auto Overview: pick a transfer host without touching the rail or + // Classic's retained `selected_core`. + if this.overview_wallet_pick != Some(cid) { + this.overview_wallet_pick = Some(cid); + if let Err(error) = + this.backend.read(cx).session.refresh_transfer_assets(cid) + { + log::warn!("assets refresh failed for core {cid}: {error}"); + window.push_notification( + MoonNotification::error(error.to_string()), + cx, + ); } - return; + let backend = this.backend.clone(); + this.rebuild_cache(backend.read(cx)); + cx.notify(); } + return; } } if this.selected_core != Some(cid) { diff --git a/crates/moon-ui-gpui/src/panels/assets/window.rs b/crates/moon-ui-gpui/src/panels/assets/window.rs index 2364618ec..9749bfba5 100644 --- a/crates/moon-ui-gpui/src/panels/assets/window.rs +++ b/crates/moon-ui-gpui/src/panels/assets/window.rs @@ -49,13 +49,12 @@ pub fn open( cx: &mut App, ) { // Focus the existing singleton instead of opening a duplicate. - if let Some(handle) = backend.read(cx).assets_window { - if handle + if let Some(handle) = backend.read(cx).assets_window + && handle .update(cx, |_, window, _| window.activate_window()) .is_ok() - { - return; - } + { + return; } let saved = backend.read(cx).layout.assets_window; let bounds = saved.map_or( diff --git a/crates/moon-ui-gpui/src/panels/chart/mod.rs b/crates/moon-ui-gpui/src/panels/chart/mod.rs index 51dd726ee..045e0852c 100644 --- a/crates/moon-ui-gpui/src/panels/chart/mod.rs +++ b/crates/moon-ui-gpui/src/panels/chart/mod.rs @@ -597,7 +597,7 @@ impl ChartPanel { // A fresh panel holds no override yet, so its effective values ARE its kind's defaults. let settings_sig = { let b = backend.read(cx); - chart_settings_sig(&b, None, None, None, kind) + chart_settings_sig(b, None, None, None, kind) }; let display_time_revision = backend.read(cx).display_time_revision.clone(); cx.observe(&display_time_revision, |this, _revision, cx| { @@ -648,7 +648,7 @@ impl ChartPanel { ( sig, chart_settings_sig( - &b, + b, this.chart_graphics, this.candle_view, this.chart_labels.clone(), @@ -831,7 +831,7 @@ impl ChartPanel { // A fresh panel holds no override yet, so its effective values ARE the global defaults. let settings_sig = { let b = backend.read(cx); - chart_settings_sig(&b, None, None, None, kind) + chart_settings_sig(b, None, None, None, kind) }; let display_time_revision = backend.read(cx).display_time_revision.clone(); cx.observe(&display_time_revision, |this, _revision, cx| { @@ -881,7 +881,7 @@ impl ChartPanel { ( sig, chart_settings_sig( - &b, + b, this.chart_graphics, this.candle_view, this.chart_labels.clone(), @@ -1508,7 +1508,7 @@ impl ChartPanel { self.settings_sig = { let b = self.backend.read(cx); chart_settings_sig( - &b, + b, self.chart_graphics, cfg, self.chart_labels.clone(), @@ -1540,7 +1540,7 @@ impl ChartPanel { self.settings_sig = { let b = self.backend.read(cx); chart_settings_sig( - &b, + b, cfg, self.candle_view, self.chart_labels.clone(), @@ -1573,7 +1573,7 @@ impl ChartPanel { self.settings_sig = { let b = self.backend.read(cx); chart_settings_sig( - &b, + b, self.chart_graphics, self.candle_view, cfg, @@ -1867,7 +1867,7 @@ impl ChartPanel { let settings_sig = { let b = self.backend.read(cx); chart_settings_sig( - &b, + b, self.chart_graphics, self.candle_view, self.chart_labels.clone(), diff --git a/crates/moon-ui-gpui/src/panels/chart/render.rs b/crates/moon-ui-gpui/src/panels/chart/render.rs index a3175afd6..fc10424b9 100644 --- a/crates/moon-ui-gpui/src/panels/chart/render.rs +++ b/crates/moon-ui-gpui/src/panels/chart/render.rs @@ -475,12 +475,10 @@ impl Render for ChartPanel { f32::from(bounds.size.height) * zoom, platform_sf, ); - if is_main { - if let Some(probe) = firetest_probe { - backend.update(cx, |b, _| { - crate::firetest::observe_chart_probe(b, probe); - }); - } + if is_main && let Some(probe) = firetest_probe { + backend.update(cx, |b, _| { + crate::firetest::observe_chart_probe(b, probe); + }); } }, ) diff --git a/crates/moon-ui-gpui/src/panels/chart/render_input.rs b/crates/moon-ui-gpui/src/panels/chart/render_input.rs index 50acd7d6a..3900c7ab5 100644 --- a/crates/moon-ui-gpui/src/panels/chart/render_input.rs +++ b/crates/moon-ui-gpui/src/panels/chart/render_input.rs @@ -314,14 +314,13 @@ pub(super) fn scroll_wheel( // In an AddToChart stack, wheel input over the left price-axis strip scrolls the stack rather // than zooming: leave the event unconsumed so it bubbles to MoonVirtualList. Over the graph or // book, handle zoom below and stop propagation so the stack does not scroll too. - if this.num.is_some() && within { - if let Some(idx) = this.input.pane_at(pos.0, pos.1) { - if let Some((_, rect)) = this.input.pane_rects.iter().find(|(i, _)| *i == idx) { - if pos.0 <= rect.x + moon_chart::PRICE_AXIS_W * sf { - return; - } - } - } + if this.num.is_some() + && within + && let Some(idx) = this.input.pane_at(pos.0, pos.1) + && let Some((_, rect)) = this.input.pane_rects.iter().find(|(i, _)| *i == idx) + && pos.0 <= rect.x + moon_chart::PRICE_AXIS_W * sf + { + return; } // Lines represent discrete mouse-wheel clicks, commonly +/-1 or +/-3 on Windows. Pixels are // precise trackpad/Magic Mouse input on macOS, delivered as a continuous inertial stream. @@ -1084,10 +1083,8 @@ pub(super) fn mouse_move( } let cursor_changed = prev_cursor != this.input.cursor || prev_hovered != this.input.hovered_pane; - if cursor_changed { - if this.sync_native_cursor(cx) { - crate::diag::bump(&crate::diag::CHART_CURSOR_UPDATE); - } + if cursor_changed && this.sync_native_cursor(cx) { + crate::diag::bump(&crate::diag::CHART_CURSOR_UPDATE); } // Dragging changes cameras/axes and GPUI-side controls. Cursor-only motion remains in retained // gpu_canvas, which presents the crosshair/readout without cx.notify(). diff --git a/crates/moon-ui-gpui/src/panels/chart/trade.rs b/crates/moon-ui-gpui/src/panels/chart/trade.rs index 8dcf3415b..3642158c3 100644 --- a/crates/moon-ui-gpui/src/panels/chart/trade.rs +++ b/crates/moon-ui-gpui/src/panels/chart/trade.rs @@ -898,7 +898,7 @@ impl ChartPanel { // denotes manual/join orders. The row's `coin` was resolved with this core's exchange // rules and is what the menu writes into the coin blacklists. let b = self.backend.read(cx); - if !self.workspace_action_allowed(&b, core) { + if !self.workspace_action_allowed(b, core) { return false; } let order = b @@ -1312,7 +1312,7 @@ impl ChartPanel { if hit.on_start_cross { return false; } - if !self.workspace_action_allowed(&self.backend.read(cx), hit.core) { + if !self.workspace_action_allowed(self.backend.read(cx), hit.core) { return false; } let price = hit.price as f64; diff --git a/crates/moon-ui-gpui/src/panels/chart/warn.rs b/crates/moon-ui-gpui/src/panels/chart/warn.rs index ba7e61362..ac09095a0 100644 --- a/crates/moon-ui-gpui/src/panels/chart/warn.rs +++ b/crates/moon-ui-gpui/src/panels/chart/warn.rs @@ -464,10 +464,10 @@ fn merge_axis(cluster: &mut WarnCluster, episode: &WarnEpisode) { // history, so it has nothing to draw on a time axis. WarnAxis::ApiExpiry | WarnAxis::ApiQuota => {} } - if let Some(core) = episode.core_id { - if !cluster.cores.contains(&core) { - cluster.cores.push(core); - } + if let Some(core) = episode.core_id + && !cluster.cores.contains(&core) + { + cluster.cores.push(core); } } diff --git a/crates/moon-ui-gpui/src/panels/core_status/mod.rs b/crates/moon-ui-gpui/src/panels/core_status/mod.rs index 56511e2ef..2d33868e9 100644 --- a/crates/moon-ui-gpui/src/panels/core_status/mod.rs +++ b/crates/moon-ui-gpui/src/panels/core_status/mod.rs @@ -59,9 +59,10 @@ use moon_core::session::core_update::CoreUpdatePhase; use rust_i18n::t; /// Chart X-axis span selectable in the detached window. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] enum ChartWindow { /// Last five minutes. + #[default] Min5, /// Last hour. Hour1, @@ -85,12 +86,6 @@ impl ChartWindow { } } -impl Default for ChartWindow { - fn default() -> Self { - Self::Min5 - } -} - /// Available Core Status presentations. #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum CoreStatusMode { @@ -1358,7 +1353,7 @@ impl CoreStatusView { cores, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, - &t!("core_status.all_cores").to_string(), + t!("core_status.all_cores").as_ref(), &|n| t!("core_status.cores_n", n = n).to_string(), ) .label @@ -1386,7 +1381,7 @@ impl CoreStatusView { crate::controls::core_combo( "core-status-core", cores, - &venues, + venues, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, t!("core_status.all_cores").to_string(), diff --git a/crates/moon-ui-gpui/src/panels/core_status/server_view.rs b/crates/moon-ui-gpui/src/panels/core_status/server_view.rs index 84e864aff..c3c0e0b70 100644 --- a/crates/moon-ui-gpui/src/panels/core_status/server_view.rs +++ b/crates/moon-ui-gpui/src/panels/core_status/server_view.rs @@ -243,51 +243,50 @@ pub(super) fn grouped_server_view( let tree = MoonTree::custom(state, move |entry, meta, _window, app| { let p = MoonPalette::active(app); if entry.is_root() { - if let Some(server_index) = server_positions.get(entry.item().id()).copied() { - if let Some(group) = groups.get(server_index) { - let editing_input = (editing == Some(group.key)) - .then(|| edit_input.clone()) - .flatten(); - // Highlight follows the body-click selection (chart target). - return MoonListItem::new(meta.index) - .selected(chart_selected == Some(group.key)) - .child(server_row( - group, - ip_masked, - entry.is_expanded(), - editing_input, - widths, - &weak_view, - &backend, - p, - app, - )); - } - } - } else if let Some(&(server_index, core_index)) = core_positions.get(entry.item().id()) { - if let Some(core) = groups - .get(server_index) - .and_then(|group| group.cores.get(core_index)) + if let Some(server_index) = server_positions.get(entry.item().id()).copied() + && let Some(group) = groups.get(server_index) { - // The highlight follows the SELECTION now, not the chart: a plain click still - // charts the core and selects it alone, so the single-click case looks exactly as - // it did, while a Ctrl or Shift click builds a set the chart has no opinion about. + let editing_input = (editing == Some(group.key)) + .then(|| edit_input.clone()) + .flatten(); + // Highlight follows the body-click selection (chart target). return MoonListItem::new(meta.index) - .selected(selection.contains(Some(core.id))) - .child(core_row( - core, + .selected(chart_selected == Some(group.key)) + .child(server_row( + group, + ip_masked, + entry.is_expanded(), + editing_input, widths, - TreeSelection { - order: &order, - cores: &order_cores, - selection: &selection, - }, &weak_view, &backend, p, app, )); } + } else if let Some(&(server_index, core_index)) = core_positions.get(entry.item().id()) + && let Some(core) = groups + .get(server_index) + .and_then(|group| group.cores.get(core_index)) + { + // The highlight follows the SELECTION now, not the chart: a plain click still + // charts the core and selects it alone, so the single-click case looks exactly as + // it did, while a Ctrl or Shift click builds a set the chart has no opinion about. + return MoonListItem::new(meta.index) + .selected(selection.contains(Some(core.id))) + .child(core_row( + core, + widths, + TreeSelection { + order: &order, + cores: &order_cores, + selection: &selection, + }, + &weak_view, + &backend, + p, + app, + )); } MoonListItem::new(meta.index) .selected(false) diff --git a/crates/moon-ui-gpui/src/panels/core_status/time_offset/tests.rs b/crates/moon-ui-gpui/src/panels/core_status/time_offset/tests.rs index f6f615419..860deaab7 100644 --- a/crates/moon-ui-gpui/src/panels/core_status/time_offset/tests.rs +++ b/crates/moon-ui-gpui/src/panels/core_status/time_offset/tests.rs @@ -48,7 +48,7 @@ fn unknown_never_renders_as_utc() { /// `tz_offset_rank`: every measured value, whatever its sign, sorts before `Unknown`. #[test] fn the_rank_puts_unknown_last() { - let mut cells = vec![ + let mut cells = [ TzOffsetCell::Unknown, TzOffsetCell::Measured { offset_secs: 7_200 }, TzOffsetCell::Measured { diff --git a/crates/moon-ui-gpui/src/panels/detects/mod.rs b/crates/moon-ui-gpui/src/panels/detects/mod.rs index 2458610e1..fc008473e 100644 --- a/crates/moon-ui-gpui/src/panels/detects/mod.rs +++ b/crates/moon-ui-gpui/src/panels/detects/mod.rs @@ -531,9 +531,7 @@ impl DetectsPanel { }) .is_ok() }); - if !alive { - return; - } + if !alive {} }) .detach(); } diff --git a/crates/moon-ui-gpui/src/panels/log/controls.rs b/crates/moon-ui-gpui/src/panels/log/controls.rs index f6536bcf7..22cd0f121 100644 --- a/crates/moon-ui-gpui/src/panels/log/controls.rs +++ b/crates/moon-ui-gpui/src/panels/log/controls.rs @@ -82,7 +82,7 @@ impl LogPanel { LogSource::Aggregate | LogSource::Exchange(_) | LogSource::Local => None, }) .collect(); - let sections = crate::controls::core_menu_sections(&cores, &venues); + let sections = crate::controls::core_menu_sections(&cores, venues); let view = cx.entity(); let mut items = Vec::with_capacity(sources.len() + sections.len() + 1); for (index, item) in sources diff --git a/crates/moon-ui-gpui/src/panels/log/render.rs b/crates/moon-ui-gpui/src/panels/log/render.rs index 3563795d6..3e5f49d8d 100644 --- a/crates/moon-ui-gpui/src/panels/log/render.rs +++ b/crates/moon-ui-gpui/src/panels/log/render.rs @@ -417,7 +417,7 @@ pub(super) fn exchange_core_ids(b: &Backend, group: &str, exchange: ExchangeId) .iter() .map(|server| (server.id, server.group.as_str())), &live, - &venues, + venues, group, exchange, ) diff --git a/crates/moon-ui-gpui/src/panels/orders/controls.rs b/crates/moon-ui-gpui/src/panels/orders/controls.rs index 11db5f7b0..303afe78f 100644 --- a/crates/moon-ui-gpui/src/panels/orders/controls.rs +++ b/crates/moon-ui-gpui/src/panels/orders/controls.rs @@ -51,7 +51,7 @@ impl OrdersPanel { cores, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, - &t!("orders.all_cores").to_string(), + t!("orders.all_cores").as_ref(), &|n| t!("orders.cores_n", n = n).to_string(), ) .label @@ -83,7 +83,7 @@ impl OrdersPanel { crate::controls::core_combo( "orders-source", cores, - &venues, + venues, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, t!("orders.all_cores").to_string(), diff --git a/crates/moon-ui-gpui/src/panels/report/actions.rs b/crates/moon-ui-gpui/src/panels/report/actions.rs index f9b1bb73a..73d0bbee7 100644 --- a/crates/moon-ui-gpui/src/panels/report/actions.rs +++ b/crates/moon-ui-gpui/src/panels/report/actions.rs @@ -267,7 +267,7 @@ impl ReportPanel { let prefs = { let backend = self.backend.read(cx); next_prefs_for_period_pick( - crate::persistence::table_persist::report_filters(&backend, &id), + crate::persistence::table_persist::report_filters(backend, &id), period_bucket, picked_period, &super::state::ReportFilterSet { @@ -700,7 +700,7 @@ impl ReportPanel { let indices = selection::ordered_source_indices( &self.cols, &source_indices, - &self.table_state.read(cx), + self.table_state.read(cx), ); if self.selection.len() == 0 || indices.is_empty() { return; @@ -968,7 +968,7 @@ impl ReportPanel { .autohide(false) } }; - let _ = cx.update(|app| { + cx.update(|app| { let _ = handle.update(app, |_, window, app| { use moon_ui::MoonWindowExt as _; window.push_notification(note, app); diff --git a/crates/moon-ui-gpui/src/panels/report/controls.rs b/crates/moon-ui-gpui/src/panels/report/controls.rs index 63396a7b3..7580429b1 100644 --- a/crates/moon-ui-gpui/src/panels/report/controls.rs +++ b/crates/moon-ui-gpui/src/panels/report/controls.rs @@ -536,7 +536,7 @@ impl ReportPanel { &cores, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, - &t!("report.all_cores").to_string(), + t!("report.all_cores").as_ref(), &|n| t!("report.cores_n", n = n).to_string(), ) .label @@ -557,7 +557,7 @@ impl ReportPanel { let combo = crate::controls::core_combo( "rep-core", &cores, - &venues, + venues, selection, crate::controls::CoreAllRowMode::ImplicitOrComplete, t!("report.all_cores").to_string(), diff --git a/crates/moon-ui-gpui/src/panels/report/export.rs b/crates/moon-ui-gpui/src/panels/report/export.rs index 2d5ba85f8..bff50baed 100644 --- a/crates/moon-ui-gpui/src/panels/report/export.rs +++ b/crates/moon-ui-gpui/src/panels/report/export.rs @@ -341,11 +341,11 @@ fn write_xlsx( } // Write identifier columns as text so Excel cannot convert large i64 values to imprecise // scientific notation. - if id_text_col(name) { - if let Value::Integer(n) = val { - ws.write_string(r, c, n.to_string())?; - continue; - } + if id_text_col(name) + && let Value::Integer(n) = val + { + ws.write_string(r, c, n.to_string())?; + continue; } match val { Value::Integer(n) => { diff --git a/crates/moon-ui-gpui/src/panels/report/query.rs b/crates/moon-ui-gpui/src/panels/report/query.rs index a30e5c9ec..8625e274e 100644 --- a/crates/moon-ui-gpui/src/panels/report/query.rs +++ b/crates/moon-ui-gpui/src/panels/report/query.rs @@ -361,7 +361,7 @@ impl ReportPanel { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); executor.timer(wait).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { if this.generation_refresh.timer_fired(timer_token) { cx.notify(); @@ -425,7 +425,7 @@ impl ReportPanel { }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { if !report_query_result_is_current( request_id, diff --git a/crates/moon-ui-gpui/src/panels/report/state.rs b/crates/moon-ui-gpui/src/panels/report/state.rs index 41c8cc21b..60a965208 100644 --- a/crates/moon-ui-gpui/src/panels/report/state.rs +++ b/crates/moon-ui-gpui/src/panels/report/state.rs @@ -367,7 +367,7 @@ impl ReportPanel { .and_then(|connection| db::load_comment_pane(&connection, detached)) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { if this.detached != detached || this.show_comment != expected @@ -405,7 +405,7 @@ impl ReportPanel { let metadata = executor .spawn(async move { ReportInitialMetadata::load() }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { let ReportInitialMetadata { cores, diff --git a/crates/moon-ui-gpui/src/panels/report/totals.rs b/crates/moon-ui-gpui/src/panels/report/totals.rs index fe4e0e203..4c14f929c 100644 --- a/crates/moon-ui-gpui/src/panels/report/totals.rs +++ b/crates/moon-ui-gpui/src/panels/report/totals.rs @@ -185,16 +185,16 @@ fn traded_volume_amount(volume: &db::TradedVolume) -> Option { // persisted figure for a rate-derived USDT one, and under the current-rate mode take that // mode's wording with it. A unified figure also exists only over a fully reconstructed and // fully valued scope, which is why it can never carry a gap. - if matches!(volume.scope(), db::QuoteScope::Mixed) { - if let Some(usdt) = volume.usdt { - let (visible, exact) = native_volume(usdt, db::QuoteCurrency::usdt()); - return Some(VolumeAmountText { - visible, - exact, - unified: true, - gap: None, - }); - } + if matches!(volume.scope(), db::QuoteScope::Mixed) + && let Some(usdt) = volume.usdt + { + let (visible, exact) = native_volume(usdt, db::QuoteCurrency::usdt()); + return Some(VolumeAmountText { + visible, + exact, + unified: true, + gap: None, + }); } let mut visible = Vec::new(); let mut exact = Vec::new(); @@ -559,37 +559,37 @@ pub(super) fn footer_facts( true, )); } - if unified.is_none() { - if let Some(coverage) = mixed.then_some(totals.valuation).flatten() { - if coverage.eligible_orders > 0 { - tail.push(fact( - t!( - mode.key( - "report.valuation_progress", - "report.valuation_current_progress" - ), - ready = coverage.valued_orders, - total = coverage.eligible_orders - ) - .to_string(), - FactTone::Warn, - false, - )); - } - if coverage.unavailable_orders > 0 { - tail.push(fact( - t!( - mode.key( - "report.valuation_unavailable", - "report.valuation_current_unavailable" - ), - n = coverage.unavailable_orders - ) - .to_string(), - FactTone::Warn, - false, - )); - } + if unified.is_none() + && let Some(coverage) = mixed.then_some(totals.valuation).flatten() + { + if coverage.eligible_orders > 0 { + tail.push(fact( + t!( + mode.key( + "report.valuation_progress", + "report.valuation_current_progress" + ), + ready = coverage.valued_orders, + total = coverage.eligible_orders + ) + .to_string(), + FactTone::Warn, + false, + )); + } + if coverage.unavailable_orders > 0 { + tail.push(fact( + t!( + mode.key( + "report.valuation_unavailable", + "report.valuation_current_unavailable" + ), + n = coverage.unavailable_orders + ) + .to_string(), + FactTone::Warn, + false, + )); } } if let Some(amount) = traded_volume_amount(&totals.traded_volume) { diff --git a/crates/moon-ui-gpui/src/persistence/chart_persist.rs b/crates/moon-ui-gpui/src/persistence/chart_persist.rs index 7eaa754d9..ba29346a7 100644 --- a/crates/moon-ui-gpui/src/persistence/chart_persist.rs +++ b/crates/moon-ui-gpui/src/persistence/chart_persist.rs @@ -108,37 +108,27 @@ impl StackOrientation { /// chart prints, and `startup::action_buttons_migration` turns whatever a tab stored here into /// caption rows and clears the key. Nothing writes it again; the type survives so that one pass can /// still read a profile written before the move. -#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Default)] pub enum ChartBtnPos { Hide, Left, Center, + #[default] Right, } -impl Default for ChartBtnPos { - fn default() -> Self { - ChartBtnPos::Right - } -} - /// Per-tab price-axis position relative to the chart and order book. `Left` places the gutter left /// of the plot and is the historical default. `Right` places it to the right beyond the order book, /// so the axis does not separate the plot from the book. `Hide` removes the axis and returns its /// space to the plot. A missing specification value means `Left`. -#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Default)] pub enum PriceAxisPos { Hide, + #[default] Left, Right, } -impl Default for PriceAxisPos { - fn default() -> Self { - PriceAxisPos::Left - } -} - /// Persistent state for one chart tab. `num == 0` identifies Main; `num >= 1` identifies numbered /// AddToChart or custom tabs. #[derive(Clone, Serialize, Deserialize)] @@ -338,7 +328,7 @@ impl ChartTabSpec { /// Returns the canonical tab key from `bucket`, or derives it from legacy `core`: Some(core) /// becomes Core and None becomes Shared. pub fn bucket(&self) -> ChartBucket { - self.bucket.clone().unwrap_or_else(|| match self.core { + self.bucket.clone().unwrap_or(match self.core { Some(id) => ChartBucket::Core(id), None => ChartBucket::Shared, }) @@ -388,17 +378,17 @@ pub fn remap_core_ids(specs: &mut [ChartTabSpec], servers: &[ServerConfig]) { }; let mut remapped = 0usize; for spec in specs.iter_mut() { - if let Some(ChartBucket::Core(n)) = spec.bucket { - if let Some(uid) = pos_to_uid(n) { - spec.bucket = Some(ChartBucket::Core(uid)); - remapped += 1; - } + if let Some(ChartBucket::Core(n)) = spec.bucket + && let Some(uid) = pos_to_uid(n) + { + spec.bucket = Some(ChartBucket::Core(uid)); + remapped += 1; } - if let Some(n) = spec.core { - if let Some(uid) = pos_to_uid(n) { - spec.core = Some(uid); - remapped += 1; - } + if let Some(n) = spec.core + && let Some(uid) = pos_to_uid(n) + { + spec.core = Some(uid); + remapped += 1; } } log::info!( diff --git a/crates/moon-ui-gpui/src/persistence/dock_persist.rs b/crates/moon-ui-gpui/src/persistence/dock_persist.rs index 4044a176c..e21dd9433 100644 --- a/crates/moon-ui-gpui/src/persistence/dock_persist.rs +++ b/crates/moon-ui-gpui/src/persistence/dock_persist.rs @@ -130,10 +130,10 @@ pub(crate) fn save_all_to_path(map: &DockMap, path: &Path) -> bool { /// /// Missing, non-panel, or non-string metadata falls back to the empty group name. fn group_of(info: &PanelInfo) -> String { - if let PanelInfo::Panel(v) = info { - if let Some(g) = v.get("group").and_then(|g| g.as_str()) { - return g.to_string(); - } + if let PanelInfo::Panel(v) = info + && let Some(g) = v.get("group").and_then(|g| g.as_str()) + { + return g.to_string(); } String::new() } diff --git a/crates/moon-ui-gpui/src/screener/view.rs b/crates/moon-ui-gpui/src/screener/view.rs index f9ace62e0..13a517505 100644 --- a/crates/moon-ui-gpui/src/screener/view.rs +++ b/crates/moon-ui-gpui/src/screener/view.rs @@ -239,10 +239,10 @@ impl ScreenerView { continue; } names.insert(s.id, SharedString::from(s.name.clone())); - if let ScrSource::Core(only) = self.source { - if s.id != only { - continue; - } + if let ScrSource::Core(only) = self.source + && s.id != only + { + continue; } let Some(provider) = source.provider_of(s.id) else { continue; @@ -509,7 +509,7 @@ impl ScreenerView { .map(|(_, n)| n.clone()) .unwrap_or_else(|| format!("#{id}")), }; - let sections = crate::controls::core_menu_sections(&cores, &venues); + let sections = crate::controls::core_menu_sections(&cores, venues); let view = cx.entity(); let all_view = view.clone(); let mut items = vec![ @@ -764,13 +764,12 @@ pub fn open( cx: &mut App, ) { // Focus an existing live window instead of opening a duplicate. - if let Some(handle) = backend.read(cx).screener_window { - if handle + if let Some(handle) = backend.read(cx).screener_window + && handle .update(cx, |_, window, _| window.activate_window()) .is_ok() - { - return; - } + { + return; } let saved = backend.read(cx).layout.screener_window; let bounds = saved.map_or( diff --git a/crates/moon-ui-gpui/src/settings/badges.rs b/crates/moon-ui-gpui/src/settings/badges.rs index df6cf2993..51ee9e335 100644 --- a/crates/moon-ui-gpui/src/settings/badges.rs +++ b/crates/moon-ui-gpui/src/settings/badges.rs @@ -54,11 +54,11 @@ fn badge_input( if matches!(ev, MoonInputEvent::Change) { let val = emitter.read(cx).value().to_string(); this.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if let Some(e) = p.badges.entries.get_mut(idx) { - apply(e, val); - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && let Some(e) = p.badges.entries.get_mut(idx) + { + apply(e, val); + bcx.notify(); } }); } @@ -94,11 +94,11 @@ fn entry_color( }; super::draft_color(window, cx, init, move |p, cc| { let is_light = p.ui_theme_mode.is_light(); - if let Some(e) = p.badges.entries.get_mut(idx) { - if get(e, is_light) != cc { - set(e, is_light, cc); - return true; - } + if let Some(e) = p.badges.entries.get_mut(idx) + && get(e, is_light) != cc + { + set(e, is_light, cc); + return true; } false }) @@ -233,11 +233,11 @@ impl SettingsView { /// Delete draft entry `idx`, then rebuild editor state. fn delete_badge(&mut self, idx: usize, window: &mut Window, cx: &mut Context) { self.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if idx < p.badges.entries.len() { - p.badges.entries.remove(idx); - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && idx < p.badges.entries.len() + { + p.badges.entries.remove(idx); + bcx.notify(); } }); self.badges = build(&self.backend, window, cx); @@ -280,11 +280,11 @@ impl SettingsView { SharedString::from(format!("badge-active-{idx}")), active, move |p, v| { - if let Some(e) = p.badges.entries.get_mut(idx) { - if e.active != v { - e.active = v; - return true; - } + if let Some(e) = p.badges.entries.get_mut(idx) + && e.active != v + { + e.active = v; + return true; } false }, @@ -297,11 +297,11 @@ impl SettingsView { SharedString::from(format!("badge-dist-{idx}")), distinguish, move |p, v| { - if let Some(e) = p.badges.entries.get_mut(idx) { - if e.distinguish_dir != v { - e.distinguish_dir = v; - return true; - } + if let Some(e) = p.badges.entries.get_mut(idx) + && e.distinguish_dir != v + { + e.distinguish_dir = v; + return true; } false }, @@ -314,11 +314,11 @@ impl SettingsView { SharedString::from(format!("badge-outline-{idx}")), outline, move |p, v| { - if let Some(e) = p.badges.entries.get_mut(idx) { - if e.outline != v { - e.outline = v; - return true; - } + if let Some(e) = p.badges.entries.get_mut(idx) + && e.outline != v + { + e.outline = v; + return true; } false }, diff --git a/crates/moon-ui-gpui/src/settings/common.rs b/crates/moon-ui-gpui/src/settings/common.rs index c9648d12f..22a16d3c2 100644 --- a/crates/moon-ui-gpui/src/settings/common.rs +++ b/crates/moon-ui-gpui/src/settings/common.rs @@ -231,10 +231,10 @@ pub(super) fn draft_color( }; let c = hsla_u8(*h); this.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if apply(p, c) { - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && apply(p, c) + { + bcx.notify(); } }); }) @@ -300,10 +300,10 @@ pub(super) fn draft_slider_on( let f = f.end(); let f = if f == 0.0 { 0.0 } else { f }; this.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if apply(p, f, bcx) { - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && apply(p, f, bcx) + { + bcx.notify(); } }); }) diff --git a/crates/moon-ui-gpui/src/settings/connections/mod.rs b/crates/moon-ui-gpui/src/settings/connections/mod.rs index 84ed3a312..0302eda3f 100644 --- a/crates/moon-ui-gpui/src/settings/connections/mod.rs +++ b/crates/moon-ui-gpui/src/settings/connections/mod.rs @@ -197,16 +197,15 @@ fn conn_input( if matches!(ev, MoonInputEvent::Change) { let val = emitter.read(cx).value().to_string(); this.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if let Some(s) = p.servers.get_mut(i) { - if get(s) != val { - set(s, val); - if sync_groups { - sync_groups_from_servers(&p.servers, &mut p.groups); - } - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && let Some(s) = p.servers.get_mut(i) + && get(s) != val + { + set(s, val); + if sync_groups { + sync_groups_from_servers(&p.servers, &mut p.groups); } + bcx.notify(); } }); // This keystroke may have re-ranked the list under the field being typed into; the @@ -233,11 +232,11 @@ fn conn_color( init: [u8; 3], ) -> Entity { super::draft_color(window, cx, init, move |p, c| { - if let Some(s) = p.servers.get_mut(i) { - if s.color != c { - s.color = c; - return true; - } + if let Some(s) = p.servers.get_mut(i) + && s.color != c + { + s.color = c; + return true; } false }) diff --git a/crates/moon-ui-gpui/src/settings/connections/tab.rs b/crates/moon-ui-gpui/src/settings/connections/tab.rs index 00846a701..dbeaaba0c 100644 --- a/crates/moon-ui-gpui/src/settings/connections/tab.rs +++ b/crates/moon-ui-gpui/src/settings/connections/tab.rs @@ -334,11 +334,11 @@ fn group_header_row( let n = nm_act.clone(); let _ = weak.update(cx, |this, ctx| { this.backend.update(ctx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if let Some(gc) = p.groups.iter_mut().find(|g| g.name == n) { - gc.active = v; - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && let Some(gc) = p.groups.iter_mut().find(|g| g.name == n) + { + gc.active = v; + bcx.notify(); } }); ctx.notify(); @@ -468,11 +468,11 @@ fn icon_picker_grid( let n = nm.clone(); let _ = weak_ico.update(cx, |this, ctx| { this.backend.update(ctx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if let Some(g) = p.groups.iter_mut().find(|g| g.name == n) { - g.icon = id; - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && let Some(g) = p.groups.iter_mut().find(|g| g.name == n) + { + g.icon = id; + bcx.notify(); } }); this.picking = None; @@ -787,7 +787,7 @@ impl SettingsView { }; let st = factory_status.get(core_id).cloned(); let built = server_row( - &view_ref, + view_ref, &factory_weak, row, *draft_index, diff --git a/crates/moon-ui-gpui/src/settings/connections/table.rs b/crates/moon-ui-gpui/src/settings/connections/table.rs index 01a46f169..29ba9b2a0 100644 --- a/crates/moon-ui-gpui/src/settings/connections/table.rs +++ b/crates/moon-ui-gpui/src/settings/connections/table.rs @@ -209,11 +209,11 @@ fn draft_checkbox_weak( let _ = weak.update(cx, |this, ctx| { let changed = this.backend.update(ctx, |b, bcx| { let mut changed = false; - if let Some(p) = b.preview.as_mut() { - if apply(p, v) { - bcx.notify(); - changed = true; - } + if let Some(p) = b.preview.as_mut() + && apply(p, v) + { + bcx.notify(); + changed = true; } changed }); @@ -260,11 +260,11 @@ fn srv_check( .unwrap_or(false) }; let mut checkbox = draft_checkbox_weak(weak, id, cur, move |p, v| { - if let Some(s) = p.servers.get_mut(i) { - if get(s) != v { - set(s, v); - return true; - } + if let Some(s) = p.servers.get_mut(i) + && get(s) != v + { + set(s, v); + return true; } false }); @@ -331,19 +331,19 @@ fn paste_key_affix( key_state.update(cx, |st, c| st.set_value(text.clone(), window, c)); let _ = weak.update(cx, |this, ctx| { this.backend.update(ctx, |b, bcx| { - if let Some(pv) = b.preview.as_mut() { - if let Some(s) = pv.servers.get_mut(i) { - s.transport = moon_core::config::seeded_transport(s.transport, &text); - s.key = Secret::new(text.clone()); - // A new key can point this row at a DIFFERENT Moonbot, and strategy ids - // are unique per host, not globally — so the pinned id would silently - // name whatever strategy inherited that number there. The NAME survives - // and re-pins itself against the new host's list. - if let Some(manual) = s.manual_strategy.as_mut() { - manual.id = 0; - } - bcx.notify(); + if let Some(pv) = b.preview.as_mut() + && let Some(s) = pv.servers.get_mut(i) + { + s.transport = moon_core::config::seeded_transport(s.transport, &text); + s.key = Secret::new(text.clone()); + // A new key can point this row at a DIFFERENT Moonbot, and strategy ids + // are unique per host, not globally — so the pinned id would silently + // name whatever strategy inherited that number there. The NAME survives + // and re-pins itself against the new host's list. + if let Some(manual) = s.manual_strategy.as_mut() { + manual.id = 0; } + bcx.notify(); } }); // A nonempty-to-nonempty paste must refresh every duplicate marker. @@ -502,12 +502,12 @@ impl SettingsView { /// Nothing; the method removes the row when it exists and clears row-owned transient state. pub(super) fn delete_server(&mut self, i: usize, window: &mut Window, cx: &mut Context) { self.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if i < p.servers.len() { - p.servers.remove(i); - sync_groups_from_servers(&p.servers, &mut p.groups); - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && i < p.servers.len() + { + p.servers.remove(i); + sync_groups_from_servers(&p.servers, &mut p.groups); + bcx.notify(); } }); let rows = build_conn(&self.backend, window, cx); @@ -581,7 +581,7 @@ fn feed_popover( let feed = { let b = view.backend.read(cx); let s = b.preview.as_ref().unwrap_or(&b.config).servers.get(i); - s.map(|s| s.feed.clone()).unwrap_or_default() + s.map(|s| s.feed).unwrap_or_default() }; let on = FEED_FLAGS.iter().filter(|(_, g, _)| g(&feed)).count(); let tinted = on < FEED_FLAGS.len(); @@ -610,11 +610,11 @@ fn feed_popover( }) .on_click(move |_, _, cx| { backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if let Some(s) = p.servers.get_mut(i) { - set(&mut s.feed, !cur); - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && let Some(s) = p.servers.get_mut(i) + { + set(&mut s.feed, !cur); + bcx.notify(); } }); }), diff --git a/crates/moon-ui-gpui/src/settings/general.rs b/crates/moon-ui-gpui/src/settings/general.rs index e54417218..99ad083ae 100644 --- a/crates/moon-ui-gpui/src/settings/general.rs +++ b/crates/moon-ui-gpui/src/settings/general.rs @@ -157,14 +157,14 @@ impl SettingsView { fn adjust_idle(&mut self, delta: i32, cx: &mut Context) { let changed = self.backend.update(cx, |b, bcx| { let mut changed = false; - if let Some(p) = b.preview.as_mut() { - if p.main_idle_close_secs > 0 { - let v = (p.main_idle_close_secs as i32 + delta).clamp(5, 3600) as u32; - if p.main_idle_close_secs != v { - p.main_idle_close_secs = v; - bcx.notify(); - changed = true; - } + if let Some(p) = b.preview.as_mut() + && p.main_idle_close_secs > 0 + { + let v = (p.main_idle_close_secs as i32 + delta).clamp(5, 3600) as u32; + if p.main_idle_close_secs != v { + p.main_idle_close_secs = v; + bcx.notify(); + changed = true; } } changed diff --git a/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs b/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs index d65f4cd91..cdfdd178c 100644 --- a/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs +++ b/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs @@ -443,11 +443,11 @@ impl SettingsView { .on_hover(cx.listener(move |this, entered: &bool, _window, cx| { let next = entered.then(|| row_id.clone()); // A leave clears only this row: the next row's enter may already have landed. - if *entered || this.hotkeys_hover_row.as_deref() == Some(row_id.as_str()) { - if this.hotkeys_hover_row != next { - this.hotkeys_hover_row = next; - cx.notify(); - } + if (*entered || this.hotkeys_hover_row.as_deref() == Some(row_id.as_str())) + && this.hotkeys_hover_row != next + { + this.hotkeys_hover_row = next; + cx.notify(); } })) .w_full() diff --git a/crates/moon-ui-gpui/src/settings/import_preview.rs b/crates/moon-ui-gpui/src/settings/import_preview.rs index 4d00302ae..9f82c7080 100644 --- a/crates/moon-ui-gpui/src/settings/import_preview.rs +++ b/crates/moon-ui-gpui/src/settings/import_preview.rs @@ -125,7 +125,7 @@ impl SettingsView { Ok::<_, moonbot_import::ImportError>(plan) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { // Do not resurrect the preview if the settings window closed during loading. if !matches!(this.import, Some(ImportState::Loading)) { @@ -360,11 +360,11 @@ impl SettingsView { .checked(*on) .label(name.clone()) .on_change(cx.listener(move |this, ch: &bool, _, cx| { - if let Some(ImportState::Ready(st)) = this.import.as_mut() { - if let Some(c) = st.cores.get_mut(idx) { - c.2 = *ch; - cx.notify(); - } + if let Some(ImportState::Ready(st)) = this.import.as_mut() + && let Some(c) = st.cores.get_mut(idx) + { + c.2 = *ch; + cx.notify(); } })), ); diff --git a/crates/moon-ui-gpui/src/settings/mod.rs b/crates/moon-ui-gpui/src/settings/mod.rs index 326c0fda3..4ba38954c 100644 --- a/crates/moon-ui-gpui/src/settings/mod.rs +++ b/crates/moon-ui-gpui/src/settings/mod.rs @@ -317,11 +317,11 @@ impl SettingsView { let v = *ch; let changed = this.backend.update(cx, |b, bcx| { let mut changed = false; - if let Some(p) = b.preview.as_mut() { - if apply(p, v) { - bcx.notify(); - changed = true; - } + if let Some(p) = b.preview.as_mut() + && apply(p, v) + { + bcx.notify(); + changed = true; } changed }); @@ -936,13 +936,12 @@ pub fn open_on_tab( tab: Tab, cx: &mut App, ) { - if let Some(handle) = backend.read(cx).settings_window { - if handle + if let Some(handle) = backend.read(cx).settings_window + && handle .update(cx, |_, window, _| window.activate_window()) .is_ok() - { - return; - } + { + return; } if backend.read(cx).preview.is_some() { return; diff --git a/crates/moon-ui-gpui/src/settings/storage.rs b/crates/moon-ui-gpui/src/settings/storage.rs index c261907b2..fb17fd4d4 100644 --- a/crates/moon-ui-gpui/src/settings/storage.rs +++ b/crates/moon-ui-gpui/src/settings/storage.rs @@ -117,7 +117,7 @@ impl SettingsView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); let info = executor.spawn(async move { collect_info() }).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.storage.inflight = false; this.storage.info = Some(info); @@ -149,7 +149,7 @@ impl SettingsView { cx.spawn(async move |this, cx| { let executor = cx.update(|cx| cx.background_executor().clone()); let result = executor.spawn(async move { job() }).await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.storage.busy = false; this.status = Some(match result { @@ -244,7 +244,7 @@ impl SettingsView { /// 60, seconds otherwise. 65 s is a step and must not read as "1 min", which is what 60 s /// already says. fn trades_margin_label(secs: u32) -> String { - if secs % 60 == 0 { + if secs.is_multiple_of(60) { t!("storage.trades_min", min = secs / 60).to_string() } else { t!("storage.trades_sec", s = secs).to_string() diff --git a/crates/moon-ui-gpui/src/settings/telegram.rs b/crates/moon-ui-gpui/src/settings/telegram.rs index e469f70e2..1db0e41f7 100644 --- a/crates/moon-ui-gpui/src/settings/telegram.rs +++ b/crates/moon-ui-gpui/src/settings/telegram.rs @@ -84,11 +84,11 @@ pub(super) fn build( if matches!(ev, MoonInputEvent::Change) { let val = emitter.read(cx).value().to_string(); this.backend.update(cx, |b, bcx| { - if let Some(p) = b.preview.as_mut() { - if p.telegram.token.expose() != val { - p.telegram.token = Secret::new(val); - bcx.notify(); - } + if let Some(p) = b.preview.as_mut() + && p.telegram.token.expose() != val + { + p.telegram.token = Secret::new(val); + bcx.notify(); } }); } diff --git a/crates/moon-ui-gpui/src/shell/actions.rs b/crates/moon-ui-gpui/src/shell/actions.rs index 16026e16b..caeae12a9 100644 --- a/crates/moon-ui-gpui/src/shell/actions.rs +++ b/crates/moon-ui-gpui/src/shell/actions.rs @@ -329,7 +329,8 @@ impl Shell { ) -> bool { use crate::hotkeys::HotkeyAction; let group = self.group.clone(); - let handled = match action { + + match action { HotkeyAction::SuperZoomIn | HotkeyAction::SuperZoomOut => { self.backend.update(cx, |b, bcx| { b.super_zoom_group = Some(group.clone()); @@ -452,8 +453,7 @@ impl Shell { crate::hotkeys::apply(other, b, bcx, &group, target, active_core) }) } - }; - handled + } } } diff --git a/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs b/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs index 1312606de..911e90a9b 100644 --- a/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs +++ b/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs @@ -143,10 +143,10 @@ pub(super) fn cs_checkbox( .on_change(move |ch: &bool, _w, app| { let on = *ch; let b = backend.read(app); - if let Some(core) = resolve_core_settings_write(seeded, b.active_trade_core(&group)) { - if let Err(e) = b.session.edit_client_settings(core, edit(on)) { - log::warn!("core settings edit failed: {e:#}"); - } + if let Some(core) = resolve_core_settings_write(seeded, b.active_trade_core(&group)) + && let Err(e) = b.session.edit_client_settings(core, edit(on)) + { + log::warn!("core settings edit failed: {e:#}"); } }) } diff --git a/crates/moon-ui-gpui/src/shell/init.rs b/crates/moon-ui-gpui/src/shell/init.rs index a1cb7c228..36a686572 100644 --- a/crates/moon-ui-gpui/src/shell/init.rs +++ b/crates/moon-ui-gpui/src/shell/init.rs @@ -357,14 +357,15 @@ impl Shell { let Some((group, ix)) = this.size_edit.as_ref() else { return; }; - if let Ok(v) = inp.read(cx).value().trim().replace(',', ".").parse::() { - if v > 0.0 && *ix < 6 { - this.backend.update(cx, |b, bcx| { - b.set_order_size_value(group, *ix, v); - b.order_size_rev = b.order_size_rev.wrapping_add(1); - bcx.notify(); - }); - } + if let Ok(v) = inp.read(cx).value().trim().replace(',', ".").parse::() + && v > 0.0 + && *ix < 6 + { + this.backend.update(cx, |b, bcx| { + b.set_order_size_value(group, *ix, v); + b.order_size_rev = b.order_size_rev.wrapping_add(1); + bcx.notify(); + }); } return; } @@ -375,18 +376,19 @@ impl Shell { return; }; let raw = inp.read(cx).value().to_string(); - if let Ok(v) = raw.trim().replace(',', ".").parse::() { - if v > 0.0 && ix < 6 { - this.backend.update(cx, |b, bcx| { - b.set_order_size_value(&group, ix, v); - if let Err(error) = b.config.save() { - log::warn!("save order size failed: {error}"); - } else { - b.config_dirty = false; - } - bcx.notify(); - }); - } + if let Ok(v) = raw.trim().replace(',', ".").parse::() + && v > 0.0 + && ix < 6 + { + this.backend.update(cx, |b, bcx| { + b.set_order_size_value(&group, ix, v); + if let Err(error) = b.config.save() { + log::warn!("save order size failed: {error}"); + } else { + b.config_dirty = false; + } + bcx.notify(); + }); } cx.notify(); }) @@ -405,20 +407,20 @@ impl Shell { }; if let Ok(v) = inp.read(cx).value().trim().replace(',', ".").parse::() && v.is_finite() + && v >= 0.0 + && ix < 6 { - if v >= 0.0 && ix < 6 { - this.backend.update(cx, |b, bcx| { - b.edit_group_exit( - &group, - ClientSettingsEdit::SetFixedSellPct { - slot: ix + 1, - pct: v, - }, - ); - b.order_size_rev = b.order_size_rev.wrapping_add(1); - bcx.notify(); - }); - } + this.backend.update(cx, |b, bcx| { + b.edit_group_exit( + &group, + ClientSettingsEdit::SetFixedSellPct { + slot: ix + 1, + pct: v, + }, + ); + b.order_size_rev = b.order_size_rev.wrapping_add(1); + bcx.notify(); + }); } cx.notify(); }) diff --git a/crates/moon-ui-gpui/src/shell/ticker.rs b/crates/moon-ui-gpui/src/shell/ticker.rs index 3bebb7edc..45ce1be23 100644 --- a/crates/moon-ui-gpui/src/shell/ticker.rs +++ b/crates/moon-ui-gpui/src/shell/ticker.rs @@ -76,7 +76,7 @@ impl Shell { let query = self.ticker_input.read(cx).value().to_string(); let results = { let b = self.backend.read(cx); - coin_search::search(&b, &self.group, None, &query) + coin_search::search(b, &self.group, None, &query) }; let backend = self.backend.clone(); let view = cx.entity(); diff --git a/crates/moon-ui-gpui/src/shell/workspace.rs b/crates/moon-ui-gpui/src/shell/workspace.rs index d221a8de3..e327fcaaf 100644 --- a/crates/moon-ui-gpui/src/shell/workspace.rs +++ b/crates/moon-ui-gpui/src/shell/workspace.rs @@ -9,7 +9,7 @@ use gpui::*; use moon_core::config::{ AUTO_WORKSPACE_RAIL_WIDTH_MAX, AUTO_WORKSPACE_RAIL_WIDTH_MIN, WorkspaceMode, }; -use moon_core::feed::{ConnStatus, CoreStartupStatus}; +use moon_core::feed::ConnStatus; use moon_core::session::CoreId; use moon_core::venue::CoreVenue; use moon_ui::{ @@ -103,11 +103,11 @@ fn auto_workspace_activation_fallback(activated: bool) -> Option<&'static str> { /// /// Returns: /// The eligible name to persist, or `None` for Classic, programmatic, or ineligible events. -pub(super) fn auto_workspace_tab_to_persist<'a>( +pub(super) fn auto_workspace_tab_to_persist( auto: bool, applying_topology: bool, - panel_name: &'a str, -) -> Option<&'a str> { + panel_name: &str, +) -> Option<&str> { (auto && !applying_topology && auto_workspace_tab_is_eligible(panel_name)).then_some(panel_name) } @@ -583,7 +583,7 @@ impl Shell { cx.spawn(async move |this, cx| { cx.background_spawn(async { crate::media::exchange_logos::prewarm() }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.exchange_logos_ready = true; cx.notify(); @@ -1088,9 +1088,7 @@ impl Shell { availability: backend.workspace_core_availability(&server.group, server.id), ready: core.is_some_and(|core| core.status == ConnStatus::Ready), connection: core.map(|core| core.status.clone()), - startup: core - .map(|core| core.startup) - .unwrap_or_else(CoreStartupStatus::default), + startup: core.map(|core| core.startup).unwrap_or_default(), fault: core.and_then(|core| core.fault.clone()), // Fed the WHOLE fleet, not the membership-filtered rows below: a hidden // core still connects, so a transport suggestion computed over a subset @@ -1467,7 +1465,7 @@ fn render_rail_item( let controls = (run.exchange_controls && density != WorkspaceRailDensity::Icon && !cores.is_empty()) - .then(|| RunScope { + .then_some(RunScope { key: RunKey::Section(section), cores, reserve: run.slots, diff --git a/crates/moon-ui-gpui/src/startup/boot.rs b/crates/moon-ui-gpui/src/startup/boot.rs index 4bf8930b3..308ff4a46 100644 --- a/crates/moon-ui-gpui/src/startup/boot.rs +++ b/crates/moon-ui-gpui/src/startup/boot.rs @@ -675,8 +675,8 @@ pub(super) fn boot(cfg: AppConfig, input: BootInput, cx: &mut App) { 20_000, ); cx.update(|cx| { - if let Some(guard) = &coord_instance { - if super::instance::poll_activation(guard) { + if let Some(guard) = &coord_instance + && super::instance::poll_activation(guard) { let handles: Vec<_> = coord_backend .read(cx) .group_windows @@ -687,7 +687,6 @@ pub(super) fn boot(cfg: AppConfig, input: BootInput, cx: &mut App) { let _ = handle.update(cx, |_, window, _| window.activate_window()); } } - } let mut edges = TickEdges::default(); consume_report_commit(coord_report_immediate_dirty.as_deref(), || { edges.immediate_report = true; @@ -703,11 +702,10 @@ pub(super) fn boot(cfg: AppConfig, input: BootInput, cx: &mut App) { }); let revision = report_revision_gate.observe(edges, Instant::now()); let (show_reqs, open_debug_10) = coord_backend.update(cx, |b, cx| { - if revision.wake_valuation { - if let Some(valuation) = &b.valuation { + if revision.wake_valuation + && let Some(valuation) = &b.valuation { valuation.wake(); } - } b.tick_telegram(cx); // The startup cleanup of the trade tape, then the tape autoload of the // tuner's Entry/Exit axis — in that order, the autoload waits for the diff --git a/crates/moon-ui-gpui/src/startup/strategy_filters_migration.rs b/crates/moon-ui-gpui/src/startup/strategy_filters_migration.rs index f72006ced..ea7196ce9 100644 --- a/crates/moon-ui-gpui/src/startup/strategy_filters_migration.rs +++ b/crates/moon-ui-gpui/src/startup/strategy_filters_migration.rs @@ -79,10 +79,10 @@ pub(super) fn migrate_strategy_filters( ); } } - if let Some(mut cfg) = layout.stored_chart_labels(ChartTabKind::AddTo).cloned() { - if append_if_missing(&mut cfg) == Some(true) { - layout.store_chart_labels(ChartTabKind::AddTo, cfg); - } + if let Some(mut cfg) = layout.stored_chart_labels(ChartTabKind::AddTo).cloned() + && append_if_missing(&mut cfg) == Some(true) + { + layout.store_chart_labels(ChartTabKind::AddTo, cfg); } for spec in specs.iter_mut() { let kind = crate::chart_tabs::apply_all::spec_kind(spec); diff --git a/crates/moon-ui-gpui/src/strategies/actions.rs b/crates/moon-ui-gpui/src/strategies/actions.rs index c17071c84..9867dc7d5 100644 --- a/crates/moon-ui-gpui/src/strategies/actions.rs +++ b/crates/moon-ui-gpui/src/strategies/actions.rs @@ -202,10 +202,11 @@ impl StrategiesView { } // A removed strategy changes the captured identity just as surely as a hidden core. Check // every row before the first per-core command so no surviving subset can be sent. - if { + let res = { let store = self.backend.read(cx).session.store(); !strategy_targets_exist(&plan.targets, |(core, id)| row(store, core, id).is_some()) - } { + }; + if res { return; } let applied_cores: HashSet = plan.actions.iter().map(|(core, _)| *core).collect(); @@ -447,10 +448,11 @@ impl StrategiesView { { return; } - if { + let res = { let store = self.backend.read(cx).session.store(); !strategy_targets_exist(&plan.targets, |(core, id)| row(store, core, id).is_some()) - } { + }; + if res { return; } // Drafts the core would refuse are dropped HERE rather than in the captured plan: sending diff --git a/crates/moon-ui-gpui/src/strategies/fields.rs b/crates/moon-ui-gpui/src/strategies/fields.rs index 4e7ef3d15..6c81311fe 100644 --- a/crates/moon-ui-gpui/src/strategies/fields.rs +++ b/crates/moon-ui-gpui/src/strategies/fields.rs @@ -80,10 +80,10 @@ impl StrategiesView { cx: &mut Context, ) -> Entity { let rgb_val = parse_hex_rgb(hex); - if let Some((cached, state)) = self.field_colors.get(&id) { - if *cached == rgb_val { - return state.clone(); - } + if let Some((cached, state)) = self.field_colors.get(&id) + && *cached == rgb_val + { + return state.clone(); } let state = crate::controls::color_picker::shared_color_state(rgb_val, window, cx); let prefix = hex_alpha_prefix(hex); diff --git a/crates/moon-ui-gpui/src/strategies/full_params.rs b/crates/moon-ui-gpui/src/strategies/full_params.rs index c11a27dda..c1a6010e2 100644 --- a/crates/moon-ui-gpui/src/strategies/full_params.rs +++ b/crates/moon-ui-gpui/src/strategies/full_params.rs @@ -117,11 +117,11 @@ impl StrategiesView { _window: &mut Window, cx: &mut Context, ) -> AnyElement { - if let Some(section) = self.pending_param_scroll.take() { - if let Some(ix) = resolve_scroll_target(&flat, section) { - self.params_scroll - .scroll_to_item_strict(ix, ScrollStrategy::Top); - } + if let Some(section) = self.pending_param_scroll.take() + && let Some(ix) = resolve_scroll_target(&flat, section) + { + self.params_scroll + .scroll_to_item_strict(ix, ScrollStrategy::Top); } let frozen = self.viewing_version(); diff --git a/crates/moon-ui-gpui/src/strategies/param_entries.rs b/crates/moon-ui-gpui/src/strategies/param_entries.rs index d43fe8cae..ecf76f428 100644 --- a/crates/moon-ui-gpui/src/strategies/param_entries.rs +++ b/crates/moon-ui-gpui/src/strategies/param_entries.rs @@ -96,18 +96,18 @@ pub(super) fn flatten_params( if multi && lname == "strategyname" { continue; } - if let Some(c) = common { - if !c.contains(&lname) { - continue; - } + if let Some(c) = common + && !c.contains(&lname) + { + continue; } if differ && lname == "signaltype" { continue; } - if let Some(ch) = changed { - if !ch.contains_key(&lname) { - continue; - } + if let Some(ch) = changed + && !ch.contains_key(&lname) + { + continue; } fields.push(f.clone()); } diff --git a/crates/moon-ui-gpui/src/strategies/params.rs b/crates/moon-ui-gpui/src/strategies/params.rs index 86075dc75..6ea1330a3 100644 --- a/crates/moon-ui-gpui/src/strategies/params.rs +++ b/crates/moon-ui-gpui/src/strategies/params.rs @@ -1344,16 +1344,16 @@ impl StrategiesView { // total: Apply and Revert both empty `field_edits` for it. Only `Staged` is retired this // way — `ClearedOnly` has already discarded stale drafts and `Identical` never had any, // so testing either here would vanish the note the very frame it is set. - if let Some((key, outcome, _)) = self.versions.staged_note { - if matches!(outcome, StagedOutcome::Staged(_)) { - let remaining = self - .field_edits - .keys() - .filter(|(core, id, _)| (*core, *id) == key) - .count(); - if remaining == 0 { - self.versions.staged_note = None; - } + if let Some((key, outcome, _)) = self.versions.staged_note + && matches!(outcome, StagedOutcome::Staged(_)) + { + let remaining = self + .field_edits + .keys() + .filter(|(core, id, _)| (*core, *id) == key) + .count(); + if remaining == 0 { + self.versions.staged_note = None; } } let p = MoonPalette::active(cx); @@ -1613,10 +1613,10 @@ impl StrategiesView { if multi && lname == "strategyname" { continue; } - if let Some(c) = &common { - if !c.contains(&lname) { - continue; - } + if let Some(c) = &common + && !c.contains(&lname) + { + continue; } if differ && lname == "signaltype" { continue; @@ -1660,10 +1660,10 @@ impl StrategiesView { // either doing visibly nothing, or, worse, silently staging into a retained state left // over from an earlier per-section visit that this pane is not displaying. Editing a // formula in full mode goes through the row's own edit-in-sections button, which switches back. - if !self.prefs.params_full { - if let Some(helper) = self.formula_helper(cx) { - pane_body = pane_body.child(helper); - } + if !self.prefs.params_full + && let Some(helper) = self.formula_helper(cx) + { + pane_body = pane_body.child(helper); } col = col.child(pane_body); col.into_any_element() @@ -2418,16 +2418,14 @@ impl StrategiesView { { let b = self.backend.read(cx); let store = b.session.store(); - if let Some(sections) = selected_sections(self, store) { - if let Some(f) = sections + if let Some(sections) = selected_sections(self, store) + && let Some(f) = sections .iter() .flat_map(|s| &s.fields) .find(|f| f.name == field) - { - if f.type_name != "String" || !matches!(f.ui, SchemaFieldUi::Edit) { - return None; - } - } + && (f.type_name != "String" || !matches!(f.ui, SchemaFieldUi::Edit)) + { + return None; } } let p = MoonPalette::active(cx); diff --git a/crates/moon-ui-gpui/src/strategies/sections.rs b/crates/moon-ui-gpui/src/strategies/sections.rs index e6fbbf497..aa1ff6e9b 100644 --- a/crates/moon-ui-gpui/src/strategies/sections.rs +++ b/crates/moon-ui-gpui/src/strategies/sections.rs @@ -184,15 +184,13 @@ impl StrategiesView { let label = section_label_key(§ion.title) .filter(|_| self.prefs.human_labels) .map_or(0.0, |key| { - design::ui_caption_text_width(cx, &t!(key).to_string(), 400.0) + design::ui_caption_text_width(cx, t!(key).as_ref(), 400.0) }); raw.max(label) }) .reduce(f32::max) }) - .unwrap_or_else(|| { - design::ui_body_text_width(cx, &t!("strat.sections").to_string(), 600.0) - }) + .unwrap_or_else(|| design::ui_body_text_width(cx, t!("strat.sections").as_ref(), 600.0)) } /// Render schema sections using dependency values shared with the parameters panel. diff --git a/crates/moon-ui-gpui/src/strategies/tree/dnd.rs b/crates/moon-ui-gpui/src/strategies/tree/dnd.rs index 14b9b2cff..43643f54f 100644 --- a/crates/moon-ui-gpui/src/strategies/tree/dnd.rs +++ b/crates/moon-ui-gpui/src/strategies/tree/dnd.rs @@ -187,9 +187,7 @@ impl StrategiesView { return Some(tree::ui::TreeNote::CoreNotCut); } self.copy_folders(folders, cx); - if self.clipboard.is_none() { - return None; - } + self.clipboard.as_ref()?; let marks: Vec<(CoreId, Vec)> = folders .iter() .map(|(core, path)| (*core, ops::split_path(path))) diff --git a/crates/moon-ui-gpui/src/strategies/tree/ops/tests.rs b/crates/moon-ui-gpui/src/strategies/tree/ops/tests.rs index e14dfeab4..e9f268bd4 100644 --- a/crates/moon-ui-gpui/src/strategies/tree/ops/tests.rs +++ b/crates/moon-ui-gpui/src/strategies/tree/ops/tests.rs @@ -295,7 +295,7 @@ fn the_text_clipboard_drops_the_source_anchor() { #[test] fn copy_rows_flattens_to_target() { // A multi-selection from different folders has empty relative paths, so paste puts all in target. - let rows = vec![ + let rows = [ row(1, "a", "grpA/p1", false), row(2, "b", "grpB/sub/p2", false), ]; @@ -429,7 +429,7 @@ fn tree_ops_move_folder(rows: &[StrategyRow], folder: &str, target: &str) -> Vec #[test] fn move_to_flattens_to_target() { // Moving a multi-selection from different folders puts every row directly in the target. - let rows = vec![ + let rows = [ row(1, "a", "src/p1", false), row(2, "b", "other/grp/p2", false), ]; diff --git a/crates/moon-ui-gpui/src/strategies/versions.rs b/crates/moon-ui-gpui/src/strategies/versions.rs index 6aee65274..8f6d4a49a 100644 --- a/crates/moon-ui-gpui/src/strategies/versions.rs +++ b/crates/moon-ui-gpui/src/strategies/versions.rs @@ -169,7 +169,7 @@ impl StrategiesView { async move { moon_core::strat_db::stats::versions_with_stats(core, id as i64) }, ) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.versions.inflight = false; if this.versions.key == Some((core, id)) { @@ -183,12 +183,11 @@ impl StrategiesView { } // A reveal that named a version wins over the deleted default above: it // is the more specific ask, and it arrived from the same click. - if let Some((key, vf)) = this.versions.pending_select.take() { - if key == (core, id) - && this.versions.list.iter().any(|v| v.valid_from == vf) - { - this.select_version(Some(vf), cx); - } + if let Some((key, vf)) = this.versions.pending_select.take() + && key == (core, id) + && this.versions.list.iter().any(|v| v.valid_from == vf) + { + this.select_version(Some(vf), cx); } cx.notify(); } @@ -212,7 +211,7 @@ impl StrategiesView { let heads = executor .spawn(async move { moon_core::strat_db::stats::deleted_heads() }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.deleted_inflight = false; this.deleted_loaded = true; @@ -269,7 +268,7 @@ impl StrategiesView { Some((view.fields, ignore)) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { let Some((fields, ignore)) = payload else { return; @@ -476,7 +475,7 @@ impl StrategiesView { Some((head, fields)) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let Some((head, fields)) = payload else { log::warn!("восстановление {id}: нет head/версий в strat_db"); return; @@ -580,7 +579,7 @@ impl StrategiesView { ) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { let Some(view) = view else { return }; if this.versions.sel != Some(vf) @@ -610,10 +609,9 @@ impl StrategiesView { }); if let Some(mut r) = base { if let Some((_, n)) = view.fields.iter().find(|(k, _)| k == "StrategyName") + && !n.is_empty() { - if !n.is_empty() { - r.name = n.clone(); - } + r.name = n.clone(); } r.fields = view.fields; this.versions.changed = view @@ -652,7 +650,9 @@ impl StrategiesView { if single { self.ensure_versions(cx); // Keep the count on the collapsed strip current. } - let count = single.then(|| self.versions.list.len()).filter(|n| *n > 0); + let count = single + .then_some(self.versions.list.len()) + .filter(|n| *n > 0); return v_flex() .id("versions-collapsed") .w(design::ui_px(cx, 22.0)) @@ -998,8 +998,7 @@ impl StrategiesView { // away (defect 5, and it must be unlosable). if let (Some(vf), true) = (self.versions.sel, live_exists) { let compact = - design::ui_body_text_width(cx, &t!("strat.version_restore").to_string(), 400.0) - + 40.0 + design::ui_body_text_width(cx, t!("strat.version_restore").as_ref(), 400.0) + 40.0 > self.panels.versions_w - design::ui_value(cx, VERSIONS_PANE_PADDING * 2.0); col = col.child( div() diff --git a/crates/moon-ui-gpui/src/trade_window/mod.rs b/crates/moon-ui-gpui/src/trade_window/mod.rs index e17c7ed4c..257aea1a3 100644 --- a/crates/moon-ui-gpui/src/trade_window/mod.rs +++ b/crates/moon-ui-gpui/src/trade_window/mod.rs @@ -732,7 +732,7 @@ impl TradeWindowView { let lookup = executor .spawn(async move { strategy::StrategyLookup::read(core, strategy_id, buy_utc_ms) }) .await; - let _ = cx.update(|cx| { + cx.update(|cx| { let _ = this.update(cx, |this, cx| { this.strategy_lookup = Some(lookup); cx.notify(); diff --git a/crates/moon-ui-gpui/src/window/group_window.rs b/crates/moon-ui-gpui/src/window/group_window.rs index e8ae706ee..2166c2150 100644 --- a/crates/moon-ui-gpui/src/window/group_window.rs +++ b/crates/moon-ui-gpui/src/window/group_window.rs @@ -126,13 +126,12 @@ fn spawn_group_window_inner( publish_workspace_change: bool, ) { // Focus an existing live window. handle.update returns an error for a window already closed. - if let Some(handle) = backend.read(cx).group_windows.get(&group).copied() { - if handle + if let Some(handle) = backend.read(cx).group_windows.get(&group).copied() + && handle .update(cx, |_, window, _| window.activate_window()) .is_ok() - { - return; - } + { + return; } // Do not open a Main market automatically at startup. Main starts empty until the user selects // one; the former behavior used server.market with BTCUSDT as fallback. diff --git a/crates/moon-ui-gpui/src/window/windowing.rs b/crates/moon-ui-gpui/src/window/windowing.rs index 18fbafde0..f08d5eadf 100644 --- a/crates/moon-ui-gpui/src/window/windowing.rs +++ b/crates/moon-ui-gpui/src/window/windowing.rs @@ -111,7 +111,7 @@ pub(crate) fn window_hwnd(window: &Window) -> Option { let RawWindowHandle::Win32(handle) = handle.as_raw() else { return None; }; - Some(handle.hwnd.get() as isize) + Some(handle.hwnd.get()) } #[cfg(not(target_os = "windows"))] @@ -526,16 +526,14 @@ pub(crate) fn saved_or_owner_display_id( if let Some(id) = saved_uuid.and_then(|saved| display_id_for_uuid(saved, cx)) { return Some(id); } - if WINDOW_COORDS_ARE_GLOBAL { - if let Some(origin) = saved_origin { - if let Some(d) = cx - .displays() - .into_iter() - .find(|d| d.bounds().contains(&origin)) - { - return Some(d.id()); - } - } + if WINDOW_COORDS_ARE_GLOBAL + && let Some(origin) = saved_origin + && let Some(d) = cx + .displays() + .into_iter() + .find(|d| d.bounds().contains(&origin)) + { + return Some(d.id()); } let owner_id = owner_display.or_else(|| owner_display_id(owner, cx)); owner_id.or_else(|| cx.primary_display().map(|display| display.id())) diff --git a/crates/moon-ui-gpui/src/workspace/tests.rs b/crates/moon-ui-gpui/src/workspace/tests.rs index c9ee58004..e575096de 100644 --- a/crates/moon-ui-gpui/src/workspace/tests.rs +++ b/crates/moon-ui-gpui/src/workspace/tests.rs @@ -307,7 +307,7 @@ fn repeated_activity_in_the_same_workspace_does_not_republish_owner() { /// singleton tools fall back to Classic when the first completed window publishes or renders. #[test] fn rebuild_keeps_an_owner_reopened_second_in_singleton_scope() { - let completed = vec!["alpha".to_string()]; + let completed = ["alpha".to_string()]; let opening = vec!["beta".to_string()]; let owner_registered = completed .iter() diff --git a/crates/moon-ui-gpui/tests/theme_contract/chart.rs b/crates/moon-ui-gpui/tests/theme_contract/chart.rs index f6034e29f..d2a62f41c 100644 --- a/crates/moon-ui-gpui/tests/theme_contract/chart.rs +++ b/crates/moon-ui-gpui/tests/theme_contract/chart.rs @@ -1266,7 +1266,7 @@ fn empty_chart_stack_keeps_its_localized_size_probed_hint() { &main_stack, "fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement", ); - let branch = braced_body(&render, "if self.charts.is_empty() {"); + let branch = braced_body(render, "if self.charts.is_empty() {"); assert!( branch.contains("empty::empty_screen("), "the empty Main stack branch must render the empty screen" diff --git a/crates/moon-ui-gpui/tests/theme_contract/shell.rs b/crates/moon-ui-gpui/tests/theme_contract/shell.rs index b89ffa83d..a0aaf783b 100644 --- a/crates/moon-ui-gpui/tests/theme_contract/shell.rs +++ b/crates/moon-ui-gpui/tests/theme_contract/shell.rs @@ -1687,7 +1687,7 @@ fn the_multi_select_hint_clips_instead_of_wrapping() { let coin_search = read_src("controls/coin_search.rs"); let popup = braced_body(&coin_search, "pub(crate) fn render_popup("); let hint = chain_between( - &popup, + popup, "if multi_select {", "chart.coin.multi_hint", "the multi-select hint", diff --git a/crates/moon-ui-gpui/tests/theme_contract/strategies.rs b/crates/moon-ui-gpui/tests/theme_contract/strategies.rs index 9e9bc8f33..66ac1d027 100644 --- a/crates/moon-ui-gpui/tests/theme_contract/strategies.rs +++ b/crates/moon-ui-gpui/tests/theme_contract/strategies.rs @@ -1203,7 +1203,7 @@ fn a_core_folder_row_counter_cluster_stays_passive() { /// Overview for the whole process lifetime — the reported bug, in full. #[test] fn strategies_window_seeds_expansion_from_the_auto_workspace() { - let ctor = code_only(&braced_body( + let ctor = code_only(braced_body( &read_src("strategies/state.rs"), "pub(super) fn new(", )); @@ -1292,19 +1292,19 @@ fn strategies_reopen_state_is_process_lifetime_only() { && read_src("strategies/versions.rs").contains("self.persist_session(cx)"), "Strategies mutation writers must share persist_session" ); - let observer = code_only(&braced_body(&state, "cx.observe(&workspace_revision,")); + let observer = code_only(braced_body(&state, "cx.observe(&workspace_revision,")); assert!( observer.contains("this.rail_seen_core = rail") && !observer.contains("this.expanded_cores"), "the live window's workspace observer must move only the rail overlay, never the persisted set" ); - let capture = code_only(&braced_body(&session, "pub(super) fn capture(")); + let capture = code_only(braced_body(&session, "pub(super) fn capture(")); assert!( capture.contains("expanded_cores: view.expanded_cores.clone()") && !capture.contains("rail"), "capture must snapshot the persisted set alone, never the rail overlay" ); - let session_struct = code_only(&braced_body( + let session_struct = code_only(braced_body( &session, "pub(crate) struct StrategiesSessionState", )); @@ -1331,7 +1331,7 @@ fn strategies_reopen_state_is_process_lifetime_only() { /// construction. A call only on the create path would not catch this breakage. #[test] fn strategies_open_re_seeds_the_auto_core_on_an_existing_handle() { - let open = code_only(&braced_body( + let open = code_only(braced_body( &read_src("strategies/window.rs"), "pub fn open(", )); @@ -1439,15 +1439,14 @@ fn strategy_field_label_lookup_and_dictionary_remain_bijective() { let key = trimmed.trim_end_matches(':').to_string(); dictionary.entry(key.clone()).or_default(); current = Some(key); - } else if let Some(key) = ¤t { - if let Some((locale, _)) = trimmed.split_once(':') { - if matches!(locale, "ru" | "en" | "es") { - dictionary - .get_mut(key) - .expect("current label key was inserted") - .insert(locale.to_string()); - } - } + } else if let Some(key) = ¤t + && let Some((locale, _)) = trimmed.split_once(':') + && matches!(locale, "ru" | "en" | "es") + { + dictionary + .get_mut(key) + .expect("current label key was inserted") + .insert(locale.to_string()); } } let dictionary_keys: BTreeSet = dictionary.keys().cloned().collect(); From 6ea9babe8704a324a584b9e0bdff9358c4073d54 Mon Sep 17 00:00:00 2001 From: kirillDevPro <113171057+kirillDevPro@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:18:42 +0200 Subject: [PATCH 3/5] chore(clippy): clear the remaining warnings The machine-applicable pass left local rewrites and a few suggestions that would change a signature, drop a wire-format comment, or collapse a match that does not compile. Those last ones are allowed on the item, with the reason beside the attribute. --- crates/moon-chart/src/order_geometry.rs | 4 +- crates/moon-chart/src/trade_marks/tests.rs | 8 ++-- .../moon-core/src/config/detect_view/tests.rs | 2 + .../src/config/moonbot_import/schema_v7.rs | 2 + crates/moon-core/src/config/paths.rs | 5 ++- crates/moon-core/src/config/tests.rs | 8 ++-- crates/moon-core/src/config/theme/tests.rs | 20 ++++++--- crates/moon-core/src/data/orderbook.rs | 5 +++ crates/moon-core/src/db/analytics/mod.rs | 2 + crates/moon-core/src/db/quote.rs | 2 + crates/moon-core/src/db/tuner/mod.rs | 2 +- .../db/tuner/threshold_search/search/tests.rs | 2 + crates/moon-core/src/db/valuation/worker.rs | 15 +++---- .../src/feed/live/client_settings.rs | 2 + crates/moon-core/src/feed/live/commands.rs | 3 ++ .../moon-core/src/feed/live/convert/tests.rs | 2 + crates/moon-core/src/feed/mod.rs | 6 +++ crates/moon-core/src/feed/trade.rs | 3 +- crates/moon-core/src/feed/types.rs | 2 + .../src/market/source/history/tests.rs | 8 ++-- .../src/market/trade_replay/worker.rs | 2 + crates/moon-core/src/telegram/web.rs | 6 +++ .../src/analytics/calendar/mod.rs | 1 + .../src/analytics/profit_monitor/table.rs | 2 + .../src/analytics/profit_monitor/tests.rs | 2 + .../src/analytics/tuner/filter/actions.rs | 4 +- .../src/analytics/tuner/filter/mod.rs | 4 +- crates/moon-ui-gpui/src/backend/core_warn.rs | 20 ++++----- .../src/backend/core_warn/tests.rs | 4 ++ .../moon-ui-gpui/src/backend/open_request.rs | 2 + .../moon-ui-gpui/src/chart_tabs/add_stack.rs | 4 +- .../src/chart_tabs/candle_popup.rs | 2 + crates/moon-ui-gpui/src/chart_tabs/common.rs | 2 + .../src/chartdx/data_state/market.rs | 2 +- .../src/chartdx/text/labels/tests.rs | 44 +++++++++++-------- crates/moon-ui-gpui/src/controls/fmt.rs | 4 +- crates/moon-ui-gpui/src/core_order.rs | 4 ++ crates/moon-ui-gpui/src/hotkeys.rs | 2 + crates/moon-ui-gpui/src/panels/chart/mod.rs | 6 ++- crates/moon-ui-gpui/src/panels/chart/refs.rs | 11 +++-- crates/moon-ui-gpui/src/panels/chart/trade.rs | 22 +++------- .../src/persistence/auto_dock_persist.rs | 2 + .../src/settings/import_preview.rs | 3 ++ crates/moon-ui-gpui/src/shell/workspace.rs | 2 + crates/moon-ui-gpui/src/startup/tests.rs | 2 +- crates/moon-ui-gpui/src/strategies/params.rs | 2 + .../moon-ui-gpui/src/strategies/versions.rs | 2 + .../tests/theme_contract/workspace.rs | 4 +- 48 files changed, 173 insertions(+), 97 deletions(-) diff --git a/crates/moon-chart/src/order_geometry.rs b/crates/moon-chart/src/order_geometry.rs index 71003f915..b72da59fb 100644 --- a/crates/moon-chart/src/order_geometry.rs +++ b/crates/moon-chart/src/order_geometry.rs @@ -729,9 +729,9 @@ pub fn build_order_geometry( // the per-tab flag would leave a row of dots marking steps of a staircase that is no // longer there. if st.knots && !has_server_trace && show_move_history { - for i in 1..n { + for point in points.iter().skip(1) { markers.push(MarkerInstance::at_price( - to_rel(points[i].0), + to_rel(point.0), cur_p, st.knot_size * highlight_marker_mul, st.marker_thickness * highlight_thickness_mul, diff --git a/crates/moon-chart/src/trade_marks/tests.rs b/crates/moon-chart/src/trade_marks/tests.rs index 6d1e99d39..a0cb69855 100644 --- a/crates/moon-chart/src/trade_marks/tests.rs +++ b/crates/moon-chart/src/trade_marks/tests.rs @@ -141,9 +141,11 @@ fn normalize_folds_the_band_fields_onto_the_one_switch() { use moon_core::market::candles::{ VOLUME_STYLE_HILLS, VOLUME_STYLE_LEGACY_BARS, VOLUME_STYLE_OFF, }; - let mut cfg = ChartGraphicsCfg::default(); - cfg.candle_volume_style = VOLUME_STYLE_LEGACY_BARS; - cfg.candle_volume_sides = false; + let mut cfg = ChartGraphicsCfg { + candle_volume_style: VOLUME_STYLE_LEGACY_BARS, + candle_volume_sides: false, + ..ChartGraphicsCfg::default() + }; let out = normalize_chart_graphics(cfg); assert_eq!(out.candle_volume_style, VOLUME_STYLE_HILLS); assert!(out.candle_volume_sides); diff --git a/crates/moon-core/src/config/detect_view/tests.rs b/crates/moon-core/src/config/detect_view/tests.rs index b3db645dd..26d8838b1 100644 --- a/crates/moon-core/src/config/detect_view/tests.rs +++ b/crates/moon-core/src/config/detect_view/tests.rs @@ -4,6 +4,8 @@ use super::*; /// detects_view.toml and for Copy/Paste): active size, per-size w/h/chart/rail, /// and every flag in every slot. #[test] +// Nested slot writes cannot move into one literal; each field stays beside the round-trip it proves. +#[allow(clippy::field_reassign_with_default)] fn detect_view_roundtrip_preserves_every_field() { let mut cfg = DetectViewCfg::default(); cfg.size = DETECT_SIZE_LARGE; diff --git a/crates/moon-core/src/config/moonbot_import/schema_v7.rs b/crates/moon-core/src/config/moonbot_import/schema_v7.rs index 9f9554509..872d169e4 100644 --- a/crates/moon-core/src/config/moonbot_import/schema_v7.rs +++ b/crates/moon-core/src/config/moonbot_import/schema_v7.rs @@ -409,6 +409,8 @@ pub(super) mod build { } /// Builds a UI v3 body with specified hotkey values and fixed values for everything else. + // Each `push` is one labelled wire byte. Folding them into a literal would drop those names. + #[allow(clippy::vec_init_then_push)] pub fn ui_body( order_sizes: [f64; 6], order_size_keys: [u16; 6], diff --git a/crates/moon-core/src/config/paths.rs b/crates/moon-core/src/config/paths.rs index bb7fb8627..b7a58c2e4 100644 --- a/crates/moon-core/src/config/paths.rs +++ b/crates/moon-core/src/config/paths.rs @@ -6,8 +6,9 @@ //! and settings: //! - macOS: `~/Library/Application Support/com.moonbot.moonterminal/` //! - Linux: `~/.config/com.moonbot.moonterminal/` -//! `servers.enc` is encrypted with its own file key, wrapped by one slot per machine (each -//! machine's key lives in its OS keyring) plus an optional password slot; see `crypto/`. +//! +//! `servers.enc` is encrypted with its own file key, wrapped by one slot per machine (each +//! machine's key lives in its OS keyring) plus an optional password slot; see `crypto/`. //! //! All paths are based on `data_dir()`; on Windows, `data_dir() == exe_dir()`. //! diff --git a/crates/moon-core/src/config/tests.rs b/crates/moon-core/src/config/tests.rs index 284ecae20..f35503b78 100644 --- a/crates/moon-core/src/config/tests.rs +++ b/crates/moon-core/src/config/tests.rs @@ -85,9 +85,11 @@ fn a_malformed_core_list_is_refused() { /// a pinned layout was impossible. #[test] fn a_plaintext_config_keeps_the_settings_it_was_given() { - let mut settings = super::schema::SettingsFile::default(); - settings.charts_split_by_core = false; - settings.chart_stack_height = 321; + let settings = super::schema::SettingsFile { + charts_split_by_core: false, + chart_stack_height: 321, + ..super::schema::SettingsFile::default() + }; let config = AppConfig::build_plaintext_config( None, diff --git a/crates/moon-core/src/config/theme/tests.rs b/crates/moon-core/src/config/theme/tests.rs index 1d0ed3a5a..e010af58f 100644 --- a/crates/moon-core/src/config/theme/tests.rs +++ b/crates/moon-core/src/config/theme/tests.rs @@ -36,8 +36,10 @@ fn share_roundtrip() { /// Old flat theme.toml becomes dark while the caller's light theme remains current. #[test] fn share_flat_legacy_goes_dark() { - let mut flat = ChartTheme::default(); - flat.bg = [10, 20, 30]; + let flat = ChartTheme { + bg: [10, 20, 30], + ..ChartTheme::default() + }; let text = toml::to_string_pretty(&flat).unwrap(); let mut current = ChartThemeSet::default(); current.light.bg = [200, 200, 200]; @@ -128,6 +130,8 @@ fn current_revision_keeps_a_deliberately_reselected_retired_value() { /// `theme.rs:ChartThemeSet::retire_old_defaults` must stamp a revision-zero custom file once; /// otherwise every launch re-examines and rewrites a palette with no old colours left to move. #[test] +// Each palette channel is named on its own line so a round-trip mismatch points at that channel. +#[allow(clippy::field_reassign_with_default)] fn revision_zero_customised_palette_is_stamped_once() { let mut set = ChartThemeSet::default(); set.palette_rev = absent_palette_rev(); @@ -331,8 +335,10 @@ fn sharing_future_dark_table_with_current_light_uses_the_lower_generation() { /// taking the higher live generation would prevent a later build from migrating the pasted side. #[test] fn sharing_older_dark_table_with_newer_light_uses_the_lower_generation() { - let mut current = ChartThemeSet::default(); - current.palette_rev = CURRENT_PALETTE_REV + 2; + let current = ChartThemeSet { + palette_rev: CURRENT_PALETTE_REV + 2, + ..ChartThemeSet::default() + }; let text = format!( "palette_rev = {}\n\n[dark]\nbg = [11, 22, 33]\n", CURRENT_PALETTE_REV + 1 @@ -372,8 +378,10 @@ fn sharing_retires_both_tables_but_never_the_live_flat_light_set() { assert_eq!(parsed, ChartThemeSet::default()); let flat_text = toml::to_string_pretty(&paired.dark).expect("flat themes serialize"); - let mut current = ChartThemeSet::default(); - current.light = paired.light.clone(); + let current = ChartThemeSet { + light: paired.light.clone(), + ..ChartThemeSet::default() + }; let live_light = current.light.clone(); let parsed = ChartThemeSet::parse_share(&flat_text, ¤t).expect("a flat theme parses"); diff --git a/crates/moon-core/src/data/orderbook.rs b/crates/moon-core/src/data/orderbook.rs index 3c014da29..acf50d46a 100644 --- a/crates/moon-core/src/data/orderbook.rs +++ b/crates/moon-core/src/data/orderbook.rs @@ -170,6 +170,11 @@ impl OrderBookModel { self.raw.len() } + /// Returns whether the book currently holds no levels. + pub fn is_empty(&self) -> bool { + self.raw.is_empty() + } + /// Returns the book's best `(bid, ask)`. If only one side is populated, its best price is /// returned in both positions for a zero spread. An empty book or invalid best price returns /// `None`. `raw` stores descending bids followed by ascending asks, so the first `!is_ask` diff --git a/crates/moon-core/src/db/analytics/mod.rs b/crates/moon-core/src/db/analytics/mod.rs index c218c4616..b73ed559a 100644 --- a/crates/moon-core/src/db/analytics/mod.rs +++ b/crates/moon-core/src/db/analytics/mod.rs @@ -374,6 +374,8 @@ pub fn calendar_data( } /// Preflight result that prevents unsafe raw-money analytics from carrying scalar data. +// `Split` carries the full quote breakdown. Boxing it would touch every analytics consumer. +#[allow(clippy::large_enum_variant)] enum ScopeDecision { /// Scalar values share this explicit unit. Comparable { diff --git a/crates/moon-core/src/db/quote.rs b/crates/moon-core/src/db/quote.rs index a598d345e..030d05724 100644 --- a/crates/moon-core/src/db/quote.rs +++ b/crates/moon-core/src/db/quote.rs @@ -1183,7 +1183,9 @@ pub enum ProfitUnit { } /// Type-level boundary between comparable analytics and split raw totals. +// `Split` is the quote breakdown by value. Boxing it changes every match on this public enum. #[derive(Clone, Debug)] +#[allow(clippy::large_enum_variant)] pub enum ProfitScope { /// Scalar data whose values share one explicit unit. Comparable { unit: ProfitUnit, data: T }, diff --git a/crates/moon-core/src/db/tuner/mod.rs b/crates/moon-core/src/db/tuner/mod.rs index 7f1baaa09..61e4ce4a6 100644 --- a/crates/moon-core/src/db/tuner/mod.rs +++ b/crates/moon-core/src/db/tuner/mod.rs @@ -881,7 +881,7 @@ pub fn suggest_field( /// Best range for one field over `(value, profit)` samples. fn best_range( - vals: &mut Vec<(f64, f64)>, + vals: &mut [(f64, f64)], min_n: usize, edges: usize, round: bool, diff --git a/crates/moon-core/src/db/tuner/threshold_search/search/tests.rs b/crates/moon-core/src/db/tuner/threshold_search/search/tests.rs index a848c2eaf..0beffd185 100644 --- a/crates/moon-core/src/db/tuner/threshold_search/search/tests.rs +++ b/crates/moon-core/src/db/tuner/threshold_search/search/tests.rs @@ -216,6 +216,8 @@ fn one_restart_reference(s: &Search, allow: &[bool], restart: usize, rng: &mut R } } let mut profit = 0.0f64; + // `t` indexes the failure flag and the profit column together. A one-slice iterator drops one. + #[allow(clippy::needless_range_loop)] for t in 0..n { if fail[t] == 0 { profit += s.cols.profits[t]; diff --git a/crates/moon-core/src/db/valuation/worker.rs b/crates/moon-core/src/db/valuation/worker.rs index 4b20d0a4d..df0be4dff 100644 --- a/crates/moon-core/src/db/valuation/worker.rs +++ b/crates/moon-core/src/db/valuation/worker.rs @@ -493,7 +493,12 @@ fn run_worker( if current.expire_stale(now_ms) { current.publish_snapshot(&generation, &dirty, now_ms); } - match attempt( + // Only `Ran { more: true }` short-circuits, and it must: the remaining currencies + // would otherwise be resolved a minute apart. Everything else falls through, + // `Attempt::CacheLost` included — a provider failure while the derived cache is + // also unhealthy belongs to the recovery stage below, whose own fault is the one + // that matters in that window. + if let Attempt::Done(StageTurn::Ran { more: true }) = attempt( &mut status, &mut sink, ValuationStage::CurrentRates, @@ -501,13 +506,7 @@ fn run_worker( &mut retry_after, || refresh_current_rates(source.as_ref(), &generation, &dirty, &mut current), ) { - // Only `Ran { more: true }` short-circuits, and it must: the remaining currencies - // would otherwise be resolved a minute apart. Everything else falls through, - // `Attempt::CacheLost` included — a provider failure while the derived cache is - // also unhealthy belongs to the recovery stage below, whose own fault is the one - // that matters in that window. - Attempt::Done(StageTurn::Ran { more: true }) => continue, - _ => {} + continue; } } else { // Current-rate mode is disabled, so this stage issues no provider request at all — the diff --git a/crates/moon-core/src/feed/live/client_settings.rs b/crates/moon-core/src/feed/live/client_settings.rs index c6272d59e..ebfeb0765 100644 --- a/crates/moon-core/src/feed/live/client_settings.rs +++ b/crates/moon-core/src/feed/live/client_settings.rs @@ -150,6 +150,8 @@ enum SequenceOp { } /// Pure next action selected from a retained settings snapshot. +// `Send` owns the settings snapshot this queue is about to write. Boxing it allocates on that path. +#[allow(clippy::large_enum_variant)] enum SequenceAction { /// No work is currently possible or required. Idle, diff --git a/crates/moon-core/src/feed/live/commands.rs b/crates/moon-core/src/feed/live/commands.rs index 9683d0e9d..f063088d6 100644 --- a/crates/moon-core/src/feed/live/commands.rs +++ b/crates/moon-core/src/feed/live/commands.rs @@ -1044,6 +1044,9 @@ pub(super) fn drain_commands( .map(|spec| anchor_on_core(spec.insert_after, server.id)) .collect(); let positions = plan_insert_positions(&ids, &anchors); + // `next_id` is the next strategy id, not a loop index. The suggested zip + // recomputes that start and is harder to see fail closed. + #[allow(clippy::explicit_counter_loop)] for (spec, at) in specs.iter().zip(positions) { let id = next_id; next_id += 1; diff --git a/crates/moon-core/src/feed/live/convert/tests.rs b/crates/moon-core/src/feed/live/convert/tests.rs index 32cd0a9d7..76afaebec 100644 --- a/crates/moon-core/src/feed/live/convert/tests.rs +++ b/crates/moon-core/src/feed/live/convert/tests.rs @@ -34,6 +34,8 @@ fn startup_status_maps_local_port_and_physical_packet_fields() { /// `KernelHealth` between releases; an exhaustive literal here turns every such /// addition into a red CI run on a commit that touched nothing near it. #[test] +// `..Default::default()` keeps this compiling when `KernelHealth` grows a field the converter ignores. +#[allow(clippy::needless_update)] fn kernel_health_maps_each_field_by_scope() { let h = moonproto::state::KernelHealth { process_cpu_percent: 12, diff --git a/crates/moon-core/src/feed/mod.rs b/crates/moon-core/src/feed/mod.rs index c438ab91b..9a906e82a 100644 --- a/crates/moon-core/src/feed/mod.rs +++ b/crates/moon-core/src/feed/mod.rs @@ -126,6 +126,8 @@ impl FeedTx { Self { data, wake } } + // The error returns the unsent message. Boxing it would change this public `Result`. + #[allow(clippy::result_large_err)] pub fn send(&self, msg: FeedMsg) -> Result<(), SendError> { self.data.send(msg)?; if let Some(wake) = &self.wake { @@ -301,7 +303,9 @@ impl OrderStopsForm { } /// Commands from the coordinator to a core backend that define the core's market role. +// `EditCoreConfig` carries the whole config. Boxing it allocates on the command path. #[derive(Debug, Clone)] +#[allow(clippy::large_enum_variant)] pub enum CoreCmd { /// Desired market role of the core as full state, not a delta. /// @@ -811,6 +815,8 @@ impl CoreCmdTx { /// /// A market-role snapshot is published only after the matching queue send succeeds. Holding the /// snapshot lock across both operations gives cloned senders and the consumer one order. + // The error returns the unsent command. Boxing it would change this public `Result`. + #[allow(clippy::result_large_err)] pub fn send(&self, cmd: CoreCmd) -> Result<(), SendError> { let assignment = match &cmd { CoreCmd::SetMarket { diff --git a/crates/moon-core/src/feed/trade.rs b/crates/moon-core/src/feed/trade.rs index 7c2b586ea..15950682d 100644 --- a/crates/moon-core/src/feed/trade.rs +++ b/crates/moon-core/src/feed/trade.rs @@ -632,6 +632,7 @@ pub(super) fn split_order_for_market( /// - an enabled stop's level comes from wire (≠0) → disable memory → strategy field /// ("StopLoss"/"TrailingStop", whose strategy percentages are negative → abs) → ClientSettings /// default (SL `price_drop_level` / TS `trailing_drop`). VStop uses wire/memory only. +/// /// The runtime compares against the live model through send-if-changed. SL/TS → `update_stops`, /// VStop → `update_vstop`. pub(super) fn set_order_stop( @@ -961,7 +962,7 @@ fn restore_from_wire_or_memory( if level != 0.0 && level.is_finite() { return Some((fixed, level, extra)); } - stop_memory_get(server_id, uid, kind).map(|(f, l, s)| (f, l, s)) + stop_memory_get(server_id, uid, kind) } /// Explicit per-order stop overrides made FROM THE TERMINAL, scoped to the session. diff --git a/crates/moon-core/src/feed/types.rs b/crates/moon-core/src/feed/types.rs index 2f17d63f4..40f217ac0 100644 --- a/crates/moon-core/src/feed/types.rs +++ b/crates/moon-core/src/feed/types.rs @@ -1254,7 +1254,9 @@ pub struct CoreTimeOffsetStatus { } /// Account updates and transient notifications delivered from one core's feed. +// `CoreConfig` is delivered by value on the feed. Boxing it allocates on every such message. #[derive(Debug, Clone)] +#[allow(clippy::large_enum_variant)] pub enum FeedMsg { /// Already deduplicated actual trade edges; independent of order-table publication. TradeSounds(Vec), diff --git a/crates/moon-core/src/market/source/history/tests.rs b/crates/moon-core/src/market/source/history/tests.rs index 93e828333..5eca03a06 100644 --- a/crates/moon-core/src/market/source/history/tests.rs +++ b/crates/moon-core/src/market/source/history/tests.rs @@ -247,9 +247,11 @@ fn visible_fit_windowed_coarse_scan_equals_a_full_scan() { .filter(|(_, tf)| f64::from(*tf) == hour) .map(|(c, _)| c.t_open_ms) .collect(); - let mut cursor = ChartHistoryCursor::default(); - cursor.coarse_fill = fill.clone(); - cursor.coarse_fill_max_tf = Some(hour); + let cursor = ChartHistoryCursor { + coarse_fill: fill.clone(), + coarse_fill_max_tf: Some(hour), + ..ChartHistoryCursor::default() + }; let last = t; let mut overhang_hits = 0; for q in 0..3_000 { diff --git a/crates/moon-core/src/market/trade_replay/worker.rs b/crates/moon-core/src/market/trade_replay/worker.rs index 635fc89b3..234d06565 100644 --- a/crates/moon-core/src/market/trade_replay/worker.rs +++ b/crates/moon-core/src/market/trade_replay/worker.rs @@ -133,7 +133,9 @@ const TRADE_PAGE_BUDGET: usize = 240; /// An authoritative EMPTY is an answer too, and a valuable one: a delisted or halted market /// answers empty every time, so refetching it on each reopen spends the host's budget to learn /// something already known. +// `Ready` owns the series a reopen draws. Boxing it allocates on every remembered answer. #[derive(Clone, Debug)] +#[allow(clippy::large_enum_variant)] enum Remembered { /// Rows to draw. Ready { diff --git a/crates/moon-core/src/telegram/web.rs b/crates/moon-core/src/telegram/web.rs index 7009c396f..907fb85a3 100644 --- a/crates/moon-core/src/telegram/web.rs +++ b/crates/moon-core/src/telegram/web.rs @@ -297,6 +297,8 @@ impl App { } /// Validate initData HMAC and paired identity. Body is not consumed. + // Failures are HTTP responses. Boxing `Response` would change every `?` on this path. + #[allow(clippy::result_large_err)] fn authenticate( &self, request: &Request, @@ -360,6 +362,8 @@ fn check_peer_and_headers(headers: &HeaderMap, host: Option<&str>) -> Result<(), } /// Require `application/json` (optional charset) on API POSTs. +// The error is the HTTP response itself. Boxing it changes the helper's `Result`. +#[allow(clippy::result_large_err)] fn require_json_content_type(headers: &HeaderMap) -> Result<(), Response> { let value = headers .get("content-type") @@ -376,6 +380,8 @@ fn require_json_content_type(headers: &HeaderMap) -> Result<(), Response> } /// Read a JSON object body capped at [`MAX_BODY_BYTES`]. +// The error is the HTTP response itself. Boxing it changes the helper's `Result`. +#[allow(clippy::result_large_err)] fn read_limited_json_object(request: Request) -> Result> { if let Some(len) = request.body().len() { if len > MAX_BODY_BYTES { diff --git a/crates/moon-ui-gpui/src/analytics/calendar/mod.rs b/crates/moon-ui-gpui/src/analytics/calendar/mod.rs index 270c7ab7d..159f403b6 100644 --- a/crates/moon-ui-gpui/src/analytics/calendar/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/calendar/mod.rs @@ -9,6 +9,7 @@ //! row on top (with the delta to the previous month), a plus/minus-day bar //! below. Clicking a day switches to "Day" mode; //! - "Day" — hour-by-hour detail of a single day. See `day`. +//! //! Each mode builds its own query (`cal_query` in mod.rs); the window's period //! bar is hidden here. diff --git a/crates/moon-ui-gpui/src/analytics/profit_monitor/table.rs b/crates/moon-ui-gpui/src/analytics/profit_monitor/table.rs index 2c35a6446..a95805d44 100644 --- a/crates/moon-ui-gpui/src/analytics/profit_monitor/table.rs +++ b/crates/moon-ui-gpui/src/analytics/profit_monitor/table.rs @@ -555,6 +555,8 @@ pub(super) fn table( palette, cx, ); + // The virtual-list closure shares this UI-thread list. The entry type is not `Send`. + #[allow(clippy::arc_with_non_send_sync)] let entries = Arc::new(entries); let row_count = entries.len(); let list_entries = entries.clone(); diff --git a/crates/moon-ui-gpui/src/analytics/profit_monitor/tests.rs b/crates/moon-ui-gpui/src/analytics/profit_monitor/tests.rs index 414d131b7..1cb79407a 100644 --- a/crates/moon-ui-gpui/src/analytics/profit_monitor/tests.rs +++ b/crates/moon-ui-gpui/src/analytics/profit_monitor/tests.rs @@ -275,6 +275,8 @@ fn retired_bot_preference_falls_back_to_core() { /// scale multiplier, or shifting a threshold makes the budget or one adjacent pair red and blocks /// or clips the narrow window. #[test] +// The compared values are named constants. The assertion reddens when a layout constant stops fitting. +#[allow(clippy::assertions_on_constants)] fn responsive_layout_degrades_at_the_documented_boundaries() { assert!( super::MIN_WINDOW_WIDTH diff --git a/crates/moon-ui-gpui/src/analytics/tuner/filter/actions.rs b/crates/moon-ui-gpui/src/analytics/tuner/filter/actions.rs index ff1396e61..c713b242e 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/filter/actions.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/filter/actions.rs @@ -223,13 +223,13 @@ impl AnalyticsView { ); let by_field: HashMap<&str, _> = res.fields.into_iter().map(|f| (f.field, f)).collect(); - for fi in 0..FIELDS.len() { + for (fi, field) in FIELDS.iter().enumerate() { // Leave fields that were not searched alone (fixed/disabled). if !this.tuner.enabled[fi] { continue; } let (from, to) = by_field - .get(FIELDS[fi].col) + .get(field.col) .map(|f| (fmt_bound(f.from), fmt_bound(f.to))) .unwrap_or_default(); this.tuner.bounds[0][fi] = (from, to); diff --git a/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs b/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs index ceb9a74a9..d145383b9 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs @@ -581,8 +581,8 @@ impl AnalyticsView { .unwrap_or_else(|| Arc::new(StratFilters::default())); let mut grid = v_flex().w_full().child(head); let mut last_class: Option = None; - for fi in 0..FIELDS.len() { - let class = FIELDS[fi].class; + for (fi, field) in FIELDS.iter().enumerate() { + let class = field.class; // Headers: the MoonBot section (the parent), then the indented // subgroup (BV/SV inside Volumes, the Δ2/Δ3 slots inside Deltas). let sub = class.parent() != class; diff --git a/crates/moon-ui-gpui/src/backend/core_warn.rs b/crates/moon-ui-gpui/src/backend/core_warn.rs index dbe2ca012..d4b184728 100644 --- a/crates/moon-ui-gpui/src/backend/core_warn.rs +++ b/crates/moon-ui-gpui/src/backend/core_warn.rs @@ -455,6 +455,9 @@ struct CoreTrack { impl CoreTrack { /// Average `(process, system)` CPU over the last `CPU_WINDOW_SECS` seconds. + /// + /// A zero sample count is unknown CPU, not 0%. `checked_div` would report zero. + #[allow(clippy::manual_checked_ops)] fn averaged(&self, now_sec: i64) -> (Option, Option) { let (mut proc, mut system, mut n) = (0u32, 0u32, 0u32); for bucket in &self.cpu { @@ -1156,11 +1159,7 @@ fn server_snapshot(samples: &[CoreSample], ip: IpAddr) -> WarnSnapshot { sys_cpu: freshest_u8(|sys| sys.system_cpu_percent) .unwrap_or(0) .min(100), - occ_mem: if total > 0 { - (used_sum * 100 / total).min(100) as u8 - } else { - 0 - }, + occ_mem: (used_sum * 100).checked_div(total).unwrap_or(0).min(100) as u8, free_mb: free.unwrap_or(0), used_mb: used_sum.min(u64::from(u32::MAX)) as u32, logical_cpus: freshest_u8(|sys| sys.logical_cpu_count).unwrap_or(0), @@ -1255,11 +1254,7 @@ fn build_ring_samples(samples: &[CoreSample]) -> Vec { // per-core lines stay consistent with it (total unavailable → 0). let free = freshest(&|sys| sys.free_physical_memory_mb).map(u64::from); let total = free.map(|free| used_sum + free).unwrap_or(0); - let occ = if total > 0 { - (used_sum * 100 / total).min(100) as u8 - } else { - 0 - }; + let occ = (used_sum * 100).checked_div(total).unwrap_or(0).min(100) as u8; out.push(RingSample { subject: RingSubject::Server(*ip), cpu: sys_cpu, @@ -1270,7 +1265,10 @@ fn build_ring_samples(samples: &[CoreSample]) -> Vec { for sample in cores { let proc_cpu = sample.sys.process_cpu_percent.unwrap_or(0).min(100); let proc_mem = match sample.sys.used_memory_mb { - Some(used) if total > 0 => (u64::from(used) * 100 / total).min(100) as u8, + Some(used) => (u64::from(used) * 100) + .checked_div(total) + .unwrap_or(0) + .min(100) as u8, _ => 0, }; // Per-core pings, but only while Ready — a dropped core keeps its last (possibly diff --git a/crates/moon-ui-gpui/src/backend/core_warn/tests.rs b/crates/moon-ui-gpui/src/backend/core_warn/tests.rs index 69ceb8039..a3273825b 100644 --- a/crates/moon-ui-gpui/src/backend/core_warn/tests.rs +++ b/crates/moon-ui-gpui/src/backend/core_warn/tests.rs @@ -123,6 +123,8 @@ fn sustained_cpu_opens_then_closes_one_episode() { // Drop CPU; the averaging window needs a few low seconds to fall under the threshold. let mut sec = CPU_SUSTAIN_SECS as i64 + 4; + // `sec` is the simulated clock, stepped beside each tick. Folding it into the header hides that. + #[allow(clippy::explicit_counter_loop)] for _ in 0..5 { tick_one(&mut engine, sec, 1, IP, Some(5), Some(500)); sec += 1; @@ -156,6 +158,8 @@ fn memory_growth_opens_then_closes_per_core_episode() { // Fall back to baseline: current returns to the window minimum, so growth is zero. let mut sec = rise.len() as i64 + 1; + // `sec` is the simulated clock, stepped beside each tick. Folding it into the header hides that. + #[allow(clippy::explicit_counter_loop)] for _ in 0..3 { tick_one(&mut engine, sec, 7, IP, Some(10), Some(400)); sec += 1; diff --git a/crates/moon-ui-gpui/src/backend/open_request.rs b/crates/moon-ui-gpui/src/backend/open_request.rs index 6c7188690..17db4c7f9 100644 --- a/crates/moon-ui-gpui/src/backend/open_request.rs +++ b/crates/moon-ui-gpui/src/backend/open_request.rs @@ -18,7 +18,9 @@ pub(crate) struct OpenMainRequest { } /// Durable history policy applied to one exact Main-chart target. +// `Report` owns the filter snapshot for one click. Boxing it changes every history-scope match. #[derive(Clone, Debug, Default, PartialEq, Eq)] +#[allow(clippy::large_enum_variant)] pub(crate) enum ChartHistoryScope { /// Load all durable closed trades for the exact target core and market aliases. #[default] diff --git a/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs b/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs index 0c5dd9fae..4e1c157ee 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/add_stack.rs @@ -1308,9 +1308,7 @@ impl Render for AddChartStack { border, // An empty retained COMPRESS slot maps to `None`, so render shows a transparent tile. move |s, ix| { - let Some(&real_ix) = panel_order.get(ix) else { - return None; - }; + let &real_ix = panel_order.get(ix)?; s.charts .get(real_ix) .filter(|e| !e.vacated) diff --git a/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs b/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs index d4626821d..57e86825d 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs @@ -87,6 +87,8 @@ fn zone_step_text(step: u16, max_label: &str) -> String { } /// Build a multiline hint below a control. +// `t!` is not a `str`. The suggested rewrite drops `key` and calls a different macro. +#[allow(clippy::unnecessary_to_owned)] fn hint_block(key: &str, p: MoonPalette, cx: &App) -> impl IntoElement { v_flex().children( t!(key) diff --git a/crates/moon-ui-gpui/src/chart_tabs/common.rs b/crates/moon-ui-gpui/src/chart_tabs/common.rs index 66b29048b..017dacee9 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/common.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/common.rs @@ -85,7 +85,9 @@ pub(crate) fn seg_row( /// Not `Copy`: the caption configuration it carries owns a name string per row, and a value that /// silently copies a heap-owning payload through a walk that touches every tab is a cost nobody /// sees until it is large. +// Caption rows own strings. Boxing one arm would allocate on every tab-settings copy. #[derive(Clone, Debug, PartialEq)] +#[allow(clippy::large_enum_variant)] pub(crate) enum StackSetting { /// Layout mode plus separate Fit and Scroll heights. Layout(Option, Option, Option), diff --git a/crates/moon-ui-gpui/src/chartdx/data_state/market.rs b/crates/moon-ui-gpui/src/chartdx/data_state/market.rs index 450bc4343..6202a8ba3 100644 --- a/crates/moon-ui-gpui/src/chartdx/data_state/market.rs +++ b/crates/moon-ui-gpui/src/chartdx/data_state/market.rs @@ -923,7 +923,7 @@ impl ChartDataState { // core streams some, and the hide-candles zone below refuses to blank a bucket // that has no crosses to replace it. Re-stamped on every full range read; an // incremental drain returns just the live edge, so it only fills a NaN (below). - pr.combo_left_rel = history.combo_left_rel_ms.map(|v| v).unwrap_or(f32::NAN); + pr.combo_left_rel = history.combo_left_rel_ms.unwrap_or(f32::NAN); // Restart the pan budget from the reset that ACTUALLY happened, whatever raised // it. Stamping back where the decision was made would also credit a frame whose // read returned nothing, and would miss the capacity-driven re-read that resets diff --git a/crates/moon-ui-gpui/src/chartdx/text/labels/tests.rs b/crates/moon-ui-gpui/src/chartdx/text/labels/tests.rs index 199ee7f21..0b4790d91 100644 --- a/crates/moon-ui-gpui/src/chartdx/text/labels/tests.rs +++ b/crates/moon-ui-gpui/src/chartdx/text/labels/tests.rs @@ -452,11 +452,13 @@ fn arb_inputs( #[test] fn the_column_prints_one_line_per_venue() { let cfg = cfg_of(&[ChartLabelField::ArbColumn]); - let mut view = ArbViewCfg::default(); - view.venues = vec![ - moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(4)), - moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(9)), - ]; + let view = ArbViewCfg { + venues: vec![ + moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(4)), + moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(9)), + ], + ..ArbViewCfg::default() + }; let texts = texts_with( &cfg, @@ -501,10 +503,12 @@ fn each_line_addresses_its_own_run() { #[test] fn the_roster_decides_what_each_line_prints() { let cfg = cfg_of(&[ChartLabelField::ArbColumn]); - let mut view = ArbViewCfg::default(); - view.venues = vec![moon_core::config::ArbVenueCfg::new( - moon_core::market::ArbVenue::from_code(4), - )]; + let mut view = ArbViewCfg { + venues: vec![moon_core::config::ArbVenueCfg::new( + moon_core::market::ArbVenue::from_code(4), + )], + ..ArbViewCfg::default() + }; view.show = moon_core::config::ArbShow::Price; let price_only = texts_with(&cfg, arb_inputs(vec![arb_quote(4, 101.0)], view.clone())); @@ -544,11 +548,13 @@ fn the_venue_name_is_the_lines_prefix() { #[test] fn the_column_lines_its_cells_up() { let cfg = cfg_of(&[ChartLabelField::ArbColumn]); - let mut view = ArbViewCfg::default(); - view.venues = vec![ - moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(4)), - moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(101)), - ]; + let view = ArbViewCfg { + venues: vec![ + moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(4)), + moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(101)), + ], + ..ArbViewCfg::default() + }; // "BinanceF" is eight characters and "UpBit" five; the prices differ in width too. let quotes = vec![arb_quote(4, 9.5), arb_quote(101, 101.25)]; @@ -590,14 +596,14 @@ fn the_column_lines_its_cells_up() { #[test] fn the_roster_floor_drops_quiet_venues() { let cfg = cfg_of(&[ChartLabelField::ArbColumn]); - let mut view = ArbViewCfg { + let view = ArbViewCfg { min_abs_pct: 1.0, + venues: vec![ + moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(4)), + moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(9)), + ], ..ArbViewCfg::default() }; - view.venues = vec![ - moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(4)), - moon_core::config::ArbVenueCfg::new(moon_core::market::ArbVenue::from_code(9)), - ]; let texts = texts_with( &cfg, diff --git a/crates/moon-ui-gpui/src/controls/fmt.rs b/crates/moon-ui-gpui/src/controls/fmt.rs index e3dd80041..005d9288f 100644 --- a/crates/moon-ui-gpui/src/controls/fmt.rs +++ b/crates/moon-ui-gpui/src/controls/fmt.rs @@ -33,9 +33,7 @@ pub fn fmt_field2_signed(v: f32) -> String { /// Trailing zeros are removed, which also hides floating-point noise such as 0.6000000238. pub fn fmt_adaptive(v: f64) -> String { let a = v.abs(); - let decimals: usize = if a == 0.0 { - 0 - } else if a >= 100.0 { + let decimals: usize = if a == 0.0 || a >= 100.0 { 0 } else if a >= 10.0 { 1 diff --git a/crates/moon-ui-gpui/src/core_order.rs b/crates/moon-ui-gpui/src/core_order.rs index ec6efb536..a16815a04 100644 --- a/crates/moon-ui-gpui/src/core_order.rs +++ b/crates/moon-ui-gpui/src/core_order.rs @@ -224,6 +224,8 @@ impl CoreOrder { /// Order the live sessions kept by `keep` (group / scope filter). /// /// The predicate controls membership; this method only canonicalizes the retained rows. + // The name matches the other ordering entry points. Dropping `self` would lose the rank table. + #[allow(clippy::wrong_self_convention)] pub(crate) fn from_sessions( &self, sessions: &[moon_core::session::CoreSession], @@ -246,6 +248,8 @@ impl CoreOrder { /// Database-only cores whose server is absent from the current config share the `u32::MAX` /// rank `rank` hands out for anything unknown, so they land after every configured core and /// keep the query order — `sort_by_key` is a STABLE sort. + // Same rank table as `from_sessions`. A `from_*` rename would churn every caller. + #[allow(clippy::wrong_self_convention)] pub(crate) fn from_db(&self, mut rows: Vec<(CoreId, String)>) -> OrderedCores { rows.sort_by_key(|(id, _)| self.rank(*id)); OrderedCores(rows) diff --git a/crates/moon-ui-gpui/src/hotkeys.rs b/crates/moon-ui-gpui/src/hotkeys.rs index 63a0435e3..9722fd5fb 100644 --- a/crates/moon-ui-gpui/src/hotkeys.rs +++ b/crates/moon-ui-gpui/src/hotkeys.rs @@ -1110,6 +1110,8 @@ pub fn apply( // no switch, no pill and no summary on screen to say it happened — and the next order // would go out under it. Refusing lets the key propagate, exactly like the no-core arm. A::ManualStrategy(_) if b.is_auto_overview_scope(group) => false, + // Collapsing this into the guard arm above makes the match non-exhaustive. + #[allow(clippy::collapsible_match)] A::ManualStrategy(i) => match active_core { Some(core) => { if crate::controls::select_manual_strategy(b, core, i) { diff --git a/crates/moon-ui-gpui/src/panels/chart/mod.rs b/crates/moon-ui-gpui/src/panels/chart/mod.rs index 045e0852c..3dd62e4c8 100644 --- a/crates/moon-ui-gpui/src/panels/chart/mod.rs +++ b/crates/moon-ui-gpui/src/panels/chart/mod.rs @@ -60,8 +60,10 @@ use windows::core::PCWSTR; #[cfg(windows)] fn monitor_refresh_hz() -> u32 { unsafe { - let mut mode = DEVMODEW::default(); - mode.dmSize = std::mem::size_of::() as u16; + let mut mode = DEVMODEW { + dmSize: std::mem::size_of::() as u16, + ..DEVMODEW::default() + }; if EnumDisplaySettingsW(PCWSTR::null(), ENUM_CURRENT_SETTINGS, &mut mode).as_bool() && mode.dmDisplayFrequency > 1 { diff --git a/crates/moon-ui-gpui/src/panels/chart/refs.rs b/crates/moon-ui-gpui/src/panels/chart/refs.rs index 17ed22890..cded051dc 100644 --- a/crates/moon-ui-gpui/src/panels/chart/refs.rs +++ b/crates/moon-ui-gpui/src/panels/chart/refs.rs @@ -77,12 +77,11 @@ impl ChartPanel { /// Ask the core for strategy-filter rows on this panel's active market, or clear the request. pub(super) fn sync_chart_text(&mut self, cx: &mut App) { - let want = if self.historical { - None - } else if !self - .settings_sig - .chart_labels - .any_drawn(|f| f == ChartLabelField::StrategyFilters) + let want = if self.historical + || !self + .settings_sig + .chart_labels + .any_drawn(|f| f == ChartLabelField::StrategyFilters) { None } else { diff --git a/crates/moon-ui-gpui/src/panels/chart/trade.rs b/crates/moon-ui-gpui/src/panels/chart/trade.rs index 3642158c3..1453d5a8c 100644 --- a/crates/moon-ui-gpui/src/panels/chart/trade.rs +++ b/crates/moon-ui-gpui/src/panels/chart/trade.rs @@ -633,9 +633,7 @@ impl ChartPanel { if !self.order_gestures_allowed(cx) { return None; } - let Some(pane) = self.input.pane_at(pos.0, pos.1) else { - return None; - }; + let pane = self.input.pane_at(pos.0, pos.1)?; // No line lives in the horizontal-volume zone — lines run from their start to the plot's // right edge and on into the book, never left of the plot — so nothing there is a hit. Said // HERE rather than at each caller: a press in the zone is neither a grab nor a cancel, @@ -644,16 +642,11 @@ impl ChartPanel { if self.hvol_pane_at(pos).is_some() { return None; } - let Some((core, market)) = self + let (core, market) = self .chart - .with_container(|container| container.target(pane)) - else { - return None; - }; - let Some(plot) = self.local_plot_rect(pane) else { - return None; - }; - let Some((center, range, epoch_ms, left_rel, window_ms)) = + .with_container(|container| container.target(pane))?; + let plot = self.local_plot_rect(pane)?; + let (center, range, epoch_ms, left_rel, window_ms) = self.chart.with_container(|container| { container.pane(pane).map(|pane| { let (left, window) = pane.view.visible_x(plot.w); @@ -665,10 +658,7 @@ impl ChartPanel { window, ) }) - }) - else { - return None; - }; + })?; if plot.h <= 1.0 || !(range > 0.0) || !(window_ms > 0.0) { return None; } diff --git a/crates/moon-ui-gpui/src/persistence/auto_dock_persist.rs b/crates/moon-ui-gpui/src/persistence/auto_dock_persist.rs index 9944bba65..93d3e2b4c 100644 --- a/crates/moon-ui-gpui/src/persistence/auto_dock_persist.rs +++ b/crates/moon-ui-gpui/src/persistence/auto_dock_persist.rs @@ -10,7 +10,9 @@ use moon_core::config::{paths, write_file_atomic}; use moon_ui::DockTopologyByName; /// Classified startup result for the shared Auto topology file. +// `Loaded` owns the topology read once at startup. Boxing it does not shrink the steady state. #[derive(Clone, Debug, PartialEq)] +#[allow(clippy::large_enum_variant)] pub(crate) enum AutoDockLoad { /// No file exists yet, so first Auto entry may seed and persist the requested default. Missing, diff --git a/crates/moon-ui-gpui/src/settings/import_preview.rs b/crates/moon-ui-gpui/src/settings/import_preview.rs index 9f82c7080..28d3e1fc3 100644 --- a/crates/moon-ui-gpui/src/settings/import_preview.rs +++ b/crates/moon-ui-gpui/src/settings/import_preview.rs @@ -34,6 +34,9 @@ pub(super) struct ImportReady { } /// State of an open import preview. +// `Ready` owns the import plan for the open dialog. Boxing it allocates on that cold path only +// after every match site changes, which is a wider edit than this lint. +#[allow(clippy::large_enum_variant)] pub(super) enum ImportState { /// The clipboard passed the MoonBot sniff and is being parsed and planned in the background. Loading, diff --git a/crates/moon-ui-gpui/src/shell/workspace.rs b/crates/moon-ui-gpui/src/shell/workspace.rs index e327fcaaf..39ac53b7c 100644 --- a/crates/moon-ui-gpui/src/shell/workspace.rs +++ b/crates/moon-ui-gpui/src/shell/workspace.rs @@ -442,7 +442,9 @@ fn icon_workspace_summary(configured: usize) -> String { } /// One flattened virtual-list item in the all-core rail. +// `Exchange` holds the logo and the core list for one heading. The rail rebuilds these by value. #[derive(Clone)] +#[allow(clippy::large_enum_variant)] enum RailItem { /// Current group aggregate scope. Overview { selected: bool }, diff --git a/crates/moon-ui-gpui/src/startup/tests.rs b/crates/moon-ui-gpui/src/startup/tests.rs index affa11ded..3cf3b3cfd 100644 --- a/crates/moon-ui-gpui/src/startup/tests.rs +++ b/crates/moon-ui-gpui/src/startup/tests.rs @@ -294,7 +294,7 @@ fn report_revision_decision_stays_wired_to_the_coordination_loop() { "consume_report_commit(coord_valuation_status_dirty.as_deref()", ); let observe = position(&source, "let revision = report_revision_gate.observe("); - let wake = position(&source, "if revision.wake_valuation {"); + let wake = position(&source, "if revision.wake_valuation"); let notify = position(&source, "if revision.notify {"); assert!(immediate < background); diff --git a/crates/moon-ui-gpui/src/strategies/params.rs b/crates/moon-ui-gpui/src/strategies/params.rs index 6ea1330a3..4dd5deab7 100644 --- a/crates/moon-ui-gpui/src/strategies/params.rs +++ b/crates/moon-ui-gpui/src/strategies/params.rs @@ -1047,6 +1047,8 @@ fn compact_first_line(v: &str) -> String { } } +// `Content` owns the prepared parameter body. Boxing it allocates on every selection change. +#[allow(clippy::large_enum_variant)] pub(super) enum ParamsPanelModel { NoSelection, NoSchema, diff --git a/crates/moon-ui-gpui/src/strategies/versions.rs b/crates/moon-ui-gpui/src/strategies/versions.rs index 8f6d4a49a..a5bf10e80 100644 --- a/crates/moon-ui-gpui/src/strategies/versions.rs +++ b/crates/moon-ui-gpui/src/strategies/versions.rs @@ -871,6 +871,8 @@ impl StrategiesView { *stamp_counts.entry(s.as_str()).or_insert(0) += 1; } let mut previous_taken = false; + // `i` indexes the version list and the bare-stamp list together. + #[allow(clippy::needless_range_loop)] for i in 0..n_versions { let v = &self.versions.list[i]; let slot = if v.valid_to.is_none() { diff --git a/crates/moon-ui-gpui/tests/theme_contract/workspace.rs b/crates/moon-ui-gpui/tests/theme_contract/workspace.rs index fe4c242dc..feeb77594 100644 --- a/crates/moon-ui-gpui/tests/theme_contract/workspace.rs +++ b/crates/moon-ui-gpui/tests/theme_contract/workspace.rs @@ -369,7 +369,7 @@ fn main_open_requests_revalidate_live_group_before_signature_and_consume() { "pub(crate) fn pending_open_main_request_for_group(", )); assert!( - pending.contains("self.current_open_main_group().as_deref() == Some(group)") + pending.contains("self.current_open_main_group() == Some(group)") && pending.contains("self.open_main_request.pending_target()"), "read-phase routing must use the target core's current live group" ); @@ -378,7 +378,7 @@ fn main_open_requests_revalidate_live_group_before_signature_and_consume() { "pub(crate) fn pending_open_main_revision_for_group(", )); assert!( - signature.contains("self.current_open_main_group().as_deref() == Some(group)"), + signature.contains("self.current_open_main_group() == Some(group)"), "ChartTabs signatures must wake only the target core's current group" ); let take = code_only(braced_body( From 291e88d7942b12657a737ca362650cf6f33a8f50 Mon Sep 17 00:00:00 2001 From: kirillDevPro <113171057+kirillDevPro@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:30:54 +0200 Subject: [PATCH 4/5] chore(ci): require clippy -D warnings Pull requests were not linted, so warnings accumulated until -D warnings failed on the first crate. The new Windows job runs the same clippy command developers must pass, and the CI contract test reddens if that command is weakened or the job is demoted. --- .github/workflows/build.yml | 37 ++++++++++-- CONTRIBUTING.md | 7 ++- crates/moon-core/tests/ci_gate_contract.rs | 67 ++++++++++++++++++++-- docs/AGENT_RULES.md | 3 +- 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ece70dba..9c6d956f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,9 +3,10 @@ name: build permissions: contents: read -# Six jobs, five of which gate a merge: +# Seven jobs, six of which gate a merge: # Windows .exe — the real release binary, uploaded as an artifact. # Tests — `cargo test --workspace`. Blocking: a red suite is a red PR. +# Clippy — `cargo clippy --workspace --all-targets --locked -- -D warnings`. Blocking. # Audit — cargo-deny over the committed lockfile. Blocking. # Tour — deterministic interactive and AI documentation. Blocking. # Fmt — `cargo fmt --all -- --check`. Blocking. @@ -15,7 +16,7 @@ permissions: # .dmg ships, unevenly: arm64 is compiled, the Intel slice only # type-checked. Read its log; it never blocks. # -# THE LOCKFILE CONTRACT, which the three compiling jobs implement in the same three steps. +# THE LOCKFILE CONTRACT, which the four compiling jobs implement in the same three steps. # `Cargo.lock` is committed, so third-party versions move only in a deliberate commit. Each job # then, in this order and no other: # 1. verifies the committed lock still agrees with the manifests (`cargo fetch --locked`), @@ -55,9 +56,9 @@ on: workflow_dispatch: # A freeze makes exactly one thing worse: an advisory can be published against a pinned version # long after the last PR, and nothing would notice. This weekly run exists for the audit job - # alone — the three compiling jobs skip it, so it costs a couple of runner-minutes and writes + # alone — the four compiling jobs skip it, so it costs a couple of runner-minutes and writes # no cache. Side effect worth knowing when you read a commit's checks: each cron run attaches - # three `Skipped` entries to main's HEAD, so a commit whose gates really did pass can later + # four `Skipped` entries to main's HEAD, so a commit whose gates really did pass can later # display them as skipped. schedule: - cron: "0 6 * * 1" @@ -77,7 +78,7 @@ env: # Every job restores the cargo cache but only `main` writes it (`save-if` below). # A cache saved from a branch is readable only by that branch, so on any run whose -# manifest hash is new it is written once and never read again. Three jobs at ~1 GiB +# manifest hash is new it is written once and never read again. Four jobs at ~1 GiB # a piece fill the repository's 10 GB Actions quota fast, and once over it GitHub # evicts by least-recent-use — which takes the live caches, not the dead ones. jobs: @@ -143,6 +144,32 @@ jobs: - name: Run test suite run: cargo test --workspace --no-fail-fast --target x86_64-pc-windows-msvc + clippy: + name: Clippy (x86_64-msvc) + runs-on: windows-latest + # Compiles the workspace, so the weekly audit cron skips it like the other compiling jobs. + if: github.event_name != 'schedule' + steps: + - uses: actions/checkout@v7 + - uses: dtolnay/rust-toolchain@1.97.1 + with: + targets: x86_64-pc-windows-msvc + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref == 'refs/heads/main' }} + # The lockfile contract — see the header. `--locked` on the clippy step then refuses any + # further rewrite after the MoonUI refresh has been checked. + - name: Verify the committed lockfile agrees with the manifests + run: cargo fetch --locked + - name: Refresh MoonUI only + run: cargo update -p moon-gpui -p moon-gpui-platform -p moon-ui + - name: Assert the refresh moved MoonUI and nothing else + shell: bash + run: bash .github/scripts/assert-only-moonui-moved.sh + - name: Lint the workspace + run: cargo clippy --workspace --all-targets --locked -- -D warnings + macos-probe: name: macOS probe (arm64 build, x86_64 check) — diagnostic runs-on: macos-14 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 098820b5c..75782b720 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -105,14 +105,15 @@ Three kinds of test, three homes. The toolchain dictates this, not taste: she posts the mark together with a comment. A listed author turns a wrong or stuck mark green by writing `/override` in the pull request. CI still only reports: nothing but you reading it stops a red merge. Branch from fresh `main`, open a PR, squash-merge — history stays linear. -- **CI runs `fmt`, not `clippy`.** Run `cargo clippy` yourself before pushing. The tree **is** +- **CI runs `fmt` and `clippy`.** The tree **is** rustfmt-clean: `cargo fmt --all` is the correct command, `rustfmt.toml` (`style_edition = "2024"`) is the authority, and CI enforces it via the `Fmt` job — which does not need the optional `private/uidoc` overlay to pass; `cargo fmt` must (and does) work without it. Blame history across the tree-wide reformat is preserved by `.git-blame-ignore-revs` — enable it locally with `git config blame.ignoreRevsFile .git-blame-ignore-revs`. -- Five CI gates, all on every PR and all meant to be green before you merge: the Windows +- Six CI gates, all on every PR and all meant to be green before you merge: the Windows `.exe` job (~15 min), `Tests (x86_64-msvc)` running `cargo test --workspace`, + `Clippy (x86_64-msvc)` running `cargo clippy --workspace --all-targets --locked -- -D warnings`, `Dependency audit (cargo-deny)`, `Tour` building the knowledge site, and `Fmt` running `cargo fmt --all -- --check`. They run in parallel. The macOS job is diagnostic (`continue-on-error`) — read its log, but it does not block. "Gate" is a convention here, not @@ -185,6 +186,8 @@ unnoticed. make build | run | release | check | fmt ``` +- `cargo clippy --workspace --all-targets -- -D warnings` must pass before a PR. + - Windows needs **VS 2022 Build Tools** (`vcvars64`). Resolve it with `vswhere -latest -find '**\vcvars64.bat'` — machines here carry both BuildTools and Community. - **Never wrap a build in `2>&1`.** `vcvars64.bat` writes to stderr on a healthy run, and diff --git a/crates/moon-core/tests/ci_gate_contract.rs b/crates/moon-core/tests/ci_gate_contract.rs index 2e69ead2c..f5274544f 100644 --- a/crates/moon-core/tests/ci_gate_contract.rs +++ b/crates/moon-core/tests/ci_gate_contract.rs @@ -40,18 +40,18 @@ const TEST_JOB: &str = "tests"; /// Every job that compiles the workspace and therefore runs the lockfile contract's three steps /// (verify -> refresh MoonUI -> assert nothing else moved). `audit` is deliberately excluded: it /// runs cargo-deny over the already-committed lock and never touches it. -const COMPILING_JOBS: [&str; 3] = ["windows", TEST_JOB, "macos-probe"]; +const COMPILING_JOBS: [&str; 4] = ["windows", TEST_JOB, "macos-probe", "clippy"]; -/// The two compiling jobs that BLOCK a merge — the Windows `.exe` release gate and the `tests` -/// gate — and so must neither be silently skipped nor downgraded to a probe. `macos-probe` is -/// deliberately excluded here even though it shares the same `if:` condition: it already carries +/// The compiling jobs that BLOCK a merge — the Windows `.exe` release gate, the `tests` gate, and +/// the `clippy` gate — and so must neither be silently skipped nor downgraded to a probe. +/// `macos-probe` is deliberately excluded here even though it shares the same `if:` condition: it already carries /// `continue-on-error: true` and never blocks, so there is no gate left for a quiet skip to hide /// behind, and it needs no guard of its own. -const GATING_JOBS: [&str; 2] = ["windows", TEST_JOB]; +const GATING_JOBS: [&str; 3] = ["windows", TEST_JOB, "clippy"]; /// The only job-level `if:` a `GATING_JOBS` member may carry, normalized the same way /// [`normalize_if_condition`] normalizes what it reads from `build.yml`. The weekly `schedule:` -/// trigger (`build.yml`'s `on:` header) exists for the `audit` job alone, so the two gates skip +/// trigger (`build.yml`'s `on:` header) exists for the `audit` job alone, so these gates skip /// it and nothing else. const EXPECTED_SCHEDULE_EXCLUSION: &str = "github.event_name != 'schedule'"; @@ -88,6 +88,9 @@ const AUDIT_JOB: &str = "audit"; /// The formatting gate's job key, separate from compilation and test gates. const FMT_JOB: &str = "fmt"; +/// The clippy gate's job key. It compiles, so it is also in [`COMPILING_JOBS`] and [`GATING_JOBS`]. +const CLIPPY_JOB: &str = "clippy"; + fn workspace_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() @@ -482,6 +485,58 @@ fn the_fmt_job_is_a_gate_that_actually_runs_cargo_fmt() { ); } +/// Breakage guarded: changing `.github/workflows/build.yml`'s `clippy` job command away from +/// `cargo clippy --workspace --all-targets --locked -- -D warnings`, dropping `--locked` or +/// `-D warnings`, or demoting the job with `continue-on-error: true`. A warning would then merge +/// while the check still looked green. +#[test] +fn the_clippy_job_is_a_gate_that_actually_runs_cargo_clippy() { + let text = workflow_text(); + let body = job_body(&text, CLIPPY_JOB) + .unwrap_or_else(|| panic!("build.yml must keep a `{CLIPPY_JOB}:` lint job")); + + for line in &body { + let Some(value) = line.trim().strip_prefix("continue-on-error:") else { + continue; + }; + assert_eq!( + value.trim(), + "false", + "job `{CLIPPY_JOB}` runs the lint gate, so a failure must block: `{}`", + line.trim() + ); + } + + let skipped = body.iter().find(|line| line.starts_with(" if:")); + let line = skipped.unwrap_or_else(|| { + panic!("job `{CLIPPY_JOB}` compiles, so it must skip the audit-only weekly schedule") + }); + assert_eq!( + normalize_if_condition(line), + EXPECTED_SCHEDULE_EXCLUSION, + "job `{CLIPPY_JOB}` must run on push, pull_request, and workflow_dispatch: `{}`", + line.trim() + ); + + let command = body + .iter() + .filter_map(|line| line.trim().strip_prefix("run:")) + .map(str::trim) + .find(|command| command.contains("cargo clippy")) + .unwrap_or_else(|| panic!("job `{CLIPPY_JOB}` must run cargo clippy")); + assert_eq!( + command, "cargo clippy --workspace --all-targets --locked -- -D warnings", + "job `{CLIPPY_JOB}` must deny warnings on the whole workspace: `{command}`" + ); + for sep in [";", "&&", "||", "|"] { + assert!( + !command.contains(sep), + "job `{CLIPPY_JOB}` must not chain anything onto clippy — `{sep}` can swallow a \ + failure: `{command}`" + ); + } +} + /// Breakage guarded: a well-meaning reorder in `.github/workflows/build.yml`'s lockfile contract /// (verify -> refresh MoonUI -> assert nothing else moved), in any compiling job. `cargo fetch /// --locked` only proves the committed lock agrees with the manifests when it runs BEFORE diff --git a/docs/AGENT_RULES.md b/docs/AGENT_RULES.md index a2e5bb449..2e1a429d7 100644 --- a/docs/AGENT_RULES.md +++ b/docs/AGENT_RULES.md @@ -34,7 +34,8 @@ A SessionStart hook injects this file, and `CONTRIBUTING.md` beside it, into eve ## Before you push 6. `cargo test --workspace` is green on your machine before the push, not just on CI afterwards. -7. Run `cargo clippy` — CI does not (→ `CONTRIBUTING.md` § Commits and PRs). +7. `cargo clippy --workspace --all-targets -- -D warnings` must pass; CI runs that command + (→ `CONTRIBUTING.md` § Commits and PRs and § Build and checks). 8. The tree is rustfmt-clean: run `cargo fmt --all` (or `make fmt`) before you push (→ `CONTRIBUTING.md` § Commits and PRs). 9. Read `git status` before every push; never `git add -f` — fix the over-broad ignore instead. From a1158e4a5d3c144486ba3c81c073c6f14afa387a Mon Sep 17 00:00:00 2001 From: kirillDevPro <113171057+kirillDevPro@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:51:10 +0200 Subject: [PATCH 5/5] chore(clippy): correct two allow reasons CoreTrack::averaged checked the divisor by hand and claimed checked_div would report zero. checked_div returns None for a zero sample count, which is the unknown state, and the same quotient otherwise. The hotkeys allow stays; its comment now says the suggested collapse does not compile. --- crates/moon-ui-gpui/src/backend/core_warn.rs | 16 ++++++---------- crates/moon-ui-gpui/src/hotkeys.rs | 4 +++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/crates/moon-ui-gpui/src/backend/core_warn.rs b/crates/moon-ui-gpui/src/backend/core_warn.rs index d4b184728..6248b98a4 100644 --- a/crates/moon-ui-gpui/src/backend/core_warn.rs +++ b/crates/moon-ui-gpui/src/backend/core_warn.rs @@ -456,8 +456,8 @@ struct CoreTrack { impl CoreTrack { /// Average `(process, system)` CPU over the last `CPU_WINDOW_SECS` seconds. /// - /// A zero sample count is unknown CPU, not 0%. `checked_div` would report zero. - #[allow(clippy::manual_checked_ops)] + /// A zero sample count is unknown CPU, not 0%. `checked_div` returns `None` + /// for that divisor, which is that unknown state. fn averaged(&self, now_sec: i64) -> (Option, Option) { let (mut proc, mut system, mut n) = (0u32, 0u32, 0u32); for bucket in &self.cpu { @@ -467,14 +467,10 @@ impl CoreTrack { n += bucket.samples; } } - if n == 0 { - (None, None) - } else { - ( - Some((proc / n).min(255) as u8), - Some((system / n).min(255) as u8), - ) - } + ( + proc.checked_div(n).map(|v| v.min(255) as u8), + system.checked_div(n).map(|v| v.min(255) as u8), + ) } } diff --git a/crates/moon-ui-gpui/src/hotkeys.rs b/crates/moon-ui-gpui/src/hotkeys.rs index 9722fd5fb..89800f1c1 100644 --- a/crates/moon-ui-gpui/src/hotkeys.rs +++ b/crates/moon-ui-gpui/src/hotkeys.rs @@ -1110,7 +1110,9 @@ pub fn apply( // no switch, no pill and no summary on screen to say it happened — and the next order // would go out under it. Refusing lets the key propagate, exactly like the no-core arm. A::ManualStrategy(_) if b.is_auto_overview_scope(group) => false, - // Collapsing this into the guard arm above makes the match non-exhaustive. + // Clippy's suggested collapsible_match rewrite does not compile: folding + // the inner `if` into this match leaves `Some(_)` uncovered because the + // previous `ManualStrategy` arm is a guard. #[allow(clippy::collapsible_match)] A::ManualStrategy(i) => match active_core { Some(core) => {