Add rhai_fn nested attribute and skip fn parameter
This commit is contained in:
@@ -17,6 +17,15 @@ use syn::{parse::Parse, parse::ParseStream, parse::Parser, spanned::Spanned};
|
||||
pub(crate) struct ExportedFnParams {
|
||||
pub name: Option<String>,
|
||||
pub return_raw: bool,
|
||||
pub skip: bool,
|
||||
}
|
||||
|
||||
impl ExportedFnParams {
|
||||
pub fn skip() -> ExportedFnParams {
|
||||
let mut skip = ExportedFnParams::default();
|
||||
skip.skip = true;
|
||||
skip
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for ExportedFnParams {
|
||||
@@ -68,6 +77,7 @@ impl Parse for ExportedFnParams {
|
||||
|
||||
let mut name = None;
|
||||
let mut return_raw = false;
|
||||
let mut skip = false;
|
||||
for (ident, value) in attrs.drain() {
|
||||
match (ident.to_string().as_ref(), value) {
|
||||
("name", Some(s)) => name = Some(s.value()),
|
||||
@@ -76,6 +86,10 @@ impl Parse for ExportedFnParams {
|
||||
("return_raw", Some(s)) => {
|
||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||
}
|
||||
("skip", None) => skip = true,
|
||||
("skip", Some(s)) => {
|
||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||
}
|
||||
(attr, _) => {
|
||||
return Err(syn::Error::new(
|
||||
ident.span(),
|
||||
@@ -85,7 +99,7 @@ impl Parse for ExportedFnParams {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ExportedFnParams { name, return_raw })
|
||||
Ok(ExportedFnParams { name, return_raw, skip, ..Default::default() })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +109,7 @@ pub(crate) struct ExportedFn {
|
||||
signature: syn::Signature,
|
||||
is_public: bool,
|
||||
mut_receiver: bool,
|
||||
params: ExportedFnParams,
|
||||
pub params: ExportedFnParams,
|
||||
}
|
||||
|
||||
impl Parse for ExportedFn {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{parse::Parse, parse::ParseStream};
|
||||
|
||||
use crate::function::ExportedFn;
|
||||
use crate::function::{ExportedFn, ExportedFnParams};
|
||||
use crate::rhai_module::ExportedConst;
|
||||
|
||||
#[cfg(no_std)]
|
||||
@@ -12,6 +12,22 @@ use std::vec as new_vec;
|
||||
#[cfg(no_std)]
|
||||
use core::mem;
|
||||
|
||||
fn inner_fn_attributes(f: &mut syn::ItemFn) -> syn::Result<ExportedFnParams> {
|
||||
if let Some(rhai_fn_idx) = f.attrs.iter().position(|a| {
|
||||
a.path
|
||||
.get_ident()
|
||||
.map(|i| i.to_string() == "rhai_fn")
|
||||
.unwrap_or(false)
|
||||
}) {
|
||||
let rhai_fn_attr = f.attrs.remove(rhai_fn_idx);
|
||||
rhai_fn_attr.parse_args()
|
||||
} else if let syn::Visibility::Public(_) = f.vis {
|
||||
Ok(ExportedFnParams::default())
|
||||
} else {
|
||||
Ok(ExportedFnParams::skip())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Module {
|
||||
mod_all: Option<syn::ItemMod>,
|
||||
@@ -21,25 +37,27 @@ pub(crate) struct Module {
|
||||
|
||||
impl Parse for Module {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mod_all: syn::ItemMod = input.parse()?;
|
||||
let mut mod_all: syn::ItemMod = input.parse()?;
|
||||
let fns: Vec<_>;
|
||||
let consts: Vec<_>;
|
||||
if let Some((_, ref content)) = mod_all.content {
|
||||
if let Some((_, ref mut content)) = mod_all.content {
|
||||
fns = content
|
||||
.iter()
|
||||
.iter_mut()
|
||||
.filter_map(|item| match item {
|
||||
syn::Item::Fn(f) => {
|
||||
if let syn::Visibility::Public(_) = f.vis {
|
||||
Some(f)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
syn::Item::Fn(f) => Some(f),
|
||||
_ => None,
|
||||
})
|
||||
.try_fold(Vec::new(), |mut vec, itemfn| {
|
||||
.try_fold(Vec::new(), |mut vec, mut itemfn| {
|
||||
let params = match inner_fn_attributes(&mut itemfn) {
|
||||
Ok(p) => p,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
syn::parse2::<ExportedFn>(itemfn.to_token_stream())
|
||||
.map(|f| vec.push(f))
|
||||
.map(|mut f| {
|
||||
f.params = params;
|
||||
f
|
||||
})
|
||||
.map(|f| if !f.params.skip { vec.push(f) })
|
||||
.map(|_| vec)
|
||||
})?;
|
||||
consts = content
|
||||
@@ -217,6 +235,22 @@ mod module_tests {
|
||||
assert!(item_mod.consts.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_skipped_fn_module() {
|
||||
let input_tokens: TokenStream = quote! {
|
||||
pub mod one_fn {
|
||||
#[rhai_fn(skip)]
|
||||
pub fn get_mystic_number() -> INT {
|
||||
42
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let item_mod = syn::parse2::<Module>(input_tokens).unwrap();
|
||||
assert!(item_mod.fns.is_empty());
|
||||
assert!(item_mod.consts.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_private_constant_module() {
|
||||
let input_tokens: TokenStream = quote! {
|
||||
@@ -552,6 +586,36 @@ mod generate_tests {
|
||||
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_skipped_fn_module() {
|
||||
let input_tokens: TokenStream = quote! {
|
||||
pub mod one_fn {
|
||||
#[rhai_fn(skip)]
|
||||
pub fn get_mystic_number() -> INT {
|
||||
42
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let expected_tokens = quote! {
|
||||
pub mod one_fn {
|
||||
pub fn get_mystic_number() -> INT {
|
||||
42
|
||||
}
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
#[allow(unused_mut)]
|
||||
pub fn rhai_module_generate() -> Module {
|
||||
let mut m = Module::new();
|
||||
m
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let item_mod = syn::parse2::<Module>(input_tokens).unwrap();
|
||||
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_private_constant_module() {
|
||||
let input_tokens: TokenStream = quote! {
|
||||
|
Reference in New Issue
Block a user