Skip to content

Commit e9c57da

Browse files
committed
Refactor RegexExpressionHelper
1 parent 224af32 commit e9c57da

File tree

3 files changed

+49
-41
lines changed

3 files changed

+49
-41
lines changed

src/Rules/Regexp/RegularExpressionQuotingRule.php

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,25 @@
1515
use PHPStan\Rules\Rule;
1616
use PHPStan\Rules\RuleErrorBuilder;
1717
use PHPStan\ShouldNotHappenException;
18-
use PHPStan\Type\Constant\ConstantStringType;
18+
use PHPStan\Type\Php\RegexExpressionHelper;
1919
use function array_filter;
2020
use function array_merge;
2121
use function array_values;
2222
use function count;
2323
use function in_array;
2424
use function sprintf;
2525
use function strlen;
26-
use function substr;
2726

2827
/**
2928
* @implements Rule<Node\Expr\FuncCall>
3029
*/
3130
class RegularExpressionQuotingRule implements Rule
3231
{
3332

34-
public function __construct(private ReflectionProvider $reflectionProvider)
33+
public function __construct(
34+
private ReflectionProvider $reflectionProvider,
35+
private RegexExpressionHelper $regexExpressionHelper,
36+
)
3537
{
3638
}
3739

@@ -76,7 +78,7 @@ public function processNode(Node $node, Scope $scope): array
7678
return [];
7779
}
7880

79-
$patternDelimiters = $this->getDelimitersFromConcat($normalizedArgs[0]->value, $scope);
81+
$patternDelimiters = $this->regexExpressionHelper->getPatternDelimiters($normalizedArgs[0]->value, $scope);
8082
return $this->validateQuoteDelimiters($normalizedArgs[0]->value, $scope, $patternDelimiters);
8183
}
8284

@@ -193,40 +195,6 @@ private function validatePregQuote(FuncCall $pregQuote, Scope $scope, array $pat
193195
return null;
194196
}
195197

196-
/**
197-
* Get delimiters from non-constant patterns, if possible.
198-
*
199-
* @return string[]
200-
*/
201-
private function getDelimitersFromConcat(Concat $concat, Scope $scope): array
202-
{
203-
if ($concat->left instanceof Concat) {
204-
return $this->getDelimitersFromConcat($concat->left, $scope);
205-
}
206-
207-
$left = $scope->getType($concat->left);
208-
209-
$delimiters = [];
210-
foreach ($left->getConstantStrings() as $leftString) {
211-
$delimiter = $this->getDelimiterFromString($leftString);
212-
if ($delimiter === null) {
213-
continue;
214-
}
215-
216-
$delimiters[] = $delimiter;
217-
}
218-
return $delimiters;
219-
}
220-
221-
private function getDelimiterFromString(ConstantStringType $string): ?string
222-
{
223-
if ($string->getValue() === '') {
224-
return null;
225-
}
226-
227-
return substr($string->getValue(), 0, 1);
228-
}
229-
230198
/**
231199
* @param string[] $delimiters
232200
*

src/Type/Php/RegexExpressionHelper.php

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
namespace PHPStan\Type\Php;
44

55
use PhpParser\Node\Expr;
6+
use PhpParser\Node\Expr\BinaryOp\Concat;
67
use PhpParser\Node\Name;
78
use PHPStan\Analyser\Scope;
89
use PHPStan\Reflection\InitializerExprTypeResolver;
910
use PHPStan\Type\Constant\ConstantStringType;
1011
use PHPStan\Type\Type;
1112
use PHPStan\Type\TypeCombinator;
13+
use function substr;
1214

1315
final class RegexExpressionHelper
1416
{
@@ -26,7 +28,7 @@ public function __construct(
2628
*
2729
* see https://github.com/phpstan/phpstan-src/pull/3233#discussion_r1676938085
2830
*/
29-
public function resolvePatternConcat(Expr\BinaryOp\Concat $concat, Scope $scope): Type
31+
public function resolvePatternConcat(Concat $concat, Scope $scope): Type
3032
{
3133
$resolver = new class($scope) {
3234

@@ -44,7 +46,7 @@ public function resolve(Expr $expr): Type
4446
return new ConstantStringType('');
4547
}
4648

47-
if ($expr instanceof Expr\BinaryOp\Concat) {
49+
if ($expr instanceof Concat) {
4850
$left = $this->resolve($expr->left);
4951
$right = $this->resolve($expr->right);
5052

@@ -66,4 +68,38 @@ public function resolve(Expr $expr): Type
6668
return $this->initializerExprTypeResolver->getConcatType($concat->left, $concat->right, static fn (Expr $expr): Type => $resolver->resolve($expr));
6769
}
6870

71+
/**
72+
* Get delimiters from non-constant patterns, if possible.
73+
*
74+
* @return string[]
75+
*/
76+
public function getPatternDelimiters(Concat $concat, Scope $scope): array
77+
{
78+
if ($concat->left instanceof Concat) {
79+
return $this->getPatternDelimiters($concat->left, $scope);
80+
}
81+
82+
$left = $scope->getType($concat->left);
83+
84+
$delimiters = [];
85+
foreach ($left->getConstantStrings() as $leftString) {
86+
$delimiter = $this->getDelimiterFromString($leftString);
87+
if ($delimiter === null) {
88+
continue;
89+
}
90+
91+
$delimiters[] = $delimiter;
92+
}
93+
return $delimiters;
94+
}
95+
96+
private function getDelimiterFromString(ConstantStringType $string): ?string
97+
{
98+
if ($string->getValue() === '') {
99+
return null;
100+
}
101+
102+
return substr($string->getValue(), 0, 1);
103+
}
104+
69105
}

tests/PHPStan/Rules/Regexp/RegularExpressionQuotingRuleTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\Rules\Rule;
66
use PHPStan\Testing\RuleTestCase;
7+
use PHPStan\Type\Php\RegexExpressionHelper;
78
use const PHP_VERSION_ID;
89

910
/**
@@ -14,7 +15,10 @@ class RegularExpressionQuotingRuleTest extends RuleTestCase
1415

1516
protected function getRule(): Rule
1617
{
17-
return new RegularExpressionQuotingRule($this->createReflectionProvider());
18+
return new RegularExpressionQuotingRule(
19+
$this->createReflectionProvider(),
20+
self::getContainer()->getByType(RegexExpressionHelper::class),
21+
);
1822
}
1923

2024
public function testRule(): void

0 commit comments

Comments
 (0)