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