Skip to content

Commit b4157dc

Browse files
committed
Embed new flag into $flagsType
1 parent a549175 commit b4157dc

File tree

1 file changed

+24
-20
lines changed

1 file changed

+24
-20
lines changed

src/Type/Php/RegexArrayShapeMatcher.php

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
final class RegexArrayShapeMatcher
3333
{
3434

35+
/**
36+
* Pass this into $flagsType as well if the library supports emulating PREG_UNMATCHED_AS_NULL on PHP 7.2 and 7.3
37+
*/
38+
public const PREG_UNMATCHED_AS_NULL_ON_72_73 = 2048;
39+
3540
private static ?Parser $parser = null;
3641

3742
public function __construct(
@@ -40,7 +45,7 @@ public function __construct(
4045
{
4146
}
4247

43-
public function matchType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched, bool $supportsUnmatchedAsNullOn72 = false): ?Type
48+
public function matchType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched): ?Type
4449
{
4550
if ($wasMatched->no()) {
4651
return new ConstantArrayType([], []);
@@ -53,19 +58,22 @@ public function matchType(Type $patternType, ?Type $flagsType, TrinaryLogic $was
5358

5459
$flags = null;
5560
if ($flagsType !== null) {
56-
if (
57-
!$flagsType instanceof ConstantIntegerType
58-
|| !in_array($flagsType->getValue(), [PREG_OFFSET_CAPTURE, PREG_UNMATCHED_AS_NULL, PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL], true)
59-
) {
61+
if (!$flagsType instanceof ConstantIntegerType) {
6062
return null;
6163
}
6264

63-
$flags = $flagsType->getValue();
65+
/** @var int-mask<PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL | self::PREG_UNMATCHED_AS_NULL_ON_72_73> $flags */
66+
$flags = $flagsType->getValue() & (PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL | self::PREG_UNMATCHED_AS_NULL_ON_72_73);
67+
68+
// some other unsupported/unexpected flag was passed in
69+
if ($flags !== $flagsType->getValue()) {
70+
return null;
71+
}
6472
}
6573

6674
$matchedTypes = [];
6775
foreach ($constantStrings as $constantString) {
68-
$matched = $this->matchRegex($constantString->getValue(), $flags, $wasMatched, $supportsUnmatchedAsNullOn72);
76+
$matched = $this->matchRegex($constantString->getValue(), $flags, $wasMatched);
6977
if ($matched === null) {
7078
return null;
7179
}
@@ -81,9 +89,9 @@ public function matchType(Type $patternType, ?Type $flagsType, TrinaryLogic $was
8189
}
8290

8391
/**
84-
* @param int-mask<PREG_OFFSET_CAPTURE|PREG_UNMATCHED_AS_NULL>|null $flags
92+
* @param int-mask<PREG_OFFSET_CAPTURE|PREG_UNMATCHED_AS_NULL|self::PREG_UNMATCHED_AS_NULL_ON_72_73>|null $flags
8593
*/
86-
private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched, bool $supportsUnmatchedAsNullOn72): ?Type
94+
private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched): ?Type
8795
{
8896
$parseResult = $this->parseGroups($regex);
8997
if ($parseResult === null) {
@@ -100,7 +108,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
100108
$trailingOptionals++;
101109
}
102110

103-
$valueType = $this->getValueType($flags ?? 0, $supportsUnmatchedAsNullOn72);
111+
$valueType = $this->getValueType($flags ?? 0);
104112
$onlyOptionalTopLevelGroup = $this->getOnlyOptionalTopLevelGroup($groupList);
105113
$onlyTopLevelAlternationId = $this->getOnlyTopLevelAlternationId($groupList);
106114

@@ -119,7 +127,6 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
119127
$wasMatched,
120128
$trailingOptionals,
121129
$flags ?? 0,
122-
$supportsUnmatchedAsNullOn72,
123130
);
124131

125132
return TypeCombinator::union(
@@ -155,7 +162,6 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
155162
$wasMatched,
156163
$trailingOptionals,
157164
$flags ?? 0,
158-
$supportsUnmatchedAsNullOn72,
159165
);
160166

161167
$combiTypes[] = $combiType;
@@ -179,7 +185,6 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
179185
$wasMatched,
180186
$trailingOptionals,
181187
$flags ?? 0,
182-
$supportsUnmatchedAsNullOn72,
183188
);
184189
}
185190

@@ -242,7 +247,6 @@ private function buildArrayType(
242247
TrinaryLogic $wasMatched,
243248
int $trailingOptionals,
244249
int $flags,
245-
bool $supportsUnmatchedAsNullOn72,
246250
): Type
247251
{
248252
$builder = ConstantArrayTypeBuilder::createEmpty();
@@ -264,10 +268,10 @@ private function buildArrayType(
264268
} else {
265269
if ($i < $countGroups - $trailingOptionals) {
266270
$optional = false;
267-
if ($this->containsUnmatchedAsNull($flags, $supportsUnmatchedAsNullOn72)) {
271+
if ($this->containsUnmatchedAsNull($flags)) {
268272
$groupValueType = TypeCombinator::removeNull($groupValueType);
269273
}
270-
} elseif ($this->containsUnmatchedAsNull($flags, $supportsUnmatchedAsNullOn72)) {
274+
} elseif ($this->containsUnmatchedAsNull($flags)) {
271275
$optional = false;
272276
} else {
273277
$optional = $captureGroup->isOptional();
@@ -294,9 +298,9 @@ private function buildArrayType(
294298
return $builder->getArray();
295299
}
296300

297-
private function containsUnmatchedAsNull(int $flags, bool $supportsUnmatchedAsNullOn72): bool
301+
private function containsUnmatchedAsNull(int $flags): bool
298302
{
299-
return ($flags & PREG_UNMATCHED_AS_NULL) !== 0 && ($supportsUnmatchedAsNullOn72 || $this->phpVersion->supportsPregUnmatchedAsNull());
303+
return ($flags & PREG_UNMATCHED_AS_NULL) !== 0 && (($flags & self::PREG_UNMATCHED_AS_NULL_ON_72_73) !== 0 || $this->phpVersion->supportsPregUnmatchedAsNull());
300304
}
301305

302306
private function getKeyType(int|string $key): Type
@@ -308,11 +312,11 @@ private function getKeyType(int|string $key): Type
308312
return new ConstantIntegerType($key);
309313
}
310314

311-
private function getValueType(int $flags, bool $supportsUnmatchedAsNullOn72): Type
315+
private function getValueType(int $flags): Type
312316
{
313317
$valueType = new StringType();
314318
$offsetType = IntegerRangeType::fromInterval(0, null);
315-
if ($this->containsUnmatchedAsNull($flags, $supportsUnmatchedAsNullOn72)) {
319+
if ($this->containsUnmatchedAsNull($flags)) {
316320
$valueType = TypeCombinator::addNull($valueType);
317321
// unmatched groups return -1 as offset
318322
$offsetType = IntegerRangeType::fromInterval(-1, null);

0 commit comments

Comments
 (0)