Improve error message if if is missing the else (#1252)

This commit is contained in:
Nick Kocharhook 2022-06-30 11:34:11 +01:00 committed by GitHub
parent 0b750b6cd7
commit e1f729efbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 16 deletions

View File

@ -117,12 +117,23 @@ impl Display for CompileError<'_> {
DuplicateVariable { variable } => {
write!(f, "Variable `{}` has multiple definitions", variable)?;
}
ExpectedKeyword { expected, found } => write!(
ExpectedKeyword { expected, found } => {
if found.kind == TokenKind::Identifier {
write!(
f,
"Expected keyword {} but found identifier `{}`",
List::or_ticked(expected),
found
)?,
found.lexeme()
)?;
} else {
write!(
f,
"Expected keyword {} but found `{}`",
List::or_ticked(expected),
found.kind
)?;
}
}
ExtraLeadingWhitespace => {
write!(f, "Recipe line has extra leading whitespace")?;
}

View File

@ -42,7 +42,7 @@ pub(crate) enum CompileErrorKind<'src> {
},
ExpectedKeyword {
expected: Vec<Keyword>,
found: &'src str,
found: Token<'src>,
},
ExtraLeadingWhitespace,
FunctionArgumentCountMismatch {

View File

@ -33,7 +33,7 @@ pub(crate) struct Parser<'tokens, 'src> {
/// Current expected tokens
expected: BTreeSet<TokenKind>,
/// Current recursion depth
depth: u8,
depth: usize,
}
impl<'tokens, 'src> Parser<'tokens, 'src> {
@ -157,13 +157,12 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
}
fn expect_keyword(&mut self, expected: Keyword) -> CompileResult<'src, ()> {
let identifier = self.expect(Identifier)?;
let found = identifier.lexeme();
let found = self.advance()?;
if expected == found {
if found.kind == Identifier && expected == found.lexeme() {
Ok(())
} else {
Err(identifier.error(CompileErrorKind::ExpectedKeyword {
Err(found.error(CompileErrorKind::ExpectedKeyword {
expected: vec![expected],
found,
}))
@ -394,7 +393,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
/// Parse an expression, e.g. `1 + 2`
fn parse_expression(&mut self) -> CompileResult<'src, Expression<'src>> {
if self.depth == if cfg!(windows) { 64 } else { 255 } {
if self.depth == if cfg!(windows) { 48 } else { 256 } {
return Err(CompileError {
token: self.next()?,
kind: CompileErrorKind::ParsingRecursionDepthExceeded,
@ -422,6 +421,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
};
self.depth -= 1;
Ok(expression)
}
@ -735,7 +735,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
} else {
return Err(identifier.error(CompileErrorKind::ExpectedKeyword {
expected: vec![Keyword::True, Keyword::False],
found: identifier.lexeme(),
found: identifier,
}));
};

31
tests/assignment.rs Normal file
View File

@ -0,0 +1,31 @@
use super::*;
test! {
name: set_export_parse_error,
justfile: "
set export := fals
",
stdout: "",
stderr: "
error: Expected keyword `true` or `false` but found identifier `fals`
|
1 | set export := fals
| ^^^^
",
status: EXIT_FAILURE,
}
test! {
name: set_export_parse_error_EOL,
justfile: "
set export := fals
",
stdout: "",
stderr: "
error: Expected keyword `true` or `false` but found `end of line`
|
1 | set export :=
| ^
",
status: EXIT_FAILURE,
}

View File

@ -168,3 +168,33 @@ test! {
stdout: "b\n",
stderr: "echo b\n",
}
test! {
name: missing_else,
justfile: "
TEST := if path_exists('/bin/bash') == 'true' {'yes'}
",
stdout: "",
stderr: "
error: Expected keyword `else` but found `end of line`
|
1 | TEST := if path_exists('/bin/bash') == 'true' {'yes'}
| ^
",
status: EXIT_FAILURE,
}
test! {
name: incorrect_else_identifier,
justfile: "
TEST := if path_exists('/bin/bash') == 'true' {'yes'} els {'no'}
",
stdout: "",
stderr: "
error: Expected keyword `else` but found identifier `els`
|
1 | TEST := if path_exists('/bin/bash') == 'true' {'yes'} els {'no'}
| ^^^
",
status: EXIT_FAILURE,
}