From dc25cfceb6634ea42e87e1140570c136213d44ac Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 20 Nov 2022 13:55:09 +0100 Subject: [PATCH] Fix `pathinfo($s, PATHINFO_ALL)` return type --- ...infoFunctionDynamicReturnTypeExtension.php | 40 +++++++++++++------ .../Analyser/NodeScopeResolverTest.php | 1 + tests/PHPStan/Analyser/data/pathinfo.php | 17 ++++++++ 3 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/pathinfo.php diff --git a/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php b/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php index 1376ed4ff8e..df935750225 100644 --- a/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php @@ -5,13 +5,15 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Type\Constant\ConstantArrayTypeBuilder; +use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\StringType; use PHPStan\Type\Type; +use PHPStan\Type\TypeCombinator; use function count; +use const PATHINFO_ALL; class PathinfoFunctionDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension { @@ -25,24 +27,36 @@ public function getTypeFromFunctionCall( FunctionReflection $functionReflection, Node\Expr\FuncCall $functionCall, Scope $scope, - ): Type + ): ?Type { $argsCount = count($functionCall->getArgs()); if ($argsCount === 0) { - return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); - } elseif ($argsCount === 1) { - $pathType = $scope->getType($functionCall->getArgs()[0]->value); - - $builder = ConstantArrayTypeBuilder::createEmpty(); - $builder->setOffsetValueType(new ConstantStringType('dirname'), new StringType(), !$pathType->isNonEmptyString()->yes()); - $builder->setOffsetValueType(new ConstantStringType('basename'), new StringType()); - $builder->setOffsetValueType(new ConstantStringType('extension'), new StringType(), true); - $builder->setOffsetValueType(new ConstantStringType('filename'), new StringType()); + return null; + } - return $builder->getArray(); + $pathType = $scope->getType($functionCall->getArgs()[0]->value); + + $builder = ConstantArrayTypeBuilder::createEmpty(); + $builder->setOffsetValueType(new ConstantStringType('dirname'), new StringType(), !$pathType->isNonEmptyString()->yes()); + $builder->setOffsetValueType(new ConstantStringType('basename'), new StringType()); + $builder->setOffsetValueType(new ConstantStringType('extension'), new StringType(), true); + $builder->setOffsetValueType(new ConstantStringType('filename'), new StringType()); + $arrayType = $builder->getArray(); + + if ($argsCount === 1) { + return $arrayType; + } elseif ($argsCount >= 2) { + $flagsType = $scope->getType($functionCall->getArgs()[1]->value); + if ($flagsType instanceof ConstantIntegerType) { + if ($flagsType->getValue() === PATHINFO_ALL) { + return $arrayType; + } + + return new StringType(); + } } - return new StringType(); + return TypeCombinator::union($arrayType, new StringType()); } } diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index ac8b6a84bc2..379da6c4a16 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -1132,6 +1132,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8361.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8373.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Functions/data/bug-8389.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/pathinfo.php'); } /** diff --git a/tests/PHPStan/Analyser/data/pathinfo.php b/tests/PHPStan/Analyser/data/pathinfo.php new file mode 100644 index 00000000000..716e14fbf66 --- /dev/null +++ b/tests/PHPStan/Analyser/data/pathinfo.php @@ -0,0 +1,17 @@ +