summaryrefslogtreecommitdiffstats
path: root/vendor/clap/src/builder/debug_asserts.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap/src/builder/debug_asserts.rs')
-rw-r--r--vendor/clap/src/builder/debug_asserts.rs887
1 files changed, 0 insertions, 887 deletions
diff --git a/vendor/clap/src/builder/debug_asserts.rs b/vendor/clap/src/builder/debug_asserts.rs
deleted file mode 100644
index bfebbb4c4..000000000
--- a/vendor/clap/src/builder/debug_asserts.rs
+++ /dev/null
@@ -1,887 +0,0 @@
-use std::cmp::Ordering;
-
-use clap_lex::RawOsStr;
-
-use crate::builder::OsStr;
-use crate::builder::ValueRange;
-use crate::mkeymap::KeyType;
-use crate::util::FlatSet;
-use crate::util::Id;
-use crate::ArgAction;
-use crate::INTERNAL_ERROR_MSG;
-use crate::{Arg, Command, ValueHint};
-
-pub(crate) fn assert_app(cmd: &Command) {
- debug!("Command::_debug_asserts");
-
- let mut short_flags = vec![];
- let mut long_flags = vec![];
-
- // Invalid version flag settings
- if cmd.get_version().is_none() && cmd.get_long_version().is_none() {
- // PropagateVersion is meaningless if there is no version
- assert!(
- !cmd.is_propagate_version_set(),
- "Command {}: No version information via Command::version or Command::long_version to propagate",
- cmd.get_name(),
- );
-
- // Used `Command::mut_arg("version", ..) but did not provide any version information to display
- let version_needed = cmd
- .get_arguments()
- .filter(|x| matches!(x.get_action(), ArgAction::Version))
- .map(|x| x.get_id())
- .collect::<Vec<_>>();
-
- assert_eq!(version_needed, Vec::<&str>::new(), "Command {}: `ArgAction::Version` used without providing Command::version or Command::long_version"
- ,cmd.get_name()
- );
- }
-
- for sc in cmd.get_subcommands() {
- if let Some(s) = sc.get_short_flag().as_ref() {
- short_flags.push(Flag::Command(format!("-{}", s), sc.get_name()));
- }
-
- for short_alias in sc.get_all_short_flag_aliases() {
- short_flags.push(Flag::Command(format!("-{}", short_alias), sc.get_name()));
- }
-
- if let Some(l) = sc.get_long_flag().as_ref() {
- assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l);
- long_flags.push(Flag::Command(format!("--{}", l), sc.get_name()));
- }
-
- for long_alias in sc.get_all_long_flag_aliases() {
- long_flags.push(Flag::Command(format!("--{}", long_alias), sc.get_name()));
- }
- }
-
- for arg in cmd.get_arguments() {
- assert_arg(arg);
-
- assert!(
- !cmd.is_multicall_set(),
- "Command {}: Arguments like {} cannot be set on a multicall command",
- cmd.get_name(),
- arg.get_id()
- );
-
- if let Some(s) = arg.get_short() {
- short_flags.push(Flag::Arg(format!("-{}", s), arg.get_id().as_str()));
- }
-
- for (short_alias, _) in &arg.short_aliases {
- short_flags.push(Flag::Arg(
- format!("-{}", short_alias),
- arg.get_id().as_str(),
- ));
- }
-
- if let Some(l) = arg.get_long() {
- assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.get_id(), l);
- long_flags.push(Flag::Arg(format!("--{}", l), arg.get_id().as_str()));
- }
-
- for (long_alias, _) in &arg.aliases {
- long_flags.push(Flag::Arg(
- format!("--{}", long_alias),
- arg.get_id().as_str(),
- ));
- }
-
- // Name conflicts
- if let Some((first, second)) = cmd.two_args_of(|x| x.get_id() == arg.get_id()) {
- panic!(
- "Command {}: Argument names must be unique, but '{}' is in use by more than one argument or group{}",
- cmd.get_name(),
- arg.get_id(),
- duplicate_tip(cmd, first, second),
- );
- }
-
- // Long conflicts
- if let Some(l) = arg.get_long() {
- if let Some((first, second)) = cmd.two_args_of(|x| x.get_long() == Some(l)) {
- panic!(
- "Command {}: Long option names must be unique for each argument, \
- but '--{}' is in use by both '{}' and '{}'{}",
- cmd.get_name(),
- l,
- first.get_id(),
- second.get_id(),
- duplicate_tip(cmd, first, second)
- )
- }
- }
-
- // Short conflicts
- if let Some(s) = arg.get_short() {
- if let Some((first, second)) = cmd.two_args_of(|x| x.get_short() == Some(s)) {
- panic!(
- "Command {}: Short option names must be unique for each argument, \
- but '-{}' is in use by both '{}' and '{}'{}",
- cmd.get_name(),
- s,
- first.get_id(),
- second.get_id(),
- duplicate_tip(cmd, first, second),
- )
- }
- }
-
- // Index conflicts
- if let Some(idx) = arg.index {
- if let Some((first, second)) =
- cmd.two_args_of(|x| x.is_positional() && x.get_index() == Some(idx))
- {
- panic!(
- "Command {}: Argument '{}' has the same index as '{}' \
- and they are both positional arguments\n\n\t \
- Use `Arg::num_args(1..)` to allow one \
- positional argument to take multiple values",
- cmd.get_name(),
- first.get_id(),
- second.get_id()
- )
- }
- }
-
- // requires, r_if, r_unless
- for req in &arg.requires {
- assert!(
- cmd.id_exists(&req.1),
- "Command {}: Argument or group '{}' specified in 'requires*' for '{}' does not exist",
- cmd.get_name(),
- req.1,
- arg.get_id(),
- );
- }
-
- for req in &arg.r_ifs {
- assert!(
- !arg.is_required_set(),
- "Argument {}: `required` conflicts with `required_if_eq*`",
- arg.get_id()
- );
- assert!(
- cmd.id_exists(&req.0),
- "Command {}: Argument or group '{}' specified in 'required_if_eq*' for '{}' does not exist",
- cmd.get_name(),
- req.0,
- arg.get_id()
- );
- }
-
- for req in &arg.r_ifs_all {
- assert!(
- !arg.is_required_set(),
- "Argument {}: `required` conflicts with `required_if_eq_all`",
- arg.get_id()
- );
- assert!(
- cmd.id_exists(&req.0),
- "Command {}: Argument or group '{}' specified in 'required_if_eq_all' for '{}' does not exist",
- cmd.get_name(),
- req.0,
- arg.get_id()
- );
- }
-
- for req in &arg.r_unless {
- assert!(
- !arg.is_required_set(),
- "Argument {}: `required` conflicts with `required_unless*`",
- arg.get_id()
- );
- assert!(
- cmd.id_exists(req),
- "Command {}: Argument or group '{}' specified in 'required_unless*' for '{}' does not exist",
- cmd.get_name(),
- req,
- arg.get_id(),
- );
- }
-
- for req in &arg.r_unless_all {
- assert!(
- !arg.is_required_set(),
- "Argument {}: `required` conflicts with `required_unless*`",
- arg.get_id()
- );
- assert!(
- cmd.id_exists(req),
- "Command {}: Argument or group '{}' specified in 'required_unless*' for '{}' does not exist",
- cmd.get_name(),
- req,
- arg.get_id(),
- );
- }
-
- // blacklist
- for req in &arg.blacklist {
- assert!(
- cmd.id_exists(req),
- "Command {}: Argument or group '{}' specified in 'conflicts_with*' for '{}' does not exist",
- cmd.get_name(),
- req,
- arg.get_id(),
- );
- }
-
- // overrides
- for req in &arg.overrides {
- assert!(
- cmd.id_exists(req),
- "Command {}: Argument or group '{}' specified in 'overrides_with*' for '{}' does not exist",
- cmd.get_name(),
- req,
- arg.get_id(),
- );
- }
-
- if arg.is_last_set() {
- assert!(
- arg.get_long().is_none(),
- "Command {}: Flags or Options cannot have last(true) set. '{}' has both a long and last(true) set.",
- cmd.get_name(),
- arg.get_id()
- );
- assert!(
- arg.get_short().is_none(),
- "Command {}: Flags or Options cannot have last(true) set. '{}' has both a short and last(true) set.",
- cmd.get_name(),
- arg.get_id()
- );
- }
-
- assert!(
- !(arg.is_required_set() && arg.is_global_set()),
- "Command {}: Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
- cmd.get_name(),
- arg.get_id()
- );
-
- if arg.get_value_hint() == ValueHint::CommandWithArguments {
- assert!(
- arg.is_positional(),
- "Command {}: Argument '{}' has hint CommandWithArguments and must be positional.",
- cmd.get_name(),
- arg.get_id()
- );
-
- assert!(
- arg.is_trailing_var_arg_set() || arg.is_last_set(),
- "Command {}: Positional argument '{}' has hint CommandWithArguments, so Command must have `trailing_var_arg(true)` or `last(true)` set.",
- cmd.get_name(),
- arg.get_id()
- );
- }
- }
-
- for group in cmd.get_groups() {
- let derive_hint = if cfg!(feature = "derive") {
- " (note: `Args` implicitly creates `ArgGroup`s; disable with `#[group(skip)]`"
- } else {
- ""
- };
-
- // Name conflicts
- assert!(
- cmd.get_groups().filter(|x| x.id == group.id).count() < 2,
- "Command {}: Argument group name must be unique\n\n\t'{}' is already in use{}",
- cmd.get_name(),
- group.get_id(),
- derive_hint
- );
-
- // Groups should not have naming conflicts with Args
- assert!(
- !cmd.get_arguments().any(|x| x.get_id() == group.get_id()),
- "Command {}: Argument group name '{}' must not conflict with argument name{}",
- cmd.get_name(),
- group.get_id(),
- derive_hint
- );
-
- for arg in &group.args {
- // Args listed inside groups should exist
- assert!(
- cmd.get_arguments().any(|x| x.get_id() == arg),
- "Command {}: Argument group '{}' contains non-existent argument '{}'",
- cmd.get_name(),
- group.get_id(),
- arg
- );
- }
- }
-
- // Conflicts between flags and subcommands
-
- long_flags.sort_unstable();
- short_flags.sort_unstable();
-
- detect_duplicate_flags(&long_flags, "long");
- detect_duplicate_flags(&short_flags, "short");
-
- let mut subs = FlatSet::new();
- for sc in cmd.get_subcommands() {
- assert!(
- subs.insert(sc.get_name()),
- "Command {}: command name `{}` is duplicated",
- cmd.get_name(),
- sc.get_name()
- );
- for alias in sc.get_all_aliases() {
- assert!(
- subs.insert(alias),
- "Command {}: command `{}` alias `{}` is duplicated",
- cmd.get_name(),
- sc.get_name(),
- alias
- );
- }
- }
-
- _verify_positionals(cmd);
-
- #[cfg(feature = "help")]
- if let Some(help_template) = cmd.get_help_template() {
- assert!(
- !help_template.to_string().contains("{flags}"),
- "Command {}: {}",
- cmd.get_name(),
- "`{flags}` template variable was removed in clap3, they are now included in `{options}`",
- );
- assert!(
- !help_template.to_string().contains("{unified}"),
- "Command {}: {}",
- cmd.get_name(),
- "`{unified}` template variable was removed in clap3, use `{options}` instead"
- );
- #[cfg(feature = "unstable-v5")]
- assert!(
- !help_template.to_string().contains("{bin}"),
- "Command {}: {}",
- cmd.get_name(),
- "`{bin}` template variable was removed in clap5, use `{name}` instead"
- )
- }
-
- cmd._panic_on_missing_help(cmd.is_help_expected_set());
- assert_app_flags(cmd);
-}
-
-fn duplicate_tip(cmd: &Command, first: &Arg, second: &Arg) -> &'static str {
- if !cmd.is_disable_help_flag_set()
- && (first.get_id() == Id::HELP || second.get_id() == Id::HELP)
- {
- " (call `cmd.disable_help_flag(true)` to remove the auto-generated `--help`)"
- } else if !cmd.is_disable_version_flag_set()
- && (first.get_id() == Id::VERSION || second.get_id() == Id::VERSION)
- {
- " (call `cmd.disable_version_flag(true)` to remove the auto-generated `--version`)"
- } else {
- ""
- }
-}
-
-#[derive(Eq)]
-enum Flag<'a> {
- Command(String, &'a str),
- Arg(String, &'a str),
-}
-
-impl PartialEq for Flag<'_> {
- fn eq(&self, other: &Flag) -> bool {
- self.cmp(other) == Ordering::Equal
- }
-}
-
-impl PartialOrd for Flag<'_> {
- fn partial_cmp(&self, other: &Flag) -> Option<Ordering> {
- use Flag::*;
-
- match (self, other) {
- (Command(s1, _), Command(s2, _))
- | (Arg(s1, _), Arg(s2, _))
- | (Command(s1, _), Arg(s2, _))
- | (Arg(s1, _), Command(s2, _)) => {
- if s1 == s2 {
- Some(Ordering::Equal)
- } else {
- s1.partial_cmp(s2)
- }
- }
- }
- }
-}
-
-impl Ord for Flag<'_> {
- fn cmp(&self, other: &Self) -> Ordering {
- self.partial_cmp(other).unwrap()
- }
-}
-
-fn detect_duplicate_flags(flags: &[Flag], short_or_long: &str) {
- use Flag::*;
-
- for (one, two) in find_duplicates(flags) {
- match (one, two) {
- (Command(flag, one), Command(_, another)) if one != another => panic!(
- "the '{}' {} flag is specified for both '{}' and '{}' subcommands",
- flag, short_or_long, one, another
- ),
-
- (Arg(flag, one), Arg(_, another)) if one != another => panic!(
- "{} option names must be unique, but '{}' is in use by both '{}' and '{}'",
- short_or_long, flag, one, another
- ),
-
- (Arg(flag, arg), Command(_, sub)) | (Command(flag, sub), Arg(_, arg)) => panic!(
- "the '{}' {} flag for the '{}' argument conflicts with the short flag \
- for '{}' subcommand",
- flag, short_or_long, arg, sub
- ),
-
- _ => {}
- }
- }
-}
-
-/// Find duplicates in a sorted array.
-///
-/// The algorithm is simple: the array is sorted, duplicates
-/// must be placed next to each other, we can check only adjacent elements.
-fn find_duplicates<T: PartialEq>(slice: &[T]) -> impl Iterator<Item = (&T, &T)> {
- slice.windows(2).filter_map(|w| {
- if w[0] == w[1] {
- Some((&w[0], &w[1]))
- } else {
- None
- }
- })
-}
-
-fn assert_app_flags(cmd: &Command) {
- macro_rules! checker {
- ($a:ident requires $($b:ident)|+) => {
- if cmd.$a() {
- let mut s = String::new();
-
- $(
- if !cmd.$b() {
- use std::fmt::Write;
- write!(&mut s, " AppSettings::{} is required when AppSettings::{} is set.\n", std::stringify!($b), std::stringify!($a)).unwrap();
- }
- )+
-
- if !s.is_empty() {
- panic!("{}", s)
- }
- }
- };
- ($a:ident conflicts $($b:ident)|+) => {
- if cmd.$a() {
- let mut s = String::new();
-
- $(
- if cmd.$b() {
- use std::fmt::Write;
- write!(&mut s, " AppSettings::{} conflicts with AppSettings::{}.\n", std::stringify!($b), std::stringify!($a)).unwrap();
- }
- )+
-
- if !s.is_empty() {
- panic!("{}\n{}", cmd.get_name(), s)
- }
- }
- };
- }
-
- checker!(is_multicall_set conflicts is_no_binary_name_set);
-}
-
-#[cfg(debug_assertions)]
-fn _verify_positionals(cmd: &Command) -> bool {
- debug!("Command::_verify_positionals");
- // Because you must wait until all arguments have been supplied, this is the first chance
- // to make assertions on positional argument indexes
- //
- // First we verify that the index highest supplied index, is equal to the number of
- // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
- // but no 2)
-
- let highest_idx = cmd
- .get_keymap()
- .keys()
- .filter_map(|x| {
- if let KeyType::Position(n) = x {
- Some(*n)
- } else {
- None
- }
- })
- .max()
- .unwrap_or(0);
-
- let num_p = cmd.get_keymap().keys().filter(|x| x.is_position()).count();
-
- assert!(
- highest_idx == num_p,
- "Found positional argument whose index is {} but there \
- are only {} positional arguments defined",
- highest_idx,
- num_p
- );
-
- for arg in cmd.get_arguments() {
- if arg.index.unwrap_or(0) == highest_idx {
- assert!(
- !arg.is_trailing_var_arg_set() || !arg.is_last_set(),
- "{}:{}: `Arg::trailing_var_arg` and `Arg::last` cannot be used together",
- cmd.get_name(),
- arg.get_id()
- );
-
- if arg.is_trailing_var_arg_set() {
- assert!(
- arg.is_multiple(),
- "{}:{}: `Arg::trailing_var_arg` must accept multiple values",
- cmd.get_name(),
- arg.get_id()
- );
- }
- } else {
- assert!(
- !arg.is_trailing_var_arg_set(),
- "{}:{}: `Arg::trailing_var_arg` can only apply to last positional",
- cmd.get_name(),
- arg.get_id()
- );
- }
- }
-
- // Next we verify that only the highest index has takes multiple arguments (if any)
- let only_highest = |a: &Arg| a.is_multiple() && (a.get_index().unwrap_or(0) != highest_idx);
- if cmd.get_positionals().any(only_highest) {
- // First we make sure if there is a positional that allows multiple values
- // the one before it (second to last) has one of these:
- // * a value terminator
- // * ArgSettings::Last
- // * The last arg is Required
-
- // We can't pass the closure (it.next()) to the macro directly because each call to
- // find() (iterator, not macro) gets called repeatedly.
- let last = &cmd.get_keymap()[&KeyType::Position(highest_idx)];
- let second_to_last = &cmd.get_keymap()[&KeyType::Position(highest_idx - 1)];
-
- // Either the final positional is required
- // Or the second to last has a terminator or .last(true) set
- let ok = last.is_required_set()
- || (second_to_last.terminator.is_some() || second_to_last.is_last_set())
- || last.is_last_set();
- assert!(
- ok,
- "When using a positional argument with `.num_args(1..)` that is *not the \
- last* positional argument, the last positional argument (i.e. the one \
- with the highest index) *must* have .required(true) or .last(true) set."
- );
-
- // We make sure if the second to last is Multiple the last is ArgSettings::Last
- let ok = second_to_last.is_multiple() || last.is_last_set();
- assert!(
- ok,
- "Only the last positional argument, or second to last positional \
- argument may be set to `.num_args(1..)`"
- );
-
- // Next we check how many have both Multiple and not a specific number of values set
- let count = cmd
- .get_positionals()
- .filter(|p| {
- p.is_multiple_values_set()
- && !p.get_num_args().expect(INTERNAL_ERROR_MSG).is_fixed()
- })
- .count();
- let ok = count <= 1
- || (last.is_last_set()
- && last.is_multiple()
- && second_to_last.is_multiple()
- && count == 2);
- assert!(
- ok,
- "Only one positional argument with `.num_args(1..)` set is allowed per \
- command, unless the second one also has .last(true) set"
- );
- }
-
- let mut found = false;
-
- if cmd.is_allow_missing_positional_set() {
- // Check that if a required positional argument is found, all positions with a lower
- // index are also required.
- let mut foundx2 = false;
-
- for p in cmd.get_positionals() {
- if foundx2 && !p.is_required_set() {
- assert!(
- p.is_required_set(),
- "Found non-required positional argument with a lower \
- index than a required positional argument by two or more: {:?} \
- index {:?}",
- p.get_id(),
- p.get_index()
- );
- } else if p.is_required_set() && !p.is_last_set() {
- // Args that .last(true) don't count since they can be required and have
- // positionals with a lower index that aren't required
- // Imagine: prog <req1> [opt1] -- <req2>
- // Both of these are valid invocations:
- // $ prog r1 -- r2
- // $ prog r1 o1 -- r2
- if found {
- foundx2 = true;
- continue;
- }
- found = true;
- continue;
- } else {
- found = false;
- }
- }
- } else {
- // Check that if a required positional argument is found, all positions with a lower
- // index are also required
- for p in (1..=num_p).rev().filter_map(|n| cmd.get_keymap().get(&n)) {
- if found {
- assert!(
- p.is_required_set(),
- "Found non-required positional argument with a lower \
- index than a required positional argument: {:?} index {:?}",
- p.get_id(),
- p.get_index()
- );
- } else if p.is_required_set() && !p.is_last_set() {
- // Args that .last(true) don't count since they can be required and have
- // positionals with a lower index that aren't required
- // Imagine: prog <req1> [opt1] -- <req2>
- // Both of these are valid invocations:
- // $ prog r1 -- r2
- // $ prog r1 o1 -- r2
- found = true;
- continue;
- }
- }
- }
- assert!(
- cmd.get_positionals().filter(|p| p.is_last_set()).count() < 2,
- "Only one positional argument may have last(true) set. Found two."
- );
- if cmd
- .get_positionals()
- .any(|p| p.is_last_set() && p.is_required_set())
- && cmd.has_subcommands()
- && !cmd.is_subcommand_negates_reqs_set()
- {
- panic!(
- "Having a required positional argument with .last(true) set *and* child \
- subcommands without setting SubcommandsNegateReqs isn't compatible."
- );
- }
-
- true
-}
-
-fn assert_arg(arg: &Arg) {
- debug!("Arg::_debug_asserts:{}", arg.get_id());
-
- // Self conflict
- // TODO: this check should be recursive
- assert!(
- !arg.blacklist.iter().any(|x| x == arg.get_id()),
- "Argument '{}' cannot conflict with itself",
- arg.get_id(),
- );
-
- assert_eq!(
- arg.get_action().takes_values(),
- arg.is_takes_value_set(),
- "Argument `{}`'s selected action {:?} contradicts `takes_value`",
- arg.get_id(),
- arg.get_action()
- );
- if let Some(action_type_id) = arg.get_action().value_type_id() {
- assert_eq!(
- action_type_id,
- arg.get_value_parser().type_id(),
- "Argument `{}`'s selected action {:?} contradicts `value_parser` ({:?})",
- arg.get_id(),
- arg.get_action(),
- arg.get_value_parser()
- );
- }
-
- if arg.get_value_hint() != ValueHint::Unknown {
- assert!(
- arg.is_takes_value_set(),
- "Argument '{}' has value hint but takes no value",
- arg.get_id()
- );
-
- if arg.get_value_hint() == ValueHint::CommandWithArguments {
- assert!(
- arg.is_multiple_values_set(),
- "Argument '{}' uses hint CommandWithArguments and must accept multiple values",
- arg.get_id()
- )
- }
- }
-
- if arg.index.is_some() {
- assert!(
- arg.is_positional(),
- "Argument '{}' is a positional argument and can't have short or long name versions",
- arg.get_id()
- );
- assert!(
- arg.is_takes_value_set(),
- "Argument '{}` is positional, it must take a value{}",
- arg.get_id(),
- if arg.get_id() == Id::HELP {
- " (`mut_arg` no longer works with implicit `--help`)"
- } else if arg.get_id() == Id::VERSION {
- " (`mut_arg` no longer works with implicit `--version`)"
- } else {
- ""
- }
- );
- }
-
- let num_vals = arg.get_num_args().expect(INTERNAL_ERROR_MSG);
- // This can be the cause of later asserts, so put this first
- if num_vals != ValueRange::EMPTY {
- // HACK: Don't check for flags to make the derive easier
- let num_val_names = arg.get_value_names().unwrap_or(&[]).len();
- if num_vals.max_values() < num_val_names {
- panic!(
- "Argument {}: Too many value names ({}) compared to `num_args` ({})",
- arg.get_id(),
- num_val_names,
- num_vals
- );
- }
- }
-
- assert_eq!(
- num_vals.takes_values(),
- arg.is_takes_value_set(),
- "Argument {}: mismatch between `num_args` ({}) and `takes_value`",
- arg.get_id(),
- num_vals,
- );
- assert_eq!(
- num_vals.is_multiple(),
- arg.is_multiple_values_set(),
- "Argument {}: mismatch between `num_args` ({}) and `multiple_values`",
- arg.get_id(),
- num_vals,
- );
-
- if 1 < num_vals.min_values() {
- assert!(
- !arg.is_require_equals_set(),
- "Argument {}: cannot accept more than 1 arg (num_args={}) with require_equals",
- arg.get_id(),
- num_vals
- );
- }
-
- if num_vals == ValueRange::SINGLE {
- assert!(
- !arg.is_multiple_values_set(),
- "Argument {}: mismatch between `num_args` and `multiple_values`",
- arg.get_id()
- );
- }
-
- assert_arg_flags(arg);
-
- assert_defaults(arg, "default_value", arg.default_vals.iter());
- assert_defaults(
- arg,
- "default_missing_value",
- arg.default_missing_vals.iter(),
- );
- assert_defaults(
- arg,
- "default_value_if",
- arg.default_vals_ifs
- .iter()
- .filter_map(|(_, _, default)| default.as_ref()),
- );
-}
-
-fn assert_arg_flags(arg: &Arg) {
- macro_rules! checker {
- ($a:ident requires $($b:ident)|+) => {
- if arg.$a() {
- let mut s = String::new();
-
- $(
- if !arg.$b() {
- use std::fmt::Write;
- write!(&mut s, " Arg::{} is required when Arg::{} is set.\n", std::stringify!($b), std::stringify!($a)).unwrap();
- }
- )+
-
- if !s.is_empty() {
- panic!("Argument {:?}\n{}", arg.get_id(), s)
- }
- }
- }
- }
-
- checker!(is_hide_possible_values_set requires is_takes_value_set);
- checker!(is_allow_hyphen_values_set requires is_takes_value_set);
- checker!(is_allow_negative_numbers_set requires is_takes_value_set);
- checker!(is_require_equals_set requires is_takes_value_set);
- checker!(is_last_set requires is_takes_value_set);
- checker!(is_hide_default_value_set requires is_takes_value_set);
- checker!(is_multiple_values_set requires is_takes_value_set);
- checker!(is_ignore_case_set requires is_takes_value_set);
-}
-
-fn assert_defaults<'d>(
- arg: &Arg,
- field: &'static str,
- defaults: impl IntoIterator<Item = &'d OsStr>,
-) {
- for default_os in defaults {
- let value_parser = arg.get_value_parser();
- let assert_cmd = Command::new("assert");
- if let Some(delim) = arg.get_value_delimiter() {
- let default_os = RawOsStr::new(default_os);
- for part in default_os.split(delim) {
- if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), &part.to_os_str())
- {
- panic!(
- "Argument `{}`'s {}={:?} failed validation: {}",
- arg.get_id(),
- field,
- part.to_str_lossy(),
- err
- );
- }
- }
- } else if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), default_os) {
- panic!(
- "Argument `{}`'s {}={:?} failed validation: {}",
- arg.get_id(),
- field,
- default_os,
- err
- );
- }
- }
-}