diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/macros/Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/macros/src/attr.rs | 10 | ||||
| -rw-r--r-- | crates/macros/src/lib.rs | 41 |
3 files changed, 26 insertions, 26 deletions
diff --git a/crates/macros/Cargo.toml b/crates/macros/Cargo.toml index cd5b4a6..e5b9ad7 100644 --- a/crates/macros/Cargo.toml +++ b/crates/macros/Cargo.toml @@ -14,3 +14,4 @@ proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full"] } heck = "0.4" +darling = { version = "0.23.0", features = ["serde"] } diff --git a/crates/macros/src/attr.rs b/crates/macros/src/attr.rs new file mode 100644 index 0000000..ef1df86 --- /dev/null +++ b/crates/macros/src/attr.rs @@ -0,0 +1,10 @@ +use darling::FromMeta; + +#[derive(Default, FromMeta)] +#[darling(default)] +#[darling(derive_syn_parse)] +pub struct MacroArgs { + pub export_to: Option<String>, + pub export_to_path: Option<String>, + pub import_from: Option<String>, +} diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs index 1b26bf2..9e310ca 100644 --- a/crates/macros/src/lib.rs +++ b/crates/macros/src/lib.rs @@ -6,6 +6,10 @@ use syn::{ Expr, FnArg, Ident, ItemFn, Lit, MetaNameValue, Pat, PathArguments, ReturnType, Type, }; +use crate::attr::MacroArgs; + +mod attr; + fn get_lit_str_value(nv: &MetaNameValue) -> Option<String> { // In syn v2 MetaNameValue.value is an Expr (usually Expr::Lit). Extract string literal if present. match &nv.value { @@ -180,35 +184,20 @@ fn snake_to_camel(s: &str) -> String { #[proc_macro_attribute] pub fn api(attr: TokenStream, item: TokenStream) -> TokenStream { - // Parse inputs as a punctuated list of MetaNameValue (e.g. export_to = "...", import_from = "...") - // `MetaList` implements `Parse` so we can parse the raw attribute token stream reliably - struct MetaList(Punctuated<MetaNameValue, Comma>); - impl Parse for MetaList { - fn parse(input: ParseStream) -> syn::Result<Self> { - Ok(MetaList(Punctuated::parse_terminated(input)?)) - } - } - let metas = parse_macro_input!(attr as MetaList).0; + // Parse attribute args via `darling` crate + let meta: MacroArgs = match syn::parse(attr) { + Ok(meta) => meta, + Err(err) => return err.into_compile_error().into(), + }; let input_fn = parse_macro_input!(item as ItemFn); // Extract attribute args: export_to, import_from - let mut export_to: Option<String> = None; - let mut import_from: Option<String> = None; - - for nv in metas.iter() { - if let Some(ident) = nv.path.get_ident() { - let name = ident.to_string(); - if name == "export_to" { - if let Some(v) = get_lit_str_value(nv) { - export_to = Some(v); - } - } else if name == "import_from" { - if let Some(v) = get_lit_str_value(nv) { - import_from = Some(v); - } - } - } - } + let export_to = match (meta.export_to, meta.export_to_path) { + (Some(to), None) => Some(to), + (_, Some(path)) => Some(path), + (None, None) => None, + }; + let import_from = meta.import_from; // Analyze function let fn_name_ident: Ident = input_fn.sig.ident.clone(); |