From a0dc9ed9ed9760594da78810b66d3ad4696606c5 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 14 Jul 2024 09:00:49 +0200 Subject: [PATCH] Fix `pathinfo()` return type for union type flags --- ...infoFunctionDynamicReturnTypeExtension.php | 20 +++++++++++++++---- tests/PHPStan/Analyser/nsrt/pathinfo.php | 13 +++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php b/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php index bc41f983e0..11a5f74752 100644 --- a/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php @@ -54,12 +54,24 @@ public function getTypeFromFunctionCall( } $flagsType = $scope->getType($functionCall->getArgs()[1]->value); - if ($flagsType instanceof ConstantIntegerType) { - if ($flagsType->getValue() === $this->getConstant('PATHINFO_ALL')) { - return $arrayType; + + $scalarValues = $flagsType->getConstantScalarValues(); + if ($scalarValues !== []) { + $pathInfoAll = $this->getConstant('PATHINFO_ALL'); + if ($pathInfoAll === null) { + return null; + } + + $result = []; + foreach ($scalarValues as $scalarValue) { + if ($scalarValue === $pathInfoAll) { + $result[] = $arrayType; + } else { + $result[] = new StringType(); + } } - return new StringType(); + return TypeCombinator::union(...$result); } return TypeCombinator::union($arrayType, new StringType()); diff --git a/tests/PHPStan/Analyser/nsrt/pathinfo.php b/tests/PHPStan/Analyser/nsrt/pathinfo.php index e7972282fb..b58886e6d1 100644 --- a/tests/PHPStan/Analyser/nsrt/pathinfo.php +++ b/tests/PHPStan/Analyser/nsrt/pathinfo.php @@ -4,7 +4,10 @@ use function PHPStan\Testing\assertType; -function doFoo(string $s, int $i) { +/** + * @param PATHINFO_BASENAME|PATHINFO_EXTENSION $flag + */ +function doFoo(string $s, int $i, $flag) { assertType('array{dirname?: string, basename: string, extension?: string, filename: string}|string', pathinfo($s, $i)); assertType('array{dirname?: string, basename: string, extension?: string, filename: string}', pathinfo($s)); @@ -12,4 +15,12 @@ function doFoo(string $s, int $i) { assertType('string', pathinfo($s, PATHINFO_BASENAME)); assertType('string', pathinfo($s, PATHINFO_EXTENSION)); assertType('string', pathinfo($s, PATHINFO_FILENAME)); + + assertType('string', pathinfo($s, $flag)); + if ($i === PATHINFO_ALL) { + assertType('array{dirname?: string, basename: string, extension?: string, filename: string}', pathinfo($s, $i)); + } + if ($i === PATHINFO_ALL || $i === PATHINFO_DIRNAME) { + assertType('array{dirname?: string, basename: string, extension?: string, filename: string}|string', pathinfo($s, $i)); + } }