parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an identifier
parser_sugg_remove_comma = remove this comma
+
+parser_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token_str}`
+parser_expected_semi_found_keyword_str = expected `;`, found keyword `{$token_str}`
+parser_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token_str}`
+parser_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token_str}`
+parser_expected_semi_found_str = expected `;`, found `{$token_str}`
+
+parser_sugg_change_this_to_semi = change this to `;`
+parser_sugg_add_semi = add `;` here
+parser_label_unexpected_token = unexpected token
diag
}
}
+
+pub(crate) struct ExpectedSemi {
+ pub span: Span,
+ pub token_descr: TokenDescription,
+
+ pub unexpected_token_label: Option<Span>,
+ pub sugg: ExpectedSemiSugg,
+}
+
+impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, G> {
+ let mut diag = handler.struct_diagnostic(match self.token_descr.kind {
+ Some(TokenDescriptionKind::ReservedIdentifier) => {
+ fluent::parser::expected_semi_found_reserved_identifier_str
+ }
+ Some(TokenDescriptionKind::Keyword) => fluent::parser::expected_semi_found_keyword_str,
+ Some(TokenDescriptionKind::ReservedKeyword) => {
+ fluent::parser::expected_semi_found_reserved_keyword_str
+ }
+ Some(TokenDescriptionKind::DocComment) => {
+ fluent::parser::expected_semi_found_doc_comment_str
+ }
+ None => fluent::parser::expected_semi_found_str,
+ });
+ diag.set_span(self.span);
+ diag.set_arg("token_str", self.token_descr.name);
+
+ if let Some(unexpected_token_label) = self.unexpected_token_label {
+ diag.span_label(unexpected_token_label, fluent::parser::label_unexpected_token);
+ }
+
+ self.sugg.add_to_diagnostic(&mut diag);
+
+ diag
+ }
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ExpectedSemiSugg {
+ #[suggestion(
+ parser::sugg_change_this_to_semi,
+ code = ";",
+ applicability = "machine-applicable"
+ )]
+ ChangeToSemi(#[primary_span] Span),
+ #[suggestion_short(parser::sugg_add_semi, code = ";", applicability = "machine-applicable")]
+ AddSemi(#[primary_span] Span),
+}
TokenExpectType, TokenType,
};
use crate::errors::{
- AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, InInTypo,
- IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, SuggEscapeToUseAsIdentifier,
- SuggRemoveComma, UseEqInstead,
+ AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, ExpectedSemi,
+ ExpectedSemiSugg, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait,
+ SuggEscapeToUseAsIdentifier, SuggRemoveComma, UseEqInstead,
};
use crate::lexer::UnmatchedBrace;
expected.dedup();
let sm = self.sess.source_map();
- let msg = format!("expected `;`, found {}", super::token_descr(&self.token));
- let appl = Applicability::MachineApplicable;
+
+ // Special-case "expected `;`" errors
if expected.contains(&TokenType::Token(token::Semi)) {
if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
// Likely inside a macro, can't provide meaningful suggestions.
//
// let x = 32:
// let y = 42;
+ self.sess.emit_err(ExpectedSemi {
+ span: self.token.span,
+ token_descr: super::token_descr_struct(&self.token),
+ unexpected_token_label: None,
+ sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
+ });
self.bump();
- let sp = self.prev_token.span;
- self.struct_span_err(sp, &msg)
- .span_suggestion_short(sp, "change this to `;`", ";", appl)
- .emit();
return Ok(true);
} else if self.look_ahead(0, |t| {
t == &token::CloseDelim(Delimiter::Brace)
//
// let x = 32
// let y = 42;
- let sp = self.prev_token.span.shrink_to_hi();
- self.struct_span_err(sp, &msg)
- .span_label(self.token.span, "unexpected token")
- .span_suggestion_short(sp, "add `;` here", ";", appl)
- .emit();
+ let span = self.prev_token.span.shrink_to_hi();
+ self.sess.emit_err(ExpectedSemi {
+ span,
+ token_descr: super::token_descr_struct(&self.token),
+ unexpected_token_label: Some(self.token.span),
+ sugg: ExpectedSemiSugg::AddSemi(span),
+ });
return Ok(true);
}
}
)
};
self.last_unexpected_token_span = Some(self.token.span);
+ // FIXME: translation requires list formatting (for `expect`)
let mut err = self.struct_span_err(self.token.span, &msg_exp);
if let TokenKind::Ident(symbol, _) = &self.prev_token.kind {
self.prev_token.span,
&format!("write `fn` instead of `{symbol}` to declare a function"),
"fn",
- appl,
+ Applicability::MachineApplicable,
);
}
}
self.prev_token.span,
"write `pub` instead of `public` to make the item public",
"pub",
- appl,
+ Applicability::MachineApplicable,
);
}