Skip to content

Commit 2223dd9

Browse files
authored
RegexArrayShapeMatcher - (\d*) can be empty-string
1 parent a1e697b commit 2223dd9

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

src/Type/Php/RegexArrayShapeMatcher.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -572,16 +572,14 @@ private function createGroupType(TreeNode $group): Type
572572

573573
$this->walkGroupAst($group, $isNonEmpty, $isNumeric, $inOptionalQuantification);
574574

575-
$accessories = [];
576575
if ($isNumeric->yes()) {
577-
$accessories[] = new AccessoryNumericStringType();
576+
$result = new IntersectionType([new StringType(), new AccessoryNumericStringType()]);
577+
if (!$isNonEmpty->yes()) {
578+
return TypeCombinator::union(new ConstantStringType(''), $result);
579+
}
580+
return $result;
578581
} elseif ($isNonEmpty->yes()) {
579-
$accessories[] = new AccessoryNonEmptyStringType();
580-
}
581-
582-
if ($accessories !== []) {
583-
$accessories[] = new StringType();
584-
return new IntersectionType($accessories);
582+
return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]);
585583
}
586584

587585
return new StringType();

tests/PHPStan/Analyser/nsrt/bug-11311.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Bug11311;
44

55
use function PHPStan\Testing\assertType;
6+
use InvalidArgumentException;
67

78
function doFoo(string $s) {
89
if (1 === preg_match('/(?<major>\d+)\.(?<minor>\d+)(?:\.(?<patch>\d+))?/', $s, $matches, PREG_UNMATCHED_AS_NULL)) {
@@ -105,7 +106,7 @@ function (string $size): void {
105106
if (preg_match('/ab(\d+)e(\d?)/', $size, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
106107
throw new InvalidArgumentException(sprintf('Invalid size "%s"', $size));
107108
}
108-
assertType('array{string, numeric-string, numeric-string}', $matches);
109+
assertType("array{string, numeric-string, ''|numeric-string}", $matches);
109110
};
110111

111112
function (string $size): void {
@@ -187,3 +188,13 @@ function (string $s): void {
187188
assertType('array{0: string, whitespace: string, 1: string, value: string, 2: string}', $matches);
188189
}
189190
};
191+
192+
function (string $s): void {
193+
preg_match('/%a(\d*)/', $s, $matches, PREG_UNMATCHED_AS_NULL);
194+
assertType("array{0?: string, 1?: ''|numeric-string|null}", $matches); // could be array{0?: string, 1?: ''|numeric-string}
195+
};
196+
197+
function (string $s): void {
198+
preg_match('/%a(\d*)?/', $s, $matches, PREG_UNMATCHED_AS_NULL);
199+
assertType("array{0?: string, 1?: ''|numeric-string|null}", $matches); // could be array{0?: string, 1?: ''|numeric-string}
200+
};

tests/PHPStan/Analyser/nsrt/preg_match_shapes.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace PregMatchShapes;
44

55
use function PHPStan\Testing\assertType;
6-
6+
use InvalidArgumentException;
77

88
function doMatch(string $s): void {
99
if (preg_match('/Price: /i', $s, $matches)) {
@@ -519,3 +519,9 @@ function bug11323(string $s): void {
519519
assertType('array{string, non-empty-string}', $matches);
520520
}
521521
}
522+
523+
function (string $s): void {
524+
preg_match('/%a(\d*)/', $s, $matches);
525+
assertType("array{0?: string, 1?: ''|numeric-string}", $matches);
526+
};
527+

0 commit comments

Comments
 (0)