Reorganize get/set/index code into FnSpecialAccess
This commit is contained in:
parent
335d853060
commit
0a2f93439e
@ -17,24 +17,43 @@ use syn::{parse::Parse, parse::ParseStream, parse::Parser, spanned::Spanned};
|
|||||||
|
|
||||||
use crate::attrs::{ExportInfo, ExportScope, ExportedParams};
|
use crate::attrs::{ExportInfo, ExportScope, ExportedParams};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum Index {
|
||||||
|
Get,
|
||||||
|
Set,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum Property {
|
||||||
|
Get(syn::Ident),
|
||||||
|
Set(syn::Ident),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum FnSpecialAccess {
|
||||||
|
None,
|
||||||
|
Index(Index),
|
||||||
|
Property(Property),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FnSpecialAccess {
|
||||||
|
fn default() -> FnSpecialAccess {
|
||||||
|
FnSpecialAccess::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct ExportedFnParams {
|
pub(crate) struct ExportedFnParams {
|
||||||
pub name: Option<Vec<String>>,
|
pub name: Option<Vec<String>>,
|
||||||
pub return_raw: bool,
|
pub return_raw: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
pub span: Option<proc_macro2::Span>,
|
pub span: Option<proc_macro2::Span>,
|
||||||
|
pub special: FnSpecialAccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FN_IDX_GET: &str = "index$get$";
|
pub const FN_IDX_GET: &str = "index$get$";
|
||||||
pub const FN_IDX_SET: &str = "index$set$";
|
pub const FN_IDX_SET: &str = "index$set$";
|
||||||
|
|
||||||
pub fn make_getter(id: &str) -> String {
|
|
||||||
format!("get${}", id)
|
|
||||||
}
|
|
||||||
pub fn make_setter(id: &str) -> String {
|
|
||||||
format!("set${}", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for ExportedFnParams {
|
impl Parse for ExportedFnParams {
|
||||||
fn parse(args: ParseStream) -> syn::Result<Self> {
|
fn parse(args: ParseStream) -> syn::Result<Self> {
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
@ -63,6 +82,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
let mut name = Vec::new();
|
let mut name = Vec::new();
|
||||||
let mut return_raw = false;
|
let mut return_raw = false;
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
|
let mut special = FnSpecialAccess::None;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let crate::attrs::AttrItem { key, value, span: item_span } = attr;
|
let crate::attrs::AttrItem { key, value, span: item_span } = attr;
|
||||||
match (key.to_string().as_ref(), value) {
|
match (key.to_string().as_ref(), value) {
|
||||||
@ -98,10 +118,37 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
("name", Some(s)) => {
|
("name", Some(s)) => {
|
||||||
name.push(s.value())
|
name.push(s.value())
|
||||||
},
|
},
|
||||||
("get", Some(s)) => name.push(make_getter(&s.value())),
|
("set", Some(s)) => special = match special {
|
||||||
("set", Some(s)) => name.push(make_setter(&s.value())),
|
FnSpecialAccess::None =>
|
||||||
("index_get", None) => name.push(FN_IDX_GET.to_string()),
|
FnSpecialAccess::Property(Property::Set(syn::Ident::new(&s.value(),
|
||||||
("index_set", None) => name.push(FN_IDX_SET.to_string()),
|
s.span()))),
|
||||||
|
_ => {
|
||||||
|
return Err(syn::Error::new(item_span.span(), "conflicting setter"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
("get", Some(s)) => special = match special {
|
||||||
|
FnSpecialAccess::None =>
|
||||||
|
FnSpecialAccess::Property(Property::Get(syn::Ident::new(&s.value(),
|
||||||
|
s.span()))),
|
||||||
|
_ => {
|
||||||
|
return Err(syn::Error::new(item_span.span(), "conflicting getter"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
("index_get", None) => special = match special {
|
||||||
|
FnSpecialAccess::None =>
|
||||||
|
FnSpecialAccess::Index(Index::Get),
|
||||||
|
_ => {
|
||||||
|
return Err(syn::Error::new(item_span.span(), "conflicting index_get"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
("index_set", None) => special = match special {
|
||||||
|
FnSpecialAccess::None =>
|
||||||
|
FnSpecialAccess::Index(Index::Set),
|
||||||
|
_ => {
|
||||||
|
return Err(syn::Error::new(item_span.span(), "conflicting index_set"))
|
||||||
|
}
|
||||||
|
},
|
||||||
("return_raw", None) => return_raw = true,
|
("return_raw", None) => return_raw = true,
|
||||||
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
@ -121,6 +168,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
name: if name.is_empty() { None } else { Some(name) },
|
name: if name.is_empty() { None } else { Some(name) },
|
||||||
return_raw,
|
return_raw,
|
||||||
skip,
|
skip,
|
||||||
|
special,
|
||||||
span: Some(span),
|
span: Some(span),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
@ -278,6 +326,32 @@ impl ExportedFn {
|
|||||||
&self.signature.ident
|
&self.signature.ident
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn exported_names(&self) -> Vec<syn::LitStr> {
|
||||||
|
let mut literals = self.params.name.as_ref()
|
||||||
|
.map(|v| v.iter()
|
||||||
|
.map(|s| syn::LitStr::new(s, proc_macro2::Span::call_site())).collect())
|
||||||
|
.unwrap_or_else(|| Vec::new());
|
||||||
|
|
||||||
|
match self.params.special {
|
||||||
|
FnSpecialAccess::None => {},
|
||||||
|
FnSpecialAccess::Property(Property::Get(ref g)) =>
|
||||||
|
literals.push(syn::LitStr::new(&format!("get${}", g.to_string()), g.span())),
|
||||||
|
FnSpecialAccess::Property(Property::Set(ref s)) =>
|
||||||
|
literals.push(syn::LitStr::new(&format!("set${}", s.to_string()), s.span())),
|
||||||
|
FnSpecialAccess::Index(Index::Get) =>
|
||||||
|
literals.push(syn::LitStr::new(FN_IDX_GET, proc_macro2::Span::call_site())),
|
||||||
|
FnSpecialAccess::Index(Index::Set) =>
|
||||||
|
literals.push(syn::LitStr::new(FN_IDX_SET, proc_macro2::Span::call_site())),
|
||||||
|
}
|
||||||
|
|
||||||
|
if literals.is_empty() {
|
||||||
|
literals.push(syn::LitStr::new(&self.signature.ident.to_string(),
|
||||||
|
self.signature.ident.span()));
|
||||||
|
}
|
||||||
|
|
||||||
|
literals
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn exported_name<'n>(&'n self) -> Cow<'n, str> {
|
pub(crate) fn exported_name<'n>(&'n self) -> Cow<'n, str> {
|
||||||
if let Some(ref name) = self.params.name {
|
if let Some(ref name) = self.params.name {
|
||||||
Cow::Borrowed(name.last().unwrap().as_str())
|
Cow::Borrowed(name.last().unwrap().as_str())
|
||||||
|
@ -67,11 +67,7 @@ pub(crate) fn generate_body(
|
|||||||
&format!("{}_token", function.name().to_string()),
|
&format!("{}_token", function.name().to_string()),
|
||||||
function.name().span(),
|
function.name().span(),
|
||||||
);
|
);
|
||||||
let reg_names = function
|
let reg_names = function.exported_names();
|
||||||
.params()
|
|
||||||
.name
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| vec![function.name().to_string()]);
|
|
||||||
|
|
||||||
let fn_input_types: Vec<syn::Expr> = function
|
let fn_input_types: Vec<syn::Expr> = function
|
||||||
.arg_list()
|
.arg_list()
|
||||||
@ -110,9 +106,7 @@ pub(crate) fn generate_body(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for reg_name in reg_names {
|
for fn_literal in reg_names {
|
||||||
let fn_literal = syn::LitStr::new(®_name, proc_macro2::Span::call_site());
|
|
||||||
|
|
||||||
set_fn_stmts.push(
|
set_fn_stmts.push(
|
||||||
syn::parse2::<syn::Stmt>(quote! {
|
syn::parse2::<syn::Stmt>(quote! {
|
||||||
m.set_fn(#fn_literal, FnAccess::Public, &[#(#fn_input_types),*],
|
m.set_fn(#fn_literal, FnAccess::Public, &[#(#fn_input_types),*],
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
error: duplicate Rhai signature for 'get$bar'
|
error: duplicate Rhai signature for 'foo'
|
||||||
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:17:15
|
|
||||||
|
|
|
||||||
17 | #[rhai_fn(get = "bar")]
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: duplicated function renamed 'get$bar'
|
|
||||||
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:12:15
|
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:12:15
|
||||||
|
|
|
|
||||||
12 | #[rhai_fn(name = "foo", get = "bar")]
|
12 | #[rhai_fn(name = "foo", get = "bar")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: duplicated function 'foo'
|
||||||
|
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:18:12
|
||||||
|
|
|
||||||
|
18 | pub fn foo(input: Point) -> bool {
|
||||||
|
| ^^^
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:25:8
|
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:25:8
|
||||||
|
|
|
|
||||||
|
@ -4,8 +4,8 @@ error: Rhai function names may not contain dollar sign
|
|||||||
12 | #[rhai_fn(name = "big$caching")]
|
12 | #[rhai_fn(name = "big$caching")]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
--> $DIR/rhai_fn_rename_dollar_sign.rs:23:8
|
--> $DIR/rhai_fn_rename_dollar_sign.rs:23:8
|
||||||
|
|
|
|
||||||
23 | if test_module::test_fn(n) {
|
23 | if test_module::test_fn(n) {
|
||||||
| ^^^^^^^^^^^ use of undeclared type or module `test_module`
|
| ^^^^^^^^^^^ use of undeclared crate or module `test_module`
|
||||||
|
@ -4,8 +4,8 @@ error: use attribute 'index_get' instead
|
|||||||
12 | #[rhai_fn(name = "index$get$")]
|
12 | #[rhai_fn(name = "index$get$")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
--> $DIR/rhai_fn_rename_to_index_getter.rs:23:8
|
--> $DIR/rhai_fn_rename_to_index_getter.rs:23:8
|
||||||
|
|
|
|
||||||
23 | if test_module::test_fn(n) {
|
23 | if test_module::test_fn(n) {
|
||||||
| ^^^^^^^^^^^ use of undeclared type or module `test_module`
|
| ^^^^^^^^^^^ use of undeclared crate or module `test_module`
|
||||||
|
@ -4,8 +4,8 @@ error: use attribute 'index_set' instead
|
|||||||
12 | #[rhai_fn(name = "index$set$")]
|
12 | #[rhai_fn(name = "index$set$")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
--> $DIR/rhai_fn_rename_to_index_setter.rs:23:8
|
--> $DIR/rhai_fn_rename_to_index_setter.rs:23:8
|
||||||
|
|
|
|
||||||
23 | if test_module::test_fn(n) {
|
23 | if test_module::test_fn(n) {
|
||||||
| ^^^^^^^^^^^ use of undeclared type or module `test_module`
|
| ^^^^^^^^^^^ use of undeclared crate or module `test_module`
|
||||||
|
@ -4,8 +4,8 @@ error: use attribute 'getter = "foo"' instead
|
|||||||
12 | #[rhai_fn(name = "get$foo")]
|
12 | #[rhai_fn(name = "get$foo")]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
--> $DIR/rhai_fn_rename_to_prop_getter.rs:23:8
|
--> $DIR/rhai_fn_rename_to_prop_getter.rs:23:8
|
||||||
|
|
|
|
||||||
23 | if test_module::test_fn(n) {
|
23 | if test_module::test_fn(n) {
|
||||||
| ^^^^^^^^^^^ use of undeclared type or module `test_module`
|
| ^^^^^^^^^^^ use of undeclared crate or module `test_module`
|
||||||
|
@ -4,8 +4,8 @@ error: use attribute 'getter = "foo"' instead
|
|||||||
12 | #[rhai_fn(name = "get$foo")]
|
12 | #[rhai_fn(name = "get$foo")]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared type or module `test_module`
|
error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
|
||||||
--> $DIR/rhai_fn_rename_to_prop_setter.rs:23:8
|
--> $DIR/rhai_fn_rename_to_prop_setter.rs:23:8
|
||||||
|
|
|
|
||||||
23 | if test_module::test_fn(n) {
|
23 | if test_module::test_fn(n) {
|
||||||
| ^^^^^^^^^^^ use of undeclared type or module `test_module`
|
| ^^^^^^^^^^^ use of undeclared crate or module `test_module`
|
||||||
|
Loading…
Reference in New Issue
Block a user