20
20
use PHPStan \Type \StringType ;
21
21
use PHPStan \Type \Type ;
22
22
use PHPStan \Type \TypeCombinator ;
23
- use function array_merge ;
24
23
use function count ;
25
24
use function in_array ;
26
25
use function is_int ;
@@ -295,6 +294,16 @@ private function getQuantificationRange(TreeNode $node): array
295
294
296
295
private function createGroupType (TreeNode $ group , bool $ maybeConstant , string $ patternModifiers ): Type
297
296
{
297
+ $ rootAlternation = $ this ->getRootAlternation ($ group );
298
+ if ($ rootAlternation !== null ) {
299
+ $ types = [];
300
+ foreach ($ rootAlternation ->getChildren () as $ alternative ) {
301
+ $ types [] = $ this ->createGroupType ($ alternative , $ maybeConstant , $ patternModifiers );
302
+ }
303
+
304
+ return TypeCombinator::union (...$ types );
305
+ }
306
+
298
307
$ isNonEmpty = TrinaryLogic::createMaybe ();
299
308
$ isNonFalsy = TrinaryLogic::createMaybe ();
300
309
$ isNumeric = TrinaryLogic::createMaybe ();
@@ -345,6 +354,28 @@ private function createGroupType(TreeNode $group, bool $maybeConstant, string $p
345
354
return new StringType ();
346
355
}
347
356
357
+ private function getRootAlternation (TreeNode $ group ): ?TreeNode
358
+ {
359
+ if (
360
+ $ group ->getId () === '#capturing '
361
+ && count ($ group ->getChildren ()) === 1
362
+ && $ group ->getChild (0 )->getId () === '#alternation '
363
+ ) {
364
+ return $ group ->getChild (0 );
365
+ }
366
+
367
+ // 1st token within a named capturing group is a token holding the group-name
368
+ if (
369
+ $ group ->getId () === '#namedcapturing '
370
+ && count ($ group ->getChildren ()) === 2
371
+ && $ group ->getChild (1 )->getId () === '#alternation '
372
+ ) {
373
+ return $ group ->getChild (1 );
374
+ }
375
+
376
+ return null ;
377
+ }
378
+
348
379
/**
349
380
* @param array<string>|null $onlyLiterals
350
381
*/
@@ -448,7 +479,6 @@ private function walkGroupAst(
448
479
$ isNumeric = TrinaryLogic::createNo ();
449
480
}
450
481
451
- $ alternativeLiterals = [];
452
482
foreach ($ children as $ child ) {
453
483
$ this ->walkGroupAst (
454
484
$ child ,
@@ -461,24 +491,7 @@ private function walkGroupAst(
461
491
$ inClass ,
462
492
$ patternModifiers ,
463
493
);
464
-
465
- if ($ ast ->getId () !== '#alternation ' ) {
466
- continue ;
467
- }
468
-
469
- if ($ onlyLiterals !== null && $ alternativeLiterals !== null ) {
470
- $ alternativeLiterals = array_merge ($ alternativeLiterals , $ onlyLiterals );
471
- $ onlyLiterals = [];
472
- } else {
473
- $ alternativeLiterals = null ;
474
- }
475
- }
476
-
477
- if ($ alternativeLiterals === null || $ alternativeLiterals === []) {
478
- return ;
479
494
}
480
-
481
- $ onlyLiterals = $ alternativeLiterals ;
482
495
}
483
496
484
497
private function isMaybeEmptyNode (TreeNode $ node , string $ patternModifiers , bool &$ isNonFalsy ): bool
0 commit comments