fix: Clarify cause of debug asserts

Ran into one of these being a pain with porting cargo.
This commit is contained in:
Ed Page 2022-01-04 11:30:31 -06:00
parent d9906eb150
commit 91de3eb0cd
2 changed files with 61 additions and 32 deletions

View file

@ -16,7 +16,8 @@ pub(crate) fn assert_app(app: &App) {
// PropagateVersion is meaningless if there is no version // PropagateVersion is meaningless if there is no version
assert!( assert!(
!app.settings.is_set(AppSettings::PropagateVersion), !app.settings.is_set(AppSettings::PropagateVersion),
"No version information via App::version or App::long_version to propagate" "App {}: No version information via App::version or App::long_version to propagate",
app.get_name(),
); );
// Used `App::mut_arg("version", ..) but did not provide any version information to display // Used `App::mut_arg("version", ..) but did not provide any version information to display
@ -27,7 +28,9 @@ pub(crate) fn assert_app(app: &App) {
if has_mutated_version { if has_mutated_version {
assert!(app.settings.is_set(AppSettings::NoAutoVersion), assert!(app.settings.is_set(AppSettings::NoAutoVersion),
"Used App::mut_arg(\"version\", ..) without providing App::version, App::long_version or using AppSettings::NoAutoVersion"); "App {}: Used App::mut_arg(\"version\", ..) without providing App::version, App::long_version or using AppSettings::NoAutoVersion"
,app.get_name()
);
} }
} }
@ -71,7 +74,8 @@ pub(crate) fn assert_app(app: &App) {
// Name conflicts // Name conflicts
assert!( assert!(
app.two_args_of(|x| x.id == arg.id).is_none(), app.two_args_of(|x| x.id == arg.id).is_none(),
"Argument names must be unique, but '{}' is in use by more than one argument or group", "App {}: Argument names must be unique, but '{}' is in use by more than one argument or group",
app.get_name(),
arg.name, arg.name,
); );
@ -79,9 +83,12 @@ pub(crate) fn assert_app(app: &App) {
if let Some(l) = arg.long { if let Some(l) = arg.long {
if let Some((first, second)) = app.two_args_of(|x| x.long == Some(l)) { if let Some((first, second)) = app.two_args_of(|x| x.long == Some(l)) {
panic!( panic!(
"Long option names must be unique for each argument, \ "App {}: Long option names must be unique for each argument, \
but '--{}' is in use by both '{}' and '{}'", but '--{}' is in use by both '{}' and '{}'",
l, first.name, second.name app.get_name(),
l,
first.name,
second.name
) )
} }
} }
@ -90,9 +97,12 @@ pub(crate) fn assert_app(app: &App) {
if let Some(s) = arg.short { if let Some(s) = arg.short {
if let Some((first, second)) = app.two_args_of(|x| x.short == Some(s)) { if let Some((first, second)) = app.two_args_of(|x| x.short == Some(s)) {
panic!( panic!(
"Short option names must be unique for each argument, \ "App {}: Short option names must be unique for each argument, \
but '-{}' is in use by both '{}' and '{}'", but '-{}' is in use by both '{}' and '{}'",
s, first.name, second.name app.get_name(),
s,
first.name,
second.name
) )
} }
} }
@ -103,11 +113,13 @@ pub(crate) fn assert_app(app: &App) {
app.two_args_of(|x| x.is_positional() && x.index == Some(idx)) app.two_args_of(|x| x.is_positional() && x.index == Some(idx))
{ {
panic!( panic!(
"Argument '{}' has the same index as '{}' \ "App {}: Argument '{}' has the same index as '{}' \
and they are both positional arguments\n\n\t \ and they are both positional arguments\n\n\t \
Use Arg::multiple_values(true) to allow one \ Use Arg::multiple_values(true) to allow one \
positional argument to take multiple values", positional argument to take multiple values",
first.name, second.name app.get_name(),
first.name,
second.name
) )
} }
} }
@ -116,7 +128,8 @@ pub(crate) fn assert_app(app: &App) {
for req in &arg.requires { for req in &arg.requires {
assert!( assert!(
app.id_exists(&req.1), app.id_exists(&req.1),
"Argument or group '{:?}' specified in 'requires*' for '{}' does not exist", "App {}: Argument or group '{:?}' specified in 'requires*' for '{}' does not exist",
app.get_name(),
req.1, req.1,
arg.name, arg.name,
); );
@ -125,7 +138,8 @@ pub(crate) fn assert_app(app: &App) {
for req in &arg.r_ifs { for req in &arg.r_ifs {
assert!( assert!(
app.id_exists(&req.0), app.id_exists(&req.0),
"Argument or group '{:?}' specified in 'required_if_eq*' for '{}' does not exist", "App {}: Argument or group '{:?}' specified in 'required_if_eq*' for '{}' does not exist",
app.get_name(),
req.0, req.0,
arg.name arg.name
); );
@ -134,7 +148,8 @@ pub(crate) fn assert_app(app: &App) {
for req in &arg.r_ifs_all { for req in &arg.r_ifs_all {
assert!( assert!(
app.id_exists(&req.0), app.id_exists(&req.0),
"Argument or group '{:?}' specified in 'required_if_eq_all' for '{}' does not exist", "App {}: Argument or group '{:?}' specified in 'required_if_eq_all' for '{}' does not exist",
app.get_name(),
req.0, req.0,
arg.name arg.name
); );
@ -143,7 +158,8 @@ pub(crate) fn assert_app(app: &App) {
for req in &arg.r_unless { for req in &arg.r_unless {
assert!( assert!(
app.id_exists(req), app.id_exists(req),
"Argument or group '{:?}' specified in 'required_unless*' for '{}' does not exist", "App {}: Argument or group '{:?}' specified in 'required_unless*' for '{}' does not exist",
app.get_name(),
req, req,
arg.name, arg.name,
); );
@ -153,7 +169,8 @@ pub(crate) fn assert_app(app: &App) {
for req in &arg.blacklist { for req in &arg.blacklist {
assert!( assert!(
app.id_exists(req), app.id_exists(req),
"Argument or group '{:?}' specified in 'conflicts_with*' for '{}' does not exist", "App {}: Argument or group '{:?}' specified in 'conflicts_with*' for '{}' does not exist",
app.get_name(),
req, req,
arg.name, arg.name,
); );
@ -162,39 +179,45 @@ pub(crate) fn assert_app(app: &App) {
if arg.is_set(ArgSettings::Last) { if arg.is_set(ArgSettings::Last) {
assert!( assert!(
arg.long.is_none(), arg.long.is_none(),
"Flags or Options cannot have last(true) set. '{}' has both a long and last(true) set.", "App {}: Flags or Options cannot have last(true) set. '{}' has both a long and last(true) set.",
app.get_name(),
arg.name arg.name
); );
assert!( assert!(
arg.short.is_none(), arg.short.is_none(),
"Flags or Options cannot have last(true) set. '{}' has both a short and last(true) set.", "App {}: Flags or Options cannot have last(true) set. '{}' has both a short and last(true) set.",
app.get_name(),
arg.name arg.name
); );
} }
assert!( assert!(
!(arg.is_set(ArgSettings::Required) && arg.get_global()), !(arg.is_set(ArgSettings::Required) && arg.get_global()),
"Global arguments cannot be required.\n\n\t'{}' is marked as both global and required", "App {}: Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
app.get_name(),
arg.name arg.name
); );
// validators // validators
assert!( assert!(
arg.validator.is_none() || arg.validator_os.is_none(), arg.validator.is_none() || arg.validator_os.is_none(),
"Argument '{}' has both `validator` and `validator_os` set which is not allowed", "App {}: Argument '{}' has both `validator` and `validator_os` set which is not allowed",
app.get_name(),
arg.name arg.name
); );
if arg.value_hint == ValueHint::CommandWithArguments { if arg.value_hint == ValueHint::CommandWithArguments {
assert!( assert!(
arg.is_positional(), arg.is_positional(),
"Argument '{}' has hint CommandWithArguments and must be positional.", "App {}: Argument '{}' has hint CommandWithArguments and must be positional.",
app.get_name(),
arg.name arg.name
); );
assert!( assert!(
app.is_set(AppSettings::TrailingVarArg), app.is_set(AppSettings::TrailingVarArg),
"Positional argument '{}' has hint CommandWithArguments, so App must have TrailingVarArg set.", "App {}: Positional argument '{}' has hint CommandWithArguments, so App must have TrailingVarArg set.",
app.get_name(),
arg.name arg.name
); );
} }
@ -204,14 +227,16 @@ pub(crate) fn assert_app(app: &App) {
// Name conflicts // Name conflicts
assert!( assert!(
app.groups.iter().filter(|x| x.id == group.id).count() < 2, app.groups.iter().filter(|x| x.id == group.id).count() < 2,
"Argument group name must be unique\n\n\t'{}' is already in use", "App {}: Argument group name must be unique\n\n\t'{}' is already in use",
app.get_name(),
group.name, group.name,
); );
// Groups should not have naming conflicts with Args // Groups should not have naming conflicts with Args
assert!( assert!(
!app.args.args().any(|x| x.id == group.id), !app.args.args().any(|x| x.id == group.id),
"Argument group name '{}' must not conflict with argument name", "App {}: Argument group name '{}' must not conflict with argument name",
app.get_name(),
group.name, group.name,
); );
@ -223,7 +248,8 @@ pub(crate) fn assert_app(app: &App) {
.args() .args()
.any(|x| x.id == *arg && x.default_vals.is_empty()) .any(|x| x.id == *arg && x.default_vals.is_empty())
}), }),
"Argument group '{}' is required but all of it's arguments have a default value.", "App {}: Argument group '{}' is required but all of it's arguments have a default value.",
app.get_name(),
group.name group.name
) )
} }
@ -232,7 +258,8 @@ pub(crate) fn assert_app(app: &App) {
// Args listed inside groups should exist // Args listed inside groups should exist
assert!( assert!(
app.args.args().any(|x| x.id == *arg), app.args.args().any(|x| x.id == *arg),
"Argument group '{}' contains non-existent argument '{:?}'", "App {}: Argument group '{}' contains non-existent argument '{:?}'",
app.get_name(),
group.name, group.name,
arg arg
); );
@ -250,12 +277,14 @@ pub(crate) fn assert_app(app: &App) {
if let Some(help_template) = app.template { if let Some(help_template) = app.template {
assert!( assert!(
!help_template.contains("{flags}"), !help_template.contains("{flags}"),
"{}", "App {}: {}",
"`{flags}` template variable was removed in clap3, they are now included in `{options}`" app.get_name(),
"`{flags}` template variable was removed in clap3, they are now included in `{options}`",
); );
assert!( assert!(
!help_template.contains("{unified}"), !help_template.contains("{unified}"),
"{}", "App {}: {}",
app.get_name(),
"`{unified}` template variable was removed in clap3, use `{options}` instead" "`{unified}` template variable was removed in clap3, use `{options}` instead"
); );
} }
@ -351,7 +380,7 @@ fn assert_app_flags(app: &App) {
$( $(
if !app.is_set($b) { if !app.is_set($b) {
s.push_str(&format!("\nAppSettings::{} is required when AppSettings::{} is set.\n", std::stringify!($b), std::stringify!($a))); s.push_str(&format!(" AppSettings::{} is required when AppSettings::{} is set.\n", std::stringify!($b), std::stringify!($a)));
} }
)+ )+
@ -366,12 +395,12 @@ fn assert_app_flags(app: &App) {
$( $(
if app.is_set($b) { if app.is_set($b) {
s.push_str(&format!("\nAppSettings::{} conflicts with AppSettings::{}.\n", std::stringify!($b), std::stringify!($a))); s.push_str(&format!(" AppSettings::{} conflicts with AppSettings::{}.\n", std::stringify!($b), std::stringify!($a)));
} }
)+ )+
if !s.is_empty() { if !s.is_empty() {
panic!("{}", s) panic!("{}\n{}", app.get_name(), s)
} }
} }
}; };

View file

@ -56,12 +56,12 @@ fn assert_arg_flags(arg: &Arg) {
$( $(
if !arg.is_set($b) { if !arg.is_set($b) {
s.push_str(&format!("\nArgSettings::{} is required when ArgSettings::{} is set.\n", std::stringify!($b), std::stringify!($a))); s.push_str(&format!(" ArgSettings::{} is required when ArgSettings::{} is set.\n", std::stringify!($b), std::stringify!($a)));
} }
)+ )+
if !s.is_empty() { if !s.is_empty() {
panic!("{}", s) panic!("Argument {:?}\n{}", arg.get_name(), s)
} }
} }
} }