diff --git a/Cargo.lock b/Cargo.lock index ce5a23ebc..f42741471 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "autocfg" version = "1.5.0" @@ -256,6 +262,7 @@ checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" name = "fish" version = "4.3.3" dependencies = [ + "assert_matches", "bitflags", "cc", "cfg-if", @@ -376,6 +383,7 @@ version = "0.0.0" name = "fish-printf" version = "0.2.1" dependencies = [ + "assert_matches", "libc", "unicode-segmentation", "unicode-width", @@ -413,6 +421,7 @@ dependencies = [ name = "fish-wgetopt" version = "0.0.0" dependencies = [ + "assert_matches", "fish-wcstringutil", "fish-widestring", ] diff --git a/Cargo.toml b/Cargo.toml index 6190677cf..a8055c746 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/fish-shell/fish-shell" license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0" [workspace.dependencies] +assert_matches = "1.5.0" bitflags = "2.5.0" cc = "1.0.94" cfg-if = "1.0.3" @@ -94,6 +95,7 @@ homepage = "https://fishshell.com" readme = "README.rst" [dependencies] +assert_matches.workspace = true bitflags.workspace = true cfg-if.workspace = true errno.workspace = true diff --git a/crates/printf/Cargo.toml b/crates/printf/Cargo.toml index de87ad0bc..966d003cc 100644 --- a/crates/printf/Cargo.toml +++ b/crates/printf/Cargo.toml @@ -8,10 +8,11 @@ description = "printf implementation, based on musl" license = "MIT" [dependencies] +assert_matches.workspace = true libc.workspace = true -widestring = { workspace = true, optional = true } unicode-segmentation.workspace = true unicode-width.workspace = true +widestring = { workspace = true, optional = true } [lints] workspace = true diff --git a/crates/printf/src/arg.rs b/crates/printf/src/arg.rs index 22dceb242..7064dbb20 100644 --- a/crates/printf/src/arg.rs +++ b/crates/printf/src/arg.rs @@ -199,27 +199,28 @@ fn to_arg(self) -> Arg<'a> { #[cfg(test)] mod tests { use super::*; + use assert_matches::assert_matches; #[cfg(feature = "widestring")] use widestring::utf32str; #[test] fn test_to_arg() { - assert!(matches!("test".to_arg(), Arg::Str("test"))); - assert!(matches!(String::from("test").to_arg(), Arg::Str(_))); + assert_matches!("test".to_arg(), Arg::Str("test")); + assert_matches!(String::from("test").to_arg(), Arg::Str(_)); #[cfg(feature = "widestring")] - assert!(matches!(utf32str!("test").to_arg(), Arg::WStr(_))); + assert_matches!(utf32str!("test").to_arg(), Arg::WStr(_)); #[cfg(feature = "widestring")] - assert!(matches!(WString::from("test").to_arg(), Arg::WStr(_))); - assert!(matches!(42f32.to_arg(), Arg::Float(_))); - assert!(matches!(42f64.to_arg(), Arg::Float(_))); - assert!(matches!('x'.to_arg(), Arg::UInt(120))); + assert_matches!(WString::from("test").to_arg(), Arg::WStr(_)); + assert_matches!(42f32.to_arg(), Arg::Float(_)); + assert_matches!(42f64.to_arg(), Arg::Float(_)); + assert_matches!('x'.to_arg(), Arg::UInt(120)); let mut usize_val: usize = 0; - assert!(matches!((&mut usize_val).to_arg(), Arg::USizeRef(_))); - assert!(matches!(42i8.to_arg(), Arg::SInt(42))); - assert!(matches!(42i16.to_arg(), Arg::SInt(42))); - assert!(matches!(42i32.to_arg(), Arg::SInt(42))); - assert!(matches!(42i64.to_arg(), Arg::SInt(42))); - assert!(matches!(42isize.to_arg(), Arg::SInt(42))); + assert_matches!((&mut usize_val).to_arg(), Arg::USizeRef(_)); + assert_matches!(42i8.to_arg(), Arg::SInt(42)); + assert_matches!(42i16.to_arg(), Arg::SInt(42)); + assert_matches!(42i32.to_arg(), Arg::SInt(42)); + assert_matches!(42i64.to_arg(), Arg::SInt(42)); + assert_matches!(42isize.to_arg(), Arg::SInt(42)); assert_eq!((-42i8).to_arg(), Arg::SInt(-42)); assert_eq!((-42i16).to_arg(), Arg::SInt(-42)); @@ -227,14 +228,14 @@ fn test_to_arg() { assert_eq!((-42i64).to_arg(), Arg::SInt(-42)); assert_eq!((-42isize).to_arg(), Arg::SInt(-42)); - assert!(matches!(42u8.to_arg(), Arg::UInt(42))); - assert!(matches!(42u16.to_arg(), Arg::UInt(42))); - assert!(matches!(42u32.to_arg(), Arg::UInt(42))); - assert!(matches!(42u64.to_arg(), Arg::UInt(42))); - assert!(matches!(42usize.to_arg(), Arg::UInt(42))); + assert_matches!(42u8.to_arg(), Arg::UInt(42)); + assert_matches!(42u16.to_arg(), Arg::UInt(42)); + assert_matches!(42u32.to_arg(), Arg::UInt(42)); + assert_matches!(42u64.to_arg(), Arg::UInt(42)); + assert_matches!(42usize.to_arg(), Arg::UInt(42)); let ptr = std::ptr::from_ref(&42f32); - assert!(matches!(ptr.to_arg(), Arg::UInt(_))); + assert_matches!(ptr.to_arg(), Arg::UInt(_)); } #[test] diff --git a/crates/printf/src/fmt_fp/mod.rs b/crates/printf/src/fmt_fp/mod.rs index d1efa9172..fb0d1a3b3 100644 --- a/crates/printf/src/fmt_fp/mod.rs +++ b/crates/printf/src/fmt_fp/mod.rs @@ -4,6 +4,7 @@ use super::locale::Locale; use super::printf_impl::{ConversionSpec, Error, ModifierFlags, pad}; +use assert_matches::debug_assert_matches; use decimal::{DIGIT_WIDTH, Decimal, DigitLimit}; use std::cmp::min; use std::fmt::Write; @@ -129,10 +130,10 @@ pub(crate) fn format_float( ) -> Result { // Only float conversions are expected. type CS = ConversionSpec; - debug_assert!(matches!( + debug_assert_matches!( conv_spec, CS::e | CS::E | CS::f | CS::F | CS::g | CS::G | CS::a | CS::A - )); + ); let prefix = match (y.is_sign_negative(), flags.mark_pos, flags.pad_pos) { (true, _, _) => "-", (false, true, _) => "+", diff --git a/crates/printf/src/printf_impl.rs b/crates/printf/src/printf_impl.rs index a7f39d83a..510e8c7d7 100644 --- a/crates/printf/src/printf_impl.rs +++ b/crates/printf/src/printf_impl.rs @@ -2,6 +2,7 @@ use super::arg::Arg; use super::fmt_fp::format_float; use super::locale::Locale; +use assert_matches::assert_matches; use std::fmt::{self, Write}; use std::mem; use std::result::Result; @@ -301,7 +302,7 @@ pub(super) fn pad( min_width: usize, current_width: usize, ) -> fmt::Result { - assert!(c == '0' || c == ' '); + assert_matches!(c, '0' | ' '); if current_width >= min_width { return Ok(()); } diff --git a/crates/wgetopt/Cargo.toml b/crates/wgetopt/Cargo.toml index aff82797d..e03089a6b 100644 --- a/crates/wgetopt/Cargo.toml +++ b/crates/wgetopt/Cargo.toml @@ -7,6 +7,7 @@ repository.workspace = true license.workspace = true [dependencies] +assert_matches.workspace = true fish-wcstringutil.workspace = true fish-widestring.workspace = true diff --git a/crates/wgetopt/src/lib.rs b/crates/wgetopt/src/lib.rs index 61b36a7d2..d2b1a1c59 100644 --- a/crates/wgetopt/src/lib.rs +++ b/crates/wgetopt/src/lib.rs @@ -24,6 +24,7 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +use assert_matches::assert_matches; use fish_widestring::prelude::*; /// Special char used with [`Ordering::ReturnInOrder`]. @@ -397,7 +398,7 @@ fn update_long_opt( option_index: usize, ) -> char { self.wopt_index += 1; - assert!(matches!(self.remaining_text.char_at(name_end), '\0' | '=')); + assert_matches!(self.remaining_text.char_at(name_end), '\0' | '='); if self.remaining_text.char_at(name_end) == '=' { if opt_found.arg_type == ArgType::NoArgument { diff --git a/src/ast.rs b/src/ast.rs index 7d7fde1ee..31da44a7c 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -263,7 +263,7 @@ trait NodeMut: Node + AcceptorMut {} impl NodeMut for T where T: Node + AcceptorMut {} /// The different kinds of nodes. Note that Token and Keyword have different subtypes. -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub enum Kind<'a> { Redirection(&'a Redirection), Token(&'a dyn Token), diff --git a/src/autoload.rs b/src/autoload.rs index f12471733..dd8452160 100644 --- a/src/autoload.rs +++ b/src/autoload.rs @@ -51,11 +51,13 @@ enum AssetDir { Completions, } +#[derive(Debug)] pub enum AutoloadPath { Embedded(String), Path(WString), } +#[derive(Debug)] pub enum AutoloadResult { Path(AutoloadPath), Loaded, @@ -455,6 +457,7 @@ mod tests { use super::{Autoload, AutoloadResult}; use crate::prelude::*; use crate::tests::prelude::*; + use assert_matches::assert_matches; #[test] #[serial] @@ -505,39 +508,39 @@ fn touch_file(path: &wstr) { autoload.invalidate_cache(); assert!(!autoload.autoload_in_progress(L!("file1"))); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file1"), paths), AutoloadResult::Path(_) - )); - assert!(matches!( + ); + assert_matches!( autoload.resolve_command_impl(L!("file1"), paths), AutoloadResult::Pending - )); + ); assert!(autoload.autoload_in_progress(L!("file1"))); assert_eq!(autoload.get_autoloaded_commands(), vec![L!("file1")]); autoload.mark_autoload_finished(L!("file1")); assert!(!autoload.autoload_in_progress(L!("file1"))); assert_eq!(autoload.get_autoloaded_commands(), vec![L!("file1")]); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file1"), paths), AutoloadResult::Loaded - )); + ); assert!( autoload .resolve_command_impl(L!("nothing"), paths) .is_none() ); assert!(autoload.resolve_command_impl(L!("file2"), paths).is_some()); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file2"), paths), AutoloadResult::Pending - )); + ); autoload.mark_autoload_finished(L!("file2")); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file2"), paths), AutoloadResult::Loaded - )); + ); assert_eq!( autoload.get_autoloaded_commands(), vec![L!("file1"), L!("file2")] @@ -546,26 +549,26 @@ fn touch_file(path: &wstr) { autoload.clear(); assert!(autoload.resolve_command_impl(L!("file1"), paths).is_some()); autoload.mark_autoload_finished(L!("file1")); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file1"), paths), AutoloadResult::Loaded - )); + ); assert!( autoload .resolve_command_impl(L!("nothing"), paths) .is_none() ); assert!(autoload.resolve_command_impl(L!("file2"), paths).is_some()); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file2"), paths), AutoloadResult::Pending - )); + ); autoload.mark_autoload_finished(L!("file2")); - assert!(matches!( + assert_matches!( autoload.resolve_command_impl(L!("file1"), paths), AutoloadResult::Loaded - )); + ); touch_file(&sprintf!("%s/file1.fish", p1)); autoload.invalidate_cache(); assert!(autoload.resolve_command_impl(L!("file1"), paths).is_some()); diff --git a/src/builtins/fish_indent.rs b/src/builtins/fish_indent.rs index 0c0ea4791..05d670b5b 100644 --- a/src/builtins/fish_indent.rs +++ b/src/builtins/fish_indent.rs @@ -30,6 +30,7 @@ use crate::tokenizer::{TOK_SHOW_BLANK_LINES, TOK_SHOW_COMMENTS, TokenType, Tokenizer}; use crate::topic_monitor::topic_monitor_init; use crate::wutil::fish_iswalnum; +use assert_matches::assert_matches; use fish_wcstringutil::count_preceding_backslashes; use fish_wgetopt::{ArgType, WGetopter, WOption, wopt}; use std::fmt::Write as _; @@ -394,7 +395,7 @@ fn gap_text_flags_before_node(&self, node: &dyn Node) -> GapFlags { return result; } let p = self.traversal.parent(p); - assert!(matches!(p.kind(), Kind::Statement(_))); + assert_matches!(p.kind(), Kind::Statement(_)); let p = self.traversal.parent(p); if let Kind::JobPipeline(job) = p.kind() { if !job.variables.is_empty() { diff --git a/src/complete.rs b/src/complete.rs index 23da9f7a1..99cd27a5c 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -45,6 +45,7 @@ localization::{LocalizableString, localizable_string}, reader::{get_quote, is_backslashed}, }; +use assert_matches::assert_matches; use bitflags::bitflags; use fish_util::wcsfilecmp; use fish_wcstringutil::{ @@ -720,7 +721,7 @@ fn perform_for_commandline_impl(&mut self, cmdline: WString) { } for tok in &tokens { // If there was an error, it was in the last token. - assert!(matches!(tok.type_, TokenType::String | TokenType::Redirect)); + assert_matches!(tok.type_, TokenType::String | TokenType::Redirect); } // If we are completing a variable name or a tilde expansion user name, we do that and // return. No need for any other completions. diff --git a/src/env/var.rs b/src/env/var.rs index 7f78027c5..3225f8aa3 100644 --- a/src/env/var.rs +++ b/src/env/var.rs @@ -323,6 +323,7 @@ mod tests { use crate::env::environment::{EnvStack, Environment}; use crate::prelude::*; use crate::tests::prelude::*; + use assert_matches::assert_matches; use std::{ mem::MaybeUninit, time::{SystemTime, UNIX_EPOCH}, @@ -361,7 +362,7 @@ fn test_timezone_env_vars() { let first_tstamp = return_timezone_hour(tstamp, L!("UTC-1")); let second_tstamp = return_timezone_hour(tstamp, L!("UTC-2")); let delta = second_tstamp - first_tstamp; - assert!(delta == 1 || delta == -23); + assert_matches!(delta, 1 | -23); } // Verify that setting special env vars have the expected effect on the current shell process. diff --git a/src/fd_monitor.rs b/src/fd_monitor.rs index f974635a8..94e2b63b4 100644 --- a/src/fd_monitor.rs +++ b/src/fd_monitor.rs @@ -473,6 +473,7 @@ mod tests { use std::thread; use std::time::Duration; + use assert_matches::assert_matches; use errno::errno; use crate::fd_monitor::{FdEventSignaller, FdMonitor}; @@ -694,8 +695,9 @@ fn test_dup2_during_select_ebadf() { Some(read_fd) }; let result = do_something_bad_during_select(dup2_it); - assert!( - matches!(result, Err(libc::EBADF) | Ok(0 | 1)), + assert_matches!( + result, + Err(libc::EBADF) | Ok(0 | 1), "select/poll should have failed with EBADF or timed out or the fd should be ready" ); // Ensure these stay alive until after thread is joined. diff --git a/src/parser.rs b/src/parser.rs index abc4f1c7a..71680e7ca 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -35,6 +35,7 @@ use crate::wait_handle::WaitHandleStore; use crate::wutil::perror; use crate::{flog, flogf, function}; +use assert_matches::assert_matches; use fish_util::get_time; use fish_widestring::WExt; use libc::c_int; @@ -568,7 +569,7 @@ pub fn eval_parsed_source( block_type: BlockType, test_only_suppress_stderr: bool, ) -> EvalRes { - assert!(matches!(block_type, BlockType::top | BlockType::subst)); + assert_matches!(block_type, BlockType::top | BlockType::subst); let job_list = ps.top_job_list(); if !job_list.is_empty() { // Execute the top job list. @@ -647,8 +648,9 @@ pub fn eval_node( test_only_suppress_stderr: bool, ) -> EvalRes { // Only certain blocks are allowed. - assert!( - matches!(block_type, BlockType::top | BlockType::subst), + assert_matches!( + block_type, + BlockType::top | BlockType::subst, "Invalid block type" ); diff --git a/src/reader/reader.rs b/src/reader/reader.rs index 5ebcdb63a..0fbbaf78f 100644 --- a/src/reader/reader.rs +++ b/src/reader/reader.rs @@ -142,6 +142,7 @@ use crate::wildcard::wildcard_has; use crate::wutil::{fstat, perror, write_to_fd, wstat}; use crate::{abbrs, event, function}; +use assert_matches::assert_matches; use fish_fallback::fish_wcwidth; use fish_wcstringutil::{ CaseSensitivity, StringFuzzyMatch, count_preceding_backslashes, join_strings, @@ -6782,10 +6783,7 @@ fn reader_can_replace(s: &wstr, flags: CompleteFlags) -> bool { impl<'a> Reader<'a> { /// Compute completions and update the pager and/or commandline as needed. fn compute_and_apply_completions(&mut self, c: ReadlineCmd) { - assert!(matches!( - c, - ReadlineCmd::Complete | ReadlineCmd::CompleteAndSearch - )); + assert_matches!(c, ReadlineCmd::Complete | ReadlineCmd::CompleteAndSearch); assert!( !get_tty_protocols_active(), "should not be called with TTY protocols active" diff --git a/src/terminal.rs b/src/terminal.rs index 74533249c..95852e54c 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -39,14 +39,14 @@ pub fn set_color_support(val: ColorSupport) { COLOR_SUPPORT.store(val.bits(), Ordering::Relaxed); } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub(crate) enum Paintable { Foreground, Background, Underline, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub(crate) enum TerminalCommand<'a> { // Text attributes ExitAttributeMode, @@ -311,7 +311,7 @@ fn rgb_color(out: &mut impl Output, paintable: Paintable, rgb: Color24) -> bool true } -#[derive(Clone)] +#[derive(Debug, Clone)] pub(crate) enum CardinalDirection { Up, Left, diff --git a/src/wutil/dir_iter.rs b/src/wutil/dir_iter.rs index 5ba650c8b..69162b671 100644 --- a/src/wutil/dir_iter.rs +++ b/src/wutil/dir_iter.rs @@ -331,6 +331,7 @@ fn next(&mut self) -> Option { mod tests { use super::{DirEntryType, DirIter}; use crate::prelude::*; + use assert_matches::assert_matches; use fish_widestring::L; use nix::sys::stat::Mode; use std::fs::File; @@ -383,7 +384,7 @@ fn test_dir_iter() { panic!("Expected error"); }; let err = err.raw_os_error().expect("Should have an errno value"); - assert!(err == ENOENT || err == EACCES); + assert_matches!(err, ENOENT | EACCES); let temp_dir = fish_tempfile::new_dir().unwrap(); let basepath = WString::from(temp_dir.path().to_str().unwrap());