diff --git a/resources/functionMap_php84delta.php b/resources/functionMap_php84delta.php index 4c18488e8b..c5b395c292 100644 --- a/resources/functionMap_php84delta.php +++ b/resources/functionMap_php84delta.php @@ -17,6 +17,8 @@ 'new' => [ 'http_get_last_response_header ' => ['list'], 'http_clear_last_response_header' => ['void'], + 'mb_lcfirst' => ['string', 'string'=>'string', 'encoding='=>'string'], + 'mb_ucfirst' => ['string', 'string'=>'string', 'encoding='=>'string'], ], 'old' => [ diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index c2d959661e..e65c907163 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1017,9 +1017,9 @@ private function specifyTypesForConstantStringBinaryExpression( && $exprNode instanceof FuncCall && $exprNode->name instanceof Name && in_array(strtolower($exprNode->name->toString()), [ - 'substr', 'strstr', 'stristr', 'strchr', 'strrchr', 'strtolower', 'strtoupper', - 'mb_substr', 'mb_strstr', 'mb_stristr', 'mb_strchr', 'mb_strrchr', 'mb_strtolower', 'mb_strtoupper', - 'ucfirst', 'lcfirst', 'ucwords', 'mb_convert_case', 'mb_convert_kana', + 'substr', 'strstr', 'stristr', 'strchr', 'strrchr', 'strtolower', 'strtoupper', 'ucfirst', 'lcfirst', + 'mb_substr', 'mb_strstr', 'mb_stristr', 'mb_strchr', 'mb_strrchr', 'mb_strtolower', 'mb_strtoupper', 'mb_ucfirst', 'mb_lcfirst', + 'ucwords', 'mb_convert_case', 'mb_convert_kana', ], true) && isset($exprNode->getArgs()[0]) && $constantType->getValue() !== '' diff --git a/src/Type/Php/StrCaseFunctionsReturnTypeExtension.php b/src/Type/Php/StrCaseFunctionsReturnTypeExtension.php index df1dfc88e9..ebb693672d 100644 --- a/src/Type/Php/StrCaseFunctionsReturnTypeExtension.php +++ b/src/Type/Php/StrCaseFunctionsReturnTypeExtension.php @@ -34,6 +34,8 @@ class StrCaseFunctionsReturnTypeExtension implements DynamicFunctionReturnTypeEx 'mb_strtolower' => 1, 'lcfirst' => 1, 'ucfirst' => 1, + 'mb_lcfirst' => 1, + 'mb_ucfirst' => 1, 'ucwords' => 1, 'mb_convert_case' => 2, 'mb_convert_kana' => 1, diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 7146d8e31d..a134571f9e 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -1082,6 +1082,9 @@ public function dataFileAsserts(): iterable if (PHP_VERSION_ID >= 70300) { yield from $this->gatherAssertTypes(__DIR__ . '/data/str-casing.php'); } + if (PHP_VERSION_ID >= 80400) { + yield from $this->gatherAssertTypes(__DIR__ . '/data/str-caseing-php84.php'); + } yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-substr-specifying.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/unset-conditional-expressions.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/conditional-types-inference.php'); diff --git a/tests/PHPStan/Analyser/data/str-caseing-php84.php b/tests/PHPStan/Analyser/data/str-caseing-php84.php new file mode 100644 index 0000000000..ed6e8dab73 --- /dev/null +++ b/tests/PHPStan/Analyser/data/str-caseing-php84.php @@ -0,0 +1,23 @@ +