From ee78fce1354303b38ad8a8db53fd55483a650bd1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 20 Aug 2025 16:11:51 -0500 Subject: [PATCH 1/2] fix(harness)!: Rename State to TestContext --- crates/libtest2-harness/src/case.rs | 4 +-- .../src/{state.rs => context.rs} | 6 ++--- crates/libtest2-harness/src/harness.rs | 26 +++++++++---------- crates/libtest2-harness/src/lib.rs | 4 +-- .../libtest2-mimic/examples/mimic-simple.rs | 14 +++++----- crates/libtest2-mimic/src/lib.rs | 12 ++++----- crates/libtest2/examples/simple.rs | 14 +++++----- crates/libtest2/src/lib.rs | 12 ++++----- .../libtest2/tests/testsuite/all_passing.rs | 6 ++--- crates/libtest2/tests/testsuite/argfile.rs | 8 +++--- crates/libtest2/tests/testsuite/mixed_bag.rs | 26 +++++++++---------- crates/libtest2/tests/testsuite/panic.rs | 4 +-- 12 files changed, 68 insertions(+), 68 deletions(-) rename crates/libtest2-harness/src/{state.rs => context.rs} (93%) diff --git a/crates/libtest2-harness/src/case.rs b/crates/libtest2-harness/src/case.rs index d7639f5..64e21f8 100644 --- a/crates/libtest2-harness/src/case.rs +++ b/crates/libtest2-harness/src/case.rs @@ -10,9 +10,9 @@ pub trait Case: Send + Sync + 'static { fn kind(&self) -> TestKind; fn source(&self) -> Option<&Source>; /// This case cannot run in parallel to other cases within this binary - fn exclusive(&self, state: &State) -> bool; + fn exclusive(&self, state: &TestContext) -> bool; - fn run(&self, state: &State) -> Result<(), RunError>; + fn run(&self, state: &TestContext) -> Result<(), RunError>; } /// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html) diff --git a/crates/libtest2-harness/src/state.rs b/crates/libtest2-harness/src/context.rs similarity index 93% rename from crates/libtest2-harness/src/state.rs rename to crates/libtest2-harness/src/context.rs index 3253954..c026460 100644 --- a/crates/libtest2-harness/src/state.rs +++ b/crates/libtest2-harness/src/context.rs @@ -1,12 +1,12 @@ pub(crate) use crate::*; #[derive(Debug)] -pub struct State { +pub struct TestContext { mode: RunMode, run_ignored: bool, } -impl State { +impl TestContext { pub fn ignore(&self) -> Result<(), RunError> { if self.run_ignored { Ok(()) @@ -28,7 +28,7 @@ impl State { } } -impl State { +impl TestContext { pub(crate) fn new() -> Self { Self { mode: Default::default(), diff --git a/crates/libtest2-harness/src/harness.rs b/crates/libtest2-harness/src/harness.rs index c823114..a6e80a4 100644 --- a/crates/libtest2-harness/src/harness.rs +++ b/crates/libtest2-harness/src/harness.rs @@ -1,6 +1,6 @@ use libtest_lexarg::OutputFormat; -use crate::{cli, notify, Case, RunError, RunMode, State}; +use crate::{cli, notify, Case, RunError, RunMode, TestContext}; pub struct Harness { raw: std::io::Result>, @@ -275,7 +275,7 @@ fn run( let threads = opts.test_threads.map(|t| t.get()).unwrap_or(1); - let mut state = State::new(); + let mut context = TestContext::new(); let run_ignored = match opts.run_ignored { libtest_lexarg::RunIgnored::Yes | libtest_lexarg::RunIgnored::Only => true, libtest_lexarg::RunIgnored::No => false, @@ -290,9 +290,9 @@ fn run( (false, true) => RunMode::Bench, (false, false) => unreachable!("libtest-lexarg` should always ensure at least one is set"), }; - state.set_mode(mode); - state.set_run_ignored(run_ignored); - let state = std::sync::Arc::new(state); + context.set_mode(mode); + context.set_run_ignored(run_ignored); + let context = std::sync::Arc::new(context); let mut success = true; @@ -301,7 +301,7 @@ fn run( } else { cases .into_iter() - .partition::, _>(|c| c.exclusive(&state)) + .partition::, _>(|c| c.exclusive(&context)) }; if !concurrent_cases.is_empty() { notifier.threaded(true); @@ -355,14 +355,14 @@ fn run( let tx = tx.clone(); let case = std::sync::Arc::new(case); let case_fallback = case.clone(); - let state = state.clone(); - let state_fallback = state.clone(); + let context = context.clone(); + let context_fallback = context.clone(); let sync_success = sync_success.clone(); let sync_success_fallback = sync_success.clone(); let join_handle = cfg.spawn(move || { let mut notifier = SenderNotifier { tx: tx.clone() }; let case_success = - run_case(&start, case.as_ref().as_ref(), &state, &mut notifier) + run_case(&start, case.as_ref().as_ref(), &context, &mut notifier) .expect("`SenderNotifier` is infallible"); if !case_success { sync_success.store(case_success, std::sync::atomic::Ordering::Relaxed); @@ -379,7 +379,7 @@ fn run( let case_success = run_case( &start, case_fallback.as_ref().as_ref(), - &state_fallback, + &context_fallback, notifier, ) .expect("`SenderNotifier` is infallible"); @@ -411,7 +411,7 @@ fn run( if !exclusive_cases.is_empty() { notifier.threaded(false); for case in exclusive_cases { - success &= run_case(start, case.as_ref(), &state, notifier)?; + success &= run_case(start, case.as_ref(), &context, notifier)?; if !success && opts.fail_fast { break; } @@ -431,7 +431,7 @@ fn run( fn run_case( start: &std::time::Instant, case: &dyn Case, - state: &State, + context: &TestContext, notifier: &mut dyn notify::Notifier, ) -> std::io::Result { notifier.notify( @@ -443,7 +443,7 @@ fn run_case( )?; let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - __rust_begin_short_backtrace(|| case.run(state)) + __rust_begin_short_backtrace(|| case.run(context)) })) .unwrap_or_else(|e| { // The `panic` information is just an `Any` object representing the diff --git a/crates/libtest2-harness/src/lib.rs b/crates/libtest2-harness/src/lib.rs index 6f3bd0c..ba67094 100644 --- a/crates/libtest2-harness/src/lib.rs +++ b/crates/libtest2-harness/src/lib.rs @@ -26,16 +26,16 @@ #![allow(clippy::todo)] mod case; +mod context; mod harness; mod notify; -mod state; pub mod cli; pub use case::*; +pub use context::*; pub use harness::*; pub use notify::RunMode; -pub use state::*; #[doc = include_str!("../README.md")] #[cfg(doctest)] diff --git a/crates/libtest2-mimic/examples/mimic-simple.rs b/crates/libtest2-mimic/examples/mimic-simple.rs index c5a1843..beaf47f 100644 --- a/crates/libtest2-mimic/examples/mimic-simple.rs +++ b/crates/libtest2-mimic/examples/mimic-simple.rs @@ -1,6 +1,6 @@ use libtest2_mimic::RunError; use libtest2_mimic::RunResult; -use libtest2_mimic::State; +use libtest2_mimic::TestContext; use libtest2_mimic::Trial; fn main() { @@ -15,21 +15,21 @@ fn main() { // Tests -fn check_toph(_state: &State) -> RunResult { +fn check_toph(_context: &TestContext) -> RunResult { Ok(()) } -fn check_katara(_state: &State) -> RunResult { +fn check_katara(_context: &TestContext) -> RunResult { Ok(()) } -fn check_sokka(_state: &State) -> RunResult { +fn check_sokka(_context: &TestContext) -> RunResult { Err(RunError::fail("Sokka tripped and fell :(")) } -fn long_computation(state: &State) -> RunResult { - state.ignore_for("slow")?; +fn long_computation(context: &TestContext) -> RunResult { + context.ignore_for("slow")?; std::thread::sleep(std::time::Duration::from_secs(1)); Ok(()) } -fn compile_fail_dummy(_state: &State) -> RunResult { +fn compile_fail_dummy(_context: &TestContext) -> RunResult { Ok(()) } diff --git a/crates/libtest2-mimic/src/lib.rs b/crates/libtest2-mimic/src/lib.rs index 75ca2f5..6dfe36b 100644 --- a/crates/libtest2-mimic/src/lib.rs +++ b/crates/libtest2-mimic/src/lib.rs @@ -27,7 +27,7 @@ pub use libtest2_harness::Harness; pub use libtest2_harness::RunError; pub use libtest2_harness::RunResult; -pub use libtest2_harness::State; +pub use libtest2_harness::TestContext; pub use libtest2_harness::TestKind; use libtest2_harness::Case; @@ -36,13 +36,13 @@ use libtest2_harness::Source; pub struct Trial { name: String, #[allow(clippy::type_complexity)] - runner: Box Result<(), RunError> + Send + Sync>, + runner: Box Result<(), RunError> + Send + Sync>, } impl Trial { pub fn test( name: impl Into, - runner: impl Fn(&State) -> Result<(), RunError> + Send + Sync + 'static, + runner: impl Fn(&TestContext) -> Result<(), RunError> + Send + Sync + 'static, ) -> Self { Self { name: name.into(), @@ -61,12 +61,12 @@ impl Case for Trial { fn source(&self) -> Option<&Source> { None } - fn exclusive(&self, _: &State) -> bool { + fn exclusive(&self, _: &TestContext) -> bool { false } - fn run(&self, state: &State) -> Result<(), RunError> { - (self.runner)(state) + fn run(&self, context: &TestContext) -> Result<(), RunError> { + (self.runner)(context) } } diff --git a/crates/libtest2/examples/simple.rs b/crates/libtest2/examples/simple.rs index 4d8f31b..040bfce 100644 --- a/crates/libtest2/examples/simple.rs +++ b/crates/libtest2/examples/simple.rs @@ -1,6 +1,6 @@ use libtest2::RunError; use libtest2::RunResult; -use libtest2::State; +use libtest2::TestContext; libtest2::libtest2_main!( check_toph, @@ -12,21 +12,21 @@ libtest2::libtest2_main!( // Tests -fn check_toph(_state: &State) -> RunResult { +fn check_toph(_context: &TestContext) -> RunResult { Ok(()) } -fn check_katara(_state: &State) -> RunResult { +fn check_katara(_context: &TestContext) -> RunResult { Ok(()) } -fn check_sokka(_state: &State) -> RunResult { +fn check_sokka(_context: &TestContext) -> RunResult { Err(RunError::fail("Sokka tripped and fell :(")) } -fn long_computation(state: &State) -> RunResult { - state.ignore_for("slow")?; +fn long_computation(context: &TestContext) -> RunResult { + context.ignore_for("slow")?; std::thread::sleep(std::time::Duration::from_secs(1)); Ok(()) } -fn compile_fail_dummy(_state: &State) -> RunResult { +fn compile_fail_dummy(_context: &TestContext) -> RunResult { Ok(()) } diff --git a/crates/libtest2/src/lib.rs b/crates/libtest2/src/lib.rs index 2718c41..0c21b0b 100644 --- a/crates/libtest2/src/lib.rs +++ b/crates/libtest2/src/lib.rs @@ -27,7 +27,7 @@ pub use libtest2_harness::Harness; pub use libtest2_harness::RunError; pub use libtest2_harness::RunResult; -pub use libtest2_harness::State; +pub use libtest2_harness::TestContext; pub use libtest2_harness::TestKind; use libtest2_harness::Case; @@ -36,13 +36,13 @@ use libtest2_harness::Source; pub struct Trial { name: String, #[allow(clippy::type_complexity)] - runner: Box Result<(), RunError> + Send + Sync>, + runner: Box Result<(), RunError> + Send + Sync>, } impl Trial { pub fn test( name: impl Into, - runner: impl Fn(&State) -> Result<(), RunError> + Send + Sync + 'static, + runner: impl Fn(&TestContext) -> Result<(), RunError> + Send + Sync + 'static, ) -> Self { Self { name: name.into(), @@ -61,12 +61,12 @@ impl Case for Trial { fn source(&self) -> Option<&Source> { None } - fn exclusive(&self, _: &State) -> bool { + fn exclusive(&self, _: &TestContext) -> bool { false } - fn run(&self, state: &State) -> Result<(), RunError> { - (self.runner)(state) + fn run(&self, context: &TestContext) -> Result<(), RunError> { + (self.runner)(context) } } diff --git a/crates/libtest2/tests/testsuite/all_passing.rs b/crates/libtest2/tests/testsuite/all_passing.rs index 38586a4..fab4541 100644 --- a/crates/libtest2/tests/testsuite/all_passing.rs +++ b/crates/libtest2/tests/testsuite/all_passing.rs @@ -9,15 +9,15 @@ fn test_cmd() -> snapbox::cmd::Command { r#" libtest2::libtest2_main!(foo, bar, barro); -fn foo(_state: &libtest2::State) -> libtest2::RunResult { +fn foo(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn bar(_state: &libtest2::State) -> libtest2::RunResult { +fn bar(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn barro(_state: &libtest2::State) -> libtest2::RunResult { +fn barro(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } "#, diff --git a/crates/libtest2/tests/testsuite/argfile.rs b/crates/libtest2/tests/testsuite/argfile.rs index 5850833..fd42eee 100644 --- a/crates/libtest2/tests/testsuite/argfile.rs +++ b/crates/libtest2/tests/testsuite/argfile.rs @@ -9,19 +9,19 @@ fn test_cmd() -> snapbox::cmd::Command { r#" libtest2::libtest2_main!(one, two, three, one_two); -fn one(_state: &libtest2::State) -> libtest2::RunResult { +fn one(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn two(_state: &libtest2::State) -> libtest2::RunResult { +fn two(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn three(_state: &libtest2::State) -> libtest2::RunResult { +fn three(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn one_two(_state: &libtest2::State) -> libtest2::RunResult { +fn one_two(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } "#, diff --git a/crates/libtest2/tests/testsuite/mixed_bag.rs b/crates/libtest2/tests/testsuite/mixed_bag.rs index fc88276..8c9658e 100644 --- a/crates/libtest2/tests/testsuite/mixed_bag.rs +++ b/crates/libtest2/tests/testsuite/mixed_bag.rs @@ -9,40 +9,40 @@ fn test_cmd() -> snapbox::cmd::Command { r#" libtest2::libtest2_main!(cat, dog, fox, bunny, frog, owl, fly, bear); -fn cat(_state: &libtest2::State) -> libtest2::RunResult { +fn cat(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn dog(_state: &libtest2::State) -> libtest2::RunResult { +fn dog(_context: &libtest2::TestContext) -> libtest2::RunResult { Err(libtest2::RunError::fail("was not a good boy")) } -fn fox(_state: &libtest2::State) -> libtest2::RunResult { +fn fox(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn bunny(state: &libtest2::State) -> libtest2::RunResult { - state.ignore_for("fails")?; +fn bunny(context: &libtest2::TestContext) -> libtest2::RunResult { + context.ignore_for("fails")?; Err(libtest2::RunError::fail("jumped too high")) } -fn frog(state: &libtest2::State) -> libtest2::RunResult { - state.ignore_for("slow")?; +fn frog(context: &libtest2::TestContext) -> libtest2::RunResult { + context.ignore_for("slow")?; Ok(()) } -fn owl(state: &libtest2::State) -> libtest2::RunResult { - state.ignore_for("fails")?; +fn owl(context: &libtest2::TestContext) -> libtest2::RunResult { + context.ignore_for("fails")?; Err(libtest2::RunError::fail("broke neck")) } -fn fly(state: &libtest2::State) -> libtest2::RunResult { - state.ignore_for("fails")?; +fn fly(context: &libtest2::TestContext) -> libtest2::RunResult { + context.ignore_for("fails")?; Ok(()) } -fn bear(state: &libtest2::State) -> libtest2::RunResult { - state.ignore_for("fails")?; +fn bear(context: &libtest2::TestContext) -> libtest2::RunResult { + context.ignore_for("fails")?; Err(libtest2::RunError::fail("no honey")) } "#, diff --git a/crates/libtest2/tests/testsuite/panic.rs b/crates/libtest2/tests/testsuite/panic.rs index 0c786a3..b99d661 100644 --- a/crates/libtest2/tests/testsuite/panic.rs +++ b/crates/libtest2/tests/testsuite/panic.rs @@ -9,11 +9,11 @@ fn test_cmd() -> snapbox::cmd::Command { r#" libtest2::libtest2_main!(passes, panics); -fn passes(_state: &libtest2::State) -> libtest2::RunResult { +fn passes(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) } -fn panics(_state: &libtest2::State) -> libtest2::RunResult { +fn panics(_context: &libtest2::TestContext) -> libtest2::RunResult { panic!("uh oh") } "#, From a99c394dab5621260b5ae1408cbf1e0dd3c6d113 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 20 Aug 2025 16:16:45 -0500 Subject: [PATCH 2/2] fix(lex)!: Rename ErrorContext to LexError The name was too general when used outside of its original context and we are using `Context` for other things now. --- crates/lexarg-error/examples/hello-error.rs | 21 +++--- crates/lexarg-error/src/lib.rs | 8 +- crates/lexarg/examples/hello.rs | 8 +- crates/lexarg/src/lib.rs | 74 +++++++++---------- crates/libtest-lexarg/examples/libtest-cli.rs | 4 +- crates/libtest-lexarg/src/lib.rs | 14 ++-- crates/libtest2-harness/src/harness.rs | 8 +- 7 files changed, 65 insertions(+), 72 deletions(-) diff --git a/crates/lexarg-error/examples/hello-error.rs b/crates/lexarg-error/examples/hello-error.rs index d995ac1..f60d697 100644 --- a/crates/lexarg-error/examples/hello-error.rs +++ b/crates/lexarg-error/examples/hello-error.rs @@ -1,4 +1,4 @@ -use lexarg_error::ErrorContext; +use lexarg_error::LexError; struct Args { thing: String, @@ -23,21 +23,21 @@ fn parse_args() -> Result { match arg { Short("n") | Long("number") => { let value = parser.next_flag_value().ok_or_else(|| { - ErrorContext::msg("missing required value") + LexError::msg("missing required value") .within(arg) .to_string() })?; number = value .to_str() .ok_or_else(|| { - ErrorContext::msg("invalid number") + LexError::msg("invalid number") .unexpected(Value(value)) .within(arg) .to_string() })? .parse() .map_err(|e| { - ErrorContext::msg(e) + LexError::msg(e) .unexpected(Value(value)) .within(arg) .to_string() @@ -47,18 +47,17 @@ fn parse_args() -> Result { shout = true; } Value(val) if thing.is_none() => { - thing = Some(val.to_str().ok_or_else(|| { - ErrorContext::msg("invalid string") - .unexpected(arg) - .to_string() - })?); + thing = + Some(val.to_str().ok_or_else(|| { + LexError::msg("invalid string").unexpected(arg).to_string() + })?); } Short("h") | Long("help") => { println!("Usage: hello [-n|--number=NUM] [--shout] THING"); std::process::exit(0); } _ => { - return Err(ErrorContext::msg("unexpected argument") + return Err(LexError::msg("unexpected argument") .unexpected(arg) .to_string()); } @@ -68,7 +67,7 @@ fn parse_args() -> Result { Ok(Args { thing: thing .ok_or_else(|| { - ErrorContext::msg("missing argument THING") + LexError::msg("missing argument THING") .within(Value(bin_name)) .to_string() })? diff --git a/crates/lexarg-error/src/lib.rs b/crates/lexarg-error/src/lib.rs index 691116a..a747810 100644 --- a/crates/lexarg-error/src/lib.rs +++ b/crates/lexarg-error/src/lib.rs @@ -17,13 +17,13 @@ /// Collect context for creating an error #[derive(Debug)] -pub struct ErrorContext<'a> { +pub struct LexError<'a> { msg: String, within: Option>, unexpected: Option>, } -impl<'a> ErrorContext<'a> { +impl<'a> LexError<'a> { /// Create a new error object from a printable error message. #[cold] pub fn msg(message: M) -> Self @@ -52,7 +52,7 @@ impl<'a> ErrorContext<'a> { } } -impl From for ErrorContext<'_> +impl From for LexError<'_> where E: std::error::Error + Send + Sync + 'static, { @@ -62,7 +62,7 @@ where } } -impl std::fmt::Display for ErrorContext<'_> { +impl std::fmt::Display for LexError<'_> { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.msg.fmt(formatter)?; if let Some(unexpected) = &self.unexpected { diff --git a/crates/lexarg/examples/hello.rs b/crates/lexarg/examples/hello.rs index 84d4e90..b97a283 100644 --- a/crates/lexarg/examples/hello.rs +++ b/crates/lexarg/examples/hello.rs @@ -1,4 +1,4 @@ -use lexarg::ErrorContext; +use lexarg::LexError; use lexarg::Result; struct Args { @@ -40,15 +40,13 @@ fn parse_args() -> Result { std::process::exit(0); } Unexpected(_) => { - return Err(ErrorContext::msg("unexpected value") + return Err(LexError::msg("unexpected value") .unexpected(arg) .within(prev_arg) .into()); } _ => { - return Err(ErrorContext::msg("unexpected argument") - .unexpected(arg) - .into()); + return Err(LexError::msg("unexpected argument").unexpected(arg).into()); } } prev_arg = arg; diff --git a/crates/lexarg/src/lib.rs b/crates/lexarg/src/lib.rs index 587e7bd..3b439b5 100644 --- a/crates/lexarg/src/lib.rs +++ b/crates/lexarg/src/lib.rs @@ -19,12 +19,12 @@ /// Simplify parsing of arguments pub mod prelude { pub use crate::Arg::*; - pub use crate::OptionContextExt as _; - pub use crate::ResultContextExt as _; + pub use crate::OptionLexErrorExt as _; + pub use crate::ResultLexErrorExt as _; pub use crate::ValueExt as _; } -pub use lexarg_error::ErrorContext; +pub use lexarg_error::LexError; pub use lexarg_parser::Arg; pub use lexarg_parser::Parser; pub use lexarg_parser::RawArgs; @@ -50,9 +50,9 @@ impl Error { } } -impl From> for Error { +impl From> for Error { #[cold] - fn from(error: ErrorContext<'_>) -> Self { + fn from(error: LexError<'_>) -> Self { Self::msg(error.to_string()) } } @@ -72,32 +72,32 @@ impl std::fmt::Display for Error { /// Extensions for parsing [`Arg::Value`] pub trait ValueExt<'a> { /// Convert [`Arg::Value`] - fn path(self) -> Result<&'a std::path::Path, ErrorContext<'a>>; + fn path(self) -> Result<&'a std::path::Path, LexError<'a>>; /// Convert [`Arg::Value`] with a description of the intended format - fn string(self, description: &str) -> Result<&'a str, ErrorContext<'a>>; + fn string(self, description: &str) -> Result<&'a str, LexError<'a>>; /// Ensure [`Arg::Value`] is from a closed set of values - fn one_of(self, possible: &[&str]) -> Result<&'a str, ErrorContext<'a>>; + fn one_of(self, possible: &[&str]) -> Result<&'a str, LexError<'a>>; /// Parse [`Arg::Value`] - fn parse(self) -> Result> + fn parse(self) -> Result> where T::Err: std::fmt::Display; /// Custom conversion for [`Arg::Value`] - fn try_map(self, op: F) -> Result> + fn try_map(self, op: F) -> Result> where F: FnOnce(&'a std::ffi::OsStr) -> Result, E: std::fmt::Display; } impl<'a> ValueExt<'a> for &'a std::ffi::OsStr { - fn path(self) -> Result<&'a std::path::Path, ErrorContext<'a>> { + fn path(self) -> Result<&'a std::path::Path, LexError<'a>> { Ok(std::path::Path::new(self)) } - fn string(self, description: &str) -> Result<&'a str, ErrorContext<'a>> { + fn string(self, description: &str) -> Result<&'a str, LexError<'a>> { self.to_str().ok_or_else(|| { - ErrorContext::msg(format_args!("invalid {description}")).unexpected(Arg::Value(self)) + LexError::msg(format_args!("invalid {description}")).unexpected(Arg::Value(self)) }) } - fn one_of(self, possible: &[&str]) -> Result<&'a str, ErrorContext<'a>> { + fn one_of(self, possible: &[&str]) -> Result<&'a str, LexError<'a>> { self.to_str() .filter(|v| possible.contains(v)) .ok_or_else(|| { @@ -108,43 +108,43 @@ impl<'a> ValueExt<'a> for &'a std::ffi::OsStr { use std::fmt::Write as _; let _ = write!(&mut error, ", `{possible}`"); } - ErrorContext::msg(error) + LexError::msg(error) }) } - fn parse(self) -> Result> + fn parse(self) -> Result> where T::Err: std::fmt::Display, { self.string(std::any::type_name::())? .parse::() - .map_err(|err| ErrorContext::msg(err).unexpected(Arg::Value(self))) + .map_err(|err| LexError::msg(err).unexpected(Arg::Value(self))) } - fn try_map(self, op: F) -> Result> + fn try_map(self, op: F) -> Result> where F: FnOnce(&'a std::ffi::OsStr) -> Result, E: std::fmt::Display, { - op(self).map_err(|err| ErrorContext::msg(err).unexpected(Arg::Value(self))) + op(self).map_err(|err| LexError::msg(err).unexpected(Arg::Value(self))) } } -impl<'a> ValueExt<'a> for Result<&'a std::ffi::OsStr, ErrorContext<'a>> { - fn path(self) -> Result<&'a std::path::Path, ErrorContext<'a>> { +impl<'a> ValueExt<'a> for Result<&'a std::ffi::OsStr, LexError<'a>> { + fn path(self) -> Result<&'a std::path::Path, LexError<'a>> { self.and_then(|os| os.path()) } - fn string(self, description: &str) -> Result<&'a str, ErrorContext<'a>> { + fn string(self, description: &str) -> Result<&'a str, LexError<'a>> { self.and_then(|os| os.string(description)) } - fn one_of(self, possible: &[&str]) -> Result<&'a str, ErrorContext<'a>> { + fn one_of(self, possible: &[&str]) -> Result<&'a str, LexError<'a>> { self.and_then(|os| os.one_of(possible)) } - fn parse(self) -> Result> + fn parse(self) -> Result> where T::Err: std::fmt::Display, { self.and_then(|os| os.parse()) } - fn try_map(self, op: F) -> Result> + fn try_map(self, op: F) -> Result> where F: FnOnce(&'a std::ffi::OsStr) -> Result, E: std::fmt::Display, @@ -153,33 +153,33 @@ impl<'a> ValueExt<'a> for Result<&'a std::ffi::OsStr, ErrorContext<'a>> { } } -/// Extensions for extending [`ErrorContext`] -pub trait ResultContextExt<'a> { +/// Extensions for extending [`LexError`] +pub trait ResultLexErrorExt<'a> { /// [`Arg`] the error occurred within fn within(self, within: Arg<'a>) -> Self; } -impl<'a, T> ResultContextExt<'a> for Result> { +impl<'a, T> ResultLexErrorExt<'a> for Result> { fn within(self, within: Arg<'a>) -> Self { self.map_err(|err| err.within(within)) } } -/// Extensions for creating an [`ErrorContext`] -pub trait OptionContextExt { +/// Extensions for creating an [`LexError`] +pub trait OptionLexErrorExt { /// [`Arg`] that was expected /// /// For [`Arg::Value`], the contents are assumed to be a placeholder - fn ok_or_missing(self, expected: Arg<'static>) -> Result>; + fn ok_or_missing(self, expected: Arg<'static>) -> Result>; } -impl OptionContextExt for Option { - fn ok_or_missing(self, expected: Arg<'static>) -> Result> { +impl OptionLexErrorExt for Option { + fn ok_or_missing(self, expected: Arg<'static>) -> Result> { self.ok_or_else(|| match expected { - Arg::Short(short) => ErrorContext::msg(format_args!("missing required `-{short}`")), - Arg::Long(long) => ErrorContext::msg(format_args!("missing required `--{long}`")), - Arg::Escape(escape) => ErrorContext::msg(format_args!("missing required `{escape}`")), - Arg::Value(value) | Arg::Unexpected(value) => ErrorContext::msg(format_args!( + Arg::Short(short) => LexError::msg(format_args!("missing required `-{short}`")), + Arg::Long(long) => LexError::msg(format_args!("missing required `--{long}`")), + Arg::Escape(escape) => LexError::msg(format_args!("missing required `{escape}`")), + Arg::Value(value) | Arg::Unexpected(value) => LexError::msg(format_args!( "missing required `{}`", value.to_string_lossy() )), diff --git a/crates/libtest-lexarg/examples/libtest-cli.rs b/crates/libtest-lexarg/examples/libtest-cli.rs index 553928d..6a3bb32 100644 --- a/crates/libtest-lexarg/examples/libtest-cli.rs +++ b/crates/libtest-lexarg/examples/libtest-cli.rs @@ -31,7 +31,7 @@ fn main() -> lexarg::Result<()> { continue; } Unexpected(_) => { - return Err(lexarg::ErrorContext::msg("unexpected value") + return Err(lexarg::LexError::msg("unexpected value") .unexpected(arg) .within(prev_arg) .into()); @@ -43,7 +43,7 @@ fn main() -> lexarg::Result<()> { let arg = test_opts.parse_next(&mut parser, arg)?; if let Some(arg) = arg { - return Err(lexarg::ErrorContext::msg("unexpected argument") + return Err(lexarg::LexError::msg("unexpected argument") .unexpected(arg) .into()); } diff --git a/crates/libtest-lexarg/src/lib.rs b/crates/libtest-lexarg/src/lib.rs index 9d5522a..feb1eba 100644 --- a/crates/libtest-lexarg/src/lib.rs +++ b/crates/libtest-lexarg/src/lib.rs @@ -14,7 +14,7 @@ #![warn(missing_debug_implementations, elided_lifetimes_in_paths)] use lexarg::Arg; -use lexarg_error::ErrorContext; +use lexarg_error::LexError; /// Parsed command-line options /// @@ -174,7 +174,7 @@ impl TestOptsBuilder { &mut self, parser: &mut lexarg::Parser<'a>, arg: Arg<'a>, - ) -> Result>, ErrorContext<'a>> { + ) -> Result>, LexError<'a>> { use lexarg::prelude::*; match arg { @@ -257,7 +257,7 @@ impl TestOptsBuilder { .string("FEATURE") .within(arg)?; if !is_nightly() { - return Err(ErrorContext::msg("expected nightly compiler").unexpected(arg)); + return Err(LexError::msg("expected nightly compiler").unexpected(arg)); } // Don't validate `feature` as other parsers might provide values self.opts.allowed_unstable.push(feature.to_owned()); @@ -274,7 +274,7 @@ impl TestOptsBuilder { } /// Finish parsing, resolving to [`TestOpts`] - pub fn finish(mut self) -> Result> { + pub fn finish(mut self) -> Result> { let allow_unstable_options = self .opts .allowed_unstable @@ -282,9 +282,7 @@ impl TestOptsBuilder { .any(|f| f == UNSTABLE_OPTIONS); if self.format.is_some() && !allow_unstable_options { - return Err(ErrorContext::msg( - "`--format` requires `-Zunstable-options`", - )); + return Err(LexError::msg("`--format` requires `-Zunstable-options`")); } if let Some(format) = self.format { self.opts.format = format; @@ -296,7 +294,7 @@ impl TestOptsBuilder { self.opts.run_ignored = match (self.include_ignored, self.ignored) { (true, true) => { - return Err(ErrorContext::msg( + return Err(LexError::msg( "`--include-ignored` and `--ignored` are mutually exclusive", )) } diff --git a/crates/libtest2-harness/src/harness.rs b/crates/libtest2-harness/src/harness.rs index a6e80a4..5451651 100644 --- a/crates/libtest2-harness/src/harness.rs +++ b/crates/libtest2-harness/src/harness.rs @@ -81,9 +81,7 @@ impl Harness { const ERROR_EXIT_CODE: i32 = 101; -fn parse<'p>( - parser: &mut cli::Parser<'p>, -) -> Result> { +fn parse<'p>(parser: &mut cli::Parser<'p>) -> Result> { let mut test_opts = libtest_lexarg::TestOptsBuilder::new(); let bin = parser @@ -112,7 +110,7 @@ fn parse<'p>( continue; } cli::Arg::Unexpected(_) => { - return Err(cli::ErrorContext::msg("unexpected value") + return Err(cli::LexError::msg("unexpected value") .unexpected(arg) .within(prev_arg)); } @@ -123,7 +121,7 @@ fn parse<'p>( let arg = test_opts.parse_next(parser, arg)?; if let Some(arg) = arg { - return Err(cli::ErrorContext::msg("unexpected argument").unexpected(arg)); + return Err(cli::LexError::msg("unexpected argument").unexpected(arg)); } }