Fix panic on too few arguments for custom function (#10395)

# Description
Old code was comparing remaining positional arguments with total number
of arguments, where it should've compared remaining positional with
with remaining arguments of any kind. This means that if a function was
given too few arguments, `calculate_end_span` would believe that it
actually had too many arguments, since after parsing the first few
arguments, the number of remaining arguments needed were fewer than the
*total* number of arguments, of which we had used several.

Fixes #9072
Fixes: https://github.com/nushell/nushell/issues/13930
Fixes: https://github.com/nushell/nushell/issues/12069
Fixes: https://github.com/nushell/nushell/issues/8385

Extracted from #10381

## Bonus

It also improves the error handling on missing positional arguments
before keywords (no longer crashing since #9851). Instead of just giving
the keyword to the parser for the missing positional, we give an
explicit error about a missing positional argument. I would like better
descriptions than "missing var_name" though, but I'm not sure if that's
available without

Old error
```
Error: nu::parser::parse_mismatch

  × Parse mismatch during operation.
   ╭─[entry #1:1:1]
 1 │ let = if foo
   ·     ┬
   ·     ╰── expected valid variable name
   ╰────
```

New error
```
Error: nu::parser::missing_positional

  × Missing required positional argument.
   ╭─[entry #18:1:1]
 1 │ let = foo
   ·    ┬
   ·    ╰── missing var_name
   ╰────
  help: Usage: let <var_name> = <initial_value>
```

# User-Facing Changes
The program `alias = = =` is no longer accepted by the parser
This commit is contained in:
Andreas Källberg
2024-09-27 17:39:45 +02:00
committed by GitHub
parent 497954d84c
commit 8200831b07
3 changed files with 54 additions and 37 deletions

View File

@ -522,27 +522,6 @@ impl Signature {
total
}
pub fn num_positionals_after(&self, idx: usize) -> usize {
let mut total = 0;
for (curr, positional) in self.required_positional.iter().enumerate() {
match positional.shape {
SyntaxShape::Keyword(..) => {
// Keywords have a required argument, so account for that
if curr > idx {
total += 2;
}
}
_ => {
if curr > idx {
total += 1;
}
}
}
}
total
}
/// Find the matching long flag
pub fn get_long_flag(&self, name: &str) -> Option<Flag> {
for flag in &self.named {