1414use Symfony \Component \Config \Definition \ArrayNode ;
1515use Symfony \Component \Config \Definition \BaseNode ;
1616use Symfony \Component \Config \Definition \BooleanNode ;
17+ use Symfony \Component \Config \Definition \Builder \ExprBuilder ;
1718use Symfony \Component \Config \Definition \ConfigurationInterface ;
1819use Symfony \Component \Config \Definition \EnumNode ;
1920use Symfony \Component \Config \Definition \Exception \InvalidConfigurationException ;
@@ -141,8 +142,9 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n
141142 $ node ->getName (),
142143 $ this ->getType ($ childClass ->getFqcn (), $ hasNormalizationClosures )
143144 );
145+ $ nodeTypes = $ this ->getParameterTypes ($ node );
144146 $ body = $ hasNormalizationClosures ? '
145- COMMENTpublic function NAME(mixed $value = []): CLASS|static
147+ COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static
146148{
147149 if (!\is_array($value)) {
148150 $this->_usedProperties[ \'PROPERTY \'] = true;
@@ -172,7 +174,12 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n
172174 return $this->PROPERTY;
173175} ' ;
174176 $ 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+ ]);
176183
177184 $ this ->buildNode ($ node , $ childClass , $ this ->getSubNamespace ($ childClass ));
178185 }
@@ -209,19 +216,21 @@ private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuild
209216 $ methodName = $ name ;
210217 $ hasNormalizationClosures = $ this ->hasNormalizationClosures ($ node ) || $ this ->hasNormalizationClosures ($ prototype );
211218
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)) {
214222 $ class ->addUse (ParamConfigurator::class);
215223 $ property = $ class ->addProperty ($ node ->getName ());
216224 if (null === $ key = $ node ->getKeyAttribute ()) {
217225 // This is an array of values; don't use singular name
226+ $ nodeTypesWithoutArray = array_filter ($ nodeParameterTypes , static fn ($ type ) => 'array ' !== $ type );
218227 $ body = '
219228/**
220- * @param PHPDOC_TYPE $value
229+ * @param ParamConfigurator|list<ParamConfigurator|PROTOTYPE_TYPE>EXTRA_TYPE $value
221230 *
222231 * @return $this
223232 */
224- public function NAME(TYPE $value): static
233+ public function NAME(PARAM_TYPE $value): static
225234{
226235 $this->_usedProperties[ \'PROPERTY \'] = true;
227236 $this->PROPERTY = $value;
@@ -231,8 +240,9 @@ public function NAME(TYPE $value): static
231240
232241 $ class ->addMethod ($ node ->getName (), $ body , [
233242 '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 ),
236246 ]);
237247 } else {
238248 $ body = '
@@ -249,7 +259,7 @@ public function NAME(string $VAR, TYPE $VALUE): static
249259
250260 $ class ->addMethod ($ methodName , $ body , [
251261 'PROPERTY ' => $ property ->getName (),
252- 'TYPE ' => $ hasNormalizationClosures || '' === $ parameterType ? 'mixed ' : 'ParamConfigurator| ' .$ parameterType ,
262+ 'TYPE ' => \in_array ( ' mixed ' , $ prototypeParameterTypes , true ) ? 'mixed ' : 'ParamConfigurator| ' .implode ( ' | ' , $ prototypeParameterTypes ) ,
253263 'VAR ' => '' === $ key ? 'key ' : $ key ,
254264 'VALUE ' => 'value ' === $ key ? 'data ' : 'value ' ,
255265 ]);
@@ -282,7 +292,7 @@ public function NAME(string $VAR, TYPE $VALUE): static
282292
283293 if (null === $ key = $ node ->getKeyAttribute ()) {
284294 $ body = $ hasNormalizationClosures ? '
285- COMMENTpublic function NAME(mixed $value = []): CLASS|static
295+ COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static
286296{
287297 $this->_usedProperties[ \'PROPERTY \'] = true;
288298 if (!\is_array($value)) {
@@ -299,10 +309,15 @@ public function NAME(string $VAR, TYPE $VALUE): static
299309
300310 return $this->PROPERTY[] = new CLASS($value);
301311} ' ;
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+ ]);
303318 } else {
304319 $ body = $ hasNormalizationClosures ? '
305- COMMENTpublic function NAME(string $VAR, mixed $VALUE = []): CLASS|static
320+ COMMENTpublic function NAME(string $VAR, PARAM_TYPE $VALUE = []): CLASS|static
306321{
307322 if (!\is_array($VALUE)) {
308323 $this->_usedProperties[ \'PROPERTY \'] = true;
@@ -337,6 +352,7 @@ public function NAME(string $VAR, TYPE $VALUE): static
337352 'CLASS ' => $ childClass ->getFqcn (),
338353 'VAR ' => '' === $ key ? 'key ' : $ key ,
339354 'VALUE ' => 'value ' === $ key ? 'data ' : 'value ' ,
355+ 'PARAM_TYPE ' => \in_array ('mixed ' , $ prototypeParameterTypes , true ) ? 'mixed ' : implode ('| ' , $ prototypeParameterTypes ),
340356 ]);
341357 }
342358
@@ -364,35 +380,33 @@ public function NAME($value): static
364380 $ class ->addMethod ($ node ->getName (), $ body , ['PROPERTY ' => $ property ->getName (), 'COMMENT ' => $ comment ]);
365381 }
366382
367- private function getParameterType (NodeInterface $ node ): ? string
383+ private function getParameterTypes (NodeInterface $ node ): array
368384 {
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+ }
388394 }
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 ' ;
393407 }
394408
395- return null ;
409+ return array_unique ( $ paramTypes ) ;
396410 }
397411
398412 private function getComment (BaseNode $ node ): string
@@ -416,11 +430,8 @@ private function getComment(BaseNode $node): string
416430 return var_export ($ a , true );
417431 }, $ node ->getValues ())))."\n" ;
418432 } 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" ;
424435 }
425436 } else {
426437 foreach ((array ) ($ node ->getExample () ?? []) as $ example ) {
0 commit comments