diff --git a/codegen/src/attrs.rs b/codegen/src/attrs.rs index 5d1e42d7..32d258f7 100644 --- a/codegen/src/attrs.rs +++ b/codegen/src/attrs.rs @@ -22,6 +22,7 @@ pub trait ExportedParams: Sized { pub struct AttrItem { pub key: proc_macro2::Ident, pub value: Option, + pub span: proc_macro2::Span, } pub struct ExportInfo { @@ -46,6 +47,7 @@ pub fn parse_punctuated_items( let mut attrs: Vec = Vec::new(); for arg in arg_list { + let arg_span = arg.span(); let (key, value) = match arg { syn::Expr::Assign(syn::ExprAssign { ref left, @@ -78,7 +80,7 @@ pub fn parse_punctuated_items( .ok_or_else(|| syn::Error::new(attr_path.span(), "expecting attribute name"))?, x => return Err(syn::Error::new(x.span(), "expecting identifier")), }; - attrs.push(AttrItem { key, value }); + attrs.push(AttrItem { key, value, span: arg_span }); } Ok(ExportInfo { item_span: list_span, items: attrs }) diff --git a/codegen/src/function.rs b/codegen/src/function.rs index aa4001f5..2f80fb03 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -64,23 +64,38 @@ impl ExportedParams for ExportedFnParams { let mut return_raw = false; let mut skip = false; for attr in attrs { - let crate::attrs::AttrItem { key, value } = attr; + let crate::attrs::AttrItem { key, value, span: item_span } = attr; match (key.to_string().as_ref(), value) { - ("name", Some(s)) => { - // check validity of name - if s.value().contains('.') { - return Err(syn::Error::new( - s.span(), - "Rhai function names may not contain dot", - )); - } - name.push(s.value()) - } - ("get", Some(s)) => name.push(make_getter(&s.value())), - ("set", Some(s)) => name.push(make_setter(&s.value())), ("get", None) | ("set", None) | ("name", None) => { return Err(syn::Error::new(key.span(), "requires value")) - } + }, + ("name", Some(s)) if &s.value() == FN_IDX_GET => { + return Err(syn::Error::new(item_span, + "use attribute 'index_get' instead")) + }, + ("name", Some(s)) if &s.value() == FN_IDX_SET => { + return Err(syn::Error::new(item_span, + "use attribute 'index_set' instead")) + }, + ("name", Some(s)) if s.value().starts_with("get$") => { + return Err(syn::Error::new(item_span, + format!("use attribute 'getter = \"{}\"' instead", + &s.value()["get$".len()..]))) + }, + ("name", Some(s)) if s.value().starts_with("set$") => { + return Err(syn::Error::new(item_span, + format!("use attribute 'setter = \"{}\"' instead", + &s.value()["set$".len()..]))) + }, + ("name", Some(s)) if s.value().contains('.') => { + return Err(syn::Error::new(s.span(), + "Rhai function names may not contain dot")) + }, + ("name", Some(s)) => { + name.push(s.value()) + }, + ("get", Some(s)) => name.push(make_getter(&s.value())), + ("set", Some(s)) => name.push(make_setter(&s.value())), ("index_get", None) => name.push(FN_IDX_GET.to_string()), ("index_set", None) => name.push(FN_IDX_SET.to_string()), ("return_raw", None) => return_raw = true, diff --git a/codegen/src/module.rs b/codegen/src/module.rs index 07ae54da..1ebc25b8 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -53,7 +53,7 @@ impl ExportedParams for ExportedModParams { let mut skip = false; let mut scope = ExportScope::default(); for attr in attrs { - let AttrItem { key, value } = attr; + let AttrItem { key, value, .. } = attr; match (key.to_string().as_ref(), value) { ("name", Some(s)) => name = Some(s.value()), ("name", None) => return Err(syn::Error::new(key.span(), "requires value")), diff --git a/codegen/ui_tests/rhai_fn_rename_to_index_getter.rs b/codegen/ui_tests/rhai_fn_rename_to_index_getter.rs new file mode 100644 index 00000000..394113b4 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_index_getter.rs @@ -0,0 +1,28 @@ +use rhai::plugin::*; + +#[derive(Clone)] +pub struct Point { + x: f32, + y: f32, +} + +#[export_module] +pub mod test_module { + pub use super::Point; + #[rhai_fn(name = "index$get$")] + 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_fn(n) { + println!("yes"); + } else { + println!("no"); + } +} diff --git a/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr b/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr new file mode 100644 index 00000000..287283f9 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr @@ -0,0 +1,11 @@ +error: use attribute 'index_get' instead + --> $DIR/rhai_fn_rename_to_index_getter.rs:12:15 + | +12 | #[rhai_fn(name = "index$get$")] + | ^^^^^^^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: use of undeclared type or module `test_module` + --> $DIR/rhai_fn_rename_to_index_getter.rs:23:8 + | +23 | if test_module::test_fn(n) { + | ^^^^^^^^^^^ use of undeclared type or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_index_setter.rs b/codegen/ui_tests/rhai_fn_rename_to_index_setter.rs new file mode 100644 index 00000000..cb5d7c8e --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_index_setter.rs @@ -0,0 +1,28 @@ +use rhai::plugin::*; + +#[derive(Clone)] +pub struct Point { + x: f32, + y: f32, +} + +#[export_module] +pub mod test_module { + pub use super::Point; + #[rhai_fn(name = "index$set$")] + 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_fn(n) { + println!("yes"); + } else { + println!("no"); + } +} diff --git a/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr b/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr new file mode 100644 index 00000000..712f2c59 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr @@ -0,0 +1,11 @@ +error: use attribute 'index_set' instead + --> $DIR/rhai_fn_rename_to_index_setter.rs:12:15 + | +12 | #[rhai_fn(name = "index$set$")] + | ^^^^^^^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: use of undeclared type or module `test_module` + --> $DIR/rhai_fn_rename_to_index_setter.rs:23:8 + | +23 | if test_module::test_fn(n) { + | ^^^^^^^^^^^ use of undeclared type or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_prop_getter.rs b/codegen/ui_tests/rhai_fn_rename_to_prop_getter.rs new file mode 100644 index 00000000..d81aa5d5 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_prop_getter.rs @@ -0,0 +1,28 @@ +use rhai::plugin::*; + +#[derive(Clone)] +pub struct Point { + x: f32, + y: f32, +} + +#[export_module] +pub mod test_module { + pub use super::Point; + #[rhai_fn(name = "get$foo")] + 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_fn(n) { + println!("yes"); + } else { + println!("no"); + } +} diff --git a/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr b/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr new file mode 100644 index 00000000..d9d9b3e8 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr @@ -0,0 +1,11 @@ +error: use attribute 'getter = "foo"' instead + --> $DIR/rhai_fn_rename_to_prop_getter.rs:12:15 + | +12 | #[rhai_fn(name = "get$foo")] + | ^^^^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: use of undeclared type or module `test_module` + --> $DIR/rhai_fn_rename_to_prop_getter.rs:23:8 + | +23 | if test_module::test_fn(n) { + | ^^^^^^^^^^^ use of undeclared type or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_prop_setter.rs b/codegen/ui_tests/rhai_fn_rename_to_prop_setter.rs new file mode 100644 index 00000000..d81aa5d5 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_prop_setter.rs @@ -0,0 +1,28 @@ +use rhai::plugin::*; + +#[derive(Clone)] +pub struct Point { + x: f32, + y: f32, +} + +#[export_module] +pub mod test_module { + pub use super::Point; + #[rhai_fn(name = "get$foo")] + 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_fn(n) { + println!("yes"); + } else { + println!("no"); + } +} diff --git a/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr b/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr new file mode 100644 index 00000000..a1dfbebd --- /dev/null +++ b/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr @@ -0,0 +1,11 @@ +error: use attribute 'getter = "foo"' instead + --> $DIR/rhai_fn_rename_to_prop_setter.rs:12:15 + | +12 | #[rhai_fn(name = "get$foo")] + | ^^^^^^^^^^^^^^^^ + +error[E0433]: failed to resolve: use of undeclared type or module `test_module` + --> $DIR/rhai_fn_rename_to_prop_setter.rs:23:8 + | +23 | if test_module::test_fn(n) { + | ^^^^^^^^^^^ use of undeclared type or module `test_module`