Add explicit error handling for macro parsing
Dependencies
- [2]
73C6NOJ7Fix minimal `Localize` implementation on errors - [3]
YZ6PVVQCAdd error handling for common unsupported Rust code - [4]
VQBJBFEXImprove error handling for missing Fluent messages - [5]
NO3PDO7PRefactor `fluent_embed` to support structs - [6]
XGRU7WZEAdd `expand` feature for proc-macro debugging - [7]
QFPQZR4KRefactor `fluent_embed` - [8]
K3G4HK2JTrack Fluent files using `include!` - [9]
O77KA6C4Create `fluent_embed` crate - [10]
LIO32J4BFix compiler error when `expand` feature is disabled - [11]
OWXLFLRMMerge `cli_macros` shim into `fluent_embed` - [12]
4BMW4JJOAdd support for deriving items with generics - [13]
F5LG7WENEmit compilation errors from Fluent source code - [14]
CESJ4CTOMove macro-specific code into `macro_impl` module - [15]
TVRANPYBIgnore errors when setting `miette` panic hook - [16]
NFV26FRQImprove glob error handling
Change contents
- edit in fluent_embed_derive/src/macro_impl/mod.rs at line 28
#[error("Failed to parse macro input")]pub enum ParseError {#[error("invalid attribute")]InvalidAttribute(syn::Error),#[error("invalid item")]InvalidDeriveInput(syn::Error),}#[derive(Debug, Error)] - edit in fluent_embed_derive/src/macro_impl/mod.rs at line 42
ParseError(#[from] ParseError), - replacement in fluent_embed_derive/src/macro_impl/mod.rs at line 46
attribute: &syn::LitStr,derive_input: &syn::DeriveInput,attribute_stream: proc_macro2::TokenStream,derive_input_stream: proc_macro2::TokenStream, - replacement in fluent_embed_derive/src/macro_impl/mod.rs at line 61
let locales = attribute::locales(attribute)?;// Parse the token streamslet attribute: syn::LitStr = syn::parse2(attribute_stream).map_err(|parse_error| ParseError::InvalidAttribute(parse_error))?;let derive_input: syn::DeriveInput = syn::parse2(derive_input_stream).map_err(|parse_error| ParseError::InvalidDeriveInput(parse_error))?;let locales = attribute::locales(&attribute)?; - replacement in fluent_embed_derive/src/macro_impl/error.rs at line 4
MacroError, UnsupportedError, UnsupportedReason,MacroError, ParseError, UnsupportedError, UnsupportedReason, - replacement in fluent_embed_derive/src/macro_impl/error.rs at line 115
note = "There must be at least one named field (unit structs are unsupported!)"note = "There must be at least one named field (unit structs are unsupported!)";}}}}fn parse(error: ParseError, attribute_stream: TokenStream, derive_input_stream: TokenStream) {match error {ParseError::InvalidAttribute(invalid_attribute) => {emit_error! { attribute_stream, invalid_attribute;help = "Expected a path glob, for example {}",r#"#[localize("i18n/**/strings.ftl")]"#;}}ParseError::InvalidDeriveInput(invalid_derive_input) => {emit_error! { derive_input_stream, invalid_derive_input;help = "This macro can only be used on structs or enums"; - replacement in fluent_embed_derive/src/macro_impl/error.rs at line 137
pub fn emit(error: MacroError, attribute_stream: TokenStream) {pub fn emit(error: MacroError, attribute_stream: TokenStream, derive_input_stream: TokenStream) { - edit in fluent_embed_derive/src/macro_impl/error.rs at line 142
MacroError::ParseError(error) => parse(error, attribute_stream, derive_input_stream), - replacement in fluent_embed_derive/src/lib.rs at line 2
use proc_macro_error::proc_macro_error;use proc_macro_error::{proc_macro_error}; - edit in fluent_embed_derive/src/lib.rs at line 4
use syn::parse_macro_input; - replacement in fluent_embed_derive/src/lib.rs at line 11[4.510]→[4.510:580](∅→∅),[4.580]→[4.5096:5174](∅→∅),[4.5174]→[4.580:700](∅→∅),[4.580]→[4.580:700](∅→∅)
let original_item = proc_macro2::TokenStream::from(item.clone());let attribute_stream = proc_macro2::TokenStream::from(attribute.clone());let derive_attribute: syn::LitStr = parse_macro_input!(attribute);let derive_input = parse_macro_input!(item);let attribute_stream = proc_macro2::TokenStream::from(attribute);let derive_input_stream = proc_macro2::TokenStream::from(item); - replacement in fluent_embed_derive/src/lib.rs at line 14
match macro_impl::localize(&derive_attribute, &derive_input) {match macro_impl::localize(attribute_stream.clone(), derive_input_stream.clone()) { - replacement in fluent_embed_derive/src/lib.rs at line 19
#derive_input#derive_input_stream - replacement in fluent_embed_derive/src/lib.rs at line 36
macro_impl::error::emit(error, attribute_stream);macro_impl::error::emit(error, attribute_stream, derive_input_stream.clone()); - replacement in fluent_embed_derive/src/lib.rs at line 39
let ident = derive_input.ident;quote! {#original_itemimpl<W: ::std::io::Write> ::fluent_embed::Localize<W> for #ident {const CANONICAL_LOCALE: ::fluent_embed::icu_locale::LanguageIdentifier =::fluent_embed::icu_locale::langid!("en-US");fn available_locales(&self) -> Vec<::fluent_embed::icu_locale::LanguageIdentifier> {unimplemented!("Encountered error in derive macro")}match syn::parse2::<syn::DeriveInput>(derive_input_stream.clone()) {Ok(derive_input) => {let ident = derive_input.ident;quote! {#derive_input_streamimpl<W: ::std::io::Write> ::fluent_embed::Localize<W> for #ident {const CANONICAL_LOCALE: ::fluent_embed::icu_locale::LanguageIdentifier =::fluent_embed::icu_locale::langid!("en-US"); - replacement in fluent_embed_derive/src/lib.rs at line 49
fn message_for_locale(&self,writer: &mut W,locale: &::fluent_embed::icu_locale::LanguageIdentifier,) -> Result<(), ::fluent_embed::LocalizationError> {unimplemented!("Encountered error in derive macro")fn available_locales(&self) -> Vec<::fluent_embed::icu_locale::LanguageIdentifier> {unimplemented!("Encountered error in derive macro")}fn message_for_locale(&self,writer: &mut W,locale: &::fluent_embed::icu_locale::LanguageIdentifier,) -> Result<(), ::fluent_embed::LocalizationError> {unimplemented!("Encountered error in derive macro")}} - replacement in fluent_embed_derive/src/lib.rs at line 62
}},// Unable to fail gracefully if the ident is unknown, so just return the original inputErr(_) => derive_input_stream, - edit in fluent_embed_derive/src/lib.rs at line 66