Catch getter, setter, indexer errors

This commit is contained in:
J Henry Waugh 2020-09-09 16:24:37 -05:00
parent b311688fee
commit 6e701bfe83
11 changed files with 189 additions and 16 deletions

View File

@ -22,6 +22,7 @@ pub trait ExportedParams: Sized {
pub struct AttrItem {
pub key: proc_macro2::Ident,
pub value: Option<syn::LitStr>,
pub span: proc_macro2::Span,
}
pub struct ExportInfo {
@ -46,6 +47,7 @@ pub fn parse_punctuated_items(
let mut attrs: Vec<AttrItem> = 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 })

View File

@ -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,

View File

@ -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")),

View File

@ -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");
}
}

View File

@ -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`

View File

@ -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");
}
}

View File

@ -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`

View File

@ -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");
}
}

View File

@ -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`

View File

@ -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");
}
}

View File

@ -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`