Skip to content

Commit 59a4eec

Browse files
authored
marchStrictGroups variants PHPStan support (#27)
1 parent 9f7f3d2 commit 59a4eec

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

src/PHPStan/PregMatchParameterOutTypeExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function isStaticMethodSupported(MethodReflection $methodReflection, Para
3030
{
3131
return
3232
$methodReflection->getDeclaringClass()->getName() === Preg::class
33-
&& in_array($methodReflection->getName(), ['match', 'isMatch'], true)
33+
&& in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups'], true)
3434
&& $parameter->getName() === 'matches';
3535
}
3636

src/PHPStan/PregMatchTypeSpecifyingExtension.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
use PHPStan\Analyser\TypeSpecifierContext;
1212
use PHPStan\Reflection\MethodReflection;
1313
use PHPStan\TrinaryLogic;
14+
use PHPStan\Type\Constant\ConstantArrayType;
1415
use PHPStan\Type\Php\RegexArrayShapeMatcher;
1516
use PHPStan\Type\StaticMethodTypeSpecifyingExtension;
17+
use PHPStan\Type\TypeCombinator;
18+
use PHPStan\Type\Type;
1619

1720
final class PregMatchTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtension, TypeSpecifierAwareExtension
1821
{
@@ -43,7 +46,7 @@ public function getClass(): string
4346

4447
public function isStaticMethodSupported(MethodReflection $methodReflection, StaticCall $node, TypeSpecifierContext $context): bool
4548
{
46-
return in_array($methodReflection->getName(), ['match', 'isMatch'], true) && !$context->null();
49+
return in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups'], true) && !$context->null();
4750
}
4851

4952
public function specifyTypes(MethodReflection $methodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
@@ -70,6 +73,22 @@ public function specifyTypes(MethodReflection $methodReflection, StaticCall $nod
7073
return new SpecifiedTypes();
7174
}
7275

76+
if (
77+
in_array($methodReflection->getName(), ['matchStrictGroups', 'isMatchStrictGroups'], true)
78+
&& count($matchedType->getConstantArrays()) > 0
79+
) {
80+
$matchedType = $matchedType->getConstantArrays()[0];
81+
$matchedType = new ConstantArrayType(
82+
$matchedType->getKeyTypes(),
83+
array_map(static function (Type $valueType): Type {
84+
return TypeCombinator::removeNull($valueType);
85+
}, $matchedType->getValueTypes()),
86+
[0],
87+
[],
88+
$matchedType->isList()
89+
);
90+
}
91+
7392
$overwrite = false;
7493
if ($context->false()) {
7594
$overwrite = true;

tests/PHPStanTests/nsrt/preg-match.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,30 @@ function doMatch(string $s): void
3636
assertType('array{}|array{0: string, currency: string|null, 1: string|null}', $matches);
3737
}
3838

39+
function doMatchStrictGroups(string $s): void
40+
{
41+
if (Preg::matchStrictGroups('/Price: /i', $s, $matches)) {
42+
assertType('array{string}', $matches);
43+
} else {
44+
assertType('array{}', $matches);
45+
}
46+
assertType('array{}|array{string}', $matches);
47+
48+
if (Preg::matchStrictGroups('/Price: (£|€)\d+/', $s, $matches)) {
49+
assertType('array{string, string}', $matches);
50+
} else {
51+
assertType('array{}', $matches);
52+
}
53+
assertType('array{}|array{string, string}', $matches);
54+
55+
if (Preg::isMatchStrictGroups('/Price: (?<test>£|€)\d+/', $s, $matches)) {
56+
assertType('array{0: string, test: string, 1: string}', $matches);
57+
} else {
58+
assertType('array{}', $matches);
59+
}
60+
assertType('array{}|array{0: string, test: string, 1: string}', $matches);
61+
}
62+
3963
// disabled until https://github.com/phpstan/phpstan-src/pull/3185 can be resolved
4064
//
4165
//function identicalMatch(string $s): void

0 commit comments

Comments
 (0)