Print recipe signature if missing arguments (#369)

This commit is contained in:
ladysamantha 2018-11-03 15:51:06 -06:00 committed by Casey Rodarmor
parent 6430d38a6a
commit af97f3f1c1
3 changed files with 44 additions and 5 deletions

View File

@ -99,6 +99,7 @@ impl<'a> Justfile<'a> where {
if !argument_range.range_contains(argument_count) { if !argument_range.range_contains(argument_count) {
return Err(RuntimeError::ArgumentCountMismatch { return Err(RuntimeError::ArgumentCountMismatch {
recipe: recipe.name, recipe: recipe.name,
parameters: recipe.parameters.iter().collect(),
found: tail.len(), found: tail.len(),
min: recipe.min_arguments(), min: recipe.min_arguments(),
max: recipe.max_arguments(), max: recipe.max_arguments(),
@ -307,11 +308,17 @@ a return code:
{ {
ArgumentCountMismatch { ArgumentCountMismatch {
recipe, recipe,
parameters,
found, found,
min, min,
max, max,
} => { } => {
let param_names = parameters
.iter()
.map(|p| p.name)
.collect::<Vec<&str>>();
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(param_names, ["b", "c", "d"]);
assert_eq!(found, 2); assert_eq!(found, 2);
assert_eq!(min, 3); assert_eq!(min, 3);
assert_eq!(max, 3); assert_eq!(max, 3);
@ -328,11 +335,17 @@ a return code:
{ {
ArgumentCountMismatch { ArgumentCountMismatch {
recipe, recipe,
parameters,
found, found,
min, min,
max, max,
} => { } => {
let param_names = parameters
.iter()
.map(|p| p.name)
.collect::<Vec<&str>>();
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(param_names, ["b", "c", "d"]);
assert_eq!(found, 2); assert_eq!(found, 2);
assert_eq!(min, 3); assert_eq!(min, 3);
assert_eq!(max, usize::MAX - 1); assert_eq!(max, usize::MAX - 1);
@ -349,11 +362,17 @@ a return code:
{ {
ArgumentCountMismatch { ArgumentCountMismatch {
recipe, recipe,
parameters,
found, found,
min, min,
max, max,
} => { } => {
let param_names = parameters
.iter()
.map(|p| p.name)
.collect::<Vec<&str>>();
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(param_names, ["b", "c", "d"]);
assert_eq!(found, 0); assert_eq!(found, 0);
assert_eq!(min, 3); assert_eq!(min, 3);
assert_eq!(max, 3); assert_eq!(max, 3);
@ -370,11 +389,17 @@ a return code:
{ {
ArgumentCountMismatch { ArgumentCountMismatch {
recipe, recipe,
parameters,
found, found,
min, min,
max, max,
} => { } => {
let param_names = parameters
.iter()
.map(|p| p.name)
.collect::<Vec<&str>>();
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(param_names, ["b", "c", "d"]);
assert_eq!(found, 1); assert_eq!(found, 1);
assert_eq!(min, 2); assert_eq!(min, 2);
assert_eq!(max, 3); assert_eq!(max, 3);
@ -391,11 +416,17 @@ a return code:
{ {
ArgumentCountMismatch { ArgumentCountMismatch {
recipe, recipe,
parameters,
found, found,
min, min,
max, max,
} => { } => {
let param_names = parameters
.iter()
.map(|p| p.name)
.collect::<Vec<&str>>();
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(param_names, ["b", "c", "d"]);
assert_eq!(found, 0); assert_eq!(found, 0);
assert_eq!(min, 1); assert_eq!(min, 1);
assert_eq!(max, 3); assert_eq!(max, 3);

View File

@ -23,7 +23,7 @@ fn write_token_error_context(f: &mut fmt::Formatter, token: &Token) -> Result<()
#[derive(Debug)] #[derive(Debug)]
pub enum RuntimeError<'a> { pub enum RuntimeError<'a> {
ArgumentCountMismatch{recipe: &'a str, found: usize, min: usize, max: usize}, ArgumentCountMismatch{recipe: &'a str, parameters: Vec<&'a Parameter<'a>>, found: usize, min: usize, max: usize},
Backtick{token: Token<'a>, output_error: OutputError}, Backtick{token: Token<'a>, output_error: OutputError},
Code{recipe: &'a str, line_number: Option<usize>, code: i32}, Code{recipe: &'a str, line_number: Option<usize>, code: i32},
Cygpath{recipe: &'a str, output_error: OutputError}, Cygpath{recipe: &'a str, output_error: OutputError},
@ -71,7 +71,7 @@ impl<'a> Display for RuntimeError<'a> {
maybe_s(overrides.len()), maybe_s(overrides.len()),
And(&overrides.iter().map(Tick).collect::<Vec<_>>()))?; And(&overrides.iter().map(Tick).collect::<Vec<_>>()))?;
}, },
ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, ref parameters, found, min, max} => {
if min == max { if min == max {
let expected = min; let expected = min;
write!(f, "Recipe `{}` got {} argument{} but {}takes {}", write!(f, "Recipe `{}` got {} argument{} but {}takes {}",
@ -84,6 +84,14 @@ impl<'a> Display for RuntimeError<'a> {
write!(f, "Recipe `{}` got {} argument{} but takes at most {}", write!(f, "Recipe `{}` got {} argument{} but takes at most {}",
recipe, found, maybe_s(found), max)?; recipe, found, maybe_s(found), max)?;
} }
write!(f, "\nusage:\n just {}", recipe)?;
for param in parameters {
if color.stderr().active() {
write!(f, " {:#}", param)?;
} else {
write!(f, " {}", param)?;
}
}
}, },
Code{recipe, line_number, code} => { Code{recipe, line_number, code} => {
if let Some(n) = line_number { if let Some(n) = line_number {

View File

@ -779,7 +779,7 @@ foo A B:
", ",
args: ("foo", "ONE"), args: ("foo", "ONE"),
stdout: "", stdout: "",
stderr: "error: Recipe `foo` got 1 argument but takes 2\n", stderr: "error: Recipe `foo` got 1 argument but takes 2\nusage:\n just foo A B\n",
status: EXIT_FAILURE, status: EXIT_FAILURE,
} }
@ -803,7 +803,7 @@ foo A B C='C':
", ",
args: ("foo", "bar"), args: ("foo", "bar"),
stdout: "", stdout: "",
stderr: "error: Recipe `foo` got 1 argument but takes at least 2\n", stderr: "error: Recipe `foo` got 1 argument but takes at least 2\nusage:\n just foo A B C='C'\n",
status: EXIT_FAILURE, status: EXIT_FAILURE,
} }
@ -1670,7 +1670,7 @@ a x y +z:
", ",
args: ("a", "0", "1"), args: ("a", "0", "1"),
stdout: "", stdout: "",
stderr: "error: Recipe `a` got 2 arguments but takes at least 3\n", stderr: "error: Recipe `a` got 2 arguments but takes at least 3\nusage:\n just a x y +z\n",
status: EXIT_FAILURE, status: EXIT_FAILURE,
} }