Improve a few error messages (#47)

Surround variables with backticks, capitalize first letter of error
message, inflect properly depending on number of unknown overrides, and
improve wording.

Also added build dependency to `filter` recipe.
This commit is contained in:
Casey Rodarmor 2016-11-11 14:33:17 -08:00 committed by GitHub
parent e3aa13e5dd
commit 2bc55ba815
3 changed files with 96 additions and 13 deletions

View File

@ -2,7 +2,7 @@ test: build
cargo test --lib cargo test --lib
# only run tests matching PATTERN # only run tests matching PATTERN
filter PATTERN: filter PATTERN: build
cargo test --lib {{PATTERN}} cargo test --lib {{PATTERN}}
test-quine: test-quine:

View File

@ -434,7 +434,7 @@ fn unknown_override_options() {
a = `exit 222`", a = `exit 222`",
255, 255,
"", "",
"baz and foo set on the command line but not present in justfile\n", "Variables `baz` and `foo` overridden on the command line but not present in justfile\n",
); );
} }
@ -448,7 +448,21 @@ fn unknown_override_args() {
a = `exit 222`", a = `exit 222`",
255, 255,
"", "",
"baz and foo set on the command line but not present in justfile\n", "Variables `baz` and `foo` overridden on the command line but not present in justfile\n",
);
}
#[test]
fn unknown_override_arg() {
integration_test(
&["foo=bar", "a=b", "a", "b"],
"foo:
echo hello
echo {{`exit 111`}}
a = `exit 222`",
255,
"",
"Variable `foo` overridden on the command line but not present in justfile\n",
); );
} }
@ -746,3 +760,53 @@ foo A B:
"echo A:ONE B:TWO\n", "echo A:ONE B:TWO\n",
); );
} }
#[test]
fn argument_mismatch_more() {
integration_test(
&["foo", "ONE", "TWO", "THREE"],
"
foo A B:
echo A:{{A}} B:{{B}}
",
255,
"",
"Recipe `foo` got 3 arguments but only takes 2\n"
);
}
#[test]
fn argument_mismatch_fewer() {
integration_test(
&["foo", "ONE"],
"
foo A B:
echo A:{{A}} B:{{B}}
",
255,
"",
"Recipe `foo` got 1 argument but takes 2\n"
);
}
#[test]
fn unknown_recipe() {
integration_test(
&["foo"],
"hello:",
255,
"",
"Justfile does not contain recipe `foo`\n",
);
}
#[test]
fn unknown_recipes() {
integration_test(
&["foo", "bar"],
"hello:",
255,
"",
"Justfile does not contain recipes `foo` or `bar`\n",
);
}

View File

@ -708,6 +708,26 @@ fn mixed_whitespace(text: &str) -> bool {
!(text.chars().all(|c| c == ' ') || text.chars().all(|c| c == '\t')) !(text.chars().all(|c| c == ' ') || text.chars().all(|c| c == '\t'))
} }
fn maybe_s(n: usize) -> &'static str {
if n == 1 {
""
} else {
"s"
}
}
struct Tick<'a, T: 'a + Display>(&'a T);
impl<'a, T: Display> Display for Tick<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "`{}`", self.0)
}
}
fn ticks<'a, T: 'a + Display>(ts: &'a [T]) -> Vec<Tick<'a, T>> {
ts.iter().map(Tick).collect()
}
struct And<'a, T: 'a + Display>(&'a [T]); struct And<'a, T: 'a + Display>(&'a [T]);
struct Or <'a, T: 'a + Display>(&'a [T]); struct Or <'a, T: 'a + Display>(&'a [T]);
@ -1008,23 +1028,22 @@ impl<'a> Display for RunError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self { match *self {
RunError::UnknownRecipes{ref recipes} => { RunError::UnknownRecipes{ref recipes} => {
if recipes.len() == 1 { try!(write!(f, "Justfile does not contain recipe{} {}",
try!(write!(f, "Justfile does not contain recipe `{}`", recipes[0])); maybe_s(recipes.len()), Or(&ticks(&recipes))));
} else {
try!(write!(f, "Justfile does not contain recipes: {}", recipes.join(" ")));
};
}, },
RunError::UnknownOverrides{ref overrides} => { RunError::UnknownOverrides{ref overrides} => {
try!(write!(f, "{} set on the command line but not present in justfile", try!(write!(f,
And(overrides))) "Variable{} {} overridden on the command line but not present in justfile",
maybe_s(overrides.len()),
And(&overrides.iter().map(Tick).collect::<Vec<_>>())))
}, },
RunError::NonLeadingRecipeWithParameters{recipe} => { RunError::NonLeadingRecipeWithParameters{recipe} => {
try!(write!(f, "Recipe `{}` takes arguments and so must be the first and only recipe specified on the command line", recipe)); try!(write!(f, "Recipe `{}` takes arguments and so must be the first and only recipe specified on the command line", recipe));
}, },
RunError::ArgumentCountMismatch{recipe, found, expected} => { RunError::ArgumentCountMismatch{recipe, found, expected} => {
try!(write!(f, "Recipe `{}` takes {} argument{}, but {}{} were found", try!(write!(f, "Recipe `{}` got {} argument{} but {}takes {}",
recipe, expected, if expected == 1 { "" } else { "s" }, recipe, found, maybe_s(found),
if found < expected { "only " } else { "" }, found)); if expected < found { "only " } else { "" }, expected));
}, },
RunError::Code{recipe, code} => { RunError::Code{recipe, code} => {
try!(write!(f, "Recipe \"{}\" failed with exit code {}", recipe, code)); try!(write!(f, "Recipe \"{}\" failed with exit code {}", recipe, code));