Detect references to non-existant messages in Fluent resources

This commit is contained in:
clubby789 2023-01-19 23:48:08 +00:00
parent 5e37043d63
commit ed707a106c
4 changed files with 51 additions and 3 deletions

View File

@ -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 {

View File

@ -0,0 +1 @@
missing_message_ref = {message}

View File

@ -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
}
}

View File

@ -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`.