@@ -3,12 +3,15 @@ use darling::FromMeta;
33use proc_macro2:: { Span , TokenStream } ;
44use quote:: quote;
55use syn:: {
6- spanned:: Spanned as _, Attribute , AttributeArgs , Ident , Item , ItemConst , ItemFn , NestedMeta ,
6+ spanned:: Spanned as _, Attribute , AttributeArgs , Ident , Item , ItemConst , ItemFn , ItemStruct ,
7+ NestedMeta ,
78} ;
89
910use crate :: {
11+ class:: { self , Class } ,
1012 constant:: { self , Constant } ,
1113 function:: { self , Function } ,
14+ module:: generate_registered_class_impl,
1215 startup_function,
1316} ;
1417
@@ -17,6 +20,7 @@ pub(crate) struct ModuleBuilder {
1720 pub functions : Vec < ItemFn > ,
1821 pub startup_function : Option < ItemFn > ,
1922 pub constants : Vec < ItemConst > ,
23+ pub classes : Vec < ItemStruct > ,
2024 pub unmapped : Vec < Item > ,
2125}
2226
@@ -37,27 +41,39 @@ impl ModuleBuilder {
3741 self . constants . push ( constant) ;
3842 }
3943
44+ pub fn add_class ( & mut self , class : ItemStruct ) {
45+ self . classes . push ( class) ;
46+ }
47+
4048 pub fn add_unmapped ( & mut self , item : Item ) {
4149 self . unmapped . push ( item) ;
4250 }
4351
4452 pub fn build ( & self ) -> TokenStream {
53+ let ( class_stream, classes) = self . build_classes ( ) ;
4554 let ( function_stream, functions) = self . build_functions ( ) ;
4655 let ( constant_stream, constants) = self . build_constants ( ) ;
47- let ( startup_function, startup_ident) = self . build_startup_function ( & constants) . unwrap ( ) ;
56+ let ( startup_function, startup_ident) =
57+ self . build_startup_function ( & classes, & constants) . unwrap ( ) ;
4858
4959 let functions = functions
5060 . iter ( )
5161 . map ( |func| func. get_builder ( ) )
5262 . collect :: < Vec < _ > > ( ) ;
63+ let registered_classes_impls = classes
64+ . iter ( )
65+ . map ( |class| generate_registered_class_impl ( class) )
66+ . collect :: < Result < Vec < _ > , _ > > ( )
67+ . unwrap ( ) ;
5368 let unmapped = & self . unmapped ;
5469
5570 // let describe_fn = generate_stubs(&state);
5671
5772 quote ! {
58- // #(#registered_classes_impls)*
5973
6074 mod module {
75+ #class_stream
76+ #( #registered_classes_impls) *
6177 #function_stream
6278 #constant_stream
6379 #startup_function
@@ -128,20 +144,47 @@ impl ModuleBuilder {
128144 )
129145 }
130146
131- fn build_startup_function ( & self , constants : & Vec < Constant > ) -> Result < ( TokenStream , Ident ) > {
147+ fn build_classes ( & self ) -> ( TokenStream , Vec < Class > ) {
148+ let structs = self
149+ . classes
150+ . iter ( )
151+ . map ( |class| {
152+ let args = class
153+ . attrs
154+ . iter ( )
155+ . find ( |attr| attr. path . is_ident ( "php_class" ) ) ;
156+ let args = parse_metadata ( args. unwrap ( ) ) ;
157+ class:: parser ( args, class. clone ( ) )
158+ } )
159+ . collect :: < Result < Vec < _ > , _ > > ( )
160+ . unwrap ( ) ;
161+
162+ let tokens = structs. iter ( ) . map ( |( tokens, _) | tokens) ;
163+
164+ (
165+ quote ! { #( #tokens) * } ,
166+ structs. into_iter ( ) . map ( |( _, c) | c) . collect ( ) ,
167+ )
168+ }
169+
170+ fn build_startup_function (
171+ & self ,
172+ classes : & Vec < Class > ,
173+ constants : & Vec < Constant > ,
174+ ) -> Result < ( TokenStream , Ident ) > {
132175 self . startup_function
133176 . as_ref ( )
134177 . map ( |f| {
135178 let attr = f. attrs . iter ( ) . find ( |a| a. path . is_ident ( "php_startup" ) ) ;
136179 let args = parse_attr ( attr. unwrap ( ) ) . unwrap ( ) ;
137- startup_function:: parser ( Some ( args) , f, constants)
180+ startup_function:: parser ( Some ( args) , f, classes , constants)
138181 } )
139182 . unwrap_or_else ( || {
140183 let parsed = syn:: parse2 ( quote ! {
141184 fn php_module_startup( ) { }
142185 } )
143186 . map_err ( |_| anyhow ! ( "Unable to generate PHP module startup function." ) ) ?;
144- startup_function:: parser ( None , & parsed, constants)
187+ startup_function:: parser ( None , & parsed, classes , constants)
145188 } )
146189 }
147190}
0 commit comments