@@ -14,10 +14,10 @@ use rustc_span::{FileLines, SourceFile, Span};
14
14
15
15
use crate :: snippet:: { Annotation , AnnotationType , Line , MultilineAnnotation , Style , StyledString } ;
16
16
use crate :: styled_buffer:: StyledBuffer ;
17
+ use crate :: translation:: Translate ;
17
18
use crate :: {
18
- CodeSuggestion , Diagnostic , DiagnosticArg , DiagnosticId , DiagnosticMessage , FluentBundle ,
19
- Handler , LazyFallbackBundle , Level , MultiSpan , SubDiagnostic , SubstitutionHighlight ,
20
- SuggestionStyle ,
19
+ CodeSuggestion , Diagnostic , DiagnosticId , DiagnosticMessage , FluentBundle , Handler ,
20
+ LazyFallbackBundle , Level , MultiSpan , SubDiagnostic , SubstitutionHighlight , SuggestionStyle ,
21
21
} ;
22
22
23
23
use rustc_lint_defs:: pluralize;
@@ -200,7 +200,7 @@ impl Margin {
200
200
const ANONYMIZED_LINE_NUM : & str = "LL" ;
201
201
202
202
/// Emitter trait for emitting errors.
203
- pub trait Emitter {
203
+ pub trait Emitter : Translate {
204
204
/// Emit a structured diagnostic.
205
205
fn emit_diagnostic ( & mut self , diag : & Diagnostic ) ;
206
206
@@ -231,102 +231,6 @@ pub trait Emitter {
231
231
232
232
fn source_map ( & self ) -> Option < & Lrc < SourceMap > > ;
233
233
234
- /// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
235
- /// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
236
- /// should be used.
237
- fn fluent_bundle ( & self ) -> Option < & Lrc < FluentBundle > > ;
238
-
239
- /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
240
- /// Used when the user has not requested a specific language or when a localized diagnostic is
241
- /// unavailable for the requested locale.
242
- fn fallback_fluent_bundle ( & self ) -> & FluentBundle ;
243
-
244
- /// Convert diagnostic arguments (a rustc internal type that exists to implement
245
- /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
246
- ///
247
- /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
248
- /// passed around as a reference thereafter.
249
- fn to_fluent_args < ' arg > ( & self , args : & [ DiagnosticArg < ' arg > ] ) -> FluentArgs < ' arg > {
250
- FromIterator :: from_iter ( args. to_vec ( ) . drain ( ..) )
251
- }
252
-
253
- /// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
254
- fn translate_messages (
255
- & self ,
256
- messages : & [ ( DiagnosticMessage , Style ) ] ,
257
- args : & FluentArgs < ' _ > ,
258
- ) -> Cow < ' _ , str > {
259
- Cow :: Owned (
260
- messages. iter ( ) . map ( |( m, _) | self . translate_message ( m, args) ) . collect :: < String > ( ) ,
261
- )
262
- }
263
-
264
- /// Convert a `DiagnosticMessage` to a string, performing translation if necessary.
265
- fn translate_message < ' a > (
266
- & ' a self ,
267
- message : & ' a DiagnosticMessage ,
268
- args : & ' a FluentArgs < ' _ > ,
269
- ) -> Cow < ' _ , str > {
270
- trace ! ( ?message, ?args) ;
271
- let ( identifier, attr) = match message {
272
- DiagnosticMessage :: Str ( msg) => return Cow :: Borrowed ( & msg) ,
273
- DiagnosticMessage :: FluentIdentifier ( identifier, attr) => ( identifier, attr) ,
274
- } ;
275
-
276
- let translate_with_bundle = |bundle : & ' a FluentBundle | -> Option < ( Cow < ' _ , str > , Vec < _ > ) > {
277
- let message = bundle. get_message ( & identifier) ?;
278
- let value = match attr {
279
- Some ( attr) => message. get_attribute ( attr) ?. value ( ) ,
280
- None => message. value ( ) ?,
281
- } ;
282
- debug ! ( ?message, ?value) ;
283
-
284
- let mut errs = vec ! [ ] ;
285
- let translated = bundle. format_pattern ( value, Some ( & args) , & mut errs) ;
286
- debug ! ( ?translated, ?errs) ;
287
- Some ( ( translated, errs) )
288
- } ;
289
-
290
- self . fluent_bundle ( )
291
- . and_then ( |bundle| translate_with_bundle ( bundle) )
292
- // If `translate_with_bundle` returns `None` with the primary bundle, this is likely
293
- // just that the primary bundle doesn't contain the message being translated, so
294
- // proceed to the fallback bundle.
295
- //
296
- // However, when errors are produced from translation, then that means the translation
297
- // is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
298
- //
299
- // In debug builds, assert so that compiler devs can spot the broken translation and
300
- // fix it..
301
- . inspect ( |( _, errs) | {
302
- debug_assert ! (
303
- errs. is_empty( ) ,
304
- "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}" ,
305
- identifier,
306
- attr,
307
- args,
308
- errs
309
- ) ;
310
- } )
311
- // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
312
- // just hide it and try with the fallback bundle.
313
- . filter ( |( _, errs) | errs. is_empty ( ) )
314
- . or_else ( || translate_with_bundle ( self . fallback_fluent_bundle ( ) ) )
315
- . map ( |( translated, errs) | {
316
- // Always bail out for errors with the fallback bundle.
317
- assert ! (
318
- errs. is_empty( ) ,
319
- "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}" ,
320
- identifier,
321
- attr,
322
- args,
323
- errs
324
- ) ;
325
- translated
326
- } )
327
- . expect ( "failed to find message in primary or fallback fluent bundles" )
328
- }
329
-
330
234
/// Formats the substitutions of the primary_span
331
235
///
332
236
/// There are a lot of conditions to this method, but in short:
@@ -616,18 +520,20 @@ pub trait Emitter {
616
520
}
617
521
}
618
522
619
- impl Emitter for EmitterWriter {
620
- fn source_map ( & self ) -> Option < & Lrc < SourceMap > > {
621
- self . sm . as_ref ( )
622
- }
623
-
523
+ impl Translate for EmitterWriter {
624
524
fn fluent_bundle ( & self ) -> Option < & Lrc < FluentBundle > > {
625
525
self . fluent_bundle . as_ref ( )
626
526
}
627
527
628
528
fn fallback_fluent_bundle ( & self ) -> & FluentBundle {
629
529
& * * self . fallback_bundle
630
530
}
531
+ }
532
+
533
+ impl Emitter for EmitterWriter {
534
+ fn source_map ( & self ) -> Option < & Lrc < SourceMap > > {
535
+ self . sm . as_ref ( )
536
+ }
631
537
632
538
fn emit_diagnostic ( & mut self , diag : & Diagnostic ) {
633
539
let fluent_args = self . to_fluent_args ( diag. args ( ) ) ;
@@ -672,18 +578,20 @@ pub struct SilentEmitter {
672
578
pub fatal_note : Option < String > ,
673
579
}
674
580
675
- impl Emitter for SilentEmitter {
676
- fn source_map ( & self ) -> Option < & Lrc < SourceMap > > {
677
- None
678
- }
679
-
581
+ impl Translate for SilentEmitter {
680
582
fn fluent_bundle ( & self ) -> Option < & Lrc < FluentBundle > > {
681
583
None
682
584
}
683
585
684
586
fn fallback_fluent_bundle ( & self ) -> & FluentBundle {
685
587
panic ! ( "silent emitter attempted to translate message" )
686
588
}
589
+ }
590
+
591
+ impl Emitter for SilentEmitter {
592
+ fn source_map ( & self ) -> Option < & Lrc < SourceMap > > {
593
+ None
594
+ }
687
595
688
596
fn emit_diagnostic ( & mut self , d : & Diagnostic ) {
689
597
if d. level == Level :: Fatal {
0 commit comments