Use Fluent AST when reporting error spans
Dependencies
- [2]
VQBJBFEXImprove error handling for missing Fluent messages - [3]
2SITVDYWHandle common errors in Fluent code - [4]
3NMKD6I5Refactor `Localize` trait to use `std::io::Write` - [5]
D652S2N3Rename `parse` module to `parse_fluent` - [6]
F5LG7WENEmit compilation errors from Fluent source code - [7]
NO3PDO7PRefactor `fluent_embed` to support structs - [8]
CESJ4CTOMove macro-specific code into `macro_impl` module - [9]
C6W7N6N5Implement `Localize` for `FixedDecimal` and primitive number types - [10]
7M4UI3TWUpdate dependencies to latest versions - [11]
XGRU7WZEAdd `expand` feature for proc-macro debugging - [12]
HJMYJDC7Simplify `fluent_embed::group` module - [13]
5TEX4MNUSplit `fluent_embed` into `group` and `parse` modules - [14]
QFPQZR4KRefactor `fluent_embed` - [15]
GJMBIJOEMigrate to latest env_preferences version - [16]
7FYXVNABIgnore comments in Fluent source code - [*]
VZYZRAO4Move `output-macros` crate into workspace - [*]
UKFEFT6LCreate basic `Output` proc-macro
Change contents
- replacement in fluent_embed_derive/src/fluent/mod.rs at line 5
use fluent_syntax::ast::{Entry, Message, Pattern, Resource};use fluent_syntax::ast::{Entry, Message, Pattern}; - edit in fluent_embed_derive/src/fluent/mod.rs at line 58
root_id: &'context str, - replacement in fluent_embed_derive/src/fluent/mod.rs at line 64
path: PathBuf,syntax_tree: fluent_syntax::ast::Resource<String>,named_source: NamedSource<String>, - edit in fluent_embed_derive/src/fluent/mod.rs at line 72
let named_source = NamedSource::new(path.to_string_lossy(), file_contents.clone()); - replacement in fluent_embed_derive/src/fluent/mod.rs at line 111
path,syntax_tree,named_source, - edit in fluent_embed_derive/src/fluent/mod.rs at line 116
/// Calculate the byte offset of the serializedfn source_with_message_offset(&self, id: &str) -> (NamedSource<String>, usize) {// Find the message position in the ASTlet ast_index = self.syntax_tree.body.iter().position(|entry| {if let Entry::Message(message) = entry {message.id.name == id} else {false}}).unwrap();let options = fluent_syntax::serializer::Options {// Make sure to include all source code in error snippet, even if marked as "junk"with_junk: true,};// Serialize everything before this message to get the byte offsetlet source_before_message = fluent_syntax::serializer::serialize_with_options(&Resource {body: self.syntax_tree.body[0..ast_index].to_vec(),},options,);let byte_offset = source_before_message.len();let source_after_offset = fluent_syntax::serializer::serialize_with_options(&Resource {body: self.syntax_tree.body[ast_index..].to_vec(),},options,);let source = format!("{source_before_message}{source_after_offset}");let named_source = NamedSource::new(self.path.to_string_lossy(), source);(named_source, byte_offset)} - edit in fluent_embed_derive/src/fluent/mod.rs at line 128[2.1591]→[3.3459:3460](∅→∅),[3.3459]→[3.3459:3460](∅→∅),[3.3460]→[2.1592:1808](∅→∅),[2.1808]→[3.3937:3938](∅→∅),[3.3937]→[3.3937:3938](∅→∅),[3.3938]→[2.1809:2272](∅→∅)
// fn remove_expression(// &mut self,// id: &str,// derive_context: &derive::Context,// ) -> Result<syn::Expr, Error> {// let message = self.messages.remove(id).unwrap();// let message_context = MessageContext {// source: &self,// root_id: id,// // Any message where this value is `None` shouldn't be accessed directly, see:// // https://docs.rs/fluent-syntax/latest/fluent_syntax/ast/struct.Attribute.html#example// pattern: message.value.as_ref().unwrap(),// derive_context,// };// ast::message_body(message_context)// } - replacement in fluent_embed_derive/src/fluent/group.rs at line 73
let mut unexpected_keys = source_file.message_ids().filter(|id: &&str| !canonical_keys.contains(id));let mut unexpected_keys =source_file.messages.iter().filter(|(message_id, _message_value)| {!canonical_keys.contains(&message_id.as_str())}); - replacement in fluent_embed_derive/src/fluent/group.rs at line 81
if let Some(unexpected_key) = unexpected_keys.next() {let (src, message_offset) = source_file.source_with_message_offset(unexpected_key);// TODO: group all unexpected keys into single errorif let Some((unexpected_key, unexpected_message)) = unexpected_keys.next() {let source_code = source_file.named_source.clone(); - replacement in fluent_embed_derive/src/fluent/group.rs at line 89
source_code: src,span: SourceSpan::new(message_offset.into(), unexpected_key.len()),source_code,span: SourceSpan::from(unexpected_message.id.span.0.clone()), - edit in fluent_embed_derive/src/fluent/group.rs at line 123
root_id: &id, - edit in fluent_embed_derive/src/fluent/group.rs at line 147
root_id: &id, - replacement in fluent_embed_derive/src/fluent/ast.rs at line 19
PatternElement::TextElement { value } => {PatternElement::TextElement { value, span: _ } => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 23
PatternElement::Placeable { expression } => {PatternElement::Placeable {expression,span: _,} => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 28
Expression::Select { selector, variants } => {Expression::Select { selector, variants, span: _ } => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 71
Expression::Inline(expression) => {Expression::Inline(expression, _span) => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 92
InlineExpression::StringLiteral { value } => {InlineExpression::StringLiteral { value, span: _ } => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 96
InlineExpression::NumberLiteral { value } => {InlineExpression::NumberLiteral { value, span: _ } => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 104
InlineExpression::VariableReference { id } => {InlineExpression::VariableReference { id, span } => { - replacement in fluent_embed_derive/src/fluent/ast.rs at line 116[3.4668]→[3.5701:5863](∅→∅),[3.5863]→[3.5265:5266](∅→∅),[3.5265]→[3.5265:5266](∅→∅),[3.5266]→[3.5864:5925](∅→∅),[3.5925]→[3.3418:3472](∅→∅),[3.3472]→[3.5977:6037](∅→∅),[3.5977]→[3.5977:6037](∅→∅)
let (source_code, offset) = message_context.source.source_with_message_offset(message_context.root_id);let location = source_code.inner()[offset..].find(&format!("${fluent_name}")).unwrap()+ offset;let source_code = message_context.source.named_source.clone(); - replacement in fluent_embed_derive/src/fluent/ast.rs at line 122
span: SourceSpan::new(location.into(), fluent_name.len()),span: SourceSpan::from(span.0.to_owned()), - replacement in Cargo.toml at line 14
fluent-syntax = "0.11.1"fluent-syntax = { git = "https://github.com/Ertanic/fluent-rs", branch = "span", features = ["spans",] } - replacement in Cargo.lock at line 272
source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d"source = "git+https://github.com/Ertanic/fluent-rs?branch=span#27615271d3f8d990e935d3c99053329863d6129e" - replacement in Cargo.lock at line 274
"thiserror 1.0.69","memchr","thiserror 2.0.12",