From db6553b946924949f8448178ccebf0c4941cf646 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 20 Nov 2023 02:01:56 +0800 Subject: [PATCH] add FluentRaw to represent fluent raw content --- compiler/rustc_error_messages/src/lib.rs | 18 +++++++++- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_errors/src/translation.rs | 28 ++++++++------- .../src/diagnostics/diagnostic.rs | 2 +- .../src/diagnostics/diagnostic_builder.rs | 10 +++--- .../src/diagnostics/subdiagnostic.rs | 2 +- compiler/rustc_parse/src/errors.rs | 35 +++++++++++-------- compiler/rustc_parse/src/parser/attr.rs | 12 +++++-- compiler/rustc_parse/src/parser/expr.rs | 2 ++ 9 files changed, 73 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 35bd45e64a269..1d57dcb39b988 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -266,6 +266,8 @@ type FluentId = Cow<'static, str>; pub enum SubdiagnosticMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), + /// Translatable diagnostic message in Fluent raw format. + FluentRaw(Cow<'static, str>), /// Translatable message which has already been translated eagerly. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would @@ -313,6 +315,8 @@ impl From> for SubdiagnosticMessage { pub enum DiagnosticMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), + /// Translatable diagnostic message in Fluent raw format. + FluentRaw(Cow<'static, str>), /// Translatable message which has already been translated eagerly. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would @@ -342,6 +346,7 @@ impl DiagnosticMessage { pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { let attr = match sub { SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s), + SubdiagnosticMessage::FluentRaw(s) => return DiagnosticMessage::FluentRaw(s), SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s), SubdiagnosticMessage::FluentIdentifier(id) => { return DiagnosticMessage::FluentIdentifier(id, None); @@ -351,6 +356,7 @@ impl DiagnosticMessage { match self { DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), + DiagnosticMessage::FluentRaw(s) => DiagnosticMessage::FluentRaw(s.clone()), DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()), DiagnosticMessage::FluentIdentifier(id, _) => { DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) @@ -360,7 +366,9 @@ impl DiagnosticMessage { pub fn as_str(&self) -> Option<&str> { match self { - DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s), + DiagnosticMessage::Eager(s) + | DiagnosticMessage::Str(s) + | DiagnosticMessage::FluentRaw(s) => Some(s), DiagnosticMessage::FluentIdentifier(_, _) => None, } } @@ -382,6 +390,13 @@ impl From> for DiagnosticMessage { } } +#[macro_export] +macro_rules! fluent_raw { + ($str:expr) => { + DiagnosticMessage::FluentRaw(Cow::Borrowed($str)) + }; +} + /// A workaround for "good path" ICEs when formatting types in disabled lints. /// /// Delays formatting until `.into(): DiagnosticMessage` is used. @@ -402,6 +417,7 @@ impl Into for DiagnosticMessage { fn into(self) -> SubdiagnosticMessage { match self { DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), + DiagnosticMessage::FluentRaw(s) => SubdiagnosticMessage::FluentRaw(s), DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s), DiagnosticMessage::FluentIdentifier(id, None) => { SubdiagnosticMessage::FluentIdentifier(id) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 1cee57843f073..c16727d7761f1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -38,7 +38,7 @@ use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::AtomicRef; pub use rustc_error_messages::{ - fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, + fallback_fluent_bundle, fluent_bundle, fluent_raw, DelayDm, DiagnosticMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, }; use rustc_fluent_macro::fluent_messages; diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index e3091ea07b8a4..4542b49fa6a83 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -65,21 +65,23 @@ pub trait Translate { trace!(?message, ?args); let (identifier, attr) = match message { DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => { + return Ok(Cow::Borrowed(msg)); + } + DiagnosticMessage::FluentRaw(msg) => { // FIXME(yukang): A hack for raw fluent content for new diagnostics proc format - let trimed = msg.replace(" ", ""); - if trimed.contains("$") || trimed.contains("{\"") || trimed.contains("\"}") { - let fluent_text = format!("dummy = {}", msg); - if let Ok(resource) = FluentResource::try_new(fluent_text) { - let mut bundle = RawFluentBundle::new(vec![langid!("en-US")]); - bundle.add_resource(resource).unwrap(); - let mut errors = vec![]; - let pattern = bundle.get_message("dummy").unwrap().value().unwrap(); - let res = bundle.format_pattern(&pattern, Some(args), &mut errors); - return Ok(Cow::Owned( - res.to_string().replace("\u{2068}", "").replace("\u{2069}", ""), - )); - } + let fluent_text = format!("dummy = {}", msg); + if let Ok(resource) = FluentResource::try_new(fluent_text) { + let mut bundle = RawFluentBundle::new(vec![langid!("en-US")]); + bundle.add_resource(resource).unwrap(); + let mut errors = vec![]; + let pattern = bundle.get_message("dummy").unwrap().value().unwrap(); + let res = bundle.format_pattern(&pattern, Some(args), &mut errors); + return Ok(Cow::Owned( + res.to_string().replace("\u{2068}", "").replace("\u{2069}", ""), + )); } + + // If the message is not a valid Fluent resource, just return the original return Ok(Cow::Borrowed(msg)); } DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 0e9a694639629..2e5a1946f71a4 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -69,7 +69,7 @@ impl<'a> DiagnosticDerive<'a> { } (None, Some(raw_label)) => { quote! { - let mut #diag = #handler.struct_diagnostic(DiagnosticMessage::Str(#raw_label.into())); + let mut #diag = #handler.struct_diagnostic(DiagnosticMessage::FluentRaw(#raw_label.into())); } } (Some(_slug), Some(_raw_label)) => { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index c1f6dbe8f2950..ea5267d42ee9f 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -509,7 +509,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let suggestion_label = if let Some(raw_label) = raw_label { quote! { - #raw_label + DiagnosticMessage::FluentRaw(Cow::Borrowed(#raw_label)) } } else { quote! { @@ -547,7 +547,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return quote! { #diag.#fn_name( #field_binding, - #raw_label + DiagnosticMessage::FluentRaw(Cow::Borrowed(#raw_label)) ); }; } @@ -555,7 +555,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { quote! { #diag.#fn_name( #field_binding, - #raw_label + DiagnosticMessage::FluentRaw(Cow::Borrowed(#raw_label)) ); } } else { @@ -579,12 +579,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let diag = &self.parent.diag; if let Some(raw_label) = raw_label { return quote! { - #diag.#kind(#raw_label); + #diag.#kind(DiagnosticMessage::FluentRaw(Cow::Borrowed(#raw_label))); }; } if let Some(raw_label) = self.get_attr(kind.to_string().as_str()) { quote! { - #diag.#kind(#raw_label); + #diag.#kind(DiagnosticMessage::FluentRaw(Cow::Borrowed(#raw_label))); } } else { quote! { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 7be3a3c03cdec..41f3285ae5783 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -527,7 +527,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); }, ); } else { - calls.extend(quote! { let #message = #f(#diag, #raw_label.into()); }); + calls.extend(quote! { let #message = #f(#diag, DiagnosticMessage::FluentRaw(Cow::Borrowed(#raw_label)).into()); }); } let name = format_ident!( diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index da1921b26bfb1..fa0d1ac98aa1a 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,9 +1,10 @@ // ignore-tidy-filelength use std::borrow::Cow; +use crate::parser::{ForbiddenLetReason, TokenDescription}; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; -use rustc_errors::DiagnosticMessage; +use rustc_errors::{fluent_raw, DiagnosticMessage}; use rustc_errors::{AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -11,8 +12,6 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; -use crate::parser::{ForbiddenLetReason, TokenDescription}; - #[derive(Diagnostic)] #[diag("ambiguous `+` in a type")] pub(crate) struct AmbiguousPlus { @@ -1205,18 +1204,22 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { let mut diag = handler.struct_diagnostic(match token_descr { Some(TokenDescription::ReservedIdentifier) => { - "expected identifier, found reserved identifier `{$token}`" + fluent_raw!("expected identifier, found reserved identifier `{$token}`") } - Some(TokenDescription::Keyword) => "expected identifier, found keyword `{$token}`", + Some(TokenDescription::Keyword) => { + fluent_raw!("expected identifier, found keyword `{$token}`") + } + Some(TokenDescription::ReservedKeyword) => { - "expected identifier, found reserved keyword `{$token}`" + fluent_raw!("expected identifier, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - "expected identifier, found doc comment `{$token}`" + fluent_raw!("expected identifier, found doc comment `{$token}`") + } + None => { + fluent_raw!("expected identifier, found `{$token}`") } - - None => "expected identifier, found `{$token}`", }); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1264,14 +1267,18 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi { let mut diag = handler.struct_diagnostic(match token_descr { Some(TokenDescription::ReservedIdentifier) => { - "expected `;`, found reserved identifier `{$token}`" + fluent_raw!("expected `;`, found reserved identifier `{$token}`") + } + Some(TokenDescription::Keyword) => { + fluent_raw!("expected `;`, found keyword `{$token}`") } - Some(TokenDescription::Keyword) => "expected `;`, found keyword `{$token}`", Some(TokenDescription::ReservedKeyword) => { - "expected `;`, found reserved keyword `{$token}`" + fluent_raw!("expected `;`, found reserved keyword `{$token}`") + } + Some(TokenDescription::DocComment) => { + fluent_raw!("expected `;`, found doc comment `{$token}`") } - Some(TokenDescription::DocComment) => "expected `;`, found doc comment `{$token}`", - None => "expected `;`, found `{$token}`", + None => fluent_raw!("expected `;`, found `{$token}`"), }); diag.set_span(self.span); diag.set_arg("token", self.token); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index c7b2d1c55f492..28c453776844c 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -3,8 +3,11 @@ use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; +use rustc_errors::fluent_raw; +use rustc_errors::DiagnosticMessage; use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; +use std::borrow::Cow; use std::convert::TryInto; use thin_vec::ThinVec; use tracing::debug; @@ -175,10 +178,15 @@ impl<'a> Parser<'a> { Ok(Some(item)) => { // FIXME(#100717) err.set_arg("item", item.kind.descr()); - err.span_label(item.span, "the inner {$item_type} doesn't annotate this {$item}"); + err.span_label( + item.span, + fluent_raw!("the inner {$item_type} doesn't annotate this {$item}"), + ); err.span_suggestion_verbose( replacement_span, - "to annotate the {$item}, change the {$item_type} from inner to outer style", + fluent_raw!( + "to annotate the {$item}, change the {$item_type} from inner to outer style" + ), match attr_type { OuterAttributeType::Attribute => "", OuterAttributeType::DocBlockComment => "*", diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 585864d1fa709..2eb7a5fbe47cc 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -24,6 +24,7 @@ use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, R use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::DiagnosticMessage; use rustc_errors::{ AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult, StashKey, @@ -36,6 +37,7 @@ use rustc_span::source_map::{self, Spanned}; use rustc_span::symbol::kw::PathRoot; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos, Span}; +use std::borrow::Cow; use thin_vec::{thin_vec, ThinVec}; /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression