From ba10f2c0f2548bafa2bbdca346921c6719f2e6ea Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 4 Sep 2022 20:12:00 +0200 Subject: [PATCH] Migrate "expected semicolon" diagnostics to diagnostic structs --- .../locales/en-US/parser.ftl | 10 ++++ compiler/rustc_parse/src/errors.rs | 51 +++++++++++++++++++ .../rustc_parse/src/parser/diagnostics.rs | 37 ++++++++------ 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 61450e288b4..22fb65f0268 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -306,3 +306,13 @@ parser_expected_identifier = expected identifier 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 diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 3b86dd15747..07785b7344f 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -963,3 +963,54 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { diag } } + +pub(crate) struct ExpectedSemi { + pub span: Span, + pub token_descr: TokenDescription, + + pub unexpected_token_label: Option, + 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), +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 8c2a925a231..ba48e4e1c25 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -4,9 +4,9 @@ use super::{ 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; @@ -388,8 +388,8 @@ impl<'a> Parser<'a> { 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. @@ -417,11 +417,13 @@ impl<'a> Parser<'a> { // // 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) @@ -439,11 +441,13 @@ impl<'a> Parser<'a> { // // 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); } } @@ -480,6 +484,7 @@ impl<'a> Parser<'a> { ) }; 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 { @@ -488,7 +493,7 @@ impl<'a> Parser<'a> { self.prev_token.span, &format!("write `fn` instead of `{symbol}` to declare a function"), "fn", - appl, + Applicability::MachineApplicable, ); } } @@ -502,7 +507,7 @@ impl<'a> Parser<'a> { self.prev_token.span, "write `pub` instead of `public` to make the item public", "pub", - appl, + Applicability::MachineApplicable, ); }