@@ -12,9 +12,8 @@ mod syn_ext;
12
12
mod zval;
13
13
14
14
use proc_macro:: TokenStream ;
15
- use syn:: {
16
- parse_macro_input, DeriveInput , ItemConst , ItemFn , ItemForeignMod , ItemImpl , ItemStruct ,
17
- } ;
15
+ use proc_macro2:: TokenStream as TokenStream2 ;
16
+ use syn:: { DeriveInput , ItemConst , ItemFn , ItemForeignMod , ItemImpl , ItemStruct } ;
18
17
19
18
extern crate proc_macro;
20
19
@@ -203,14 +202,17 @@ extern crate proc_macro;
203
202
// END DOCS FROM classes.md
204
203
#[ proc_macro_attribute]
205
204
pub fn php_class ( args : TokenStream , input : TokenStream ) -> TokenStream {
206
- let input = parse_macro_input ! ( input as ItemStruct ) ;
205
+ php_class_internal ( args. into ( ) , input. into ( ) ) . into ( )
206
+ }
207
+
208
+ #[ allow( clippy:: needless_pass_by_value) ]
209
+ fn php_class_internal ( args : TokenStream2 , input : TokenStream2 ) -> TokenStream2 {
210
+ let input = parse_macro_input2 ! ( input as ItemStruct ) ;
207
211
if !args. is_empty ( ) {
208
- return err ! ( input => "`#[php_class(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) . into ( ) ;
212
+ return err ! ( input => "`#[php_class(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) ;
209
213
}
210
214
211
- class:: parser ( input)
212
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
213
- . into ( )
215
+ class:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
214
216
}
215
217
216
218
// BEGIN DOCS FROM function.md
@@ -371,14 +373,17 @@ pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream {
371
373
// END DOCS FROM function.md
372
374
#[ proc_macro_attribute]
373
375
pub fn php_function ( args : TokenStream , input : TokenStream ) -> TokenStream {
374
- let input = parse_macro_input ! ( input as ItemFn ) ;
376
+ php_function_internal ( args. into ( ) , input. into ( ) ) . into ( )
377
+ }
378
+
379
+ #[ allow( clippy:: needless_pass_by_value) ]
380
+ fn php_function_internal ( args : TokenStream2 , input : TokenStream2 ) -> TokenStream2 {
381
+ let input = parse_macro_input2 ! ( input as ItemFn ) ;
375
382
if !args. is_empty ( ) {
376
- return err ! ( input => "`#[php_function(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) . into ( ) ;
383
+ return err ! ( input => "`#[php_function(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) ;
377
384
}
378
385
379
- function:: parser ( input)
380
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
381
- . into ( )
386
+ function:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
382
387
}
383
388
384
389
// BEGIN DOCS FROM constant.md
@@ -436,14 +441,17 @@ pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream {
436
441
// END DOCS FROM constant.md
437
442
#[ proc_macro_attribute]
438
443
pub fn php_const ( args : TokenStream , input : TokenStream ) -> TokenStream {
439
- let input = parse_macro_input ! ( input as ItemConst ) ;
444
+ php_const_internal ( args. into ( ) , input. into ( ) ) . into ( )
445
+ }
446
+
447
+ #[ allow( clippy:: needless_pass_by_value) ]
448
+ fn php_const_internal ( args : TokenStream2 , input : TokenStream2 ) -> TokenStream2 {
449
+ let input = parse_macro_input2 ! ( input as ItemConst ) ;
440
450
if !args. is_empty ( ) {
441
- return err ! ( input => "`#[php_const(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) . into ( ) ;
451
+ return err ! ( input => "`#[php_const(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) ;
442
452
}
443
453
444
- constant:: parser ( input)
445
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
446
- . into ( )
454
+ constant:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
447
455
}
448
456
449
457
// BEGIN DOCS FROM module.md
@@ -516,14 +524,17 @@ pub fn php_const(args: TokenStream, input: TokenStream) -> TokenStream {
516
524
// END DOCS FROM module.md
517
525
#[ proc_macro_attribute]
518
526
pub fn php_module ( args : TokenStream , input : TokenStream ) -> TokenStream {
519
- let input = parse_macro_input ! ( input as ItemFn ) ;
527
+ php_module_internal ( args. into ( ) , input. into ( ) ) . into ( )
528
+ }
529
+
530
+ #[ allow( clippy:: needless_pass_by_value) ]
531
+ fn php_module_internal ( args : TokenStream2 , input : TokenStream2 ) -> TokenStream2 {
532
+ let input = parse_macro_input2 ! ( input as ItemFn ) ;
520
533
if !args. is_empty ( ) {
521
- return err ! ( input => "`#[php_module(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) . into ( ) ;
534
+ return err ! ( input => "`#[php_module(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) ;
522
535
}
523
536
524
- module:: parser ( input)
525
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
526
- . into ( )
537
+ module:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
527
538
}
528
539
529
540
// BEGIN DOCS FROM impl.md
@@ -713,14 +724,17 @@ pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream {
713
724
// END DOCS FROM impl.md
714
725
#[ proc_macro_attribute]
715
726
pub fn php_impl ( args : TokenStream , input : TokenStream ) -> TokenStream {
716
- let input = parse_macro_input ! ( input as ItemImpl ) ;
727
+ php_impl_internal ( args. into ( ) , input. into ( ) ) . into ( )
728
+ }
729
+
730
+ #[ allow( clippy:: needless_pass_by_value) ]
731
+ fn php_impl_internal ( args : TokenStream2 , input : TokenStream2 ) -> TokenStream2 {
732
+ let input = parse_macro_input2 ! ( input as ItemImpl ) ;
717
733
if !args. is_empty ( ) {
718
- return err ! ( input => "`#[php_impl(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) . into ( ) ;
734
+ return err ! ( input => "`#[php_impl(<args>)]` args are no longer supported. Please use `#[php(<args>)]` instead." ) . to_compile_error ( ) ;
719
735
}
720
736
721
- impl_:: parser ( input)
722
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
723
- . into ( )
737
+ impl_:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
724
738
}
725
739
726
740
// BEGIN DOCS FROM extern.md
@@ -789,12 +803,15 @@ pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream {
789
803
/// [`Zval`]: crate::types::Zval
790
804
// END DOCS FROM extern.md
791
805
#[ proc_macro_attribute]
792
- pub fn php_extern ( _: TokenStream , input : TokenStream ) -> TokenStream {
793
- let input = parse_macro_input ! ( input as ItemForeignMod ) ;
806
+ pub fn php_extern ( args : TokenStream , input : TokenStream ) -> TokenStream {
807
+ php_extern_internal ( args. into ( ) , input. into ( ) ) . into ( )
808
+ }
809
+
810
+ #[ allow( clippy:: needless_pass_by_value) ]
811
+ fn php_extern_internal ( _: TokenStream2 , input : TokenStream2 ) -> TokenStream2 {
812
+ let input = parse_macro_input2 ! ( input as ItemForeignMod ) ;
794
813
795
- extern_:: parser ( input)
796
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
797
- . into ( )
814
+ extern_:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
798
815
}
799
816
800
817
// BEGIN DOCS FROM zval_convert.md
@@ -953,11 +970,13 @@ pub fn php_extern(_: TokenStream, input: TokenStream) -> TokenStream {
953
970
// END DOCS FROM zval_convert.md
954
971
#[ proc_macro_derive( ZvalConvert ) ]
955
972
pub fn zval_convert_derive ( input : TokenStream ) -> TokenStream {
956
- let input = parse_macro_input ! ( input as DeriveInput ) ;
973
+ zval_convert_derive_internal ( input. into ( ) ) . into ( )
974
+ }
957
975
958
- zval:: parser ( input)
959
- . unwrap_or_else ( |e| e. to_compile_error ( ) )
960
- . into ( )
976
+ fn zval_convert_derive_internal ( input : TokenStream2 ) -> TokenStream2 {
977
+ let input = parse_macro_input2 ! ( input as DeriveInput ) ;
978
+
979
+ zval:: parser ( input) . unwrap_or_else ( |e| e. to_compile_error ( ) )
961
980
}
962
981
963
982
/// Defines an `extern` function with the Zend fastcall convention based on
@@ -992,35 +1011,61 @@ pub fn zval_convert_derive(input: TokenStream) -> TokenStream {
992
1011
/// Rust and the `abi_vectorcall` feature enabled.
993
1012
#[ proc_macro]
994
1013
pub fn zend_fastcall ( input : TokenStream ) -> TokenStream {
995
- let input = parse_macro_input ! ( input as ItemFn ) ;
1014
+ zend_fastcall_internal ( input. into ( ) ) . into ( )
1015
+ }
996
1016
997
- fastcall:: parser ( input) . into ( )
1017
+ fn zend_fastcall_internal ( input : TokenStream2 ) -> TokenStream2 {
1018
+ let input = parse_macro_input2 ! ( input as ItemFn ) ;
1019
+
1020
+ fastcall:: parser ( input)
998
1021
}
999
1022
1000
1023
/// Wraps a function to be used in the [`Module::function`] method.
1001
1024
#[ proc_macro]
1002
1025
pub fn wrap_function ( input : TokenStream ) -> TokenStream {
1003
- let input = parse_macro_input ! ( input as syn:: Path ) ;
1026
+ wrap_function_internal ( input. into ( ) ) . into ( )
1027
+ }
1028
+
1029
+ fn wrap_function_internal ( input : TokenStream2 ) -> TokenStream2 {
1030
+ let input = parse_macro_input2 ! ( input as syn:: Path ) ;
1004
1031
1005
1032
match function:: wrap ( & input) {
1006
1033
Ok ( parsed) => parsed,
1007
1034
Err ( e) => e. to_compile_error ( ) ,
1008
1035
}
1009
- . into ( )
1010
1036
}
1011
1037
1012
1038
/// Wraps a constant to be used in the [`ModuleBuilder::constant`] method.
1013
1039
#[ proc_macro]
1014
1040
pub fn wrap_constant ( input : TokenStream ) -> TokenStream {
1015
- let input = parse_macro_input ! ( input as syn:: Path ) ;
1041
+ wrap_constant_internal ( input. into ( ) ) . into ( )
1042
+ }
1043
+
1044
+ fn wrap_constant_internal ( input : TokenStream2 ) -> TokenStream2 {
1045
+ let input = parse_macro_input2 ! ( input as syn:: Path ) ;
1016
1046
1017
1047
match constant:: wrap ( & input) {
1018
1048
Ok ( parsed) => parsed,
1019
1049
Err ( e) => e. to_compile_error ( ) ,
1020
1050
}
1021
- . into ( )
1022
1051
}
1023
1052
1053
+ macro_rules! parse_macro_input2 {
1054
+ ( $tokenstream: ident as $ty: ty) => {
1055
+ match syn:: parse2:: <$ty>( $tokenstream) {
1056
+ Ok ( data) => data,
1057
+ Err ( err) => {
1058
+ return proc_macro2:: TokenStream :: from( err. to_compile_error( ) ) ;
1059
+ }
1060
+ }
1061
+ } ;
1062
+ ( $tokenstream: ident) => {
1063
+ $crate:: parse_macro_input!( $tokenstream as _)
1064
+ } ;
1065
+ }
1066
+
1067
+ pub ( crate ) use parse_macro_input2;
1068
+
1024
1069
macro_rules! err {
1025
1070
( $span: expr => $( $msg: tt) * ) => {
1026
1071
:: syn:: Error :: new( :: syn:: spanned:: Spanned :: span( & $span) , format!( $( $msg) * ) )
@@ -1061,3 +1106,62 @@ pub(crate) mod prelude {
1061
1106
pub ( crate ) use crate :: { bail, err} ;
1062
1107
pub ( crate ) type Result < T > = std:: result:: Result < T , syn:: Error > ;
1063
1108
}
1109
+
1110
+ #[ cfg( test) ]
1111
+ mod tests {
1112
+ use super :: * ;
1113
+ use std:: path:: PathBuf ;
1114
+
1115
+ type AttributeFn =
1116
+ fn ( proc_macro2:: TokenStream , proc_macro2:: TokenStream ) -> proc_macro2:: TokenStream ;
1117
+ type FunctionLikeFn = fn ( proc_macro2:: TokenStream ) -> proc_macro2:: TokenStream ;
1118
+
1119
+ #[ test]
1120
+ pub fn test_expand ( ) {
1121
+ macrotest:: expand ( "tests/expand/*.rs" ) ;
1122
+ for entry in glob:: glob ( "tests/expand/*.rs" ) . expect ( "Failed to read expand tests glob" ) {
1123
+ let entry = entry. expect ( "Failed to read expand test file" ) ;
1124
+ runtime_expand_attr ( & entry) ;
1125
+ runtime_expand_func ( & entry) ;
1126
+ runtime_expand_derive ( & entry) ;
1127
+ }
1128
+ }
1129
+
1130
+ fn runtime_expand_attr ( path : & PathBuf ) {
1131
+ let file = std:: fs:: File :: open ( path) . expect ( "Failed to open expand test file" ) ;
1132
+ runtime_macros:: emulate_attributelike_macro_expansion (
1133
+ file,
1134
+ & [
1135
+ ( "php_class" , php_class_internal as AttributeFn ) ,
1136
+ ( "php_const" , php_const_internal as AttributeFn ) ,
1137
+ ( "php_extern" , php_extern_internal as AttributeFn ) ,
1138
+ ( "php_function" , php_function_internal as AttributeFn ) ,
1139
+ ( "php_impl" , php_impl_internal as AttributeFn ) ,
1140
+ ( "php_module" , php_module_internal as AttributeFn ) ,
1141
+ ] ,
1142
+ )
1143
+ . expect ( "Failed to expand attribute macros in test file" ) ;
1144
+ }
1145
+
1146
+ fn runtime_expand_func ( path : & PathBuf ) {
1147
+ let file = std:: fs:: File :: open ( path) . expect ( "Failed to open expand test file" ) ;
1148
+ runtime_macros:: emulate_functionlike_macro_expansion (
1149
+ file,
1150
+ & [
1151
+ ( "zend_fastcall" , zend_fastcall_internal as FunctionLikeFn ) ,
1152
+ ( "wrap_function" , wrap_function_internal as FunctionLikeFn ) ,
1153
+ ( "wrap_constant" , wrap_constant_internal as FunctionLikeFn ) ,
1154
+ ] ,
1155
+ )
1156
+ . expect ( "Failed to expand function-like macros in test file" ) ;
1157
+ }
1158
+
1159
+ fn runtime_expand_derive ( path : & PathBuf ) {
1160
+ let file = std:: fs:: File :: open ( path) . expect ( "Failed to open expand test file" ) ;
1161
+ runtime_macros:: emulate_derive_macro_expansion (
1162
+ file,
1163
+ & [ ( "ZvalConvert" , zval_convert_derive_internal) ] ,
1164
+ )
1165
+ . expect ( "Failed to expand derive macros in test file" ) ;
1166
+ }
1167
+ }
0 commit comments