Improve recovery on malformed format call

If a comma in a format call is replaced with a similar token, then we
emit an error and continue parsing, instead of stopping at this point.
This commit is contained in:
Sasha 2020-08-31 11:45:50 +02:00
parent 8ed5cb56b5
commit 3524c3ef43
13 changed files with 88 additions and 53 deletions

View file

@ -161,14 +161,26 @@ fn parse_args<'a>(
while p.token != token::Eof {
if !p.eat(&token::Comma) {
if first {
// After `format!(""` we always expect *only* a comma...
let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`");
err.span_label(p.token.span, "expected `,`");
p.maybe_annotate_with_ascription(&mut err, false);
return Err(err);
} else {
// ...after that delegate to `expect` to also include the other expected tokens.
let _ = p.expect(&token::Comma)?;
p.clear_expected_tokens();
}
// `Parser::expect` tries to recover using the
// `Parser::unexpected_try_recover` function. This function is able
// to recover if the expected token is a closing delimiter.
//
// As `,` is not a closing delimiter, it will always return an `Err`
// variant.
let mut err = p.expect(&token::Comma).unwrap_err();
match token::TokenKind::Comma.similar_tokens() {
Some(tks) if tks.contains(&p.token.kind) => {
// If a similar token is found, then it may be a typo. We
// consider it as a comma, and continue parsing.
err.emit();
p.bump();
}
// Otherwise stop the parsing and return the error.
_ => return Err(err),
}
}
first = false;