Extract Translator struct
This commit is contained in:
parent
8de4c7234d
commit
07b9bb1855
18 changed files with 190 additions and 250 deletions
|
|
@ -14,10 +14,10 @@ use rustc_data_structures::jobserver::{self, Acquired};
|
|||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
|
||||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::translation::Translator;
|
||||
use rustc_errors::{
|
||||
Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan,
|
||||
Style, Suggestions,
|
||||
Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, Level, MultiSpan, Style,
|
||||
Suggestions,
|
||||
};
|
||||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
|
|
@ -1889,16 +1889,6 @@ impl SharedEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for SharedEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
panic!("shared emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SharedEmitter {
|
||||
fn emit_diagnostic(
|
||||
&mut self,
|
||||
|
|
@ -1932,6 +1922,10 @@ impl Emitter for SharedEmitter {
|
|||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
None
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
panic!("shared emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl SharedEmitterMain {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ use rustc_data_structures::profiling::{
|
|||
};
|
||||
use rustc_errors::emitter::stderr_destination;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::translation::Translator;
|
||||
use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown};
|
||||
use rustc_feature::find_gated_cfg;
|
||||
// This avoids a false positive with `-Wunused_crate_dependencies`.
|
||||
|
|
@ -109,6 +110,10 @@ use crate::session_diagnostics::{
|
|||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub fn default_translator() -> Translator {
|
||||
Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false)
|
||||
}
|
||||
|
||||
pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
||||
// tidy-alphabetical-start
|
||||
crate::DEFAULT_LOCALE_RESOURCE,
|
||||
|
|
@ -1413,11 +1418,10 @@ fn report_ice(
|
|||
extra_info: fn(&DiagCtxt),
|
||||
using_internal_features: &AtomicBool,
|
||||
) {
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
|
||||
let translator = default_translator();
|
||||
let emitter = Box::new(rustc_errors::emitter::HumanEmitter::new(
|
||||
stderr_destination(rustc_errors::ColorConfig::Auto),
|
||||
fallback_bundle,
|
||||
translator,
|
||||
));
|
||||
let dcx = rustc_errors::DiagCtxt::new(emitter);
|
||||
let dcx = dcx.handle();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
|
|||
use fluent_syntax::parser::ParserError;
|
||||
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
|
||||
use intl_memoizer::concurrent::IntlLangMemoizer;
|
||||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -204,16 +204,16 @@ fn register_functions(bundle: &mut FluentBundle) {
|
|||
|
||||
/// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily
|
||||
/// evaluated fluent bundle.
|
||||
pub type LazyFallbackBundle = Arc<LazyLock<FluentBundle, impl FnOnce() -> FluentBundle>>;
|
||||
pub type LazyFallbackBundle =
|
||||
Arc<LazyLock<FluentBundle, Box<dyn FnOnce() -> FluentBundle + DynSend>>>;
|
||||
|
||||
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
|
||||
#[instrument(level = "trace", skip(resources))]
|
||||
#[define_opaque(LazyFallbackBundle)]
|
||||
pub fn fallback_fluent_bundle(
|
||||
resources: Vec<&'static str>,
|
||||
with_directionality_markers: bool,
|
||||
) -> LazyFallbackBundle {
|
||||
Arc::new(LazyLock::new(move || {
|
||||
Arc::new(LazyLock::new(Box::new(move || {
|
||||
let mut fallback_bundle = new_bundle(vec![langid!("en-US")]);
|
||||
|
||||
register_functions(&mut fallback_bundle);
|
||||
|
|
@ -228,7 +228,7 @@ pub fn fallback_fluent_bundle(
|
|||
}
|
||||
|
||||
fallback_bundle
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
/// Identifier for the Fluent message/attribute corresponding to a diagnostic message.
|
||||
|
|
|
|||
|
|
@ -15,17 +15,15 @@ use rustc_span::source_map::SourceMap;
|
|||
use crate::emitter::FileWithAnnotatedLines;
|
||||
use crate::registry::Registry;
|
||||
use crate::snippet::Line;
|
||||
use crate::translation::{Translate, to_fluent_args};
|
||||
use crate::translation::{Translator, to_fluent_args};
|
||||
use crate::{
|
||||
CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, FluentBundle, LazyFallbackBundle,
|
||||
Level, MultiSpan, Style, Subdiag,
|
||||
CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag,
|
||||
};
|
||||
|
||||
/// Generates diagnostics using annotate-snippet
|
||||
pub struct AnnotateSnippetEmitter {
|
||||
source_map: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
translator: Translator,
|
||||
|
||||
/// If true, hides the longer explanation text
|
||||
short_message: bool,
|
||||
|
|
@ -35,16 +33,6 @@ pub struct AnnotateSnippetEmitter {
|
|||
macro_backtrace: bool,
|
||||
}
|
||||
|
||||
impl Translate for AnnotateSnippetEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
self.fluent_bundle.as_deref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for AnnotateSnippetEmitter {
|
||||
/// The entry point for the diagnostics generation
|
||||
fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) {
|
||||
|
|
@ -78,6 +66,10 @@ impl Emitter for AnnotateSnippetEmitter {
|
|||
fn should_show_explain(&self) -> bool {
|
||||
!self.short_message
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
&self.translator
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the source string for the given `line` of `file`
|
||||
|
|
@ -104,19 +96,11 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::Level {
|
|||
impl AnnotateSnippetEmitter {
|
||||
pub fn new(
|
||||
source_map: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
translator: Translator,
|
||||
short_message: bool,
|
||||
macro_backtrace: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
source_map,
|
||||
fluent_bundle,
|
||||
fallback_bundle,
|
||||
short_message,
|
||||
ui_testing: false,
|
||||
macro_backtrace,
|
||||
}
|
||||
Self { source_map, translator, short_message, ui_testing: false, macro_backtrace }
|
||||
}
|
||||
|
||||
/// Allows to modify `Self` to enable or disable the `ui_testing` flag.
|
||||
|
|
@ -137,7 +121,7 @@ impl AnnotateSnippetEmitter {
|
|||
_children: &[Subdiag],
|
||||
_suggestions: &[CodeSuggestion],
|
||||
) {
|
||||
let message = self.translate_messages(messages, args);
|
||||
let message = self.translator.translate_messages(messages, args);
|
||||
if let Some(source_map) = &self.source_map {
|
||||
// Make sure our primary file comes first
|
||||
let primary_lo = if let Some(primary_span) = msp.primary_span().as_ref() {
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ use crate::snippet::{
|
|||
};
|
||||
use crate::styled_buffer::StyledBuffer;
|
||||
use crate::timings::TimingRecord;
|
||||
use crate::translation::{Translate, to_fluent_args};
|
||||
use crate::translation::{Translator, to_fluent_args};
|
||||
use crate::{
|
||||
CodeSuggestion, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle, Level,
|
||||
MultiSpan, Subdiag, SubstitutionHighlight, SuggestionStyle, TerminalUrl,
|
||||
CodeSuggestion, DiagInner, DiagMessage, ErrCode, Level, MultiSpan, Subdiag,
|
||||
SubstitutionHighlight, SuggestionStyle, TerminalUrl,
|
||||
};
|
||||
|
||||
/// Default column width, used in tests and when terminal dimensions cannot be determined.
|
||||
|
|
@ -175,7 +175,7 @@ const ANONYMIZED_LINE_NUM: &str = "LL";
|
|||
pub type DynEmitter = dyn Emitter + DynSend;
|
||||
|
||||
/// Emitter trait for emitting errors and other structured information.
|
||||
pub trait Emitter: Translate {
|
||||
pub trait Emitter {
|
||||
/// Emit a structured diagnostic.
|
||||
fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry);
|
||||
|
||||
|
|
@ -212,6 +212,8 @@ pub trait Emitter: Translate {
|
|||
|
||||
fn source_map(&self) -> Option<&SourceMap>;
|
||||
|
||||
fn translator(&self) -> &Translator;
|
||||
|
||||
/// Formats the substitutions of the primary_span
|
||||
///
|
||||
/// There are a lot of conditions to this method, but in short:
|
||||
|
|
@ -224,13 +226,17 @@ pub trait Emitter: Translate {
|
|||
/// * If the current `DiagInner` has multiple suggestions,
|
||||
/// we leave `primary_span` and the suggestions untouched.
|
||||
fn primary_span_formatted(
|
||||
&mut self,
|
||||
&self,
|
||||
primary_span: &mut MultiSpan,
|
||||
suggestions: &mut Vec<CodeSuggestion>,
|
||||
fluent_args: &FluentArgs<'_>,
|
||||
) {
|
||||
if let Some((sugg, rest)) = suggestions.split_first() {
|
||||
let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap();
|
||||
let msg = self
|
||||
.translator()
|
||||
.translate_message(&sugg.msg, fluent_args)
|
||||
.map_err(Report::new)
|
||||
.unwrap();
|
||||
if rest.is_empty()
|
||||
// ^ if there is only one suggestion
|
||||
// don't display multi-suggestions as labels
|
||||
|
|
@ -491,16 +497,6 @@ pub trait Emitter: Translate {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for HumanEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
self.fluent_bundle.as_deref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for HumanEmitter {
|
||||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
self.sm.as_deref()
|
||||
|
|
@ -538,6 +534,10 @@ impl Emitter for HumanEmitter {
|
|||
fn supports_color(&self) -> bool {
|
||||
self.dst.supports_color()
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
&self.translator
|
||||
}
|
||||
}
|
||||
|
||||
/// An emitter that does nothing when emitting a non-fatal diagnostic.
|
||||
|
|
@ -549,16 +549,6 @@ pub struct SilentEmitter {
|
|||
pub emit_fatal_diagnostic: bool,
|
||||
}
|
||||
|
||||
impl Translate for SilentEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
self.fatal_emitter.fallback_fluent_bundle()
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentEmitter {
|
||||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
None
|
||||
|
|
@ -572,6 +562,10 @@ impl Emitter for SilentEmitter {
|
|||
self.fatal_emitter.emit_diagnostic(diag, registry);
|
||||
}
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
self.fatal_emitter.translator()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maximum number of suggestions to be shown
|
||||
|
|
@ -615,9 +609,8 @@ pub struct HumanEmitter {
|
|||
#[setters(skip)]
|
||||
dst: IntoDynSyncSend<Destination>,
|
||||
sm: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
#[setters(skip)]
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
translator: Translator,
|
||||
short_message: bool,
|
||||
ui_testing: bool,
|
||||
ignored_directories_in_source_blocks: Vec<String>,
|
||||
|
|
@ -637,12 +630,11 @@ pub(crate) struct FileWithAnnotatedLines {
|
|||
}
|
||||
|
||||
impl HumanEmitter {
|
||||
pub fn new(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
|
||||
pub fn new(dst: Destination, translator: Translator) -> HumanEmitter {
|
||||
HumanEmitter {
|
||||
dst: IntoDynSyncSend(dst),
|
||||
sm: None,
|
||||
fluent_bundle: None,
|
||||
fallback_bundle,
|
||||
translator,
|
||||
short_message: false,
|
||||
ui_testing: false,
|
||||
ignored_directories_in_source_blocks: Vec::new(),
|
||||
|
|
@ -1433,7 +1425,7 @@ impl HumanEmitter {
|
|||
// very *weird* formats
|
||||
// see?
|
||||
for (text, style) in msgs.iter() {
|
||||
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
|
||||
let text = self.translator.translate_message(text, args).map_err(Report::new).unwrap();
|
||||
let text = &normalize_whitespace(&text);
|
||||
let lines = text.split('\n').collect::<Vec<_>>();
|
||||
if lines.len() > 1 {
|
||||
|
|
@ -1528,7 +1520,8 @@ impl HumanEmitter {
|
|||
}
|
||||
let mut line = 0;
|
||||
for (text, style) in msgs.iter() {
|
||||
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
|
||||
let text =
|
||||
self.translator.translate_message(text, args).map_err(Report::new).unwrap();
|
||||
// Account for newlines to align output to its label.
|
||||
for text in normalize_whitespace(&text).lines() {
|
||||
buffer.append(
|
||||
|
|
@ -1560,7 +1553,7 @@ impl HumanEmitter {
|
|||
.into_iter()
|
||||
.filter_map(|label| match label.label {
|
||||
Some(msg) if label.is_primary => {
|
||||
let text = self.translate_message(&msg, args).ok()?;
|
||||
let text = self.translator.translate_message(&msg, args).ok()?;
|
||||
if !text.trim().is_empty() { Some(text.to_string()) } else { None }
|
||||
}
|
||||
_ => None,
|
||||
|
|
@ -3104,7 +3097,11 @@ impl FileWithAnnotatedLines {
|
|||
|
||||
let label = label.as_ref().map(|m| {
|
||||
normalize_whitespace(
|
||||
&emitter.translate_message(m, args).map_err(Report::new).unwrap(),
|
||||
&emitter
|
||||
.translator()
|
||||
.translate_message(m, args)
|
||||
.map_err(Report::new)
|
||||
.unwrap(),
|
||||
)
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,8 @@ use crate::emitter::{
|
|||
};
|
||||
use crate::registry::Registry;
|
||||
use crate::timings::{TimingRecord, TimingSection};
|
||||
use crate::translation::{Translate, to_fluent_args};
|
||||
use crate::{
|
||||
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, Subdiag, Suggestions,
|
||||
TerminalUrl,
|
||||
};
|
||||
use crate::translation::{Translator, to_fluent_args};
|
||||
use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
@ -47,9 +44,8 @@ pub struct JsonEmitter {
|
|||
dst: IntoDynSyncSend<Box<dyn Write + Send>>,
|
||||
#[setters(skip)]
|
||||
sm: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
#[setters(skip)]
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
translator: Translator,
|
||||
#[setters(skip)]
|
||||
pretty: bool,
|
||||
ui_testing: bool,
|
||||
|
|
@ -67,7 +63,7 @@ impl JsonEmitter {
|
|||
pub fn new(
|
||||
dst: Box<dyn Write + Send>,
|
||||
sm: Option<Arc<SourceMap>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
translator: Translator,
|
||||
pretty: bool,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
color_config: ColorConfig,
|
||||
|
|
@ -75,8 +71,7 @@ impl JsonEmitter {
|
|||
JsonEmitter {
|
||||
dst: IntoDynSyncSend(dst),
|
||||
sm,
|
||||
fluent_bundle: None,
|
||||
fallback_bundle,
|
||||
translator,
|
||||
pretty,
|
||||
ui_testing: false,
|
||||
ignored_directories_in_source_blocks: Vec::new(),
|
||||
|
|
@ -110,16 +105,6 @@ enum EmitTyped<'a> {
|
|||
UnusedExtern(UnusedExterns<'a>),
|
||||
}
|
||||
|
||||
impl Translate for JsonEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
self.fluent_bundle.as_deref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for JsonEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: crate::DiagInner, registry: &Registry) {
|
||||
let data = Diagnostic::from_errors_diagnostic(diag, self, registry);
|
||||
|
|
@ -194,6 +179,10 @@ impl Emitter for JsonEmitter {
|
|||
fn should_show_explain(&self) -> bool {
|
||||
!self.json_rendered.short()
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
&self.translator
|
||||
}
|
||||
}
|
||||
|
||||
// The following data types are provided just for serialisation.
|
||||
|
|
@ -324,7 +313,7 @@ impl Diagnostic {
|
|||
let args = to_fluent_args(diag.args.iter());
|
||||
let sugg_to_diag = |sugg: &CodeSuggestion| {
|
||||
let translated_message =
|
||||
je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();
|
||||
je.translator.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();
|
||||
Diagnostic {
|
||||
message: translated_message.to_string(),
|
||||
code: None,
|
||||
|
|
@ -368,7 +357,7 @@ impl Diagnostic {
|
|||
}
|
||||
}
|
||||
|
||||
let translated_message = je.translate_messages(&diag.messages, &args);
|
||||
let translated_message = je.translator.translate_messages(&diag.messages, &args);
|
||||
|
||||
let code = if let Some(code) = diag.code {
|
||||
Some(DiagnosticCode {
|
||||
|
|
@ -396,10 +385,9 @@ impl Diagnostic {
|
|||
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
|
||||
ColorConfig::Never => {}
|
||||
}
|
||||
HumanEmitter::new(dst, Arc::clone(&je.fallback_bundle))
|
||||
HumanEmitter::new(dst, je.translator.clone())
|
||||
.short_message(short)
|
||||
.sm(je.sm.clone())
|
||||
.fluent_bundle(je.fluent_bundle.clone())
|
||||
.diagnostic_width(je.diagnostic_width)
|
||||
.macro_backtrace(je.macro_backtrace)
|
||||
.track_diagnostics(je.track_diagnostics)
|
||||
|
|
@ -430,7 +418,7 @@ impl Diagnostic {
|
|||
args: &FluentArgs<'_>,
|
||||
je: &JsonEmitter,
|
||||
) -> Diagnostic {
|
||||
let translated_message = je.translate_messages(&subdiag.messages, args);
|
||||
let translated_message = je.translator.translate_messages(&subdiag.messages, args);
|
||||
Diagnostic {
|
||||
message: translated_message.to_string(),
|
||||
code: None,
|
||||
|
|
@ -454,7 +442,7 @@ impl DiagnosticSpan {
|
|||
span.is_primary,
|
||||
span.label
|
||||
.as_ref()
|
||||
.map(|m| je.translate_message(m, args).unwrap())
|
||||
.map(|m| je.translator.translate_message(m, args).unwrap())
|
||||
.map(|m| m.to_string()),
|
||||
suggestion,
|
||||
je,
|
||||
|
|
|
|||
|
|
@ -41,14 +41,14 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
|||
rustc_span::create_default_session_globals_then(|| {
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
|
||||
let fallback_bundle =
|
||||
crate::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
let translator =
|
||||
Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
|
||||
let output = Arc::new(Mutex::new(Vec::new()));
|
||||
let je = JsonEmitter::new(
|
||||
Box::new(Shared { data: output.clone() }),
|
||||
Some(sm),
|
||||
fallback_bundle,
|
||||
translator,
|
||||
true, // pretty
|
||||
HumanReadableErrorType::Short,
|
||||
ColorConfig::Never,
|
||||
|
|
|
|||
|
|
@ -761,14 +761,8 @@ impl DiagCtxt {
|
|||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
unimplemented!("false emitter must only used during `make_silent`")
|
||||
}
|
||||
}
|
||||
|
||||
impl translation::Translate for FalseEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
unimplemented!("false emitter must only used during `make_silent`")
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
fn translator(&self) -> &translation::Translator {
|
||||
unimplemented!("false emitter must only used during `make_silent`")
|
||||
}
|
||||
}
|
||||
|
|
@ -1771,7 +1765,12 @@ impl DiagCtxtInner {
|
|||
args: impl Iterator<Item = DiagArg<'a>>,
|
||||
) -> String {
|
||||
let args = crate::translation::to_fluent_args(args);
|
||||
self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
|
||||
self.emitter
|
||||
.translator()
|
||||
.translate_message(&message, &args)
|
||||
.map_err(Report::new)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn eagerly_translate_for_subdiag(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
|
||||
use rustc_error_messages::{DiagMessage, langid};
|
||||
|
|
@ -5,23 +7,9 @@ use rustc_error_messages::{DiagMessage, langid};
|
|||
use crate::FluentBundle;
|
||||
use crate::error::{TranslateError, TranslateErrorKind};
|
||||
use crate::fluent_bundle::*;
|
||||
use crate::translation::Translate;
|
||||
use crate::translation::Translator;
|
||||
|
||||
struct Dummy {
|
||||
bundle: FluentBundle,
|
||||
}
|
||||
|
||||
impl Translate for Dummy {
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&self.bundle
|
||||
}
|
||||
}
|
||||
|
||||
fn make_dummy(ftl: &'static str) -> Dummy {
|
||||
fn make_translator(ftl: &'static str) -> Translator {
|
||||
let resource = FluentResource::try_new(ftl.into()).expect("Failed to parse an FTL string.");
|
||||
|
||||
let langid_en = langid!("en-US");
|
||||
|
|
@ -33,12 +21,15 @@ fn make_dummy(ftl: &'static str) -> Dummy {
|
|||
|
||||
bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle.");
|
||||
|
||||
Dummy { bundle }
|
||||
Translator {
|
||||
fluent_bundle: None,
|
||||
fallback_fluent_bundle: Arc::new(LazyLock::new(Box::new(|| bundle))),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wellformed_fluent() {
|
||||
let dummy = make_dummy("mir_build_borrow_of_moved_value = borrow of moved value
|
||||
let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value
|
||||
.label = value moved into `{$name}` here
|
||||
.occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
|
||||
.value_borrowed_label = value borrowed here after move
|
||||
|
|
@ -54,7 +45,7 @@ fn wellformed_fluent() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
dummy.translate_message(&message, &args).unwrap(),
|
||||
translator.translate_message(&message, &args).unwrap(),
|
||||
"borrow this binding in the pattern to avoid moving the value"
|
||||
);
|
||||
}
|
||||
|
|
@ -66,7 +57,7 @@ fn wellformed_fluent() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
dummy.translate_message(&message, &args).unwrap(),
|
||||
translator.translate_message(&message, &args).unwrap(),
|
||||
"value borrowed here after move"
|
||||
);
|
||||
}
|
||||
|
|
@ -78,7 +69,7 @@ fn wellformed_fluent() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
dummy.translate_message(&message, &args).unwrap(),
|
||||
translator.translate_message(&message, &args).unwrap(),
|
||||
"move occurs because `\u{2068}Foo\u{2069}` has type `\u{2068}std::string::String\u{2069}` which does not implement the `Copy` trait"
|
||||
);
|
||||
|
||||
|
|
@ -89,7 +80,7 @@ fn wellformed_fluent() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
dummy.translate_message(&message, &args).unwrap(),
|
||||
translator.translate_message(&message, &args).unwrap(),
|
||||
"value moved into `\u{2068}Foo\u{2069}` here"
|
||||
);
|
||||
}
|
||||
|
|
@ -98,7 +89,7 @@ fn wellformed_fluent() {
|
|||
|
||||
#[test]
|
||||
fn misformed_fluent() {
|
||||
let dummy = make_dummy("mir_build_borrow_of_moved_value = borrow of moved value
|
||||
let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value
|
||||
.label = value moved into `{name}` here
|
||||
.occurs_because_label = move occurs because `{$oops}` has type `{$ty}` which does not implement the `Copy` trait
|
||||
.suggestion = borrow this binding in the pattern to avoid moving the value");
|
||||
|
|
@ -112,7 +103,7 @@ fn misformed_fluent() {
|
|||
Some("value_borrowed_label".into()),
|
||||
);
|
||||
|
||||
let err = dummy.translate_message(&message, &args).unwrap_err();
|
||||
let err = translator.translate_message(&message, &args).unwrap_err();
|
||||
assert!(
|
||||
matches!(
|
||||
&err,
|
||||
|
|
@ -141,7 +132,7 @@ fn misformed_fluent() {
|
|||
Some("label".into()),
|
||||
);
|
||||
|
||||
let err = dummy.translate_message(&message, &args).unwrap_err();
|
||||
let err = translator.translate_message(&message, &args).unwrap_err();
|
||||
if let TranslateError::Two {
|
||||
primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. },
|
||||
fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. },
|
||||
|
|
@ -168,7 +159,7 @@ fn misformed_fluent() {
|
|||
Some("occurs_because_label".into()),
|
||||
);
|
||||
|
||||
let err = dummy.translate_message(&message, &args).unwrap_err();
|
||||
let err = translator.translate_message(&message, &args).unwrap_err();
|
||||
if let TranslateError::Two {
|
||||
primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. },
|
||||
fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. },
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::borrow::Cow;
|
||||
use std::env;
|
||||
use std::error::Report;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use rustc_error_messages::FluentArgs;
|
||||
pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle};
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::error::{TranslateError, TranslateErrorKind};
|
||||
|
|
@ -28,19 +29,33 @@ pub fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> Flue
|
|||
args
|
||||
}
|
||||
|
||||
pub trait Translate {
|
||||
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
|
||||
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
|
||||
/// should be used.
|
||||
fn fluent_bundle(&self) -> Option<&FluentBundle>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Translator {
|
||||
/// Localized diagnostics for the locale requested by the user. If no language was requested by
|
||||
/// the user then this will be `None` and `fallback_fluent_bundle` should be used.
|
||||
pub fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
|
||||
/// Used when the user has not requested a specific language or when a localized diagnostic is
|
||||
/// unavailable for the requested locale.
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle;
|
||||
pub fallback_fluent_bundle: LazyFallbackBundle,
|
||||
}
|
||||
|
||||
impl Translator {
|
||||
pub fn with_fallback_bundle(
|
||||
resources: Vec<&'static str>,
|
||||
with_directionality_markers: bool,
|
||||
) -> Translator {
|
||||
Translator {
|
||||
fluent_bundle: None,
|
||||
fallback_fluent_bundle: crate::fallback_fluent_bundle(
|
||||
resources,
|
||||
with_directionality_markers,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `DiagMessage`s to a string, performing translation if necessary.
|
||||
fn translate_messages(
|
||||
pub fn translate_messages(
|
||||
&self,
|
||||
messages: &[(DiagMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
|
|
@ -54,7 +69,7 @@ pub trait Translate {
|
|||
}
|
||||
|
||||
/// Convert a `DiagMessage` to a string, performing translation if necessary.
|
||||
fn translate_message<'a>(
|
||||
pub fn translate_message<'a>(
|
||||
&'a self,
|
||||
message: &'a DiagMessage,
|
||||
args: &'a FluentArgs<'_>,
|
||||
|
|
@ -91,7 +106,7 @@ pub trait Translate {
|
|||
};
|
||||
|
||||
try {
|
||||
match self.fluent_bundle().map(|b| translate_with_bundle(b)) {
|
||||
match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) {
|
||||
// The primary bundle was present and translation succeeded
|
||||
Some(Ok(t)) => t,
|
||||
|
||||
|
|
@ -102,7 +117,7 @@ pub trait Translate {
|
|||
primary @ TranslateError::One {
|
||||
kind: TranslateErrorKind::MessageMissing, ..
|
||||
},
|
||||
)) => translate_with_bundle(self.fallback_fluent_bundle())
|
||||
)) => translate_with_bundle(&self.fallback_fluent_bundle)
|
||||
.map_err(|fallback| primary.and(fallback))?,
|
||||
|
||||
// Always yeet out for errors on debug (unless
|
||||
|
|
@ -118,11 +133,11 @@ pub trait Translate {
|
|||
|
||||
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
|
||||
// just hide it and try with the fallback bundle.
|
||||
Some(Err(primary)) => translate_with_bundle(self.fallback_fluent_bundle())
|
||||
Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle)
|
||||
.map_err(|fallback| primary.and(fallback))?,
|
||||
|
||||
// The primary bundle is missing, proceed to the fallback bundle
|
||||
None => translate_with_bundle(self.fallback_fluent_bundle())
|
||||
None => translate_with_bundle(&self.fallback_fluent_bundle)
|
||||
.map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, Toke
|
|||
use rustc_ast::{self as ast, PatKind, visit};
|
||||
use rustc_ast_pretty::pprust::item_to_string;
|
||||
use rustc_errors::emitter::{HumanEmitter, OutputTheme};
|
||||
use rustc_errors::translation::Translator;
|
||||
use rustc_errors::{DiagCtxt, MultiSpan, PResult};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
|
|
@ -41,9 +42,8 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
|
|||
fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
|
||||
let output = Arc::new(Mutex::new(Vec::new()));
|
||||
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
let mut emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
|
||||
let translator = Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
let mut emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), translator)
|
||||
.sm(Some(source_map.clone()))
|
||||
.diagnostic_width(Some(140));
|
||||
emitter = emitter.theme(theme);
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ use rustc_ast::node_id::NodeId;
|
|||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sync::{AppendOnlyVec, Lock};
|
||||
use rustc_errors::emitter::{HumanEmitter, SilentEmitter, stderr_destination};
|
||||
use rustc_errors::translation::Translator;
|
||||
use rustc_errors::{
|
||||
ColorConfig, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, EmissionGuarantee, MultiSpan,
|
||||
StashKey, fallback_fluent_bundle,
|
||||
StashKey,
|
||||
};
|
||||
use rustc_feature::{GateIssue, UnstableFeatures, find_feature_issue};
|
||||
use rustc_span::edition::Edition;
|
||||
|
|
@ -242,10 +243,10 @@ pub struct ParseSess {
|
|||
impl ParseSess {
|
||||
/// Used for testing.
|
||||
pub fn new(locale_resources: Vec<&'static str>) -> Self {
|
||||
let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
|
||||
let translator = Translator::with_fallback_bundle(locale_resources, false);
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let emitter = Box::new(
|
||||
HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle)
|
||||
HumanEmitter::new(stderr_destination(ColorConfig::Auto), translator)
|
||||
.sm(Some(Arc::clone(&sm))),
|
||||
);
|
||||
let dcx = DiagCtxt::new(emitter);
|
||||
|
|
@ -277,12 +278,13 @@ impl ParseSess {
|
|||
pub fn with_silent_emitter(
|
||||
locale_resources: Vec<&'static str>,
|
||||
fatal_note: String,
|
||||
|
||||
emit_fatal_diagnostic: bool,
|
||||
) -> Self {
|
||||
let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
|
||||
let translator = Translator::with_fallback_bundle(locale_resources, false);
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let fatal_emitter =
|
||||
Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle));
|
||||
Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), translator));
|
||||
let dcx = DiagCtxt::new(Box::new(SilentEmitter {
|
||||
fatal_emitter,
|
||||
fatal_note: Some(fatal_note),
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ use rustc_errors::emitter::{
|
|||
};
|
||||
use rustc_errors::json::JsonEmitter;
|
||||
use rustc_errors::timings::TimingSectionHandler;
|
||||
use rustc_errors::translation::Translator;
|
||||
use rustc_errors::{
|
||||
Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
|
||||
FluentBundle, LazyFallbackBundle, TerminalUrl, fallback_fluent_bundle,
|
||||
TerminalUrl, fallback_fluent_bundle,
|
||||
};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
pub use rustc_span::def_id::StableCrateId;
|
||||
|
|
@ -948,8 +949,7 @@ impl Session {
|
|||
fn default_emitter(
|
||||
sopts: &config::Options,
|
||||
source_map: Arc<SourceMap>,
|
||||
bundle: Option<Arc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
translator: Translator,
|
||||
) -> Box<DynEmitter> {
|
||||
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
|
||||
let track_diagnostics = sopts.unstable_opts.track_diagnostics;
|
||||
|
|
@ -974,17 +974,11 @@ fn default_emitter(
|
|||
let short = kind.short();
|
||||
|
||||
if let HumanReadableErrorType::AnnotateSnippet = kind {
|
||||
let emitter = AnnotateSnippetEmitter::new(
|
||||
source_map,
|
||||
bundle,
|
||||
fallback_bundle,
|
||||
short,
|
||||
macro_backtrace,
|
||||
);
|
||||
let emitter =
|
||||
AnnotateSnippetEmitter::new(source_map, translator, short, macro_backtrace);
|
||||
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
|
||||
} else {
|
||||
let emitter = HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
|
||||
.fluent_bundle(bundle)
|
||||
let emitter = HumanEmitter::new(stderr_destination(color_config), translator)
|
||||
.sm(source_map)
|
||||
.short_message(short)
|
||||
.diagnostic_width(sopts.diagnostic_width)
|
||||
|
|
@ -1006,12 +1000,11 @@ fn default_emitter(
|
|||
JsonEmitter::new(
|
||||
Box::new(io::BufWriter::new(io::stderr())),
|
||||
source_map,
|
||||
fallback_bundle,
|
||||
translator,
|
||||
pretty,
|
||||
json_rendered,
|
||||
color_config,
|
||||
)
|
||||
.fluent_bundle(bundle)
|
||||
.ui_testing(sopts.unstable_opts.ui_testing)
|
||||
.ignored_directories_in_source_blocks(
|
||||
sopts.unstable_opts.ignore_directory_in_diagnostics_source_blocks.clone(),
|
||||
|
|
@ -1030,7 +1023,7 @@ fn default_emitter(
|
|||
pub fn build_session(
|
||||
sopts: config::Options,
|
||||
io: CompilerIO,
|
||||
bundle: Option<Arc<rustc_errors::FluentBundle>>,
|
||||
fluent_bundle: Option<Arc<rustc_errors::FluentBundle>>,
|
||||
registry: rustc_errors::registry::Registry,
|
||||
fluent_resources: Vec<&'static str>,
|
||||
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
|
||||
|
|
@ -1052,12 +1045,15 @@ pub fn build_session(
|
|||
let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
|
||||
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
|
||||
|
||||
let fallback_bundle = fallback_fluent_bundle(
|
||||
fluent_resources,
|
||||
sopts.unstable_opts.translate_directionality_markers,
|
||||
);
|
||||
let translator = Translator {
|
||||
fluent_bundle,
|
||||
fallback_fluent_bundle: fallback_fluent_bundle(
|
||||
fluent_resources,
|
||||
sopts.unstable_opts.translate_directionality_markers,
|
||||
),
|
||||
};
|
||||
let source_map = rustc_span::source_map::get_source_map().unwrap();
|
||||
let emitter = default_emitter(&sopts, Arc::clone(&source_map), bundle, fallback_bundle);
|
||||
let emitter = default_emitter(&sopts, Arc::clone(&source_map), translator);
|
||||
|
||||
let mut dcx = DiagCtxt::new(emitter)
|
||||
.with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings))
|
||||
|
|
@ -1500,13 +1496,13 @@ impl EarlyDiagCtxt {
|
|||
fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
||||
// FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will
|
||||
// need to reference every crate that might emit an early error for translation to work.
|
||||
let fallback_bundle =
|
||||
fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false);
|
||||
let translator =
|
||||
Translator::with_fallback_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false);
|
||||
let emitter: Box<DynEmitter> = match output {
|
||||
config::ErrorOutputType::HumanReadable { kind, color_config } => {
|
||||
let short = kind.short();
|
||||
Box::new(
|
||||
HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
|
||||
HumanEmitter::new(stderr_destination(color_config), translator)
|
||||
.theme(if let HumanReadableErrorType::Unicode = kind {
|
||||
OutputTheme::Unicode
|
||||
} else {
|
||||
|
|
@ -1519,7 +1515,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
|||
Box::new(JsonEmitter::new(
|
||||
Box::new(io::BufWriter::new(io::stderr())),
|
||||
Some(Arc::new(SourceMap::new(FilePathMapping::empty()))),
|
||||
fallback_bundle,
|
||||
translator,
|
||||
pretty,
|
||||
json_rendered,
|
||||
color_config,
|
||||
|
|
|
|||
|
|
@ -149,15 +149,12 @@ pub(crate) fn new_dcx(
|
|||
diagnostic_width: Option<usize>,
|
||||
unstable_opts: &UnstableOptions,
|
||||
) -> rustc_errors::DiagCtxt {
|
||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
|
||||
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
|
||||
false,
|
||||
);
|
||||
let translator = rustc_driver::default_translator();
|
||||
let emitter: Box<DynEmitter> = match error_format {
|
||||
ErrorOutputType::HumanReadable { kind, color_config } => {
|
||||
let short = kind.short();
|
||||
Box::new(
|
||||
HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
|
||||
HumanEmitter::new(stderr_destination(color_config), translator)
|
||||
.sm(source_map.map(|sm| sm as _))
|
||||
.short_message(short)
|
||||
.diagnostic_width(diagnostic_width)
|
||||
|
|
@ -178,7 +175,7 @@ pub(crate) fn new_dcx(
|
|||
JsonEmitter::new(
|
||||
Box::new(io::BufWriter::new(io::stderr())),
|
||||
Some(source_map),
|
||||
fallback_bundle,
|
||||
translator,
|
||||
pretty,
|
||||
json_rendered,
|
||||
color_config,
|
||||
|
|
|
|||
|
|
@ -456,16 +456,13 @@ fn parse_source(
|
|||
let filename = FileName::anon_source_code(&wrapped_source);
|
||||
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
|
||||
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
|
||||
false,
|
||||
);
|
||||
let translator = rustc_driver::default_translator();
|
||||
info.supports_color =
|
||||
HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone())
|
||||
HumanEmitter::new(stderr_destination(ColorConfig::Auto), translator.clone())
|
||||
.supports_color();
|
||||
// Any errors in parsing should also appear when the doctest is compiled for real, so just
|
||||
// send all the errors that the parser emits directly into a `Sink` instead of stderr.
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), translator);
|
||||
|
||||
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
||||
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use std::sync::Arc;
|
|||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::translation::{Translate, to_fluent_args};
|
||||
use rustc_errors::{Applicability, DiagCtxt, DiagInner, LazyFallbackBundle};
|
||||
use rustc_errors::translation::{Translator, to_fluent_args};
|
||||
use rustc_errors::{Applicability, DiagCtxt, DiagInner};
|
||||
use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
|
||||
use rustc_resolve::rustdoc::source_span_for_markdown_range;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
|
@ -36,11 +36,8 @@ fn check_rust_syntax(
|
|||
code_block: RustCodeBlock,
|
||||
) {
|
||||
let buffer = Arc::new(Lock::new(Buffer::default()));
|
||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
|
||||
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
|
||||
false,
|
||||
);
|
||||
let emitter = BufferEmitter { buffer: Arc::clone(&buffer), fallback_bundle };
|
||||
let translator = rustc_driver::default_translator();
|
||||
let emitter = BufferEmitter { buffer: Arc::clone(&buffer), translator };
|
||||
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
|
||||
|
|
@ -149,17 +146,7 @@ struct Buffer {
|
|||
|
||||
struct BufferEmitter {
|
||||
buffer: Arc<Lock<Buffer>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
}
|
||||
|
||||
impl Translate for BufferEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
&self.fallback_bundle
|
||||
}
|
||||
translator: Translator,
|
||||
}
|
||||
|
||||
impl Emitter for BufferEmitter {
|
||||
|
|
@ -168,6 +155,7 @@ impl Emitter for BufferEmitter {
|
|||
|
||||
let fluent_args = to_fluent_args(diag.args.iter());
|
||||
let translated_main_message = self
|
||||
.translator
|
||||
.translate_message(&diag.messages[0].0, &fluent_args)
|
||||
.unwrap_or_else(|e| panic!("{e}"));
|
||||
|
||||
|
|
@ -180,4 +168,8 @@ impl Emitter for BufferEmitter {
|
|||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
None
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
&self.translator
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,9 +42,8 @@ pub fn check(
|
|||
let mut test_attr_spans = vec![];
|
||||
let filename = FileName::anon_source_code(&code);
|
||||
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
|
||||
let translator = rustc_driver::default_translator();
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), translator);
|
||||
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
|
||||
#[expect(clippy::arc_with_non_send_sync)] // `Arc` is expected by with_dcx
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination};
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::translation::Translator;
|
||||
use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
|
||||
use rustc_session::parse::ParseSess as RawParseSess;
|
||||
use rustc_span::{
|
||||
|
|
@ -47,16 +47,6 @@ impl SilentOnIgnoredFilesEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for SilentOnIgnoredFilesEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> {
|
||||
self.emitter.fluent_bundle()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
self.emitter.fallback_fluent_bundle()
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentOnIgnoredFilesEmitter {
|
||||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
None
|
||||
|
|
@ -84,6 +74,10 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
|
|||
}
|
||||
self.handle_non_ignoreable_error(diag, registry);
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
self.emitter.translator()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for ColorConfig {
|
||||
|
|
@ -110,12 +104,9 @@ fn default_dcx(
|
|||
ColorConfig::Never
|
||||
};
|
||||
|
||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
|
||||
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
|
||||
false,
|
||||
);
|
||||
let translator = rustc_driver::default_translator();
|
||||
let emitter = Box::new(
|
||||
HumanEmitter::new(stderr_destination(emit_color), fallback_bundle)
|
||||
HumanEmitter::new(stderr_destination(emit_color), translator)
|
||||
.sm(Some(source_map.clone())),
|
||||
);
|
||||
|
||||
|
|
@ -335,16 +326,6 @@ mod tests {
|
|||
num_emitted_errors: Arc<AtomicU32>,
|
||||
}
|
||||
|
||||
impl Translate for TestEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("test emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for TestEmitter {
|
||||
fn source_map(&self) -> Option<&SourceMap> {
|
||||
None
|
||||
|
|
@ -353,6 +334,10 @@ mod tests {
|
|||
fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {
|
||||
self.num_emitted_errors.fetch_add(1, Ordering::Release);
|
||||
}
|
||||
|
||||
fn translator(&self) -> &Translator {
|
||||
panic!("test emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> DiagInner {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue