Skip to content

Commit 1d3746d

Browse files
committed
RegexArrayShapeMatcher: Support resolving of constants in patterns
Refactors RegexArrayShapeMatcher to re-use InitializerExprTypeResolver
1 parent c4c0269 commit 1d3746d

File tree

2 files changed

+51
-29
lines changed

2 files changed

+51
-29
lines changed

src/Type/Php/RegexArrayShapeMatcher.php

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PhpParser\Node\Name;
1414
use PHPStan\Analyser\Scope;
1515
use PHPStan\Php\PhpVersion;
16+
use PHPStan\Reflection\InitializerExprTypeResolver;
1617
use PHPStan\ShouldNotHappenException;
1718
use PHPStan\TrinaryLogic;
1819
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
@@ -55,6 +56,7 @@ final class RegexArrayShapeMatcher
5556

5657
public function __construct(
5758
private PhpVersion $phpVersion,
59+
private InitializerExprTypeResolver $initializerExprTypeResolver,
5860
)
5961
{
6062
}
@@ -724,38 +726,33 @@ private function getPatternType(Expr $patternExpr, Scope $scope): Type
724726
*/
725727
private function resolvePatternConcat(Expr\BinaryOp\Concat $concat, Scope $scope): Type
726728
{
727-
if (
728-
$concat->left instanceof Expr\FuncCall
729-
&& $concat->left->name instanceof Name
730-
&& $concat->left->name->toLowerString() === 'preg_quote'
731-
) {
732-
$left = new ConstantStringType('');
733-
} elseif ($concat->left instanceof Expr\BinaryOp\Concat) {
734-
$left = $this->resolvePatternConcat($concat->left, $scope);
735-
} else {
736-
$left = $scope->getType($concat->left);
737-
}
738-
739-
if (
740-
$concat->right instanceof Expr\FuncCall
741-
&& $concat->right->name instanceof Name
742-
&& $concat->right->name->toLowerString() === 'preg_quote'
743-
) {
744-
$right = new ConstantStringType('');
745-
} elseif ($concat->right instanceof Expr\BinaryOp\Concat) {
746-
$right = $this->resolvePatternConcat($concat->right, $scope);
747-
} else {
748-
$right = $scope->getType($concat->right);
749-
}
729+
$resolveConcat = static function (Expr $expr) use (&$resolveConcat, $scope) {
730+
if (
731+
$expr instanceof Expr\FuncCall
732+
&& $expr->name instanceof Name
733+
&& $expr->name->toLowerString() === 'preg_quote'
734+
) {
735+
return new ConstantStringType('');
736+
}
737+
738+
if ($expr instanceof Expr\BinaryOp\Concat) {
739+
$left = $resolveConcat($expr->left);
740+
$right = $resolveConcat($expr->right);
741+
742+
$strings = [];
743+
foreach ($left->toString()->getConstantStrings() as $leftString) {
744+
foreach ($right->toString()->getConstantStrings() as $rightString) {
745+
$strings[] = new ConstantStringType($leftString->getValue() . $rightString->getValue());
746+
}
747+
}
750748

751-
$strings = [];
752-
foreach ($left->getConstantStrings() as $leftString) {
753-
foreach ($right->getConstantStrings() as $rightString) {
754-
$strings[] = new ConstantStringType($leftString->getValue() . $rightString->getValue());
749+
return TypeCombinator::union(...$strings);
755750
}
756-
}
757751

758-
return TypeCombinator::union(...$strings);
752+
return $scope->getType($expr);
753+
};
754+
755+
return $this->initializerExprTypeResolver->getConcatType($concat->left, $concat->right, $resolveConcat);
759756
}
760757

761758
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
define('VAL', 5);
8+
9+
class Bar
10+
{
11+
public const VAL = 3;
12+
}
13+
14+
class HelloWorld
15+
{
16+
public function sayHello(string $s): void
17+
{
18+
if (preg_match('{(' . VAL . ')}', $s, $m)) {
19+
assertType('array{string, numeric-string}', $m);
20+
}
21+
if (preg_match('{(' . Bar::VAL . ')}', $s, $m)) {
22+
assertType('array{string, numeric-string}', $m);
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)