diff options
Diffstat (limited to 'vendor/clap/src/parser/validator.rs')
-rw-r--r-- | vendor/clap/src/parser/validator.rs | 692 |
1 files changed, 0 insertions, 692 deletions
diff --git a/vendor/clap/src/parser/validator.rs b/vendor/clap/src/parser/validator.rs deleted file mode 100644 index ebf2b234d..000000000 --- a/vendor/clap/src/parser/validator.rs +++ /dev/null @@ -1,692 +0,0 @@ -// Internal -use crate::builder::{AppSettings, Arg, ArgPredicate, Command, PossibleValue}; -use crate::error::{Error, Result as ClapResult}; -use crate::output::fmt::Stream; -use crate::output::Usage; -use crate::parser::{ArgMatcher, MatchedArg, ParseState}; -use crate::util::ChildGraph; -use crate::util::Id; -use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8}; - -pub(crate) struct Validator<'help, 'cmd> { - cmd: &'cmd Command<'help>, - required: ChildGraph<Id>, -} - -impl<'help, 'cmd> Validator<'help, 'cmd> { - pub(crate) fn new(cmd: &'cmd Command<'help>) -> Self { - let required = cmd.required_graph(); - Validator { cmd, required } - } - - pub(crate) fn validate( - &mut self, - parse_state: ParseState, - matcher: &mut ArgMatcher, - ) -> ClapResult<()> { - debug!("Validator::validate"); - let mut conflicts = Conflicts::new(); - let has_subcmd = matcher.subcommand_name().is_some(); - - if let ParseState::Opt(a) = parse_state { - debug!("Validator::validate: needs_val_of={:?}", a); - - let o = &self.cmd[&a]; - let should_err = if let Some(v) = matcher.args.get(&o.id) { - v.all_val_groups_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0) - } else { - true - }; - if should_err { - return Err(Error::empty_value( - self.cmd, - &get_possible_values(o) - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) - .collect::<Vec<_>>(), - o.to_string(), - )); - } - } - - if !has_subcmd && self.cmd.is_arg_required_else_help_set() { - let num_user_values = matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - .count(); - if num_user_values == 0 { - let message = self.cmd.write_help_err(false, Stream::Stderr)?; - return Err(Error::display_help_error(self.cmd, message)); - } - } - #[allow(deprecated)] - if !has_subcmd && self.cmd.is_subcommand_required_set() { - let bn = self - .cmd - .get_bin_name() - .unwrap_or_else(|| self.cmd.get_name()); - return Err(Error::missing_subcommand( - self.cmd, - bn.to_string(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } else if !has_subcmd && self.cmd.is_set(AppSettings::SubcommandRequiredElseHelp) { - debug!("Validator::new::get_matches_with: SubcommandRequiredElseHelp=true"); - let message = self.cmd.write_help_err(false, Stream::Stderr)?; - return Err(Error::display_help_error(self.cmd, message)); - } - - self.validate_conflicts(matcher, &mut conflicts)?; - if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) { - self.validate_required(matcher, &mut conflicts)?; - } - self.validate_matched_args(matcher)?; - - Ok(()) - } - - fn validate_arg_values(&self, arg: &Arg, ma: &MatchedArg) -> ClapResult<()> { - debug!("Validator::validate_arg_values: arg={:?}", arg.name); - for val in ma.raw_vals_flatten() { - if !arg.possible_vals.is_empty() { - debug!( - "Validator::validate_arg_values: possible_vals={:?}", - arg.possible_vals - ); - let val_str = val.to_string_lossy(); - let ok = arg - .possible_vals - .iter() - .any(|pv| pv.matches(&val_str, arg.is_ignore_case_set())); - if !ok { - return Err(Error::invalid_value( - self.cmd, - val_str.into_owned(), - &arg.possible_vals - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) - .collect::<Vec<_>>(), - arg.to_string(), - )); - } - } - { - #![allow(deprecated)] - if arg.is_forbid_empty_values_set() && val.is_empty() { - debug!("Validator::validate_arg_values: illegal empty val found"); - return Err(Error::empty_value( - self.cmd, - &get_possible_values(arg) - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) - .collect::<Vec<_>>(), - arg.to_string(), - )); - } - } - - if let Some(ref vtor) = arg.validator { - debug!("Validator::validate_arg_values: checking validator..."); - let mut vtor = vtor.lock().unwrap(); - if let Err(e) = vtor(&*val.to_string_lossy()) { - debug!("error"); - return Err(Error::value_validation( - arg.to_string(), - val.to_string_lossy().into_owned(), - e, - ) - .with_cmd(self.cmd)); - } else { - debug!("good"); - } - } - if let Some(ref vtor) = arg.validator_os { - debug!("Validator::validate_arg_values: checking validator_os..."); - let mut vtor = vtor.lock().unwrap(); - if let Err(e) = vtor(val) { - debug!("error"); - return Err(Error::value_validation( - arg.to_string(), - val.to_string_lossy().into(), - e, - ) - .with_cmd(self.cmd)); - } else { - debug!("good"); - } - } - } - Ok(()) - } - - fn validate_conflicts( - &mut self, - matcher: &ArgMatcher, - conflicts: &mut Conflicts, - ) -> ClapResult<()> { - debug!("Validator::validate_conflicts"); - - self.validate_exclusive(matcher)?; - - for arg_id in matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - .filter(|arg_id| self.cmd.find(arg_id).is_some()) - { - debug!("Validator::validate_conflicts::iter: id={:?}", arg_id); - let conflicts = conflicts.gather_conflicts(self.cmd, matcher, arg_id); - self.build_conflict_err(arg_id, &conflicts, matcher)?; - } - - Ok(()) - } - - fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> { - debug!("Validator::validate_exclusive"); - let args_count = matcher - .arg_ids() - .filter(|arg_id| { - matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent) - }) - .count(); - if args_count <= 1 { - // Nothing present to conflict with - return Ok(()); - } - - matcher - .arg_ids() - .filter(|arg_id| { - matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent) - }) - .filter_map(|name| { - debug!("Validator::validate_exclusive:iter:{:?}", name); - self.cmd - .find(name) - // Find `arg`s which are exclusive but also appear with other args. - .filter(|&arg| arg.is_exclusive_set() && args_count > 1) - }) - // Throw an error for the first conflict found. - .try_for_each(|arg| { - Err(Error::argument_conflict( - self.cmd, - arg.to_string(), - Vec::new(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )) - }) - } - - fn build_conflict_err( - &self, - name: &Id, - conflict_ids: &[Id], - matcher: &ArgMatcher, - ) -> ClapResult<()> { - if conflict_ids.is_empty() { - return Ok(()); - } - - debug!("Validator::build_conflict_err: name={:?}", name); - let mut seen = std::collections::HashSet::new(); - let conflicts = conflict_ids - .iter() - .flat_map(|c_id| { - if self.cmd.find_group(c_id).is_some() { - self.cmd.unroll_args_in_group(c_id) - } else { - vec![c_id.clone()] - } - }) - .filter_map(|c_id| { - seen.insert(c_id.clone()).then(|| { - let c_arg = self.cmd.find(&c_id).expect(INTERNAL_ERROR_MSG); - c_arg.to_string() - }) - }) - .collect(); - - let former_arg = self.cmd.find(name).expect(INTERNAL_ERROR_MSG); - let usg = self.build_conflict_err_usage(matcher, conflict_ids); - Err(Error::argument_conflict( - self.cmd, - former_arg.to_string(), - conflicts, - usg, - )) - } - - fn build_conflict_err_usage(&self, matcher: &ArgMatcher, conflicting_keys: &[Id]) -> String { - let used_filtered: Vec<Id> = matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - .filter(|n| { - // Filter out the args we don't want to specify. - self.cmd.find(n).map_or(true, |a| !a.is_hide_set()) - }) - .filter(|key| !conflicting_keys.contains(key)) - .cloned() - .collect(); - let required: Vec<Id> = used_filtered - .iter() - .filter_map(|key| self.cmd.find(key)) - .flat_map(|arg| arg.requires.iter().map(|item| &item.1)) - .filter(|key| !used_filtered.contains(key) && !conflicting_keys.contains(key)) - .chain(used_filtered.iter()) - .cloned() - .collect(); - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&required) - } - - fn gather_requires(&mut self, matcher: &ArgMatcher) { - debug!("Validator::gather_requires"); - for name in matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - { - debug!("Validator::gather_requires:iter:{:?}", name); - if let Some(arg) = self.cmd.find(name) { - let is_relevant = |(val, req_arg): &(ArgPredicate<'_>, Id)| -> Option<Id> { - let required = matcher.check_explicit(&arg.id, *val); - required.then(|| req_arg.clone()) - }; - - for req in self.cmd.unroll_arg_requires(is_relevant, &arg.id) { - self.required.insert(req); - } - } else if let Some(g) = self.cmd.find_group(name) { - debug!("Validator::gather_requires:iter:{:?}:group", name); - for r in &g.requires { - self.required.insert(r.clone()); - } - } - } - } - - fn validate_matched_args(&self, matcher: &ArgMatcher) -> ClapResult<()> { - debug!("Validator::validate_matched_args"); - matcher.iter().try_for_each(|(name, ma)| { - debug!( - "Validator::validate_matched_args:iter:{:?}: vals={:#?}", - name, - ma.vals_flatten() - ); - if let Some(arg) = self.cmd.find(name) { - self.validate_arg_num_vals(arg, ma)?; - self.validate_arg_values(arg, ma)?; - self.validate_arg_num_occurs(arg, ma)?; - } - Ok(()) - }) - } - - fn validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> { - #![allow(deprecated)] - debug!( - "Validator::validate_arg_num_occurs: {:?}={}", - a.name, - ma.get_occurrences() - ); - // Occurrence of positional argument equals to number of values rather - // than number of grouped values. - if ma.get_occurrences() > 1 && !a.is_multiple_occurrences_set() && !a.is_positional() { - // Not the first time, and we don't allow multiples - return Err(Error::unexpected_multiple_usage( - self.cmd, - a.to_string(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - if let Some(max_occurs) = a.max_occurs { - debug!( - "Validator::validate_arg_num_occurs: max_occurs set...{}", - max_occurs - ); - let occurs = ma.get_occurrences() as usize; - if occurs > max_occurs { - return Err(Error::too_many_occurrences( - self.cmd, - a.to_string(), - max_occurs, - occurs, - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - } - - Ok(()) - } - - fn validate_arg_num_vals(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> { - debug!("Validator::validate_arg_num_vals"); - if let Some(num) = a.num_vals { - let total_num = ma.num_vals(); - debug!("Validator::validate_arg_num_vals: num_vals set...{}", num); - #[allow(deprecated)] - let should_err = if a.is_multiple_occurrences_set() { - total_num % num != 0 - } else { - num != total_num - }; - if should_err { - debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); - return Err(Error::wrong_number_of_values( - self.cmd, - a.to_string(), - num, - #[allow(deprecated)] - if a.is_multiple_occurrences_set() { - total_num % num - } else { - total_num - }, - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - } - if let Some(num) = a.max_vals { - debug!("Validator::validate_arg_num_vals: max_vals set...{}", num); - if ma.num_vals() > num { - debug!("Validator::validate_arg_num_vals: Sending error TooManyValues"); - return Err(Error::too_many_values( - self.cmd, - ma.raw_vals_flatten() - .last() - .expect(INTERNAL_ERROR_MSG) - .to_str() - .expect(INVALID_UTF8) - .to_string(), - a.to_string(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - } - let min_vals_zero = if let Some(num) = a.min_vals { - debug!("Validator::validate_arg_num_vals: min_vals set: {}", num); - if ma.num_vals() < num && num != 0 { - debug!("Validator::validate_arg_num_vals: Sending error TooFewValues"); - return Err(Error::too_few_values( - self.cmd, - a.to_string(), - num, - ma.num_vals(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - num == 0 - } else { - false - }; - // Issue 665 (https://github.com/clap-rs/clap/issues/665) - // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) - if a.is_takes_value_set() && !min_vals_zero && ma.all_val_groups_empty() { - return Err(Error::empty_value( - self.cmd, - &get_possible_values(a) - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) - .collect::<Vec<_>>(), - a.to_string(), - )); - } - Ok(()) - } - - fn validate_required( - &mut self, - matcher: &ArgMatcher, - conflicts: &mut Conflicts, - ) -> ClapResult<()> { - debug!("Validator::validate_required: required={:?}", self.required); - self.gather_requires(matcher); - - let is_exclusive_present = matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - .any(|id| { - self.cmd - .find(id) - .map(|arg| arg.is_exclusive_set()) - .unwrap_or_default() - }); - debug!( - "Validator::validate_required: is_exclusive_present={}", - is_exclusive_present - ); - - for arg_or_group in self - .required - .iter() - .filter(|r| !matcher.check_explicit(r, ArgPredicate::IsPresent)) - { - debug!("Validator::validate_required:iter:aog={:?}", arg_or_group); - if let Some(arg) = self.cmd.find(arg_or_group) { - debug!("Validator::validate_required:iter: This is an arg"); - if !is_exclusive_present && !self.is_missing_required_ok(arg, matcher, conflicts) { - return self.missing_required_error(matcher, vec![]); - } - } else if let Some(group) = self.cmd.find_group(arg_or_group) { - debug!("Validator::validate_required:iter: This is a group"); - if !self - .cmd - .unroll_args_in_group(&group.id) - .iter() - .any(|a| matcher.check_explicit(a, ArgPredicate::IsPresent)) - { - return self.missing_required_error(matcher, vec![]); - } - } - } - - // Validate the conditionally required args - for a in self.cmd.get_arguments() { - for (other, val) in &a.r_ifs { - if matcher.check_explicit(other, ArgPredicate::Equals(std::ffi::OsStr::new(*val))) - && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent) - { - return self.missing_required_error(matcher, vec![a.id.clone()]); - } - } - - let match_all = a.r_ifs_all.iter().all(|(other, val)| { - matcher.check_explicit(other, ArgPredicate::Equals(std::ffi::OsStr::new(*val))) - }); - if match_all - && !a.r_ifs_all.is_empty() - && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent) - { - return self.missing_required_error(matcher, vec![a.id.clone()]); - } - } - - self.validate_required_unless(matcher)?; - - Ok(()) - } - - fn is_missing_required_ok( - &self, - a: &Arg<'help>, - matcher: &ArgMatcher, - conflicts: &mut Conflicts, - ) -> bool { - debug!("Validator::is_missing_required_ok: {}", a.name); - let conflicts = conflicts.gather_conflicts(self.cmd, matcher, &a.id); - !conflicts.is_empty() - } - - fn validate_required_unless(&self, matcher: &ArgMatcher) -> ClapResult<()> { - debug!("Validator::validate_required_unless"); - let failed_args: Vec<_> = self - .cmd - .get_arguments() - .filter(|&a| { - (!a.r_unless.is_empty() || !a.r_unless_all.is_empty()) - && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent) - && self.fails_arg_required_unless(a, matcher) - }) - .map(|a| a.id.clone()) - .collect(); - if failed_args.is_empty() { - Ok(()) - } else { - self.missing_required_error(matcher, failed_args) - } - } - - // Failing a required unless means, the arg's "unless" wasn't present, and neither were they - fn fails_arg_required_unless(&self, a: &Arg<'help>, matcher: &ArgMatcher) -> bool { - debug!("Validator::fails_arg_required_unless: a={:?}", a.name); - let exists = |id| matcher.check_explicit(id, ArgPredicate::IsPresent); - - (a.r_unless_all.is_empty() || !a.r_unless_all.iter().all(exists)) - && !a.r_unless.iter().any(exists) - } - - // `incl`: an arg to include in the error even if not used - fn missing_required_error(&self, matcher: &ArgMatcher, incl: Vec<Id>) -> ClapResult<()> { - debug!("Validator::missing_required_error; incl={:?}", incl); - debug!( - "Validator::missing_required_error: reqs={:?}", - self.required - ); - - let usg = Usage::new(self.cmd).required(&self.required); - - let req_args = usg - .get_required_usage_from(&incl, Some(matcher), true) - .into_iter() - .collect::<Vec<_>>(); - - debug!( - "Validator::missing_required_error: req_args={:#?}", - req_args - ); - - let used: Vec<Id> = matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - .filter(|n| { - // Filter out the args we don't want to specify. - self.cmd.find(n).map_or(true, |a| !a.is_hide_set()) - }) - .cloned() - .chain(incl) - .collect(); - - Err(Error::missing_required_argument( - self.cmd, - req_args, - usg.create_usage_with_title(&used), - )) - } -} - -#[derive(Default, Clone, Debug)] -struct Conflicts { - potential: std::collections::HashMap<Id, Vec<Id>>, -} - -impl Conflicts { - fn new() -> Self { - Self::default() - } - - fn gather_conflicts(&mut self, cmd: &Command, matcher: &ArgMatcher, arg_id: &Id) -> Vec<Id> { - debug!("Conflicts::gather_conflicts: arg={:?}", arg_id); - let mut conflicts = Vec::new(); - for other_arg_id in matcher - .arg_ids() - .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent)) - { - if arg_id == other_arg_id { - continue; - } - - if self - .gather_direct_conflicts(cmd, arg_id) - .contains(other_arg_id) - { - conflicts.push(other_arg_id.clone()); - } - if self - .gather_direct_conflicts(cmd, other_arg_id) - .contains(arg_id) - { - conflicts.push(other_arg_id.clone()); - } - } - debug!("Conflicts::gather_conflicts: conflicts={:?}", conflicts); - conflicts - } - - fn gather_direct_conflicts(&mut self, cmd: &Command, arg_id: &Id) -> &[Id] { - self.potential.entry(arg_id.clone()).or_insert_with(|| { - let conf = if let Some(arg) = cmd.find(arg_id) { - let mut conf = arg.blacklist.clone(); - for group_id in cmd.groups_for_arg(arg_id) { - let group = cmd.find_group(&group_id).expect(INTERNAL_ERROR_MSG); - conf.extend(group.conflicts.iter().cloned()); - if !group.multiple { - for member_id in &group.args { - if member_id != arg_id { - conf.push(member_id.clone()); - } - } - } - } - - // Overrides are implicitly conflicts - conf.extend(arg.overrides.iter().cloned()); - - conf - } else if let Some(group) = cmd.find_group(arg_id) { - group.conflicts.clone() - } else { - debug_assert!(false, "id={:?} is unknown", arg_id); - Vec::new() - }; - debug!( - "Conflicts::gather_direct_conflicts id={:?}, conflicts={:?}", - arg_id, conf - ); - conf - }) - } -} - -fn get_possible_values<'help>(a: &Arg<'help>) -> Vec<PossibleValue<'help>> { - #![allow(deprecated)] - if !a.is_takes_value_set() { - vec![] - } else if let Some(pvs) = a.get_possible_values() { - // Check old first in case the user explicitly set possible values and the derive inferred - // a `ValueParser` with some. - pvs.to_vec() - } else { - a.get_value_parser() - .possible_values() - .map(|pvs| pvs.collect()) - .unwrap_or_default() - } -} |