use proc_macro2::Span;
use syn::meta::ParseNestedMeta;
use syn::{Ident, LitStr, Result};
#[derive(Default)]
pub(crate) struct LuaAttr {
pub(crate) span: Option<Span>,
pub(crate) name: Option<String>,
pub(crate) infallible: bool,
pub(crate) skip: bool,
pub(crate) get: bool,
pub(crate) set: bool,
pub(crate) getter: bool,
pub(crate) setter: bool,
pub(crate) field: bool,
pub(crate) meta: bool,
}
impl LuaAttr {
pub(crate) fn parse_inner(&mut self, meta: ParseNestedMeta) -> Result<()> {
match &meta.path {
path if path.is_ident("skip") => {
if meta.value().is_ok() {
return Err(meta.error("`skip` does not take a value"));
}
self.skip = true;
}
path if path.is_ident("infallible") => {
if meta.value().is_ok() {
return Err(meta.error("`infallible` does not take a value"));
}
self.infallible = true;
}
path if path.is_ident("get") => self.get = true,
path if path.is_ident("set") => self.set = true,
path if path.is_ident("getter") => self.getter = true,
path if path.is_ident("setter") => self.setter = true,
path if path.is_ident("field") => self.field = true,
path if path.is_ident("meta") => self.meta = true,
path if path.is_ident("name") => {
let value = meta.value()?;
let lit: LitStr = value.parse()?;
self.name = Some(lit.value());
}
_ => {
return Err(meta.error(
"unsupported lua attribute, expected: ".to_string()
+ "`skip`, `infallible`, `get`, `set`, `getter`, `setter`, `field`, `meta`, `name`",
));
}
}
Ok(())
}
pub(crate) fn name(&self, ident: &Ident) -> String {
self.name.clone().unwrap_or_else(|| ident.to_string())
}
pub(crate) fn span(&self) -> Span {
self.span.unwrap_or_else(Span::call_site)
}
pub(crate) fn effective_meta_name(&self, fn_ident: &Ident) -> Result<String> {
if let Some(ref name) = self.name {
return Ok(name.clone());
}
let fn_name = fn_ident.to_string();
if fn_name.starts_with("__") {
return Ok(fn_name);
}
Err(syn::Error::new(
fn_ident.span(),
format!(
"could not infer metamethod name from `{fn_name}`, either add `name = \"...\"` to `#[lua(meta, ...)]` or prefix the function with `__`"
),
))
}
}