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:
parent
7f91697b50
commit
d5119c5b9f
23 changed files with 322 additions and 46 deletions
13
Cargo.lock
13
Cargo.lock
|
@ -1238,16 +1238,6 @@ dependencies = [
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fluent"
|
|
||||||
version = "0.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7"
|
|
||||||
dependencies = [
|
|
||||||
"fluent-bundle",
|
|
||||||
"unic-langid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluent-bundle"
|
name = "fluent-bundle"
|
||||||
version = "0.15.2"
|
version = "0.15.2"
|
||||||
|
@ -3719,7 +3709,8 @@ version = "0.0.0"
|
||||||
name = "rustc_error_messages"
|
name = "rustc_error_messages"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluent",
|
"fluent-bundle",
|
||||||
|
"fluent-syntax",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
|
|
|
@ -1172,10 +1172,12 @@ static DEFAULT_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send +
|
||||||
/// When `install_ice_hook` is called, this function will be called as the panic
|
/// When `install_ice_hook` is called, this function will be called as the panic
|
||||||
/// hook.
|
/// hook.
|
||||||
pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle =
|
||||||
|
rustc_errors::fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
|
||||||
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
|
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
|
||||||
rustc_errors::ColorConfig::Auto,
|
rustc_errors::ColorConfig::Auto,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -7,7 +7,8 @@ edition = "2021"
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluent = "0.16.0"
|
fluent-bundle = "0.15.2"
|
||||||
|
fluent-syntax = "0.11"
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_serialize = { path = "../rustc_serialize" }
|
rustc_serialize = { path = "../rustc_serialize" }
|
||||||
rustc_span = { path = "../rustc_span" }
|
rustc_span = { path = "../rustc_span" }
|
||||||
|
|
|
@ -1,24 +1,169 @@
|
||||||
|
#![feature(path_try_exists)]
|
||||||
|
|
||||||
|
use fluent_bundle::FluentResource;
|
||||||
|
use fluent_syntax::parser::ParserError;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_macros::{Decodable, Encodable};
|
use rustc_macros::{Decodable, Encodable};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use tracing::debug;
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fs;
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
use tracing::{instrument, trace};
|
||||||
|
|
||||||
pub use fluent::{FluentArgs, FluentValue};
|
pub use fluent_bundle::{FluentArgs, FluentError, FluentValue};
|
||||||
|
pub use unic_langid::{langid, LanguageIdentifier};
|
||||||
|
|
||||||
static FALLBACK_FLUENT_RESOURCE: &'static str = include_str!("../locales/en-US/diagnostics.ftl");
|
static FALLBACK_FLUENT_RESOURCE: &'static str = include_str!("../locales/en-US/diagnostics.ftl");
|
||||||
|
|
||||||
pub type FluentBundle = fluent::FluentBundle<fluent::FluentResource>;
|
pub type FluentBundle = fluent_bundle::FluentBundle<FluentResource>;
|
||||||
|
|
||||||
/// Return the default `FluentBundle` with standard en-US diagnostic messages.
|
#[derive(Debug)]
|
||||||
pub fn fallback_fluent_bundle() -> Lrc<FluentBundle> {
|
pub enum TranslationBundleError {
|
||||||
let fallback_resource = fluent::FluentResource::try_new(FALLBACK_FLUENT_RESOURCE.to_string())
|
/// Failed to read from `.ftl` file.
|
||||||
.expect("failed to parse ftl resource");
|
ReadFtl(io::Error),
|
||||||
debug!(?fallback_resource);
|
/// Failed to parse contents of `.ftl` file.
|
||||||
let mut fallback_bundle = FluentBundle::new(vec![unic_langid::langid!("en-US")]);
|
ParseFtl(ParserError),
|
||||||
fallback_bundle.add_resource(fallback_resource).expect("failed to add resource to bundle");
|
/// Failed to add `FluentResource` to `FluentBundle`.
|
||||||
|
AddResource(FluentError),
|
||||||
|
/// `$sysroot/share/locale/$locale` does not exist.
|
||||||
|
MissingLocale(io::Error),
|
||||||
|
/// Cannot read directory entries of `$sysroot/share/locale/$locale`.
|
||||||
|
ReadLocalesDir(io::Error),
|
||||||
|
/// Cannot read directory entry of `$sysroot/share/locale/$locale`.
|
||||||
|
ReadLocalesDirEntry(io::Error),
|
||||||
|
/// `$sysroot/share/locale/$locale` is not a directory.
|
||||||
|
LocaleIsNotDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TranslationBundleError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
TranslationBundleError::ReadFtl(e) => write!(f, "could not read ftl file: {}", e),
|
||||||
|
TranslationBundleError::ParseFtl(e) => {
|
||||||
|
write!(f, "could not parse ftl file: {}", e)
|
||||||
|
}
|
||||||
|
TranslationBundleError::AddResource(e) => write!(f, "failed to add resource: {}", e),
|
||||||
|
TranslationBundleError::MissingLocale(e) => {
|
||||||
|
write!(f, "missing locale directory: {}", e)
|
||||||
|
}
|
||||||
|
TranslationBundleError::ReadLocalesDir(e) => {
|
||||||
|
write!(f, "could not read locales dir: {}", e)
|
||||||
|
}
|
||||||
|
TranslationBundleError::ReadLocalesDirEntry(e) => {
|
||||||
|
write!(f, "could not read locales dir entry: {}", e)
|
||||||
|
}
|
||||||
|
TranslationBundleError::LocaleIsNotDir => {
|
||||||
|
write!(f, "`$sysroot/share/locales/$locale` is not a directory")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for TranslationBundleError {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
TranslationBundleError::ReadFtl(e) => Some(e),
|
||||||
|
TranslationBundleError::ParseFtl(e) => Some(e),
|
||||||
|
TranslationBundleError::AddResource(e) => Some(e),
|
||||||
|
TranslationBundleError::MissingLocale(e) => Some(e),
|
||||||
|
TranslationBundleError::ReadLocalesDir(e) => Some(e),
|
||||||
|
TranslationBundleError::ReadLocalesDirEntry(e) => Some(e),
|
||||||
|
TranslationBundleError::LocaleIsNotDir => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(FluentResource, Vec<ParserError>)> for TranslationBundleError {
|
||||||
|
fn from((_, mut errs): (FluentResource, Vec<ParserError>)) -> Self {
|
||||||
|
TranslationBundleError::ParseFtl(errs.pop().expect("failed ftl parse with no errors"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<FluentError>> for TranslationBundleError {
|
||||||
|
fn from(mut errs: Vec<FluentError>) -> Self {
|
||||||
|
TranslationBundleError::AddResource(
|
||||||
|
errs.pop().expect("failed adding resource to bundle with no errors"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns Fluent bundle with the user's locale resources from
|
||||||
|
/// `$sysroot/share/locale/$requested_locale/*.ftl`.
|
||||||
|
///
|
||||||
|
/// If `-Z additional-ftl-path` was provided, load that resource and add it to the bundle
|
||||||
|
/// (overriding any conflicting messages).
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
pub fn fluent_bundle(
|
||||||
|
sysroot: &Path,
|
||||||
|
requested_locale: Option<LanguageIdentifier>,
|
||||||
|
additional_ftl_path: Option<&Path>,
|
||||||
|
) -> Result<Option<Lrc<FluentBundle>>, TranslationBundleError> {
|
||||||
|
if requested_locale.is_none() && additional_ftl_path.is_none() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is only `-Z additional-ftl-path`, assume locale is "en-US", otherwise use user
|
||||||
|
// provided locale.
|
||||||
|
let locale = requested_locale.clone().unwrap_or_else(|| langid!("en-US"));
|
||||||
|
trace!(?locale);
|
||||||
|
let mut bundle = FluentBundle::new(vec![locale]);
|
||||||
|
|
||||||
|
if let Some(requested_locale) = requested_locale {
|
||||||
|
let mut sysroot = sysroot.to_path_buf();
|
||||||
|
sysroot.push("share");
|
||||||
|
sysroot.push("locale");
|
||||||
|
sysroot.push(requested_locale.to_string());
|
||||||
|
trace!(?sysroot);
|
||||||
|
|
||||||
|
let _ = sysroot.try_exists().map_err(TranslationBundleError::MissingLocale)?;
|
||||||
|
|
||||||
|
if !sysroot.is_dir() {
|
||||||
|
return Err(TranslationBundleError::LocaleIsNotDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in sysroot.read_dir().map_err(TranslationBundleError::ReadLocalesDir)? {
|
||||||
|
let entry = entry.map_err(TranslationBundleError::ReadLocalesDirEntry)?;
|
||||||
|
let path = entry.path();
|
||||||
|
trace!(?path);
|
||||||
|
if path.extension().and_then(|s| s.to_str()) != Some("ftl") {
|
||||||
|
trace!("skipping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let resource_str = fs::read_to_string(path).map_err(TranslationBundleError::ReadFtl)?;
|
||||||
|
let resource =
|
||||||
|
FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
|
||||||
|
trace!(?resource);
|
||||||
|
bundle.add_resource(resource).map_err(TranslationBundleError::from)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(additional_ftl_path) = additional_ftl_path {
|
||||||
|
let resource_str =
|
||||||
|
fs::read_to_string(additional_ftl_path).map_err(TranslationBundleError::ReadFtl)?;
|
||||||
|
let resource =
|
||||||
|
FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
|
||||||
|
trace!(?resource);
|
||||||
|
bundle.add_resource_overriding(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bundle = Lrc::new(bundle);
|
||||||
|
Ok(Some(bundle))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
pub fn fallback_fluent_bundle() -> Result<Lrc<FluentBundle>, TranslationBundleError> {
|
||||||
|
let fallback_resource = FluentResource::try_new(FALLBACK_FLUENT_RESOURCE.to_string())
|
||||||
|
.map_err(TranslationBundleError::from)?;
|
||||||
|
trace!(?fallback_resource);
|
||||||
|
let mut fallback_bundle = FluentBundle::new(vec![langid!("en-US")]);
|
||||||
|
fallback_bundle.add_resource(fallback_resource).map_err(TranslationBundleError::from)?;
|
||||||
let fallback_bundle = Lrc::new(fallback_bundle);
|
let fallback_bundle = Lrc::new(fallback_bundle);
|
||||||
fallback_bundle
|
Ok(fallback_bundle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identifier for the Fluent message/attribute corresponding to a diagnostic message.
|
/// Identifier for the Fluent message/attribute corresponding to a diagnostic message.
|
||||||
|
|
|
@ -21,6 +21,7 @@ use rustc_span::SourceFile;
|
||||||
/// Generates diagnostics using annotate-snippet
|
/// Generates diagnostics using annotate-snippet
|
||||||
pub struct AnnotateSnippetEmitterWriter {
|
pub struct AnnotateSnippetEmitterWriter {
|
||||||
source_map: Option<Lrc<SourceMap>>,
|
source_map: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
|
|
||||||
/// If true, hides the longer explanation text
|
/// If true, hides the longer explanation text
|
||||||
|
@ -63,7 +64,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
None
|
self.fluent_bundle.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
|
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
|
||||||
|
@ -99,11 +100,19 @@ fn annotation_type_for_level(level: Level) -> AnnotationType {
|
||||||
impl AnnotateSnippetEmitterWriter {
|
impl AnnotateSnippetEmitterWriter {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
source_map: Option<Lrc<SourceMap>>,
|
source_map: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
short_message: bool,
|
short_message: bool,
|
||||||
macro_backtrace: bool,
|
macro_backtrace: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self { source_map, fallback_bundle, short_message, ui_testing: false, macro_backtrace }
|
Self {
|
||||||
|
source_map,
|
||||||
|
fluent_bundle,
|
||||||
|
fallback_bundle,
|
||||||
|
short_message,
|
||||||
|
ui_testing: false,
|
||||||
|
macro_backtrace,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows to modify `Self` to enable or disable the `ui_testing` flag.
|
/// Allows to modify `Self` to enable or disable the `ui_testing` flag.
|
||||||
|
|
|
@ -59,6 +59,7 @@ impl HumanReadableErrorType {
|
||||||
self,
|
self,
|
||||||
dst: Box<dyn Write + Send>,
|
dst: Box<dyn Write + Send>,
|
||||||
source_map: Option<Lrc<SourceMap>>,
|
source_map: Option<Lrc<SourceMap>>,
|
||||||
|
bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
terminal_width: Option<usize>,
|
terminal_width: Option<usize>,
|
||||||
|
@ -69,6 +70,7 @@ impl HumanReadableErrorType {
|
||||||
EmitterWriter::new(
|
EmitterWriter::new(
|
||||||
dst,
|
dst,
|
||||||
source_map,
|
source_map,
|
||||||
|
bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short,
|
short,
|
||||||
teach,
|
teach,
|
||||||
|
@ -568,7 +570,7 @@ impl Emitter for EmitterWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
None
|
self.fluent_bundle.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
|
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
|
||||||
|
@ -686,6 +688,7 @@ impl ColorConfig {
|
||||||
pub struct EmitterWriter {
|
pub struct EmitterWriter {
|
||||||
dst: Destination,
|
dst: Destination,
|
||||||
sm: Option<Lrc<SourceMap>>,
|
sm: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
short_message: bool,
|
short_message: bool,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
|
@ -706,6 +709,7 @@ impl EmitterWriter {
|
||||||
pub fn stderr(
|
pub fn stderr(
|
||||||
color_config: ColorConfig,
|
color_config: ColorConfig,
|
||||||
source_map: Option<Lrc<SourceMap>>,
|
source_map: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
short_message: bool,
|
short_message: bool,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
|
@ -716,6 +720,7 @@ impl EmitterWriter {
|
||||||
EmitterWriter {
|
EmitterWriter {
|
||||||
dst,
|
dst,
|
||||||
sm: source_map,
|
sm: source_map,
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short_message,
|
short_message,
|
||||||
teach,
|
teach,
|
||||||
|
@ -728,6 +733,7 @@ impl EmitterWriter {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
dst: Box<dyn Write + Send>,
|
dst: Box<dyn Write + Send>,
|
||||||
source_map: Option<Lrc<SourceMap>>,
|
source_map: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
short_message: bool,
|
short_message: bool,
|
||||||
teach: bool,
|
teach: bool,
|
||||||
|
@ -738,6 +744,7 @@ impl EmitterWriter {
|
||||||
EmitterWriter {
|
EmitterWriter {
|
||||||
dst: Raw(dst, colored),
|
dst: Raw(dst, colored),
|
||||||
sm: source_map,
|
sm: source_map,
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short_message,
|
short_message,
|
||||||
teach,
|
teach,
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub struct JsonEmitter {
|
||||||
dst: Box<dyn Write + Send>,
|
dst: Box<dyn Write + Send>,
|
||||||
registry: Option<Registry>,
|
registry: Option<Registry>,
|
||||||
sm: Lrc<SourceMap>,
|
sm: Lrc<SourceMap>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
ui_testing: bool,
|
ui_testing: bool,
|
||||||
|
@ -49,6 +50,7 @@ impl JsonEmitter {
|
||||||
pub fn stderr(
|
pub fn stderr(
|
||||||
registry: Option<Registry>,
|
registry: Option<Registry>,
|
||||||
source_map: Lrc<SourceMap>,
|
source_map: Lrc<SourceMap>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
json_rendered: HumanReadableErrorType,
|
json_rendered: HumanReadableErrorType,
|
||||||
|
@ -59,6 +61,7 @@ impl JsonEmitter {
|
||||||
dst: Box::new(io::BufWriter::new(io::stderr())),
|
dst: Box::new(io::BufWriter::new(io::stderr())),
|
||||||
registry,
|
registry,
|
||||||
sm: source_map,
|
sm: source_map,
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
pretty,
|
pretty,
|
||||||
ui_testing: false,
|
ui_testing: false,
|
||||||
|
@ -71,6 +74,7 @@ impl JsonEmitter {
|
||||||
pub fn basic(
|
pub fn basic(
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
json_rendered: HumanReadableErrorType,
|
json_rendered: HumanReadableErrorType,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
terminal_width: Option<usize>,
|
terminal_width: Option<usize>,
|
||||||
macro_backtrace: bool,
|
macro_backtrace: bool,
|
||||||
|
@ -79,6 +83,7 @@ impl JsonEmitter {
|
||||||
JsonEmitter::stderr(
|
JsonEmitter::stderr(
|
||||||
None,
|
None,
|
||||||
Lrc::new(SourceMap::new(file_path_mapping)),
|
Lrc::new(SourceMap::new(file_path_mapping)),
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
pretty,
|
pretty,
|
||||||
json_rendered,
|
json_rendered,
|
||||||
|
@ -91,6 +96,7 @@ impl JsonEmitter {
|
||||||
dst: Box<dyn Write + Send>,
|
dst: Box<dyn Write + Send>,
|
||||||
registry: Option<Registry>,
|
registry: Option<Registry>,
|
||||||
source_map: Lrc<SourceMap>,
|
source_map: Lrc<SourceMap>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
json_rendered: HumanReadableErrorType,
|
json_rendered: HumanReadableErrorType,
|
||||||
|
@ -101,6 +107,7 @@ impl JsonEmitter {
|
||||||
dst,
|
dst,
|
||||||
registry,
|
registry,
|
||||||
sm: source_map,
|
sm: source_map,
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
pretty,
|
pretty,
|
||||||
ui_testing: false,
|
ui_testing: false,
|
||||||
|
@ -182,7 +189,7 @@ impl Emitter for JsonEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
None
|
self.fluent_bundle.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
|
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
|
||||||
|
@ -395,6 +402,7 @@ impl Diagnostic {
|
||||||
.new_emitter(
|
.new_emitter(
|
||||||
Box::new(buf),
|
Box::new(buf),
|
||||||
Some(je.sm.clone()),
|
Some(je.sm.clone()),
|
||||||
|
je.fluent_bundle.clone(),
|
||||||
je.fallback_bundle.clone(),
|
je.fallback_bundle.clone(),
|
||||||
false,
|
false,
|
||||||
je.terminal_width,
|
je.terminal_width,
|
||||||
|
|
|
@ -39,13 +39,15 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
||||||
rustc_span::create_default_session_globals_then(|| {
|
rustc_span::create_default_session_globals_then(|| {
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
|
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
|
||||||
let fallback_bundle = crate::fallback_fluent_bundle();
|
let fallback_bundle =
|
||||||
|
crate::fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
|
||||||
|
|
||||||
let output = Arc::new(Mutex::new(Vec::new()));
|
let output = Arc::new(Mutex::new(Vec::new()));
|
||||||
let je = JsonEmitter::new(
|
let je = JsonEmitter::new(
|
||||||
Box::new(Shared { data: output.clone() }),
|
Box::new(Shared { data: output.clone() }),
|
||||||
None,
|
None,
|
||||||
sm,
|
sm,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
true,
|
true,
|
||||||
HumanReadableErrorType::Short(ColorConfig::Never),
|
HumanReadableErrorType::Short(ColorConfig::Never),
|
||||||
|
|
|
@ -32,7 +32,8 @@ use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use rustc_data_structures::sync::{self, Lock, Lrc};
|
use rustc_data_structures::sync::{self, Lock, Lrc};
|
||||||
use rustc_data_structures::AtomicRef;
|
use rustc_data_structures::AtomicRef;
|
||||||
pub use rustc_error_messages::{
|
pub use rustc_error_messages::{
|
||||||
fallback_fluent_bundle, DiagnosticMessage, FluentBundle, MultiSpan, SpanLabel,
|
fallback_fluent_bundle, fluent_bundle, DiagnosticMessage, FluentBundle, LanguageIdentifier,
|
||||||
|
MultiSpan, SpanLabel,
|
||||||
};
|
};
|
||||||
pub use rustc_lint_defs::{pluralize, Applicability};
|
pub use rustc_lint_defs::{pluralize, Applicability};
|
||||||
use rustc_serialize::json::Json;
|
use rustc_serialize::json::Json;
|
||||||
|
@ -544,11 +545,13 @@ impl Handler {
|
||||||
can_emit_warnings: bool,
|
can_emit_warnings: bool,
|
||||||
treat_err_as_bug: Option<NonZeroUsize>,
|
treat_err_as_bug: Option<NonZeroUsize>,
|
||||||
sm: Option<Lrc<SourceMap>>,
|
sm: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::with_tty_emitter_and_flags(
|
Self::with_tty_emitter_and_flags(
|
||||||
color_config,
|
color_config,
|
||||||
sm,
|
sm,
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
||||||
)
|
)
|
||||||
|
@ -557,12 +560,14 @@ impl Handler {
|
||||||
pub fn with_tty_emitter_and_flags(
|
pub fn with_tty_emitter_and_flags(
|
||||||
color_config: ColorConfig,
|
color_config: ColorConfig,
|
||||||
sm: Option<Lrc<SourceMap>>,
|
sm: Option<Lrc<SourceMap>>,
|
||||||
|
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
flags: HandlerFlags,
|
flags: HandlerFlags,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let emitter = Box::new(EmitterWriter::stderr(
|
let emitter = Box::new(EmitterWriter::stderr(
|
||||||
color_config,
|
color_config,
|
||||||
sm,
|
sm,
|
||||||
|
fluent_bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -127,7 +127,8 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
||||||
create_default_session_if_not_set_then(|_| {
|
create_default_session_if_not_set_then(|_| {
|
||||||
let output = Arc::new(Mutex::new(Vec::new()));
|
let output = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle =
|
||||||
|
rustc_errors::fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
|
||||||
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
|
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
|
||||||
|
|
||||||
|
@ -143,6 +144,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
||||||
let emitter = EmitterWriter::new(
|
let emitter = EmitterWriter::new(
|
||||||
Box::new(Shared { data: output.clone() }),
|
Box::new(Shared { data: output.clone() }),
|
||||||
Some(source_map.clone()),
|
Some(source_map.clone()),
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -2856,6 +2856,7 @@ crate mod dep_tracking {
|
||||||
use crate::lint;
|
use crate::lint;
|
||||||
use crate::options::WasiExecModel;
|
use crate::options::WasiExecModel;
|
||||||
use crate::utils::{NativeLib, NativeLibKind};
|
use crate::utils::{NativeLib, NativeLibKind};
|
||||||
|
use rustc_errors::LanguageIdentifier;
|
||||||
use rustc_feature::UnstableFeatures;
|
use rustc_feature::UnstableFeatures;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::RealFileName;
|
use rustc_span::RealFileName;
|
||||||
|
@ -2948,6 +2949,7 @@ crate mod dep_tracking {
|
||||||
LocationDetail,
|
LocationDetail,
|
||||||
BranchProtection,
|
BranchProtection,
|
||||||
OomStrategy,
|
OomStrategy,
|
||||||
|
LanguageIdentifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<T1, T2> DepTrackingHash for (T1, T2)
|
impl<T1, T2> DepTrackingHash for (T1, T2)
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::early_error;
|
||||||
use crate::lint;
|
use crate::lint;
|
||||||
use crate::search_paths::SearchPath;
|
use crate::search_paths::SearchPath;
|
||||||
use crate::utils::NativeLib;
|
use crate::utils::NativeLib;
|
||||||
|
use rustc_errors::LanguageIdentifier;
|
||||||
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
|
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
|
||||||
use rustc_target::spec::{
|
use rustc_target::spec::{
|
||||||
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
|
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
|
||||||
|
@ -365,6 +366,7 @@ mod desc {
|
||||||
pub const parse_string: &str = "a string";
|
pub const parse_string: &str = "a string";
|
||||||
pub const parse_opt_string: &str = parse_string;
|
pub const parse_opt_string: &str = parse_string;
|
||||||
pub const parse_string_push: &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_opt_pathbuf: &str = "a path";
|
||||||
pub const parse_list: &str = "a space-separated list of strings";
|
pub const parse_list: &str = "a space-separated list of strings";
|
||||||
pub const parse_opt_comma_list: &str = "a comma-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 {
|
crate fn parse_opt_pathbuf(slot: &mut Option<PathBuf>, v: Option<&str>) -> bool {
|
||||||
match v {
|
match v {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
|
@ -1462,6 +1475,13 @@ options! {
|
||||||
"the directory the intermediate files are written to"),
|
"the directory the intermediate files are written to"),
|
||||||
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
|
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
|
||||||
"set the current terminal width"),
|
"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],
|
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||||
"select processor to schedule for (`rustc --print target-cpus` for details)"),
|
"select processor to schedule for (`rustc --print target-cpus` for details)"),
|
||||||
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
|
|
|
@ -174,13 +174,15 @@ pub struct ParseSess {
|
||||||
impl ParseSess {
|
impl ParseSess {
|
||||||
/// Used for testing.
|
/// Used for testing.
|
||||||
pub fn new(file_path_mapping: FilePathMapping) -> Self {
|
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 sm = Lrc::new(SourceMap::new(file_path_mapping));
|
||||||
let handler = Handler::with_tty_emitter(
|
let handler = Handler::with_tty_emitter(
|
||||||
ColorConfig::Auto,
|
ColorConfig::Auto,
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
Some(sm.clone()),
|
Some(sm.clone()),
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
);
|
);
|
||||||
ParseSess::with_span_handler(handler, sm)
|
ParseSess::with_span_handler(handler, sm)
|
||||||
|
@ -211,10 +213,11 @@ impl ParseSess {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
|
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 sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let fatal_handler =
|
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(
|
let handler = Handler::with_emitter(
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -20,8 +20,8 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
|
||||||
use rustc_errors::json::JsonEmitter;
|
use rustc_errors::json::JsonEmitter;
|
||||||
use rustc_errors::registry::Registry;
|
use rustc_errors::registry::Registry;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed,
|
fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
||||||
FluentBundle, MultiSpan,
|
ErrorGuaranteed, FluentBundle, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
pub use rustc_span::def_id::StableCrateId;
|
pub use rustc_span::def_id::StableCrateId;
|
||||||
|
@ -1069,6 +1069,7 @@ fn default_emitter(
|
||||||
sopts: &config::Options,
|
sopts: &config::Options,
|
||||||
registry: rustc_errors::registry::Registry,
|
registry: rustc_errors::registry::Registry,
|
||||||
source_map: Lrc<SourceMap>,
|
source_map: Lrc<SourceMap>,
|
||||||
|
bundle: Option<Lrc<FluentBundle>>,
|
||||||
fallback_bundle: Lrc<FluentBundle>,
|
fallback_bundle: Lrc<FluentBundle>,
|
||||||
emitter_dest: Option<Box<dyn Write + Send>>,
|
emitter_dest: Option<Box<dyn Write + Send>>,
|
||||||
) -> Box<dyn Emitter + sync::Send> {
|
) -> Box<dyn Emitter + sync::Send> {
|
||||||
|
@ -1080,6 +1081,7 @@ fn default_emitter(
|
||||||
if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
|
if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
|
||||||
let emitter = AnnotateSnippetEmitterWriter::new(
|
let emitter = AnnotateSnippetEmitterWriter::new(
|
||||||
Some(source_map),
|
Some(source_map),
|
||||||
|
bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short,
|
short,
|
||||||
macro_backtrace,
|
macro_backtrace,
|
||||||
|
@ -1090,6 +1092,7 @@ fn default_emitter(
|
||||||
None => EmitterWriter::stderr(
|
None => EmitterWriter::stderr(
|
||||||
color_config,
|
color_config,
|
||||||
Some(source_map),
|
Some(source_map),
|
||||||
|
bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short,
|
short,
|
||||||
sopts.debugging_opts.teach,
|
sopts.debugging_opts.teach,
|
||||||
|
@ -1099,6 +1102,7 @@ fn default_emitter(
|
||||||
Some(dst) => EmitterWriter::new(
|
Some(dst) => EmitterWriter::new(
|
||||||
dst,
|
dst,
|
||||||
Some(source_map),
|
Some(source_map),
|
||||||
|
bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short,
|
short,
|
||||||
false, // no teach messages when writing to a buffer
|
false, // no teach messages when writing to a buffer
|
||||||
|
@ -1114,6 +1118,7 @@ fn default_emitter(
|
||||||
JsonEmitter::stderr(
|
JsonEmitter::stderr(
|
||||||
Some(registry),
|
Some(registry),
|
||||||
source_map,
|
source_map,
|
||||||
|
bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
pretty,
|
pretty,
|
||||||
json_rendered,
|
json_rendered,
|
||||||
|
@ -1127,6 +1132,7 @@ fn default_emitter(
|
||||||
dst,
|
dst,
|
||||||
Some(registry),
|
Some(registry),
|
||||||
source_map,
|
source_map,
|
||||||
|
bundle,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
pretty,
|
pretty,
|
||||||
json_rendered,
|
json_rendered,
|
||||||
|
@ -1198,9 +1204,15 @@ pub fn build_session(
|
||||||
hash_kind,
|
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 =
|
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(
|
let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
|
||||||
emitter,
|
emitter,
|
||||||
|
@ -1433,13 +1445,14 @@ pub enum IncrCompSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
|
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 {
|
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(kind) => {
|
config::ErrorOutputType::HumanReadable(kind) => {
|
||||||
let (short, color_config) = kind.unzip();
|
let (short, color_config) = kind.unzip();
|
||||||
Box::new(EmitterWriter::stderr(
|
Box::new(EmitterWriter::stderr(
|
||||||
color_config,
|
color_config,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short,
|
short,
|
||||||
false,
|
false,
|
||||||
|
@ -1448,7 +1461,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
config::ErrorOutputType::Json { pretty, json_rendered } => {
|
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)
|
rustc_errors::Handler::with_emitter(true, None, emitter)
|
||||||
|
|
|
@ -143,7 +143,8 @@ crate fn new_handler(
|
||||||
source_map: Option<Lrc<source_map::SourceMap>>,
|
source_map: Option<Lrc<source_map::SourceMap>>,
|
||||||
debugging_opts: &DebuggingOptions,
|
debugging_opts: &DebuggingOptions,
|
||||||
) -> rustc_errors::Handler {
|
) -> rustc_errors::Handler {
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle =
|
||||||
|
rustc_errors::fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
|
||||||
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
|
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
|
||||||
ErrorOutputType::HumanReadable(kind) => {
|
ErrorOutputType::HumanReadable(kind) => {
|
||||||
let (short, color_config) = kind.unzip();
|
let (short, color_config) = kind.unzip();
|
||||||
|
@ -151,6 +152,7 @@ crate fn new_handler(
|
||||||
EmitterWriter::stderr(
|
EmitterWriter::stderr(
|
||||||
color_config,
|
color_config,
|
||||||
source_map.map(|sm| sm as _),
|
source_map.map(|sm| sm as _),
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
short,
|
short,
|
||||||
debugging_opts.teach,
|
debugging_opts.teach,
|
||||||
|
@ -168,6 +170,7 @@ crate fn new_handler(
|
||||||
JsonEmitter::stderr(
|
JsonEmitter::stderr(
|
||||||
None,
|
None,
|
||||||
source_map,
|
source_map,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
pretty,
|
pretty,
|
||||||
json_rendered,
|
json_rendered,
|
||||||
|
|
|
@ -537,10 +537,12 @@ crate fn make_test(
|
||||||
// Any errors in parsing should also appear when the doctest is compiled for real, so just
|
// Any errors in parsing should also appear when the doctest is compiled for real, so just
|
||||||
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
|
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle = rustc_errors::fallback_fluent_bundle()
|
||||||
|
.expect("failed to load fallback fluent bundle");
|
||||||
supports_color = EmitterWriter::stderr(
|
supports_color = EmitterWriter::stderr(
|
||||||
ColorConfig::Auto,
|
ColorConfig::Auto,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
fallback_bundle.clone(),
|
fallback_bundle.clone(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
@ -552,6 +554,7 @@ crate fn make_test(
|
||||||
let emitter = EmitterWriter::new(
|
let emitter = EmitterWriter::new(
|
||||||
box io::sink(),
|
box io::sink(),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -32,7 +32,8 @@ struct SyntaxChecker<'a, 'tcx> {
|
||||||
impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
|
impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
|
||||||
fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) {
|
fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) {
|
||||||
let buffer = Lrc::new(Lock::new(Buffer::default()));
|
let buffer = Lrc::new(Lock::new(Buffer::default()));
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle =
|
||||||
|
rustc_errors::fallback_fluent_bundle().expect("failed to load fallback fluent bundle");
|
||||||
let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
|
let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
|
||||||
|
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
|
|
33
src/test/run-make/translation/Makefile
Normal file
33
src/test/run-make/translation/Makefile
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
include ../../run-make-fulldeps/tools.mk
|
||||||
|
|
||||||
|
# This test uses `ln -s` rather than copying to save testing time, but its
|
||||||
|
# usage doesn't work on Windows.
|
||||||
|
# ignore-windows
|
||||||
|
|
||||||
|
SYSROOT:=$(shell $(RUSTC) --print sysroot)
|
||||||
|
FAKEROOT=$(TMPDIR)/fakeroot
|
||||||
|
|
||||||
|
all: normal custom sysroot
|
||||||
|
|
||||||
|
normal: basic-translation.rs
|
||||||
|
$(RUSTC) $< 2>&1 | grep "struct literal body without path"
|
||||||
|
|
||||||
|
custom: basic-translation.rs basic-translation.ftl
|
||||||
|
$(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/basic-translation.ftl 2>&1 | grep "this is a test message"
|
||||||
|
|
||||||
|
# Make a local copy of the sysroot and add the custom locale to it.
|
||||||
|
sysroot: basic-translation.rs basic-translation.ftl
|
||||||
|
mkdir $(FAKEROOT)
|
||||||
|
ln -s $(SYSROOT)/* $(FAKEROOT)
|
||||||
|
rm -f $(FAKEROOT)/lib
|
||||||
|
mkdir $(FAKEROOT)/lib
|
||||||
|
ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib
|
||||||
|
rm -f $(FAKEROOT)/lib/rustlib
|
||||||
|
mkdir $(FAKEROOT)/lib/rustlib
|
||||||
|
ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib
|
||||||
|
rm -f $(FAKEROOT)/lib/rustlib/src
|
||||||
|
mkdir $(FAKEROOT)/lib/rustlib/src
|
||||||
|
ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src
|
||||||
|
mkdir -p $(FAKEROOT)/share/locale/zh-CN/
|
||||||
|
ln -s $(CURDIR)/basic-translation.ftl $(FAKEROOT)/share/locale/zh-CN/basic-translation.ftl
|
||||||
|
$(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 | grep "this is a test message"
|
2
src/test/run-make/translation/basic-translation.ftl
Normal file
2
src/test/run-make/translation/basic-translation.ftl
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
parser-struct-literal-body-without-path = this is a test message
|
||||||
|
.suggestion = this is a test suggestion
|
18
src/test/run-make/translation/basic-translation.rs
Normal file
18
src/test/run-make/translation/basic-translation.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Exact error being tested isn't relevant, it just needs to be known that it uses Fluent-backed
|
||||||
|
// diagnostics.
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
val: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() -> Foo {
|
||||||
|
val: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = foo();
|
||||||
|
x.val == 42;
|
||||||
|
let x = {
|
||||||
|
val: (),
|
||||||
|
};
|
||||||
|
}
|
|
@ -621,10 +621,12 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
||||||
let filename = FileName::anon_source_code(&code);
|
let filename = FileName::anon_source_code(&code);
|
||||||
|
|
||||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle = rustc_errors::fallback_fluent_bundle()
|
||||||
|
.expect("failed to load fallback fluent bundle");
|
||||||
let emitter = EmitterWriter::new(
|
let emitter = EmitterWriter::new(
|
||||||
Box::new(io::sink()),
|
Box::new(io::sink()),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -165,10 +165,12 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||||
// Separate the output with an empty line
|
// Separate the output with an empty line
|
||||||
eprintln!();
|
eprintln!();
|
||||||
|
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle = rustc_errors::fallback_fluent_bundle()
|
||||||
|
.expect("failed to load fallback fluent bundle");
|
||||||
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
|
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
|
||||||
rustc_errors::ColorConfig::Auto,
|
rustc_errors::ColorConfig::Auto,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -114,10 +114,12 @@ fn default_handler(
|
||||||
let emitter = if hide_parse_errors {
|
let emitter = if hide_parse_errors {
|
||||||
silent_emitter()
|
silent_emitter()
|
||||||
} else {
|
} else {
|
||||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle();
|
let fallback_bundle = rustc_errors::fallback_fluent_bundle()
|
||||||
|
.expect("failed to load fallback fluent bundle");
|
||||||
Box::new(EmitterWriter::stderr(
|
Box::new(EmitterWriter::stderr(
|
||||||
color_cfg,
|
color_cfg,
|
||||||
Some(source_map.clone()),
|
Some(source_map.clone()),
|
||||||
|
None,
|
||||||
fallback_bundle,
|
fallback_bundle,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
Loading…
Add table
Reference in a new issue