1
Fork 0

errors: implement sysroot/testing bundle loading

Extend loading of Fluent bundles so that bundles can be loaded from the
sysroot based on the language requested by the user, or using a nightly
flag.

Sysroot bundles are loaded from `$sysroot/share/locale/$locale/*.ftl`.

Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
David Wood 2022-03-28 09:36:20 +01:00
parent 7f91697b50
commit d5119c5b9f
23 changed files with 322 additions and 46 deletions

View file

@ -2856,6 +2856,7 @@ crate mod dep_tracking {
use crate::lint;
use crate::options::WasiExecModel;
use crate::utils::{NativeLib, NativeLibKind};
use rustc_errors::LanguageIdentifier;
use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
use rustc_span::RealFileName;
@ -2948,6 +2949,7 @@ crate mod dep_tracking {
LocationDetail,
BranchProtection,
OomStrategy,
LanguageIdentifier,
);
impl<T1, T2> DepTrackingHash for (T1, T2)

View file

@ -4,6 +4,7 @@ use crate::early_error;
use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::NativeLib;
use rustc_errors::LanguageIdentifier;
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
use rustc_target::spec::{
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
@ -365,6 +366,7 @@ mod desc {
pub const parse_string: &str = "a string";
pub const parse_opt_string: &str = parse_string;
pub const parse_string_push: &str = parse_string;
pub const parse_opt_langid: &str = "a language identifier";
pub const parse_opt_pathbuf: &str = "a path";
pub const parse_list: &str = "a space-separated list of strings";
pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
@ -487,6 +489,17 @@ mod parse {
}
}
/// Parse an optional language identifier, e.g. `en-US` or `zh-CN`.
crate fn parse_opt_langid(slot: &mut Option<LanguageIdentifier>, v: Option<&str>) -> bool {
match v {
Some(s) => {
*slot = rustc_errors::LanguageIdentifier::from_str(s).ok();
true
}
None => false,
}
}
crate fn parse_opt_pathbuf(slot: &mut Option<PathBuf>, v: Option<&str>) -> bool {
match v {
Some(s) => {
@ -1462,6 +1475,13 @@ options! {
"the directory the intermediate files are written to"),
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
"set the current terminal width"),
// Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
// alongside query results and changes to translation options can affect diagnostics - so
// translation options should be tracked.
translate_lang: Option<LanguageIdentifier> = (None, parse_opt_langid, [TRACKED],
"language identifier for diagnostic output"),
translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"additional fluent translation to preferentially use (for testing translation)"),
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select processor to schedule for (`rustc --print target-cpus` for details)"),
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],

View file

@ -174,13 +174,15 @@ pub struct ParseSess {
impl ParseSess {
/// Used for testing.
pub fn new(file_path_mapping: FilePathMapping) -> Self {
let fallback_bundle = fallback_fluent_bundle();
let fallback_bundle =
fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
let sm = Lrc::new(SourceMap::new(file_path_mapping));
let handler = Handler::with_tty_emitter(
ColorConfig::Auto,
true,
None,
Some(sm.clone()),
None,
fallback_bundle,
);
ParseSess::with_span_handler(handler, sm)
@ -211,10 +213,11 @@ impl ParseSess {
}
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
let fallback_bundle = fallback_fluent_bundle();
let fallback_bundle =
fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fatal_handler =
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, fallback_bundle);
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
let handler = Handler::with_emitter(
false,
None,

View file

@ -20,8 +20,8 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed,
FluentBundle, MultiSpan,
fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
ErrorGuaranteed, FluentBundle, MultiSpan,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@ -1069,6 +1069,7 @@ fn default_emitter(
sopts: &config::Options,
registry: rustc_errors::registry::Registry,
source_map: Lrc<SourceMap>,
bundle: Option<Lrc<FluentBundle>>,
fallback_bundle: Lrc<FluentBundle>,
emitter_dest: Option<Box<dyn Write + Send>>,
) -> Box<dyn Emitter + sync::Send> {
@ -1080,6 +1081,7 @@ fn default_emitter(
if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
let emitter = AnnotateSnippetEmitterWriter::new(
Some(source_map),
bundle,
fallback_bundle,
short,
macro_backtrace,
@ -1090,6 +1092,7 @@ fn default_emitter(
None => EmitterWriter::stderr(
color_config,
Some(source_map),
bundle,
fallback_bundle,
short,
sopts.debugging_opts.teach,
@ -1099,6 +1102,7 @@ fn default_emitter(
Some(dst) => EmitterWriter::new(
dst,
Some(source_map),
bundle,
fallback_bundle,
short,
false, // no teach messages when writing to a buffer
@ -1114,6 +1118,7 @@ fn default_emitter(
JsonEmitter::stderr(
Some(registry),
source_map,
bundle,
fallback_bundle,
pretty,
json_rendered,
@ -1127,6 +1132,7 @@ fn default_emitter(
dst,
Some(registry),
source_map,
bundle,
fallback_bundle,
pretty,
json_rendered,
@ -1198,9 +1204,15 @@ pub fn build_session(
hash_kind,
));
let fallback_bundle = fallback_fluent_bundle();
let bundle = fluent_bundle(
&sysroot,
sopts.debugging_opts.translate_lang.clone(),
sopts.debugging_opts.translate_additional_ftl.as_deref(),
)
.expect("failed to load fluent bundle");
let fallback_bundle = fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
let emitter =
default_emitter(&sopts, registry, source_map.clone(), fallback_bundle.clone(), write_dest);
default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle, write_dest);
let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
emitter,
@ -1433,13 +1445,14 @@ pub enum IncrCompSession {
}
fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
let fallback_bundle = fallback_fluent_bundle();
let fallback_bundle = fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
let emitter: Box<dyn Emitter + sync::Send> = match output {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
Box::new(EmitterWriter::stderr(
color_config,
None,
None,
fallback_bundle,
short,
false,
@ -1448,7 +1461,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
))
}
config::ErrorOutputType::Json { pretty, json_rendered } => {
Box::new(JsonEmitter::basic(pretty, json_rendered, fallback_bundle, None, false))
Box::new(JsonEmitter::basic(pretty, json_rendered, None, fallback_bundle, None, false))
}
};
rustc_errors::Handler::with_emitter(true, None, emitter)