diff --git a/resources/functionMap.php b/resources/functionMap.php index 51a7c99426..a02d4feb5d 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -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):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_split' => ['array|false', 'pattern'=>'string', 'subject'=>'string', 'limit='=>'?int', 'flags='=>'int'], 'prev' => ['mixed', '&rw_array_arg'=>'array|object'], diff --git a/resources/functionMap_php74delta.php b/resources/functionMap_php74delta.php index 3a831fc9ef..ff3f99ba0d 100644 --- a/resources/functionMap_php74delta.php +++ b/resources/functionMap_php74delta.php @@ -43,7 +43,7 @@ 'password_algos' => ['array'], '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):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int', 'flags='=>'int'], 'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array', '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'], diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index e0b0bbf1f4..8387354dee 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -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): string, Closure(string): string given.', + 6, + ], + [ + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(string): string given.', + 13, + ], + [ + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(array): void given.', + 20, + ], + [ + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(): void given.', + 25, + ], + ]); + } + public function testUasortCallback(): void { $this->analyse([__DIR__ . '/data/uasort.php'], [ diff --git a/tests/PHPStan/Rules/Functions/data/preg_replace_callback.php b/tests/PHPStan/Rules/Functions/data/preg_replace_callback.php new file mode 100644 index 0000000000..573275406a --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/preg_replace_callback.php @@ -0,0 +1,50 @@ +