Skip to content

Commit 0f754ed

Browse files
committed
Mangle conflicting idents (#2806)
1 parent c06c731 commit 0f754ed

File tree

1 file changed

+63
-13
lines changed

1 file changed

+63
-13
lines changed

crates/macro-support/src/parser.rs

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,29 @@ use syn::spanned::Spanned;
1515

1616
thread_local!(static ATTRS: AttributeParseState = Default::default());
1717

18+
/// Javascript keywords which are not keywords in Rust.
19+
const JS_KEYWORDS: [&str; 20] = [
20+
"class",
21+
"case",
22+
"catch",
23+
"debugger",
24+
"default",
25+
"delete",
26+
"export",
27+
"extends",
28+
"finally",
29+
"function",
30+
"import",
31+
"instanceof",
32+
"new",
33+
"null",
34+
"switch",
35+
"this",
36+
"throw",
37+
"var",
38+
"void",
39+
"with",
40+
];
1841
#[derive(Default)]
1942
struct AttributeParseState {
2043
parsed: Cell<usize>,
@@ -462,6 +485,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a ast::ImportModule)> for syn::ForeignIte
462485
self.vis.clone(),
463486
false,
464487
None,
488+
false,
465489
)?
466490
.0;
467491
let catch = opts.catch().is_some();
@@ -704,13 +728,19 @@ impl ConvertToAst<BindgenAttrs> for syn::ItemFn {
704728
self.vis,
705729
false,
706730
None,
731+
false,
707732
)?;
708733
attrs.check_used()?;
709734
Ok(ret.0)
710735
}
711736
}
712737

738+
pub(crate) fn is_js_keyword(keyword: &str) -> bool {
739+
JS_KEYWORDS.contains(&keyword)
740+
}
741+
713742
/// Construct a function (and gets the self type if appropriate) for our AST from a syn function.
743+
#[allow(clippy::too_many_arguments)]
714744
fn function_from_decl(
715745
decl_name: &syn::Ident,
716746
opts: &BindgenAttrs,
@@ -719,6 +749,7 @@ fn function_from_decl(
719749
vis: syn::Visibility,
720750
allow_self: bool,
721751
self_ty: Option<&Ident>,
752+
is_from_impl: bool,
722753
) -> Result<(ast::Function, Option<ast::MethodSelf>), Diagnostic> {
723754
if sig.variadic.is_some() {
724755
bail_span!(sig.variadic, "can't #[wasm_bindgen] variadic functions");
@@ -754,11 +785,21 @@ fn function_from_decl(
754785
})
755786
};
756787

788+
let replace_colliding_arg = |i: &mut syn::PatType| {
789+
if let syn::Pat::Ident(ref mut i) = *i.pat {
790+
let ident = i.ident.to_string();
791+
if is_js_keyword(ident.as_str()) {
792+
i.ident = Ident::new(format!("_{}", ident).as_str(), i.ident.span());
793+
}
794+
}
795+
};
796+
757797
let mut method_self = None;
758798
let arguments = inputs
759799
.into_iter()
760800
.filter_map(|arg| match arg {
761801
syn::FnArg::Typed(mut c) => {
802+
replace_colliding_arg(&mut c);
762803
c.ty = Box::new(replace_self(*c.ty));
763804
Some(c)
764805
}
@@ -784,21 +825,29 @@ fn function_from_decl(
784825
syn::ReturnType::Type(_, ty) => Some(replace_self(*ty)),
785826
};
786827

787-
let (name, name_span, renamed_via_js_name) =
788-
if let Some((js_name, js_name_span)) = opts.js_name() {
789-
let kind = operation_kind(&opts);
790-
let prefix = match kind {
791-
OperationKind::Setter(_) => "set_",
792-
_ => "",
793-
};
794-
(
795-
format!("{}{}", prefix, js_name.to_string()),
796-
js_name_span,
797-
true,
798-
)
828+
let (name, name_span, renamed_via_js_name) = if let Some((js_name, js_name_span)) =
829+
opts.js_name()
830+
{
831+
let kind = operation_kind(opts);
832+
let prefix = match kind {
833+
OperationKind::Setter(_) => "set_",
834+
_ => "",
835+
};
836+
let name = if prefix.is_empty() && opts.method().is_none() && is_js_keyword(js_name) {
837+
format!("_{}", js_name)
799838
} else {
800-
(decl_name.to_string(), decl_name.span(), false)
839+
format!("{}{}", prefix, js_name)
801840
};
841+
(name, js_name_span, true)
842+
} else {
843+
let name =
844+
if !is_from_impl && opts.method().is_none() && is_js_keyword(&decl_name.to_string()) {
845+
format!("_{}", decl_name)
846+
} else {
847+
decl_name.to_string()
848+
};
849+
(name, decl_name.span(), false)
850+
};
802851
Ok((
803852
ast::Function {
804853
arguments,
@@ -1054,6 +1103,7 @@ impl<'a, 'b> MacroParse<(&'a Ident, &'a str)> for &'b mut syn::ImplItemMethod {
10541103
self.vis.clone(),
10551104
true,
10561105
Some(class),
1106+
true,
10571107
)?;
10581108
let method_kind = if opts.constructor().is_some() {
10591109
ast::MethodKind::Constructor

0 commit comments

Comments
 (0)