Skip to content

Commit f84cf63

Browse files
authored
Merge pull request #60 from mRoca/feat/preg-replace-return-type
feat: infer `preg_replace_callback` return type
2 parents 5f9795e + 8294602 commit f84cf63

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

src/Type/Php/ReplaceSafeFunctionsDynamicReturnTypeExtension.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,19 @@
1616
use PHPStan\Type\TypeCombinator;
1717
use PHPStan\Type\TypeUtils;
1818

19+
/**
20+
* This file has been copy-pasted from PHPStan's source code but with isFunctionSupported changed.
21+
* For now, only preg_* functions are supported.
22+
* @See https://github.com/phpstan/phpstan-src/blob/2.1.x/src/Type/Php/ReplaceFunctionsDynamicReturnTypeExtension.php
23+
*/
1924
class ReplaceSafeFunctionsDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension
2025
{
2126

22-
/** @var array<string, int> */
27+
/** @var array<string, int> The function name associated with the typed argument position used to type the return */
2328
private array $functions = [
2429
'Safe\preg_replace' => 2,
30+
'Safe\preg_replace_callback' => 2,
31+
'Safe\preg_replace_callback_array' => 1,
2532
];
2633

2734
public function isFunctionSupported(FunctionReflection $functionReflection): bool

tests/Type/Php/data/preg_match_checked.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
// @phpstan-ignore-next-line - use of unsafe is intentional
1414
if(\preg_match($pattern, $string, $matches)) {
15-
\PHPStan\Testing\assertType($type, $matches);
15+
\PHPStan\Testing\assertSuperType($type, $matches);
1616
}
1717

1818
if(\Safe\preg_match($pattern, $string, $matches)) {
19-
\PHPStan\Testing\assertType($type, $matches);
19+
\PHPStan\Testing\assertSuperType($type, $matches);
2020
}

tests/Type/Php/data/preg_match_unchecked.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
// @phpstan-ignore-next-line - use of unsafe is intentional
1313
\preg_match($pattern, $string, $matches);
14-
\PHPStan\Testing\assertType($type, $matches);
14+
\PHPStan\Testing\assertSuperType($type, $matches);
1515

1616
\Safe\preg_match($pattern, $string, $matches);
17-
\PHPStan\Testing\assertType($type, $matches);
17+
\PHPStan\Testing\assertSuperType($type, $matches);

tests/Type/Php/data/preg_replace_return.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,33 @@
22

33
namespace TheCodingMachine\Safe\PHPStan\Type\Php\data;
44

5+
// preg_replace
6+
57
// preg_replace with a string pattern should return a string
68
$x = \Safe\preg_replace('/foo/', 'bar', 'baz');
79
\PHPStan\Testing\assertType("string", $x);
810

911
// preg_replace with an array pattern should return an array
1012
$x = \Safe\preg_replace(['/foo/'], ['bar'], ['baz']);
1113
\PHPStan\Testing\assertType("array", $x);
14+
15+
// preg_replace_callback
16+
17+
// preg_replace_callback with a string pattern should return a string
18+
$x = \Safe\preg_replace_callback('/foo/', fn (array $matches) => 'bar', 'baz');
19+
\PHPStan\Testing\assertType("string", $x);
20+
21+
// preg_replace_callback with an array pattern should return an array
22+
$x = \Safe\preg_replace_callback(['/foo/'], fn (array $matches) => 'bar', ['baz']);
23+
\PHPStan\Testing\assertType("array", $x);
24+
25+
26+
// preg_replace_callback_array
27+
28+
// preg_replace_callback_array with a string pattern should return a string
29+
$x = \Safe\preg_replace_callback_array(['/foo/' => fn (array $matches) => 'bar'], 'baz');
30+
\PHPStan\Testing\assertType("string", $x);
31+
32+
// preg_replace_callback with an array pattern should return an array
33+
$x = \Safe\preg_replace_callback_array(['/foo/' => fn (array $matches) => 'bar'], ['baz']);
34+
\PHPStan\Testing\assertType("array", $x);

0 commit comments

Comments
 (0)