Skip to content

Commit

Permalink
Narrow the type for the preg_replace_callback() callable.
Browse files Browse the repository at this point in the history
  • Loading branch information
johnbillion committed Nov 6, 2021
1 parent 6bb0fd6 commit c9e7fa7
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
2 changes: 1 addition & 1 deletion resources/functionMap.php
Expand Up @@ -8838,7 +8838,7 @@
'preg_match_all' => ['int|false|null', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'array', 'flags='=>'int', 'offset='=>'int'],
'preg_quote' => ['string', 'str'=>'string', 'delim_char='=>'string'],
'preg_replace' => ['string|array|null', 'regex'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'],
'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'],
'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable(array<int|string, string>):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'],
'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array<string,callable>', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'],
'preg_split' => ['array<int, string>|false', 'pattern'=>'string', 'subject'=>'string', 'limit='=>'?int', 'flags='=>'int'],
'prev' => ['mixed', '&rw_array_arg'=>'array|object'],
Expand Down
2 changes: 1 addition & 1 deletion resources/functionMap_php74delta.php
Expand Up @@ -43,7 +43,7 @@
'password_algos' => ['array<int, string>'],
'password_hash' => ['string|false', 'password'=>'string', 'algo'=>'string|null', 'options='=>'array'],
'password_needs_rehash' => ['bool', 'hash'=>'string', 'algo'=>'string|null', 'options='=>'array'],
'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int', 'flags='=>'int'],
'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable(array<int|string, string>):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int', 'flags='=>'int'],
'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array<string,callable>', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int', 'flags='=>'int'],
'sapi_windows_set_ctrl_handler' => ['bool', 'callable'=>'callable(int):void', 'add='=>'bool'],
'ReflectionProperty::getType' => ['?ReflectionType'],
Expand Down
22 changes: 22 additions & 0 deletions tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php
Expand Up @@ -628,6 +628,28 @@ public function testArrayWalkArrowFunctionCallback(): void
]);
}

public function testPregReplaceCallback(): void
{
$this->analyse([__DIR__ . '/data/preg_replace_callback.php'], [
[
'Parameter #2 $callback of function preg_replace_callback expects callable(array<int|string, string>): string, Closure(string): string given.',
6,
],
[
'Parameter #2 $callback of function preg_replace_callback expects callable(array<int|string, string>): string, Closure(string): string given.',
13,
],
[
'Parameter #2 $callback of function preg_replace_callback expects callable(array<int|string, string>): string, Closure(array): void given.',
20,
],
[
'Parameter #2 $callback of function preg_replace_callback expects callable(array<int|string, string>): string, Closure(): void given.',
25,
],
]);
}

public function testUasortCallback(): void
{
$this->analyse([__DIR__ . '/data/uasort.php'], [
Expand Down
50 changes: 50 additions & 0 deletions tests/PHPStan/Rules/Functions/data/preg_replace_callback.php
@@ -0,0 +1,50 @@
<?php declare(strict_types = 1);

// Incorrect
$string = preg_replace_callback(
'#pattern#',
function(string $string): string {
return $string;
},
'subject'
);
$string = preg_replace_callback(
'#pattern#',
function(string $string) {
return $string;
},
'subject'
);
$string = preg_replace_callback(
'#pattern#',
function(array $matches) {},
'subject'
);
$string = preg_replace_callback(
'#pattern#',
function() {},
'subject'
);

// Correct
$string = preg_replace_callback(
'#pattern#',
function(array $matches): string {
return $matches[0];
},
'subject'
);
$string = preg_replace_callback(
'#pattern#',
function(array $matches) {
return $matches[0];
},
'subject'
);
$string = preg_replace_callback(
'#pattern#',
function() {
return 'Hello';
},
'subject'
);

0 comments on commit c9e7fa7

Please sign in to comment.