14
14
use Symfony \Component \Config \Definition \ArrayNode ;
15
15
use Symfony \Component \Config \Definition \BaseNode ;
16
16
use Symfony \Component \Config \Definition \BooleanNode ;
17
+ use Symfony \Component \Config \Definition \Builder \ExprBuilder ;
17
18
use Symfony \Component \Config \Definition \ConfigurationInterface ;
18
19
use Symfony \Component \Config \Definition \EnumNode ;
19
20
use Symfony \Component \Config \Definition \Exception \InvalidConfigurationException ;
@@ -141,8 +142,9 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n
141
142
$ node ->getName (),
142
143
$ this ->getType ($ childClass ->getFqcn (), $ hasNormalizationClosures )
143
144
);
145
+ $ nodeTypes = $ this ->getParameterTypes ($ node );
144
146
$ body = $ hasNormalizationClosures ? '
145
- COMMENTpublic function NAME(mixed $value = []): CLASS|static
147
+ COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static
146
148
{
147
149
if (!\is_array($value)) {
148
150
$this->_usedProperties[ \'PROPERTY \'] = true;
@@ -172,7 +174,12 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n
172
174
return $this->PROPERTY;
173
175
} ' ;
174
176
$ class ->addUse (InvalidConfigurationException::class);
175
- $ class ->addMethod ($ node ->getName (), $ body , ['COMMENT ' => $ comment , 'PROPERTY ' => $ property ->getName (), 'CLASS ' => $ childClass ->getFqcn ()]);
177
+ $ class ->addMethod ($ node ->getName (), $ body , [
178
+ 'COMMENT ' => $ comment ,
179
+ 'PROPERTY ' => $ property ->getName (),
180
+ 'CLASS ' => $ childClass ->getFqcn (),
181
+ 'PARAM_TYPE ' => \in_array ('mixed ' , $ nodeTypes , true ) ? 'mixed ' : implode ('| ' , $ nodeTypes ),
182
+ ]);
176
183
177
184
$ this ->buildNode ($ node , $ childClass , $ this ->getSubNamespace ($ childClass ));
178
185
}
@@ -209,19 +216,21 @@ private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuild
209
216
$ methodName = $ name ;
210
217
$ hasNormalizationClosures = $ this ->hasNormalizationClosures ($ node ) || $ this ->hasNormalizationClosures ($ prototype );
211
218
212
- $ parameterType = $ this ->getParameterType ($ prototype );
213
- if (null !== $ parameterType || $ prototype instanceof ScalarNode) {
219
+ $ nodeParameterTypes = $ this ->getParameterTypes ($ node );
220
+ $ prototypeParameterTypes = $ this ->getParameterTypes ($ prototype );
221
+ if (!($ prototype instanceof ArrayNode && (!$ prototype instanceof PrototypedArrayNode || !$ prototype ->getPrototype () instanceof ScalarNode))) {
214
222
$ class ->addUse (ParamConfigurator::class);
215
223
$ property = $ class ->addProperty ($ node ->getName ());
216
224
if (null === $ key = $ node ->getKeyAttribute ()) {
217
225
// This is an array of values; don't use singular name
226
+ $ nodeTypesWithoutArray = array_filter ($ nodeParameterTypes , static fn ($ type ) => 'array ' !== $ type );
218
227
$ body = '
219
228
/**
220
- * @param PHPDOC_TYPE $value
229
+ * @param ParamConfigurator|list<ParamConfigurator|PROTOTYPE_TYPE>EXTRA_TYPE $value
221
230
*
222
231
* @return $this
223
232
*/
224
- public function NAME(TYPE $value): static
233
+ public function NAME(PARAM_TYPE $value): static
225
234
{
226
235
$this->_usedProperties[ \'PROPERTY \'] = true;
227
236
$this->PROPERTY = $value;
@@ -231,8 +240,9 @@ public function NAME(TYPE $value): static
231
240
232
241
$ class ->addMethod ($ node ->getName (), $ body , [
233
242
'PROPERTY ' => $ property ->getName (),
234
- 'TYPE ' => $ hasNormalizationClosures ? 'mixed ' : 'ParamConfigurator|array ' ,
235
- 'PHPDOC_TYPE ' => $ hasNormalizationClosures ? 'mixed ' : sprintf ('ParamConfigurator|list<ParamConfigurator|%s> ' , '' === $ parameterType ? 'mixed ' : $ parameterType ),
243
+ 'PROTOTYPE_TYPE ' => implode ('| ' , $ prototypeParameterTypes ),
244
+ 'EXTRA_TYPE ' => $ nodeTypesWithoutArray ? '| ' .implode ('| ' , $ nodeTypesWithoutArray ) : '' ,
245
+ 'PARAM_TYPE ' => \in_array ('mixed ' , $ nodeParameterTypes , true ) ? 'mixed ' : 'ParamConfigurator| ' .implode ('| ' , $ nodeParameterTypes ),
236
246
]);
237
247
} else {
238
248
$ body = '
@@ -249,7 +259,7 @@ public function NAME(string $VAR, TYPE $VALUE): static
249
259
250
260
$ class ->addMethod ($ methodName , $ body , [
251
261
'PROPERTY ' => $ property ->getName (),
252
- 'TYPE ' => $ hasNormalizationClosures || '' === $ parameterType ? 'mixed ' : 'ParamConfigurator| ' .$ parameterType ,
262
+ 'TYPE ' => \in_array ( ' mixed ' , $ prototypeParameterTypes , true ) ? 'mixed ' : 'ParamConfigurator| ' .implode ( ' | ' , $ prototypeParameterTypes ) ,
253
263
'VAR ' => '' === $ key ? 'key ' : $ key ,
254
264
'VALUE ' => 'value ' === $ key ? 'data ' : 'value ' ,
255
265
]);
@@ -282,7 +292,7 @@ public function NAME(string $VAR, TYPE $VALUE): static
282
292
283
293
if (null === $ key = $ node ->getKeyAttribute ()) {
284
294
$ body = $ hasNormalizationClosures ? '
285
- COMMENTpublic function NAME(mixed $value = []): CLASS|static
295
+ COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static
286
296
{
287
297
$this->_usedProperties[ \'PROPERTY \'] = true;
288
298
if (!\is_array($value)) {
@@ -299,10 +309,15 @@ public function NAME(string $VAR, TYPE $VALUE): static
299
309
300
310
return $this->PROPERTY[] = new CLASS($value);
301
311
} ' ;
302
- $ class ->addMethod ($ methodName , $ body , ['COMMENT ' => $ comment , 'PROPERTY ' => $ property ->getName (), 'CLASS ' => $ childClass ->getFqcn ()]);
312
+ $ class ->addMethod ($ methodName , $ body , [
313
+ 'COMMENT ' => $ comment ,
314
+ 'PROPERTY ' => $ property ->getName (),
315
+ 'CLASS ' => $ childClass ->getFqcn (),
316
+ 'PARAM_TYPE ' => \in_array ('mixed ' , $ nodeParameterTypes , true ) ? 'mixed ' : implode ('| ' , $ nodeParameterTypes ),
317
+ ]);
303
318
} else {
304
319
$ body = $ hasNormalizationClosures ? '
305
- COMMENTpublic function NAME(string $VAR, mixed $VALUE = []): CLASS|static
320
+ COMMENTpublic function NAME(string $VAR, PARAM_TYPE $VALUE = []): CLASS|static
306
321
{
307
322
if (!\is_array($VALUE)) {
308
323
$this->_usedProperties[ \'PROPERTY \'] = true;
@@ -337,6 +352,7 @@ public function NAME(string $VAR, TYPE $VALUE): static
337
352
'CLASS ' => $ childClass ->getFqcn (),
338
353
'VAR ' => '' === $ key ? 'key ' : $ key ,
339
354
'VALUE ' => 'value ' === $ key ? 'data ' : 'value ' ,
355
+ 'PARAM_TYPE ' => \in_array ('mixed ' , $ prototypeParameterTypes , true ) ? 'mixed ' : implode ('| ' , $ prototypeParameterTypes ),
340
356
]);
341
357
}
342
358
@@ -364,35 +380,33 @@ public function NAME($value): static
364
380
$ class ->addMethod ($ node ->getName (), $ body , ['PROPERTY ' => $ property ->getName (), 'COMMENT ' => $ comment ]);
365
381
}
366
382
367
- private function getParameterType (NodeInterface $ node ): ? string
383
+ private function getParameterTypes (NodeInterface $ node ): array
368
384
{
369
- if ($ node instanceof BooleanNode) {
370
- return 'bool ' ;
371
- }
372
-
373
- if ($ node instanceof IntegerNode) {
374
- return 'int ' ;
375
- }
376
-
377
- if ($ node instanceof FloatNode) {
378
- return 'float ' ;
379
- }
380
-
381
- if ($ node instanceof EnumNode) {
382
- return '' ;
383
- }
384
-
385
- if ($ node instanceof PrototypedArrayNode && $ node ->getPrototype () instanceof ScalarNode) {
386
- // This is just an array of variables
387
- return 'array ' ;
385
+ $ paramTypes = [];
386
+ if ($ node instanceof BaseNode) {
387
+ $ types = $ node ->getNormalizedTypes ();
388
+ if (\in_array (ExprBuilder::TYPE_ANY , $ types , true )) {
389
+ $ paramTypes [] = 'mixed ' ;
390
+ }
391
+ if (\in_array (ExprBuilder::TYPE_STRING , $ types , true )) {
392
+ $ paramTypes [] = 'string ' ;
393
+ }
388
394
}
389
-
390
- if ($ node instanceof VariableNode) {
391
- // mixed
392
- return '' ;
395
+ if ($ node instanceof BooleanNode) {
396
+ $ paramTypes [] = 'bool ' ;
397
+ } elseif ($ node instanceof IntegerNode) {
398
+ $ paramTypes [] = 'int ' ;
399
+ } elseif ($ node instanceof FloatNode) {
400
+ $ paramTypes [] = 'float ' ;
401
+ } elseif ($ node instanceof EnumNode) {
402
+ $ paramTypes [] = 'mixed ' ;
403
+ } elseif ($ node instanceof ArrayNode) {
404
+ $ paramTypes [] = 'array ' ;
405
+ } elseif ($ node instanceof VariableNode) {
406
+ $ paramTypes [] = 'mixed ' ;
393
407
}
394
408
395
- return null ;
409
+ return array_unique ( $ paramTypes ) ;
396
410
}
397
411
398
412
private function getComment (BaseNode $ node ): string
@@ -416,11 +430,8 @@ private function getComment(BaseNode $node): string
416
430
return var_export ($ a , true );
417
431
}, $ node ->getValues ())))."\n" ;
418
432
} else {
419
- $ parameterType = $ this ->getParameterType ($ node );
420
- if (null === $ parameterType || '' === $ parameterType ) {
421
- $ parameterType = 'mixed ' ;
422
- }
423
- $ comment .= ' * @param ParamConfigurator| ' .$ parameterType .' $value ' ."\n" ;
433
+ $ parameterTypes = $ this ->getParameterTypes ($ node );
434
+ $ comment .= ' * @param ParamConfigurator| ' .implode ('| ' , $ parameterTypes ).' $value ' ."\n" ;
424
435
}
425
436
} else {
426
437
foreach ((array ) ($ node ->getExample () ?? []) as $ example ) {
0 commit comments