@@ -9,12 +9,35 @@ use backend::Diagnostic;
9
9
use proc_macro2:: { Delimiter , Ident , Span , TokenStream , TokenTree } ;
10
10
use quote:: ToTokens ;
11
11
use shared;
12
- use syn;
13
12
use syn:: parse:: { Parse , ParseStream , Result as SynResult } ;
14
13
use syn:: spanned:: Spanned ;
14
+ use syn:: { self , FnArg , Pat , Signature } ;
15
15
16
16
thread_local ! ( static ATTRS : AttributeParseState = Default :: default ( ) ) ;
17
17
18
+ /// Javascript keywords which are not keywords in Rust.
19
+ const JS_KEYWORDS : [ & str ; 19 ] = [
20
+ "class" ,
21
+ "case" ,
22
+ "catch" ,
23
+ "debugger" ,
24
+ "default" ,
25
+ "delete" ,
26
+ "export" ,
27
+ "extends" ,
28
+ "finally" ,
29
+ "function" ,
30
+ "import" ,
31
+ "instaceof" ,
32
+ "new" ,
33
+ "switch" ,
34
+ "this" ,
35
+ "throw" ,
36
+ "var" ,
37
+ "void" ,
38
+ "with" ,
39
+ ] ;
40
+
18
41
#[ derive( Default ) ]
19
42
struct AttributeParseState {
20
43
parsed : Cell < usize > ,
@@ -815,6 +838,30 @@ fn function_from_decl(
815
838
) )
816
839
}
817
840
841
+ /// Checks if `keyword` is keyword in javascript.
842
+ pub ( crate ) fn is_js_keyword < T : ToString > ( keyword : T ) -> bool {
843
+ let keyword = keyword. to_string ( ) ;
844
+ JS_KEYWORDS . contains ( & keyword. as_str ( ) )
845
+ }
846
+
847
+ /// Maps signatures's arguments to idents.
848
+ pub ( crate ) fn sign_args_to_idents ( sig : & Signature ) -> Vec < Ident > {
849
+ sig. inputs
850
+ . to_owned ( )
851
+ . into_iter ( )
852
+ . filter_map ( |arg| match arg {
853
+ FnArg :: Typed ( t) => {
854
+ if let Pat :: Ident ( ident) = * t. pat {
855
+ Some ( ident. ident )
856
+ } else {
857
+ None
858
+ }
859
+ }
860
+ _ => None ,
861
+ } )
862
+ . collect ( )
863
+ }
864
+
818
865
pub ( crate ) trait MacroParse < Ctx > {
819
866
/// Parse the contents of an object into our AST, with a context if necessary.
820
867
///
@@ -854,6 +901,19 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
854
901
bail_span ! ( & f. sig. inputs, "the start function cannot have arguments" , ) ;
855
902
}
856
903
}
904
+ let fn_name_as_ident = if let Some ( ( js_name, span) ) = opts. js_name ( ) {
905
+ Ident :: new ( js_name, span)
906
+ } else {
907
+ f. sig . ident . clone ( )
908
+ } ;
909
+ if is_js_keyword ( fn_name_as_ident) {
910
+ bail_span ! ( & f. sig. ident, "function name cannot be js keyword" , ) ;
911
+ }
912
+ let fn_args = sign_args_to_idents ( & f. sig ) ;
913
+ if let Some ( ident) = fn_args. into_iter ( ) . find ( |inpt| is_js_keyword ( inpt) ) {
914
+ bail_span ! ( ident, "function argument name cannot be js keyword" , ) ;
915
+ }
916
+
857
917
let method_kind = ast:: MethodKind :: Operation ( ast:: Operation {
858
918
is_static : true ,
859
919
kind : operation_kind ( & opts) ,
@@ -978,7 +1038,13 @@ fn prepare_for_impl_recursion(
978
1038
impl_opts : & BindgenAttrs ,
979
1039
) -> Result < ( ) , Diagnostic > {
980
1040
let method = match item {
981
- syn:: ImplItem :: Method ( m) => m,
1041
+ syn:: ImplItem :: Method ( m) => {
1042
+ let fn_args = sign_args_to_idents ( & m. sig ) ;
1043
+ if let Some ( ident) = fn_args. into_iter ( ) . find ( |inpt| is_js_keyword ( inpt) ) {
1044
+ bail_span ! ( ident, "method argument name cannot be js keyword" , ) ;
1045
+ }
1046
+ m
1047
+ }
982
1048
syn:: ImplItem :: Const ( _) => {
983
1049
bail_span ! (
984
1050
& * item,
0 commit comments