summaryrefslogtreecommitdiffstats
path: root/vendor/clap/src/parser/validator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap/src/parser/validator.rs')
-rw-r--r--vendor/clap/src/parser/validator.rs692
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()
- }
-}