Skip to content

Commit ecdd6c6

Browse files
staabmondrejmirtes
authored andcommitted
RegexArrayShapeMatcher: Don't narrow 'J' modifier
1 parent 9a6e12c commit ecdd6c6

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

Diff for: src/Type/Regex/RegexGroupParser.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
final class RegexGroupParser
3535
{
3636

37+
private const NOT_SUPPORTED_MODIFIERS = [
38+
'J', // rare modifier too complicated to support
39+
];
40+
3741
private static ?Parser $parser = null;
3842

3943
public function __construct(
@@ -67,8 +71,14 @@ public function parseGroups(string $regex): ?array
6771
return null;
6872
}
6973

70-
$captureOnlyNamed = false;
7174
$modifiers = $this->regexExpressionHelper->getPatternModifiers($regex) ?? '';
75+
foreach (self::NOT_SUPPORTED_MODIFIERS as $notSupportedModifier) {
76+
if (str_contains($modifiers, $notSupportedModifier)) {
77+
return null;
78+
}
79+
}
80+
81+
$captureOnlyNamed = false;
7282
if ($this->phpVersion->supportsPregCaptureOnlyNamedGroups()) {
7383
$captureOnlyNamed = str_contains($modifiers, 'n');
7484
}

Diff for: tests/PHPStan/Analyser/nsrt/bug-12126.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php // lint >= 7.4
2+
3+
namespace Bug12126;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
8+
class HelloWorld
9+
{
10+
public function sayHello(): void
11+
{
12+
$options = ['footest', 'testfoo'];
13+
$key = array_rand($options, 1);
14+
15+
$regex = '/foo(?P<test>test)|test(?P<test>foo)/J';
16+
if (!preg_match_all($regex, $options[$key], $matches, PREG_SET_ORDER)) {
17+
return;
18+
}
19+
20+
assertType('list<array<string>>', $matches);
21+
// could be assertType("list<array{0: string, test: 'foo'|'test', 1?: 'test', 2?: 'foo'}>", $matches);
22+
if (!preg_match_all($regex, $options[$key], $matches, PREG_PATTERN_ORDER)) {
23+
return;
24+
}
25+
26+
assertType('array<list<string>>', $matches);
27+
// could be assertType("array{0: list<string>, test: list<'foo'|'test'>, 1: list<'test'|''>, 2: list<''|'foo'>}", $matches);
28+
29+
if (!preg_match($regex, $options[$key], $matches)) {
30+
return;
31+
}
32+
33+
assertType('array<string>', $matches);
34+
// could be assertType("array{0: list<string>, test: 'foo', 1: '', 2: 'foo'}|array{0: list<string>, test: 'test', 1: 'test', 2: ''}", $matches);
35+
}
36+
}

0 commit comments

Comments
 (0)