diff options
author | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
commit | a990de90fe41456a23e58bd087d2f107d321f3a1 (patch) | |
tree | 15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/clap_builder/src/parser/validator.rs | |
parent | 3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff) | |
download | fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip |
Deleted vendor folder
Diffstat (limited to 'vendor/clap_builder/src/parser/validator.rs')
-rw-r--r-- | vendor/clap_builder/src/parser/validator.rs | 561 |
1 files changed, 0 insertions, 561 deletions
diff --git a/vendor/clap_builder/src/parser/validator.rs b/vendor/clap_builder/src/parser/validator.rs deleted file mode 100644 index 55f4633..0000000 --- a/vendor/clap_builder/src/parser/validator.rs +++ /dev/null @@ -1,561 +0,0 @@ -// Internal -use crate::builder::StyledStr; -use crate::builder::{Arg, ArgGroup, ArgPredicate, Command, PossibleValue}; -use crate::error::{Error, Result as ClapResult}; -use crate::output::Usage; -use crate::parser::{ArgMatcher, ParseState}; -use crate::util::ChildGraph; -use crate::util::FlatMap; -use crate::util::FlatSet; -use crate::util::Id; -use crate::INTERNAL_ERROR_MSG; - -pub(crate) struct Validator<'cmd> { - cmd: &'cmd Command, - required: ChildGraph<Id>, -} - -impl<'cmd> Validator<'cmd> { - pub(crate) fn new(cmd: &'cmd Command) -> 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 conflicts = Conflicts::with_args(self.cmd, matcher); - 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.get_id()) { - v.all_val_groups_empty() && o.get_min_vals() != 0 - } else { - true - }; - if should_err { - return Err(Error::empty_value( - self.cmd, - &get_possible_values_cli(o) - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(|n| n.get_name().to_owned()) - .collect::<Vec<_>>(), - o.to_string(), - )); - } - } - - if !has_subcmd && self.cmd.is_arg_required_else_help_set() { - let num_user_values = matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent)) - .count(); - if num_user_values == 0 { - let message = self.cmd.write_help_err(false); - return Err(Error::display_help_error(self.cmd, message)); - } - } - if !has_subcmd && self.cmd.is_subcommand_required_set() { - let bn = self.cmd.get_bin_name_fallback(); - return Err(Error::missing_subcommand( - self.cmd, - bn.to_string(), - self.cmd - .all_subcommand_names() - .map(|s| s.to_owned()) - .collect::<Vec<_>>(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - - ok!(self.validate_conflicts(matcher, &conflicts)); - if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) { - ok!(self.validate_required(matcher, &conflicts)); - } - - Ok(()) - } - - fn validate_conflicts( - &mut self, - matcher: &ArgMatcher, - conflicts: &Conflicts, - ) -> ClapResult<()> { - debug!("Validator::validate_conflicts"); - - ok!(self.validate_exclusive(matcher)); - - for (arg_id, _) in matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&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, arg_id); - ok!(self.build_conflict_err(arg_id, &conflicts, matcher)); - } - - Ok(()) - } - - fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> { - debug!("Validator::validate_exclusive"); - let args_count = matcher - .args() - .filter(|(arg_id, matched)| { - matched.check_explicit(&crate::builder::ArgPredicate::IsPresent) - // Avoid including our own groups by checking none of them. If a group is present, the - // args for the group will be. - && self.cmd.find(arg_id).is_some() - }) - .count(); - if args_count <= 1 { - // Nothing present to conflict with - return Ok(()); - } - - matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&crate::builder::ArgPredicate::IsPresent)) - .filter_map(|(id, _)| { - debug!("Validator::validate_exclusive:iter:{id:?}"); - self.cmd - .find(id) - // Find `arg`s which are exclusive but also appear with other args. - .filter(|&arg| arg.is_exclusive_set() && args_count > 1) - }) - .next() - .map(|arg| { - // Throw an error for the first conflict found. - Err(Error::argument_conflict( - self.cmd, - arg.to_string(), - Vec::new(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )) - }) - .unwrap_or(Ok(())) - } - - 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 = FlatSet::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], - ) -> Option<StyledStr> { - let used_filtered: Vec<Id> = matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent)) - .map(|(n, _)| n) - .filter(|n| { - // Filter out the args we don't want to specify. - self.cmd - .find(n) - .map(|a| !a.is_hide_set()) - .unwrap_or_default() - }) - .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, matched) in matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&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 = matched.check_explicit(val); - required.then(|| req_arg.clone()) - }; - - for req in self.cmd.unroll_arg_requires(is_relevant, arg.get_id()) { - self.required.insert(req); - } - } else if let Some(g) = self.cmd.find_group(name) { - debug!("Validator::gather_requires:iter:{name:?}:group"); - for r in &g.requires { - self.required.insert(r.clone()); - } - } - } - } - - fn validate_required(&mut self, matcher: &ArgMatcher, conflicts: &Conflicts) -> ClapResult<()> { - debug!("Validator::validate_required: required={:?}", self.required); - self.gather_requires(matcher); - - let mut missing_required = Vec::new(); - let mut highest_index = 0; - - let is_exclusive_present = matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&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, conflicts) { - debug!( - "Validator::validate_required:iter: Missing {:?}", - arg.get_id() - ); - missing_required.push(arg.get_id().clone()); - if !arg.is_last_set() { - highest_index = highest_index.max(arg.get_index().unwrap_or(0)); - } - } - } 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)) - { - debug!( - "Validator::validate_required:iter: Missing {:?}", - group.get_id() - ); - missing_required.push(group.get_id().clone()); - } - } - } - - // Validate the conditionally required args - for a in self - .cmd - .get_arguments() - .filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent)) - { - let mut required = false; - - for (other, val) in &a.r_ifs { - if matcher.check_explicit(other, &ArgPredicate::Equals(val.into())) { - debug!( - "Validator::validate_required:iter: Missing {:?}", - a.get_id() - ); - required = true; - } - } - - let match_all = a.r_ifs_all.iter().all(|(other, val)| { - matcher.check_explicit(other, &ArgPredicate::Equals(val.into())) - }); - if match_all && !a.r_ifs_all.is_empty() { - debug!( - "Validator::validate_required:iter: Missing {:?}", - a.get_id() - ); - required = true; - } - - if (!a.r_unless.is_empty() || !a.r_unless_all.is_empty()) - && self.fails_arg_required_unless(a, matcher) - { - debug!( - "Validator::validate_required:iter: Missing {:?}", - a.get_id() - ); - required = true; - } - - if required { - missing_required.push(a.get_id().clone()); - if !a.is_last_set() { - highest_index = highest_index.max(a.get_index().unwrap_or(0)); - } - } - } - - // For display purposes, include all of the preceding positional arguments - if !self.cmd.is_allow_missing_positional_set() { - for pos in self - .cmd - .get_positionals() - .filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent)) - { - if pos.get_index() < Some(highest_index) { - debug!( - "Validator::validate_required:iter: Missing {:?}", - pos.get_id() - ); - missing_required.push(pos.get_id().clone()); - } - } - } - - if !missing_required.is_empty() { - ok!(self.missing_required_error(matcher, missing_required)); - } - - Ok(()) - } - - fn is_missing_required_ok(&self, a: &Arg, conflicts: &Conflicts) -> bool { - debug!("Validator::is_missing_required_ok: {}", a.get_id()); - if !conflicts.gather_conflicts(self.cmd, a.get_id()).is_empty() { - debug!("Validator::is_missing_required_ok: true (self)"); - return true; - } - for group_id in self.cmd.groups_for_arg(a.get_id()) { - if !conflicts.gather_conflicts(self.cmd, &group_id).is_empty() { - debug!("Validator::is_missing_required_ok: true ({group_id})"); - return true; - } - } - false - } - - // Failing a required unless means, the arg's "unless" wasn't present, and neither were they - fn fails_arg_required_unless(&self, a: &Arg, matcher: &ArgMatcher) -> bool { - debug!("Validator::fails_arg_required_unless: a={:?}", a.get_id()); - 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) - } - - // `req_args`: an arg to include in the error even if not used - fn missing_required_error( - &self, - matcher: &ArgMatcher, - raw_req_args: Vec<Id>, - ) -> ClapResult<()> { - debug!("Validator::missing_required_error; incl={raw_req_args:?}"); - debug!( - "Validator::missing_required_error: reqs={:?}", - self.required - ); - - let usg = Usage::new(self.cmd).required(&self.required); - - let req_args = { - #[cfg(feature = "usage")] - { - usg.get_required_usage_from(&raw_req_args, Some(matcher), true) - .into_iter() - .map(|s| s.to_string()) - .collect::<Vec<_>>() - } - - #[cfg(not(feature = "usage"))] - { - raw_req_args - .iter() - .map(|id| { - if let Some(arg) = self.cmd.find(id) { - arg.to_string() - } else if let Some(_group) = self.cmd.find_group(id) { - self.cmd.format_group(id).to_string() - } else { - debug_assert!(false, "id={id:?} is unknown"); - "".to_owned() - } - }) - .collect::<Vec<_>>() - } - }; - - debug!("Validator::missing_required_error: req_args={req_args:#?}"); - - let used: Vec<Id> = matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent)) - .map(|(n, _)| n) - .filter(|n| { - // Filter out the args we don't want to specify. - self.cmd - .find(n) - .map(|a| !a.is_hide_set()) - .unwrap_or_default() - }) - .cloned() - .chain(raw_req_args) - .collect(); - - Err(Error::missing_required_argument( - self.cmd, - req_args, - usg.create_usage_with_title(&used), - )) - } -} - -#[derive(Default, Clone, Debug)] -struct Conflicts { - potential: FlatMap<Id, Vec<Id>>, -} - -impl Conflicts { - fn with_args(cmd: &Command, matcher: &ArgMatcher) -> Self { - let mut potential = FlatMap::new(); - potential.extend_unchecked( - matcher - .args() - .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent)) - .map(|(id, _)| { - let conf = gather_direct_conflicts(cmd, id); - (id.clone(), conf) - }), - ); - Self { potential } - } - - fn gather_conflicts(&self, cmd: &Command, arg_id: &Id) -> Vec<Id> { - debug!("Conflicts::gather_conflicts: arg={arg_id:?}"); - let mut conflicts = Vec::new(); - - let arg_id_conflicts_storage; - let arg_id_conflicts = if let Some(arg_id_conflicts) = self.get_direct_conflicts(arg_id) { - arg_id_conflicts - } else { - // `is_missing_required_ok` is a case where we check not-present args for conflicts - arg_id_conflicts_storage = gather_direct_conflicts(cmd, arg_id); - &arg_id_conflicts_storage - }; - for (other_arg_id, other_arg_id_conflicts) in self.potential.iter() { - if arg_id == other_arg_id { - continue; - } - - if arg_id_conflicts.contains(other_arg_id) { - conflicts.push(other_arg_id.clone()); - } - if other_arg_id_conflicts.contains(arg_id) { - conflicts.push(other_arg_id.clone()); - } - } - - debug!("Conflicts::gather_conflicts: conflicts={conflicts:?}"); - conflicts - } - - fn get_direct_conflicts(&self, arg_id: &Id) -> Option<&[Id]> { - self.potential.get(arg_id).map(Vec::as_slice) - } -} - -fn gather_direct_conflicts(cmd: &Command, id: &Id) -> Vec<Id> { - let conf = if let Some(arg) = cmd.find(id) { - gather_arg_direct_conflicts(cmd, arg) - } else if let Some(group) = cmd.find_group(id) { - gather_group_direct_conflicts(group) - } else { - debug_assert!(false, "id={id:?} is unknown"); - Vec::new() - }; - debug!("Conflicts::gather_direct_conflicts id={id:?}, conflicts={conf:?}",); - conf -} - -fn gather_arg_direct_conflicts(cmd: &Command, arg: &Arg) -> Vec<Id> { - let mut conf = arg.blacklist.clone(); - for group_id in cmd.groups_for_arg(arg.get_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.get_id() { - conf.push(member_id.clone()); - } - } - } - } - - // Overrides are implicitly conflicts - conf.extend(arg.overrides.iter().cloned()); - - conf -} - -fn gather_group_direct_conflicts(group: &ArgGroup) -> Vec<Id> { - group.conflicts.clone() -} - -pub(crate) fn get_possible_values_cli(a: &Arg) -> Vec<PossibleValue> { - if !a.is_takes_value_set() { - vec![] - } else { - a.get_value_parser() - .possible_values() - .map(|pvs| pvs.collect()) - .unwrap_or_default() - } -} |