@@ -43,6 +43,7 @@ struct InterfaceData<'a> {
43
43
name : String ,
44
44
path : Path ,
45
45
attrs : StructAttributes ,
46
+ constructor : Option < Function < ' a > > ,
46
47
methods : Vec < FnBuilder > ,
47
48
constants : Vec < Constant < ' a > > ,
48
49
}
@@ -55,6 +56,12 @@ impl ToTokens for InterfaceData<'_> {
55
56
let methods_sig = & self . methods ;
56
57
let path = & self . path ;
57
58
let constants = & self . constants ;
59
+
60
+ let constructor = self . constructor
61
+ . as_ref ( )
62
+ . map ( |func| func. constructor_meta ( & path) )
63
+ . option_tokens ( ) ;
64
+
58
65
quote ! {
59
66
pub struct #interface_name;
60
67
@@ -88,8 +95,7 @@ impl ToTokens for InterfaceData<'_> {
88
95
}
89
96
90
97
fn constructor( ) -> Option <:: ext_php_rs:: class:: ConstructorMeta <Self >> {
91
- use :: ext_php_rs:: internal:: class:: PhpClassImpl ;
92
- :: ext_php_rs:: internal:: class:: PhpClassImplCollector :: <Self >:: default ( ) . get_constructor( )
98
+ None
93
99
}
94
100
95
101
fn constants( ) -> & ' static [ (
@@ -178,6 +184,7 @@ impl<'a> InterfaceData<'a> {
178
184
name : String ,
179
185
path : Path ,
180
186
attrs : StructAttributes ,
187
+ constructor : Option < Function < ' a > > ,
181
188
methods : Vec < FnBuilder > ,
182
189
constants : Vec < Constant < ' a > > ,
183
190
) -> Self {
@@ -186,6 +193,7 @@ impl<'a> InterfaceData<'a> {
186
193
name,
187
194
path,
188
195
attrs,
196
+ constructor,
189
197
methods,
190
198
constants,
191
199
}
@@ -201,11 +209,28 @@ impl<'a> Parse<'a, InterfaceData<'a>> for ItemTrait {
201
209
let interface_name = format_ident ! ( "PhpInterface{ident}" ) ;
202
210
let ts = quote ! { #interface_name } ;
203
211
let path: Path = syn:: parse2 ( ts) ?;
204
- let mut data = InterfaceData :: new ( ident, name, path, attrs, Vec :: new ( ) , Vec :: new ( ) ) ;
212
+ let mut data = InterfaceData :: new (
213
+ ident,
214
+ name,
215
+ path,
216
+ attrs,
217
+ None ,
218
+ Vec :: new ( ) ,
219
+ Vec :: new ( )
220
+ ) ;
205
221
206
222
for item in & mut self . items {
207
223
match item {
208
- TraitItem :: Fn ( f) => data. methods . push ( f. parse ( ) ?) ,
224
+ TraitItem :: Fn ( f) => {
225
+ match f. parse ( ) ? {
226
+ MethodKind :: Method ( builder) => data. methods . push ( builder) ,
227
+ MethodKind :: Constructor ( builder) => {
228
+ if data. constructor . replace ( builder) . is_some ( ) {
229
+ bail ! ( "Only one constructor can be provided per class." ) ;
230
+ }
231
+ }
232
+ } ;
233
+ } ,
209
234
TraitItem :: Const ( c) => data. constants . push ( c. parse ( ) ?) ,
210
235
_ => { }
211
236
}
@@ -229,20 +254,32 @@ pub struct PhpFunctionInterfaceAttribute {
229
254
constructor : Flag ,
230
255
}
231
256
232
- impl < ' a > Parse < ' a , FnBuilder > for TraitItemFn {
233
- fn parse ( & ' a mut self ) -> Result < FnBuilder > {
234
- let php_attr = PhpFunctionInterfaceAttribute :: from_attributes ( & self . attrs ) ?;
257
+ enum MethodKind < ' a > {
258
+ Method ( FnBuilder ) ,
259
+ Constructor ( Function < ' a > ) ,
260
+ }
261
+
262
+ impl < ' a > Parse < ' a , MethodKind < ' a > > for TraitItemFn {
263
+ fn parse ( & ' a mut self ) -> Result < MethodKind < ' a > > {
235
264
if self . default . is_some ( ) {
236
- bail ! ( "Interface could not have default impl" ) ;
265
+ bail ! ( self => "Interface could not have default impl" ) ;
237
266
}
238
267
239
- let mut args = Args :: parse_from_fnargs ( self . sig . inputs . iter ( ) , php_attr . defaults ) ? ;
240
- let docs = get_docs ( & php_attr . attrs ) ? ;
241
-
268
+ let php_attr = PhpFunctionInterfaceAttribute :: from_attributes (
269
+ & self . attrs
270
+ ) ? ;
242
271
self . attrs . clean_php ( ) ;
243
272
273
+ let mut args = Args :: parse_from_fnargs (
274
+ self . sig . inputs . iter ( ) ,
275
+ php_attr. defaults
276
+ ) ?;
277
+
278
+ let docs = get_docs ( & php_attr. attrs ) ?;
279
+
244
280
let mut modifiers: HashSet < MethodModifier > = HashSet :: new ( ) ;
245
281
modifiers. insert ( MethodModifier :: Abstract ) ;
282
+
246
283
if args. typed . first ( ) . is_some_and ( |arg| arg. name == "self_" ) {
247
284
args. typed . pop ( ) ;
248
285
} else if args. receiver . is_none ( ) {
@@ -259,20 +296,26 @@ impl<'a> Parse<'a, FnBuilder> for TraitItemFn {
259
296
docs,
260
297
) ;
261
298
262
- Ok ( FnBuilder {
263
- builder : f. abstract_function_builder ( ) ,
264
- vis : php_attr. vis . unwrap_or ( Visibility :: Public ) ,
265
- modifiers,
266
- } )
299
+ if php_attr. constructor . is_present ( ) {
300
+ Ok ( MethodKind :: Constructor ( f) )
301
+ } else {
302
+ let builder = FnBuilder {
303
+ builder : f. abstract_function_builder ( ) ,
304
+ vis : php_attr. vis . unwrap_or ( Visibility :: Public ) ,
305
+ modifiers,
306
+ } ;
307
+
308
+ Ok ( MethodKind :: Method ( builder) )
309
+ }
267
310
}
268
311
}
269
312
270
- impl < ' a > Parse < ' a , Vec < FnBuilder > > for ItemTrait {
271
- fn parse ( & ' a mut self ) -> Result < Vec < FnBuilder > > {
313
+ impl < ' a > Parse < ' a , Vec < MethodKind < ' a > > > for ItemTrait {
314
+ fn parse ( & ' a mut self ) -> Result < Vec < MethodKind < ' a > > > {
272
315
Ok ( self
273
316
. items
274
317
. iter_mut ( )
275
- . filter_map ( |item : & mut TraitItem | match item {
318
+ . filter_map ( |item| match item {
276
319
TraitItem :: Fn ( f) => Some ( f) ,
277
320
_ => None ,
278
321
} )
@@ -309,7 +352,7 @@ impl<'a> Constant<'a> {
309
352
impl < ' a > Parse < ' a , Constant < ' a > > for TraitItemConst {
310
353
fn parse ( & ' a mut self ) -> Result < Constant < ' a > > {
311
354
if self . default . is_none ( ) {
312
- bail ! ( "Interface const could not be empty" ) ;
355
+ bail ! ( self => "Interface const could not be empty" ) ;
313
356
}
314
357
315
358
let attr = PhpConstAttribute :: from_attributes ( & self . attrs ) ?;
@@ -327,7 +370,7 @@ impl<'a> Parse<'a, Vec<Constant<'a>>> for ItemTrait {
327
370
Ok ( self
328
371
. items
329
372
. iter_mut ( )
330
- . filter_map ( |item : & mut TraitItem | match item {
373
+ . filter_map ( |item| match item {
331
374
TraitItem :: Const ( c) => Some ( c) ,
332
375
_ => None ,
333
376
} )
0 commit comments