Check rename collisions with special names.

This commit is contained in:
Stephen Chung 2020-09-26 00:30:30 +08:00
parent 6b13e266b9
commit a2551a4650
3 changed files with 52 additions and 30 deletions

View File

@ -43,6 +43,30 @@ impl Default for FnSpecialAccess {
} }
} }
impl FnSpecialAccess {
pub fn get_fn_name(&self) -> Option<(String, String, proc_macro2::Span)> {
match self {
FnSpecialAccess::None => None,
FnSpecialAccess::Property(Property::Get(ref g)) => {
Some((format!("get${}", g.to_string()), g.to_string(), g.span()))
}
FnSpecialAccess::Property(Property::Set(ref s)) => {
Some((format!("set${}", s.to_string()), s.to_string(), s.span()))
}
FnSpecialAccess::Index(Index::Get) => Some((
FN_IDX_GET.to_string(),
"index_get".to_string(),
proc_macro2::Span::call_site(),
)),
FnSpecialAccess::Index(Index::Set) => Some((
FN_IDX_SET.to_string(),
"index_set".to_string(),
proc_macro2::Span::call_site(),
)),
}
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct ExportedFnParams { pub(crate) struct ExportedFnParams {
pub name: Option<Vec<String>>, pub name: Option<Vec<String>>,
@ -363,22 +387,8 @@ impl ExportedFn {
}) })
.unwrap_or_else(|| Vec::new()); .unwrap_or_else(|| Vec::new());
match self.params.special { if let Some((s, _, span)) = self.params.special.get_fn_name() {
FnSpecialAccess::None => {} literals.push(syn::LitStr::new(&s, span));
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() { if literals.is_empty() {

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use crate::attrs::ExportScope; use crate::attrs::ExportScope;
use crate::function::ExportedFn; use crate::function::{ExportedFn, FnSpecialAccess};
use crate::module::Module; use crate::module::Module;
pub(crate) type ExportedConst = (String, Box<syn::Type>, syn::Expr); pub(crate) type ExportedConst = (String, Box<syn::Type>, syn::Expr);
@ -202,18 +202,29 @@ pub(crate) fn check_rename_collisions(fns: &Vec<ExportedFn>) -> Result<(), syn::
let mut fn_sig = HashMap::<String, proc_macro2::Span>::new(); let mut fn_sig = HashMap::<String, proc_macro2::Span>::new();
for itemfn in fns.iter() { for itemfn in fns.iter() {
if let Some(ref names) = itemfn.params().name { if itemfn.params().name.is_some() || itemfn.params().special != FnSpecialAccess::None {
for name in names { let mut names = itemfn
.params()
.name
.as_ref()
.map(|v| v.iter().map(|n| (n.clone(), n.clone())).collect())
.unwrap_or_else(|| Vec::new());
if let Some((s, n, _)) = itemfn.params().special.get_fn_name() {
names.push((s, n));
}
for (name, fn_name) in names {
let current_span = itemfn.params().span.as_ref().unwrap(); let current_span = itemfn.params().span.as_ref().unwrap();
let key = make_key(name.clone(), itemfn); let key = make_key(name.clone(), itemfn);
if let Some(other_span) = renames.insert(key, *current_span) { if let Some(other_span) = renames.insert(key, *current_span) {
let mut err = syn::Error::new( let mut err = syn::Error::new(
*current_span, *current_span,
format!("duplicate Rhai signature for '{}'", &name), format!("duplicate Rhai signature for '{}'", &fn_name),
); );
err.combine(syn::Error::new( err.combine(syn::Error::new(
other_span, other_span,
format!("duplicated function renamed '{}'", &name), format!("duplicated function renamed '{}'", &fn_name),
)); ));
return Err(err); return Err(err);
} }
@ -237,14 +248,15 @@ pub(crate) fn check_rename_collisions(fns: &Vec<ExportedFn>) -> Result<(), syn::
} }
for (new_name, attr_span) in renames.drain() { for (new_name, attr_span) in renames.drain() {
let fn_name = new_name.split('.').next().unwrap();
if let Some(fn_span) = fn_sig.get(&new_name) { if let Some(fn_span) = fn_sig.get(&new_name) {
let mut err = syn::Error::new( let mut err = syn::Error::new(
attr_span, attr_span,
format!("duplicate Rhai signature for '{}'", &new_name), format!("duplicate Rhai signature for '{}'", &fn_name),
); );
err.combine(syn::Error::new( err.combine(syn::Error::new(
*fn_span, *fn_span,
format!("duplicated function '{}'", &new_name), format!("duplicated function '{}'", &fn_name),
)); ));
return Err(err); return Err(err);
} }

View File

@ -1,15 +1,15 @@
error: duplicate Rhai signature for 'foo' error: duplicate Rhai signature for 'bar'
--> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:17:15
|
17 | #[rhai_fn(get = "bar")]
| ^^^
error: duplicated function renamed '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
| |