From 14d4d7dcf63121985424b0f3ebdf5f9000951efc Mon Sep 17 00:00:00 2001 From: Bugen Zhao Date: Fri, 24 Nov 2023 01:54:12 +0800 Subject: [PATCH] support specifying path for macro Signed-off-by: Bugen Zhao --- derive/src/expand.rs | 35 ++++++++++++++++++++++++++++------- tests/macro.rs | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/derive/src/expand.rs b/derive/src/expand.rs index 5973a19..493d51f 100644 --- a/derive/src/expand.rs +++ b/derive/src/expand.rs @@ -2,8 +2,8 @@ use either::{for_both, Either}; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; use syn::{ - spanned::Spanned, DeriveInput, GenericArgument, Ident, Member, PathArguments, Result, Type, - Visibility, + spanned::Spanned, DeriveInput, GenericArgument, Ident, LitStr, Member, PathArguments, Result, + Type, Visibility, }; use crate::thiserror::ast::{Field, Input, Variant}; @@ -131,12 +131,14 @@ struct DeriveMeta { impl_type: Ident, backtrace: bool, macro_mangle: bool, + macro_path: Option, } fn resolve_meta(input: &DeriveInput) -> Result { let mut impl_type = None; let mut backtrace = false; let mut macro_mangle = false; + let mut macro_path = None; for attr in &input.attrs { if attr.path().is_ident("thiserror_ext") { @@ -150,6 +152,23 @@ fn resolve_meta(input: &DeriveInput) -> Result { meta.parse_nested_meta(|meta| { if meta.path.is_ident("mangle") { macro_mangle = true; + } else if meta.path.is_ident("path") { + let value = meta.value()?; + let path: LitStr = value.parse()?; + let mut path = path.value(); + + if path.starts_with("crate") { + path.insert(0, '$'); + if !path.ends_with("::") { + path.push_str("::"); + } + macro_path = Some(path.parse()?); + } else { + return Err(syn::Error::new_spanned( + meta.path, + "macro path should start with `crate`", + )); + } } Ok(()) })?; @@ -165,6 +184,7 @@ fn resolve_meta(input: &DeriveInput) -> Result { impl_type, backtrace, macro_mangle, + macro_path, }) } @@ -372,6 +392,7 @@ pub fn derive_macro_inner(input: &DeriveInput, bail: bool) -> Result Result &v.ident); let ctor_path = match &variant { - Either::Left(_s) => quote!(#input_type), - Either::Right(_v) => quote!(#input_type::#variant_name), + Either::Left(_s) => quote!(#macro_path #input_type), + Either::Right(_v) => quote!(#macro_path #input_type::#variant_name), }; let fields = for_both!(&variant, v => &v.fields); @@ -473,12 +494,12 @@ pub fn derive_macro_inner(input: &DeriveInput, bail: bool) -> Result, pub message: String,