Skip to content

Commit

Permalink
fix(parser): Require earlier, not-present positionals
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Aug 30, 2022
1 parent 2388ace commit 8da1f08
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
36 changes: 33 additions & 3 deletions src/parser/validator.rs
Expand Up @@ -241,6 +241,7 @@ impl<'cmd> Validator<'cmd> {
self.gather_requires(matcher);

let mut missing_required = Vec::new();
let mut highest_index = 0;

let is_exclusive_present = matcher
.arg_ids()
Expand Down Expand Up @@ -270,6 +271,9 @@ impl<'cmd> Validator<'cmd> {
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");
Expand All @@ -294,13 +298,15 @@ impl<'cmd> Validator<'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()
);
missing_required.push(a.get_id().clone());
required = true;
}
}

Expand All @@ -312,7 +318,7 @@ impl<'cmd> Validator<'cmd> {
"Validator::validate_required:iter: Missing {:?}",
a.get_id()
);
missing_required.push(a.get_id().clone());
required = true;
}

if (!a.r_unless.is_empty() || !a.r_unless_all.is_empty())
Expand All @@ -322,7 +328,31 @@ impl<'cmd> Validator<'cmd> {
"Validator::validate_required:iter: Missing {:?}",
a.get_id()
);
missing_required.push(a.id.clone());
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());
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion tests/builder/require.rs
Expand Up @@ -33,10 +33,11 @@ For more information try --help

static MISSING_REQ: &str = "error: The following required arguments were not provided:
--long-option-2 <option2>
<positional>
<positional2>
Usage:
clap-test --long-option-2 <option2> -F <positional2>
clap-test --long-option-2 <option2> -F <positional> <positional2>
For more information try --help
";
Expand Down

0 comments on commit 8da1f08

Please sign in to comment.