From 55870e7b37c40d26f9a5406f442b3a1ddbb6e7e7 Mon Sep 17 00:00:00 2001 From: J Henry Waugh Date: Fri, 21 Aug 2020 23:05:18 -0500 Subject: [PATCH] Add #[cfg] support in submodules --- codegen/src/module.rs | 107 ++++++++++++++++-- codegen/src/rhai_module.rs | 17 ++- codegen/ui_tests/rhai_mod_inner_cfg_false.rs | 29 +++++ .../ui_tests/rhai_mod_inner_cfg_false.stderr | 5 + 4 files changed, 141 insertions(+), 17 deletions(-) create mode 100644 codegen/ui_tests/rhai_mod_inner_cfg_false.rs create mode 100644 codegen/ui_tests/rhai_mod_inner_cfg_false.stderr diff --git a/codegen/src/module.rs b/codegen/src/module.rs index d3e09eca..7aa98409 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -11,6 +11,8 @@ use std::vec as new_vec; #[cfg(no_std)] use core::mem; +#[cfg(not(no_std))] +use std::mem; use std::borrow::Cow; use std::collections::HashMap; @@ -282,6 +284,10 @@ impl Parse for Module { } impl Module { + pub fn attrs(&self) -> Option<&Vec> { + self.mod_all.as_ref().map(|m| &m.attrs) + } + pub fn module_name(&self) -> Option<&syn::Ident> { self.mod_all.as_ref().map(|m| &m.ident) } @@ -324,8 +330,10 @@ impl Module { let mut mod_all = mod_all.unwrap(); let mod_name = mod_all.ident.clone(); let (_, orig_content) = mod_all.content.take().unwrap(); + let mod_attrs = mem::replace(&mut mod_all.attrs, Vec::with_capacity(0)); Ok(quote! { + #(#mod_attrs)* pub mod #mod_name { #(#orig_content)* #(#inner_modules)* @@ -1112,7 +1120,82 @@ mod generate_tests { #[allow(unused_mut)] pub fn rhai_module_generate() -> Module { let mut m = Module::new(); - m.set_sub_module("it_is", self::it_is::rhai_module_generate()); + { m.set_sub_module("it_is", self::it_is::rhai_module_generate()); } + m + } + } + }; + + let item_mod = syn::parse2::(input_tokens).unwrap(); + assert_streams_eq(item_mod.generate(), expected_tokens); + } + + #[test] + fn one_fn_with_cfg_module() { + let input_tokens: TokenStream = quote! { + pub mod one_fn { + #[cfg(not(feature = "no_float"))] + pub mod it_is { + pub fn increment(x: &mut FLOAT) { + *x += 1.0 as FLOAT; + } + } + } + }; + + let expected_tokens = quote! { + pub mod one_fn { + #[cfg(not(feature = "no_float"))] + pub mod it_is { + pub fn increment(x: &mut FLOAT) { + *x += 1.0 as FLOAT; + } + #[allow(unused_imports)] + use super::*; + #[allow(unused_mut)] + pub fn rhai_module_generate() -> Module { + let mut m = Module::new(); + m.set_fn("increment", FnAccess::Public, + &[core::any::TypeId::of::()], + CallableFunction::from_plugin(increment_token())); + m + } + #[allow(non_camel_case_types)] + struct increment_token(); + impl PluginFunction for increment_token { + fn call(&self, + args: &mut [&mut Dynamic], pos: Position + ) -> Result> { + debug_assert_eq!(args.len(), 1usize, + "wrong arg count: {} != {}", args.len(), 1usize); + let arg0: &mut _ = &mut args[0usize].write_lock::().unwrap(); + Ok(Dynamic::from(increment(arg0))) + } + + fn is_method_call(&self) -> bool { true } + fn is_varadic(&self) -> bool { false } + fn clone_boxed(&self) -> Box { + Box::new(increment_token()) + } + fn input_types(&self) -> Box<[TypeId]> { + new_vec![TypeId::of::()].into_boxed_slice() + } + } + pub fn increment_token_callable() -> CallableFunction { + CallableFunction::from_plugin(increment_token()) + } + pub fn increment_token_input_types() -> Box<[TypeId]> { + increment_token().input_types() + } + } + #[allow(unused_imports)] + use super::*; + #[allow(unused_mut)] + pub fn rhai_module_generate() -> Module { + let mut m = Module::new(); + #[cfg(not(feature = "no_float"))] { + m.set_sub_module("it_is", self::it_is::rhai_module_generate()); + } m } } @@ -1150,7 +1233,7 @@ mod generate_tests { #[allow(unused_mut)] pub fn rhai_module_generate() -> Module { let mut m = Module::new(); - m.set_sub_module("it_is", self::it_is::rhai_module_generate()); + { m.set_sub_module("it_is", self::it_is::rhai_module_generate()); } m } } @@ -1202,8 +1285,8 @@ mod generate_tests { #[allow(unused_mut)] pub fn rhai_module_generate() -> Module { let mut m = Module::new(); - m.set_sub_module("first_is", self::first_is::rhai_module_generate()); - m.set_sub_module("second_is", self::second_is::rhai_module_generate()); + { m.set_sub_module("first_is", self::first_is::rhai_module_generate()); } + { m.set_sub_module("second_is", self::second_is::rhai_module_generate()); } m } } @@ -1280,8 +1363,8 @@ mod generate_tests { pub fn rhai_module_generate() -> Module { let mut m = Module::new(); m.set_var("VALUE", 17); - m.set_sub_module("left", self::left::rhai_module_generate()); - m.set_sub_module("right", self::right::rhai_module_generate()); + { m.set_sub_module("left", self::left::rhai_module_generate()); } + { m.set_sub_module("right", self::right::rhai_module_generate()); } m } } @@ -1302,8 +1385,8 @@ mod generate_tests { pub fn rhai_module_generate() -> Module { let mut m = Module::new(); m.set_var("VALUE", 19); - m.set_sub_module("left", self::left::rhai_module_generate()); - m.set_sub_module("right", self::right::rhai_module_generate()); + { m.set_sub_module("left", self::left::rhai_module_generate()); } + { m.set_sub_module("right", self::right::rhai_module_generate()); } m } } @@ -1337,8 +1420,8 @@ mod generate_tests { pub fn rhai_module_generate() -> Module { let mut m = Module::new(); m.set_var("VALUE", 36); - m.set_sub_module("left", self::left::rhai_module_generate()); - m.set_sub_module("right", self::right::rhai_module_generate()); + { m.set_sub_module("left", self::left::rhai_module_generate()); } + { m.set_sub_module("right", self::right::rhai_module_generate()); } m } } @@ -1348,8 +1431,8 @@ mod generate_tests { pub fn rhai_module_generate() -> Module { let mut m = Module::new(); m.set_var("VALUE", 100); - m.set_sub_module("left", self::left::rhai_module_generate()); - m.set_sub_module("right", self::right::rhai_module_generate()); + { m.set_sub_module("left", self::left::rhai_module_generate()); } + { m.set_sub_module("right", self::right::rhai_module_generate()); } m } } diff --git a/codegen/src/rhai_module.rs b/codegen/src/rhai_module.rs index f4f7369e..c327c71f 100644 --- a/codegen/src/rhai_module.rs +++ b/codegen/src/rhai_module.rs @@ -12,7 +12,7 @@ pub(crate) fn generate_body( ) -> proc_macro2::TokenStream { let mut set_fn_stmts: Vec = Vec::new(); let mut set_const_stmts: Vec = Vec::new(); - let mut add_mod_stmts: Vec = Vec::new(); + let mut add_mod_blocks: Vec = Vec::new(); let str_type_path = syn::parse2::(quote! { str }).unwrap(); for (const_name, const_expr) in consts { @@ -32,9 +32,16 @@ pub(crate) fn generate_body( } else { syn::LitStr::new(&module_name.to_string(), proc_macro2::Span::call_site()) }; - add_mod_stmts.push( - syn::parse2::(quote! { - m.set_sub_module(#exported_name, self::#module_name::rhai_module_generate()); + let cfg_attrs: Vec<&syn::Attribute> = itemmod.attrs().unwrap().iter().filter(|&a| { + a.path.get_ident() + .map(|i| i.to_string() == "cfg") + .unwrap_or(false) + }).collect(); + add_mod_blocks.push( + syn::parse2::(quote! { + #(#cfg_attrs)* { + m.set_sub_module(#exported_name, self::#module_name::rhai_module_generate()); + } }) .unwrap(), ); @@ -117,7 +124,7 @@ pub(crate) fn generate_body( let mut m = Module::new(); #(#set_fn_stmts)* #(#set_const_stmts)* - #(#add_mod_stmts)* + #(#add_mod_blocks)* m } } diff --git a/codegen/ui_tests/rhai_mod_inner_cfg_false.rs b/codegen/ui_tests/rhai_mod_inner_cfg_false.rs new file mode 100644 index 00000000..cfb3e1b6 --- /dev/null +++ b/codegen/ui_tests/rhai_mod_inner_cfg_false.rs @@ -0,0 +1,29 @@ +use rhai::plugin::*; + +#[derive(Clone)] +pub struct Point { + x: f32, + y: f32, +} + +#[export_module] +pub mod test_module { + #[cfg(feature = "unset_feature")] + pub mod test_mod { + pub fn test_fn(input: Point) -> bool { + input.x > input.y + } + } +} + +fn main() { + let n = Point { + x: 0.0, + y: 10.0, + }; + if test_module::test_mod::test_fn(n) { + println!("yes"); + } else { + println!("no"); + } +} diff --git a/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr b/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr new file mode 100644 index 00000000..04068220 --- /dev/null +++ b/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr @@ -0,0 +1,5 @@ +error[E0433]: failed to resolve: could not find `test_mod` in `test_module` + --> $DIR/rhai_mod_inner_cfg_false.rs:24:21 + | +24 | if test_module::test_mod::test_fn(n) { + | ^^^^^^^^ could not find `test_mod` in `test_module`