Check for invalid args when parsing `#[lua_module(...)]` proc macro
This commit is contained in:
parent
fdb5724053
commit
0aa30226df
|
@ -1,7 +1,7 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse_macro_input, AttributeArgs, ItemFn, Lit, Meta, NestedMeta};
|
use syn::{parse_macro_input, AttributeArgs, Error, ItemFn, Lit, Meta, NestedMeta, Result};
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
use {
|
use {
|
||||||
|
@ -13,41 +13,49 @@ use {
|
||||||
struct ModuleArgs {
|
struct ModuleArgs {
|
||||||
name: Option<Ident>,
|
name: Option<Ident>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleArgs {
|
impl ModuleArgs {
|
||||||
fn parse(attr: AttributeArgs) -> Self {
|
fn parse(args: AttributeArgs) -> Result<Self> {
|
||||||
let mut ret = Self::default();
|
let mut ret = Self::default();
|
||||||
|
|
||||||
for arg in attr {
|
for arg in args {
|
||||||
match arg {
|
match arg {
|
||||||
NestedMeta::Meta(Meta::NameValue(meta)) => {
|
NestedMeta::Meta(Meta::NameValue(meta)) => {
|
||||||
if meta.path.segments.last().unwrap().ident == "name" {
|
if meta.path.is_ident("name") {
|
||||||
if let Lit::Str(val) = meta.lit {
|
match meta.lit {
|
||||||
if let Ok(val) = val.parse() {
|
Lit::Str(val) => {
|
||||||
ret.name = Some(val);
|
ret.name = Some(val.parse()?);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::new_spanned(meta.lit, "expected string literal"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::new_spanned(meta.path, "expected `name`"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::new_spanned(arg, "invalid argument"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {}
|
Ok(ret)
|
||||||
}
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let args = parse_macro_input!(attr as AttributeArgs);
|
let args = parse_macro_input!(attr as AttributeArgs);
|
||||||
let args = ModuleArgs::parse(args);
|
let args = match ModuleArgs::parse(args) {
|
||||||
|
Ok(args) => args,
|
||||||
|
Err(err) => return err.to_compile_error().into(),
|
||||||
|
};
|
||||||
let func = parse_macro_input!(item as ItemFn);
|
let func = parse_macro_input!(item as ItemFn);
|
||||||
|
|
||||||
let func_name = func.sig.ident.clone();
|
let func_name = func.sig.ident.clone();
|
||||||
let module_name = if let Some(name) = args.name {
|
let module_name = args.name.unwrap_or_else(|| func_name.clone());
|
||||||
name
|
let ext_entrypoint_name = Ident::new(&format!("luaopen_{module_name}"), Span::call_site());
|
||||||
} else {
|
|
||||||
func_name.clone()
|
|
||||||
};
|
|
||||||
let ext_entrypoint_name = Ident::new(&format!("luaopen_{}", module_name), Span::call_site());
|
|
||||||
|
|
||||||
let wrapped = quote! {
|
let wrapped = quote! {
|
||||||
::mlua::require_module_feature!();
|
::mlua::require_module_feature!();
|
||||||
|
|
|
@ -12,7 +12,7 @@ fn check_userdata(_: &Lua, ud: MyUserData) -> LuaResult<i32> {
|
||||||
Ok(ud.0)
|
Ok(ud.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[mlua::lua_module(name = "rust_module_first")]
|
#[mlua::lua_module]
|
||||||
fn rust_module(lua: &Lua) -> LuaResult<LuaTable> {
|
fn rust_module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
let exports = lua.create_table()?;
|
let exports = lua.create_table()?;
|
||||||
exports.set("sum", lua.create_function(sum)?)?;
|
exports.set("sum", lua.create_function(sum)?)?;
|
||||||
|
@ -26,8 +26,8 @@ struct MyUserData(i32);
|
||||||
|
|
||||||
impl LuaUserData for MyUserData {}
|
impl LuaUserData for MyUserData {}
|
||||||
|
|
||||||
#[mlua::lua_module]
|
#[mlua::lua_module(name = "rust_module_second")]
|
||||||
fn rust_module_second(lua: &Lua) -> LuaResult<LuaTable> {
|
fn rust_module2(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
let exports = lua.create_table()?;
|
let exports = lua.create_table()?;
|
||||||
exports.set("userdata", lua.create_userdata(MyUserData(123))?)?;
|
exports.set("userdata", lua.create_userdata(MyUserData(123))?)?;
|
||||||
Ok(exports)
|
Ok(exports)
|
||||||
|
|
Loading…
Reference in New Issue