errors: DiagnosticMessage::Eager
Add variant of `DiagnosticMessage` for eagerly translated messages (messages in the target language which don't need translated by the emitter during emission). Also adds `eager_subdiagnostic` function which is intended to be invoked by the diagnostic derive for subdiagnostic fields which are marked as needing eager translation. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
b4ac26289f
commit
540b203bf9
@ -276,6 +276,18 @@ pub enum SubdiagnosticMessage {
|
|||||||
/// Non-translatable diagnostic message.
|
/// Non-translatable diagnostic message.
|
||||||
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
|
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
|
||||||
Str(String),
|
Str(String),
|
||||||
|
/// Translatable message which has already been translated eagerly.
|
||||||
|
///
|
||||||
|
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
||||||
|
/// be instantiated multiple times with different values. As translation normally happens
|
||||||
|
/// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
|
||||||
|
/// the setting of diagnostic arguments in the derived code will overwrite previous variable
|
||||||
|
/// values and only the final value will be set when translation occurs - resulting in
|
||||||
|
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
|
||||||
|
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
||||||
|
/// stores messages which have been translated eagerly.
|
||||||
|
// FIXME(#100717): can a `Cow<'static, str>` be used here?
|
||||||
|
Eager(String),
|
||||||
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
||||||
/// `Subdiagnostic` derive.
|
/// `Subdiagnostic` derive.
|
||||||
FluentIdentifier(FluentId),
|
FluentIdentifier(FluentId),
|
||||||
@ -303,8 +315,20 @@ impl<S: Into<String>> From<S> for SubdiagnosticMessage {
|
|||||||
#[rustc_diagnostic_item = "DiagnosticMessage"]
|
#[rustc_diagnostic_item = "DiagnosticMessage"]
|
||||||
pub enum DiagnosticMessage {
|
pub enum DiagnosticMessage {
|
||||||
/// Non-translatable diagnostic message.
|
/// Non-translatable diagnostic message.
|
||||||
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
|
// FIXME(#100717): can a `Cow<'static, str>` be used here?
|
||||||
Str(String),
|
Str(String),
|
||||||
|
/// Translatable message which has already been translated eagerly.
|
||||||
|
///
|
||||||
|
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
||||||
|
/// be instantiated multiple times with different values. As translation normally happens
|
||||||
|
/// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
|
||||||
|
/// the setting of diagnostic arguments in the derived code will overwrite previous variable
|
||||||
|
/// values and only the final value will be set when translation occurs - resulting in
|
||||||
|
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
|
||||||
|
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
||||||
|
/// stores messages which have been translated eagerly.
|
||||||
|
// FIXME(#100717): can a `Cow<'static, str>` be used here?
|
||||||
|
Eager(String),
|
||||||
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
|
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
|
||||||
/// message.
|
/// message.
|
||||||
///
|
///
|
||||||
@ -323,6 +347,7 @@ impl DiagnosticMessage {
|
|||||||
pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
|
pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
|
||||||
let attr = match sub {
|
let attr = match sub {
|
||||||
SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
|
SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
|
||||||
|
SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s),
|
||||||
SubdiagnosticMessage::FluentIdentifier(id) => {
|
SubdiagnosticMessage::FluentIdentifier(id) => {
|
||||||
return DiagnosticMessage::FluentIdentifier(id, None);
|
return DiagnosticMessage::FluentIdentifier(id, None);
|
||||||
}
|
}
|
||||||
@ -331,6 +356,7 @@ impl DiagnosticMessage {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
|
DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
|
||||||
|
DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()),
|
||||||
DiagnosticMessage::FluentIdentifier(id, _) => {
|
DiagnosticMessage::FluentIdentifier(id, _) => {
|
||||||
DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
|
DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
|
||||||
}
|
}
|
||||||
@ -379,6 +405,7 @@ impl Into<SubdiagnosticMessage> for DiagnosticMessage {
|
|||||||
fn into(self) -> SubdiagnosticMessage {
|
fn into(self) -> SubdiagnosticMessage {
|
||||||
match self {
|
match self {
|
||||||
DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
|
DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
|
||||||
|
DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s),
|
||||||
DiagnosticMessage::FluentIdentifier(id, None) => {
|
DiagnosticMessage::FluentIdentifier(id, None) => {
|
||||||
SubdiagnosticMessage::FluentIdentifier(id)
|
SubdiagnosticMessage::FluentIdentifier(id)
|
||||||
}
|
}
|
||||||
|
@ -939,6 +939,23 @@ impl Diagnostic {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
|
||||||
|
/// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
|
||||||
|
/// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
|
||||||
|
/// interpolated variables).
|
||||||
|
pub fn eager_subdiagnostic(
|
||||||
|
&mut self,
|
||||||
|
handler: &crate::Handler,
|
||||||
|
subdiagnostic: impl AddToDiagnostic,
|
||||||
|
) -> &mut Self {
|
||||||
|
subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
|
||||||
|
let args = diag.args();
|
||||||
|
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
||||||
|
handler.eagerly_translate(msg, args)
|
||||||
|
});
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
|
pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
|
||||||
self.span = sp.into();
|
self.span = sp.into();
|
||||||
if let Some(span) = self.span.primary_span() {
|
if let Some(span) = self.span.primary_span() {
|
||||||
@ -994,7 +1011,7 @@ impl Diagnostic {
|
|||||||
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
|
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
|
||||||
/// combining it with the primary message of the diagnostic (if translatable, otherwise it just
|
/// combining it with the primary message of the diagnostic (if translatable, otherwise it just
|
||||||
/// passes the user's string along).
|
/// passes the user's string along).
|
||||||
fn subdiagnostic_message_to_diagnostic_message(
|
pub(crate) fn subdiagnostic_message_to_diagnostic_message(
|
||||||
&self,
|
&self,
|
||||||
attr: impl Into<SubdiagnosticMessage>,
|
attr: impl Into<SubdiagnosticMessage>,
|
||||||
) -> DiagnosticMessage {
|
) -> DiagnosticMessage {
|
||||||
|
@ -598,6 +598,17 @@ impl Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Translate `message` eagerly with `args`.
|
||||||
|
pub fn eagerly_translate<'a>(
|
||||||
|
&self,
|
||||||
|
message: DiagnosticMessage,
|
||||||
|
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
|
||||||
|
) -> SubdiagnosticMessage {
|
||||||
|
let inner = self.inner.borrow();
|
||||||
|
let args = crate::translation::to_fluent_args(args);
|
||||||
|
SubdiagnosticMessage::Eager(inner.emitter.translate_message(&message, &args).to_string())
|
||||||
|
}
|
||||||
|
|
||||||
// This is here to not allow mutation of flags;
|
// This is here to not allow mutation of flags;
|
||||||
// as of this writing it's only used in tests in librustc_middle.
|
// as of this writing it's only used in tests in librustc_middle.
|
||||||
pub fn can_emit_warnings(&self) -> bool {
|
pub fn can_emit_warnings(&self) -> bool {
|
||||||
|
@ -55,7 +55,9 @@ pub trait Translate {
|
|||||||
) -> Cow<'_, str> {
|
) -> Cow<'_, str> {
|
||||||
trace!(?message, ?args);
|
trace!(?message, ?args);
|
||||||
let (identifier, attr) = match message {
|
let (identifier, attr) = match message {
|
||||||
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => {
|
||||||
|
return Cow::Borrowed(&msg);
|
||||||
|
}
|
||||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user