diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php index 2dfa3681691..5dbd1083af8 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php @@ -10,6 +10,7 @@ use Psalm\Type\Atomic\TString; use Psalm\Type\Union; +use function call_user_func; use function count; use function in_array; @@ -50,7 +51,27 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev $return_type = Type::getString(); - if (in_array($function_id, ['preg_replace', 'preg_replace_callback'], true)) { + if (in_array($function_id, ['str_replace', 'str_ireplace'], true) + && $subject_type->isSingleStringLiteral() + ) { + $first_arg = $statements_source->node_data->getType($call_args[0]->value); + $second_arg = $statements_source->node_data->getType($call_args[1]->value); + if ($first_arg + && $second_arg && $first_arg->isSingleStringLiteral() + && $second_arg->isSingleStringLiteral() + ) { + /** + * @var string $replaced_string + */ + $replaced_string = call_user_func( + $function_id, + $first_arg->getSingleStringLiteral()->value, + $second_arg->getSingleStringLiteral()->value, + $subject_type->getSingleStringLiteral()->value + ); + $return_type = Type::getString($replaced_string); + } + } elseif (in_array($function_id, ['preg_replace', 'preg_replace_callback'], true)) { $return_type = new Union([new TString, new TNull()]); $codebase = $statements_source->getCodebase(); diff --git a/tests/ReturnTypeProvider/DirnameTest.php b/tests/ReturnTypeProvider/DirnameTest.php index 5ba691a223d..e1b4d01d382 100644 --- a/tests/ReturnTypeProvider/DirnameTest.php +++ b/tests/ReturnTypeProvider/DirnameTest.php @@ -5,6 +5,8 @@ use Psalm\Tests\TestCase; use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait; +use function addslashes; + use const DIRECTORY_SEPARATOR; class DirnameTest extends TestCase