From ed707a106cac7393db3b59d85b8b065d09840c61 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 19 Jan 2023 23:48:08 +0000 Subject: [PATCH 1/2] Detect references to non-existant messages in Fluent resources --- .../rustc_macros/src/diagnostics/fluent.rs | 34 +++++++++++++++++-- .../fluent-messages/missing-message-ref.ftl | 1 + tests/ui-fulldeps/fluent-messages/test.rs | 9 +++++ tests/ui-fulldeps/fluent-messages/test.stderr | 10 +++++- 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 32338f9dfc5e3..08098c9bb2a85 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -4,7 +4,10 @@ use annotate_snippets::{ }; use fluent_bundle::{FluentBundle, FluentError, FluentResource}; use fluent_syntax::{ - ast::{Attribute, Entry, Identifier, Message}, + ast::{ + Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, + PatternElement, + }, parser::ParserError, }; use proc_macro::{Diagnostic, Level, Span}; @@ -185,9 +188,12 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok }; let mut constants = TokenStream::new(); + let mut messagerefs = Vec::new(); for entry in resource.entries() { let span = res.krate.span(); - if let Entry::Message(Message { id: Identifier { name }, attributes, .. }) = entry { + if let Entry::Message(Message { id: Identifier { name }, attributes, value, .. }) = + entry + { let _ = previous_defns.entry(name.to_string()).or_insert(path_span); if name.contains('-') { @@ -200,6 +206,18 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok .emit(); } + if let Some(Pattern { elements }) = value { + for elt in elements { + if let PatternElement::Placeable { + expression: + Expression::Inline(InlineExpression::MessageReference { id, .. }), + } = elt + { + messagerefs.push((id.name, *name)); + } + } + } + // Require that the message name starts with the crate name // `hir_typeck_foo_bar` (in `hir_typeck.ftl`) // `const_eval_baz` (in `const_eval.ftl`) @@ -258,6 +276,18 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok } } + for (mref, name) in messagerefs.into_iter() { + if !previous_defns.contains_key(mref) { + Diagnostic::spanned( + path_span, + Level::Error, + format!("referenced message `{mref}` does not exist (in message `{name}`)"), + ) + .help(&format!("you may have meant to use a variable reference (`{{${mref}}}`)")) + .emit(); + } + } + if let Err(errs) = bundle.add_resource(resource) { for e in errs { match e { diff --git a/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl new file mode 100644 index 0000000000000..0cd8229b23010 --- /dev/null +++ b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl @@ -0,0 +1 @@ +missing_message_ref = {message} diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs index 4e8147e2b76dc..74303e97dba94 100644 --- a/tests/ui-fulldeps/fluent-messages/test.rs +++ b/tests/ui-fulldeps/fluent-messages/test.rs @@ -96,3 +96,12 @@ mod missing_crate_name { use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate_foo, with_hyphens}; } + +mod missing_message_ref { + use super::fluent_messages; + + fluent_messages! { + missing => "./missing-message-ref.ftl" +//~^ ERROR referenced message `message` does not exist + } +} diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr index d1cd4fe26da27..2631b0a623275 100644 --- a/tests/ui-fulldeps/fluent-messages/test.stderr +++ b/tests/ui-fulldeps/fluent-messages/test.stderr @@ -93,6 +93,14 @@ LL | test_crate => "./missing-crate-name.ftl", | = help: replace any '-'s with '_'s -error: aborting due to 10 previous errors +error: referenced message `message` does not exist (in message `missing_message_ref`) + --> $DIR/test.rs:104:20 + | +LL | missing => "./missing-message-ref.ftl" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: you may have meant to use a variable reference (`{$message}`) + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0428`. From 0ae0d87c5dd7b0b0b17124dadb2d5a3ce7e2bfef Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 19 Jan 2023 23:53:26 +0000 Subject: [PATCH 2/2] Fix some Fluent typos --- compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl | 2 +- compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index 08ce5172574ac..6101b28ab0cdd 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -23,7 +23,7 @@ codegen_gcc_invalid_monomorphization_unsupported_element = invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}` codegen_gcc_invalid_monomorphization_invalid_bitmask = - invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` + invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` codegen_gcc_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index c8c7afb5f9196..4924105128db6 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -179,9 +179,9 @@ codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$ codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` -codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error} +codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} -codegen_ssa_read_file = failed to read file: {message} +codegen_ssa_read_file = failed to read file: {$message} codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target