Add type alias support for plugin modules.
This commit is contained in:
@@ -10,7 +10,7 @@ use std::borrow::Cow;
|
||||
|
||||
use crate::attrs::{AttrItem, ExportInfo, ExportScope, ExportedParams};
|
||||
use crate::function::ExportedFn;
|
||||
use crate::rhai_module::ExportedConst;
|
||||
use crate::rhai_module::{ExportedConst, ExportedType};
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
|
||||
pub struct ExportedModParams {
|
||||
@@ -89,8 +89,9 @@ impl ExportedParams for ExportedModParams {
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
mod_all: syn::ItemMod,
|
||||
fns: Vec<ExportedFn>,
|
||||
consts: Vec<ExportedConst>,
|
||||
custom_types: Vec<ExportedType>,
|
||||
fns: Vec<ExportedFn>,
|
||||
sub_modules: Vec<Module>,
|
||||
params: ExportedModParams,
|
||||
}
|
||||
@@ -107,6 +108,7 @@ impl Parse for Module {
|
||||
let mut mod_all: syn::ItemMod = input.parse()?;
|
||||
let fns: Vec<_>;
|
||||
let mut consts = Vec::new();
|
||||
let mut custom_types = Vec::new();
|
||||
let mut sub_modules = Vec::new();
|
||||
|
||||
if let Some((.., ref mut content)) = mod_all.content {
|
||||
@@ -155,6 +157,25 @@ impl Parse for Module {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Gather and parse type definitions.
|
||||
for item in content.iter() {
|
||||
match item {
|
||||
syn::Item::Type(syn::ItemType {
|
||||
vis,
|
||||
ident,
|
||||
attrs,
|
||||
ty,
|
||||
..
|
||||
}) if matches!(vis, syn::Visibility::Public(..)) => {
|
||||
custom_types.push(ExportedType {
|
||||
name: ident.to_string(),
|
||||
typ: ty.clone(),
|
||||
cfg_attrs: crate::attrs::collect_cfg_attr(&attrs),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Gather and parse sub-module definitions.
|
||||
//
|
||||
// They are actually removed from the module's body, because they will need
|
||||
@@ -188,6 +209,7 @@ impl Parse for Module {
|
||||
mod_all,
|
||||
fns,
|
||||
consts,
|
||||
custom_types,
|
||||
sub_modules,
|
||||
params: ExportedModParams::default(),
|
||||
})
|
||||
@@ -241,6 +263,7 @@ impl Module {
|
||||
mut mod_all,
|
||||
mut fns,
|
||||
consts,
|
||||
custom_types,
|
||||
mut sub_modules,
|
||||
params,
|
||||
..
|
||||
@@ -257,6 +280,7 @@ impl Module {
|
||||
let mod_gen = crate::rhai_module::generate_body(
|
||||
&mut fns,
|
||||
&consts,
|
||||
&custom_types,
|
||||
&mut sub_modules,
|
||||
¶ms.scope,
|
||||
);
|
||||
@@ -300,6 +324,11 @@ impl Module {
|
||||
&self.consts
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn custom_types(&self) -> &[ExportedType] {
|
||||
&self.custom_types
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn fns(&self) -> &[ExportedFn] {
|
||||
&self.fns
|
||||
|
@@ -18,9 +18,17 @@ pub struct ExportedConst {
|
||||
pub cfg_attrs: Vec<syn::Attribute>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExportedType {
|
||||
pub name: String,
|
||||
pub typ: Box<syn::Type>,
|
||||
pub cfg_attrs: Vec<syn::Attribute>,
|
||||
}
|
||||
|
||||
pub fn generate_body(
|
||||
fns: &mut [ExportedFn],
|
||||
consts: &[ExportedConst],
|
||||
custom_types: &[ExportedType],
|
||||
sub_modules: &mut [Module],
|
||||
parent_scope: &ExportScope,
|
||||
) -> TokenStream {
|
||||
@@ -54,6 +62,29 @@ pub fn generate_body(
|
||||
);
|
||||
}
|
||||
|
||||
for ExportedType {
|
||||
name,
|
||||
typ,
|
||||
cfg_attrs,
|
||||
..
|
||||
} in custom_types
|
||||
{
|
||||
let const_literal = syn::LitStr::new(&name, Span::call_site());
|
||||
|
||||
let cfg_attrs: Vec<_> = cfg_attrs
|
||||
.iter()
|
||||
.map(syn::Attribute::to_token_stream)
|
||||
.collect();
|
||||
|
||||
set_const_statements.push(
|
||||
syn::parse2::<syn::Stmt>(quote! {
|
||||
#(#cfg_attrs)*
|
||||
m.set_custom_type::<#typ>(#const_literal);
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
for item_mod in sub_modules {
|
||||
item_mod.update_scope(&parent_scope);
|
||||
if item_mod.skipped() {
|
||||
|
@@ -37,6 +37,31 @@ mod module_tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_factory_fn_with_custom_type_module() {
|
||||
let input_tokens: TokenStream = quote! {
|
||||
pub mod one_fn {
|
||||
pub type Hello = ();
|
||||
|
||||
pub fn get_mystic_number() -> INT {
|
||||
42
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let item_mod = syn::parse2::<Module>(input_tokens).unwrap();
|
||||
assert!(item_mod.consts().is_empty());
|
||||
assert_eq!(item_mod.custom_types().len(), 1);
|
||||
assert_eq!(item_mod.custom_types()[0].name.to_string(), "Hello");
|
||||
assert_eq!(item_mod.fns().len(), 1);
|
||||
assert_eq!(item_mod.fns()[0].name().to_string(), "get_mystic_number");
|
||||
assert_eq!(item_mod.fns()[0].arg_count(), 0);
|
||||
assert_eq!(
|
||||
item_mod.fns()[0].return_type().unwrap(),
|
||||
&syn::parse2::<syn::Type>(quote! { INT }).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "metadata")]
|
||||
fn one_factory_fn_with_comments_module() {
|
||||
@@ -753,7 +778,13 @@ mod generate_tests {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Foo(pub INT);
|
||||
|
||||
pub type Hello = Foo;
|
||||
|
||||
pub const MYSTIC_NUMBER: Foo = Foo(42);
|
||||
|
||||
pub fn get_mystic_number(x: &mut Hello) -> INT {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -762,7 +793,13 @@ mod generate_tests {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Foo(pub INT);
|
||||
|
||||
pub type Hello = Foo;
|
||||
|
||||
pub const MYSTIC_NUMBER: Foo = Foo(42);
|
||||
|
||||
pub fn get_mystic_number(x: &mut Hello) -> INT {
|
||||
x.0
|
||||
}
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
@@ -774,9 +811,32 @@ mod generate_tests {
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||
m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public,
|
||||
Some(get_mystic_number_token::PARAM_NAMES), &[TypeId::of::<Hello>()],
|
||||
get_mystic_number_token().into());
|
||||
m.set_var("MYSTIC_NUMBER", MYSTIC_NUMBER);
|
||||
m.set_custom_type::<Foo>("Hello");
|
||||
if flatten {} else {}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct get_mystic_number_token();
|
||||
impl get_mystic_number_token {
|
||||
pub const PARAM_NAMES: &'static [&'static str] = &["x: &mut Hello", "INT"];
|
||||
#[inline(always)] pub fn param_types() -> [TypeId; 1usize] { [TypeId::of::<Hello>()] }
|
||||
}
|
||||
impl PluginFunction for get_mystic_number_token {
|
||||
#[inline(always)]
|
||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult {
|
||||
if args[0usize].is_read_only() {
|
||||
return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into());
|
||||
}
|
||||
let arg0 = &mut args[0usize].write_lock::<Hello>().unwrap();
|
||||
Ok(Dynamic::from(get_mystic_number(arg0)))
|
||||
}
|
||||
|
||||
#[inline(always)] fn is_method_call(&self) -> bool { true }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user