From 6086dec859676ebd0e9373e0d3f8cc7fa11e0686 Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Wed, 17 Sep 2025 01:04:37 +0200 Subject: [PATCH] feat: Added option to rename struct in Lua --- lua_typed_macro/src/lib.rs | 27 +++++++++++++++++++++++++-- tests/rename.rs | 23 +++++++++++++++++++++++ tests/ui/empty_rename.rs | 7 +++++++ tests/ui/empty_rename.stderr | 5 +++++ tests/ui/unknown_attribute.rs | 7 +++++++ tests/ui/unknown_attribute.stderr | 5 +++++ 6 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/rename.rs create mode 100644 tests/ui/empty_rename.rs create mode 100644 tests/ui/empty_rename.stderr create mode 100644 tests/ui/unknown_attribute.rs create mode 100644 tests/ui/unknown_attribute.stderr diff --git a/lua_typed_macro/src/lib.rs b/lua_typed_macro/src/lib.rs index ad86d69..1da7794 100644 --- a/lua_typed_macro/src/lib.rs +++ b/lua_typed_macro/src/lib.rs @@ -340,7 +340,7 @@ fn parse_fields( Ok(fields) } -#[proc_macro_derive(Typed, attributes(serde))] +#[proc_macro_derive(Typed, attributes(serde, typed))] pub fn typed(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -352,6 +352,7 @@ pub fn typed(input: proc_macro::TokenStream) -> proc_macro::TokenStream { fn typed_inner(ast: DeriveInput) -> syn::Result { let name = ast.ident; + let mut as_name = LitStr::new(&name.to_string(), name.span()); let mut case = None; let mut tag = None; @@ -388,11 +389,33 @@ fn typed_inner(ast: DeriveInput) -> syn::Result { { return Err(err); } + + if attr.path().is_ident("typed") + && let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path.is_ident("as") { + let value = meta.value()?; + as_name = value.parse()?; + + Ok(()) + } else { + Err(syn::Error::new(meta.path.span(), "Unknown attribute")) + } + }) + { + return Err(err); + } + } + + if as_name.value().is_empty() { + return Err(syn::Error::new( + as_name.span(), + "Name is not allowed to be empty", + )); } let type_name_fn = quote! { fn type_name() -> ::std::string::String { - stringify!(#name).to_string() + #as_name.to_string() } }; diff --git a/tests/rename.rs b/tests/rename.rs new file mode 100644 index 0000000..98dfb3c --- /dev/null +++ b/tests/rename.rs @@ -0,0 +1,23 @@ +use lua_typed::Typed; + +#[derive(Typed)] +#[typed(as = "Lua")] +struct Rust; + +#[derive(Typed)] +struct Other { + pub rust: Rust, +} + +#[test] +fn rename() { + insta::assert_snapshot!(::generate_full().unwrap(), @"---@class Lua"); +} + +#[test] +fn rename_nested() { + insta::assert_snapshot!(::generate_full().unwrap(), @r" + ---@class Other + ---@field rust Lua + "); +} diff --git a/tests/ui/empty_rename.rs b/tests/ui/empty_rename.rs new file mode 100644 index 0000000..b097164 --- /dev/null +++ b/tests/ui/empty_rename.rs @@ -0,0 +1,7 @@ +use lua_typed::Typed; + +#[derive(Typed)] +#[typed(as = "")] +struct A; + +fn main() {} diff --git a/tests/ui/empty_rename.stderr b/tests/ui/empty_rename.stderr new file mode 100644 index 0000000..dceb353 --- /dev/null +++ b/tests/ui/empty_rename.stderr @@ -0,0 +1,5 @@ +error: Name is not allowed to be empty + --> tests/ui/empty_rename.rs:4:14 + | +4 | #[typed(as = "")] + | ^^ diff --git a/tests/ui/unknown_attribute.rs b/tests/ui/unknown_attribute.rs new file mode 100644 index 0000000..1ebd79f --- /dev/null +++ b/tests/ui/unknown_attribute.rs @@ -0,0 +1,7 @@ +use lua_typed::Typed; + +#[derive(Typed)] +#[typed(cool)] +struct A; + +fn main() {} diff --git a/tests/ui/unknown_attribute.stderr b/tests/ui/unknown_attribute.stderr new file mode 100644 index 0000000..4c14e89 --- /dev/null +++ b/tests/ui/unknown_attribute.stderr @@ -0,0 +1,5 @@ +error: Unknown attribute + --> tests/ui/unknown_attribute.rs:4:9 + | +4 | #[typed(cool)] + | ^^^^