From f2b37e6fa886c3420a37d9bb6468bec7f629e47a Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 27 Apr 2022 22:47:28 +0200 Subject: [PATCH] Support non-empty-array in InArrayFunctionTypeSpecifyingExtension --- ...InArrayFunctionTypeSpecifyingExtension.php | 24 +++++++++++++++---- .../Analyser/NodeScopeResolverTest.php | 1 + .../Analyser/data/in-array-non-empty.php | 20 ++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/in-array-non-empty.php diff --git a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php index 98576400ef2..b73d877197a 100644 --- a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php @@ -9,8 +9,10 @@ use PHPStan\Analyser\TypeSpecifierAwareExtension; use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\FunctionReflection; +use PHPStan\Type\Accessory\NonEmptyArrayType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\FunctionTypeSpecifyingExtension; +use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; use function count; use function strtolower; @@ -41,22 +43,36 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n return new SpecifiedTypes([], []); } - $arrayValueType = $scope->getType($node->getArgs()[1]->value)->getIterableValueType(); + $arrayType = $scope->getType($node->getArgs()[1]->value); + $arrayValueType = $arrayType->getIterableValueType(); + + $specifiedTypes = new SpecifiedTypes([], []); if ( $context->truthy() || count(TypeUtils::getConstantScalars($arrayValueType)) > 0 ) { - return $this->typeSpecifier->create( + $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create( $node->getArgs()[0]->value, $arrayValueType, $context, false, $scope, - ); + )); + } + + if ($context->true() + && $arrayType->isArray()->yes()) { + $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create( + $node->getArgs()[1]->value, + TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), + $context, + false, + $scope, + )); } - return new SpecifiedTypes([], []); + return $specifiedTypes; } } diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 92b3dd7059b..7ba7a12ff9c 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -903,6 +903,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7115.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/constant-array-type-identical.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-str-containing-fns.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/in-array-non-empty.php'); } /** diff --git a/tests/PHPStan/Analyser/data/in-array-non-empty.php b/tests/PHPStan/Analyser/data/in-array-non-empty.php new file mode 100644 index 00000000000..abedc545385 --- /dev/null +++ b/tests/PHPStan/Analyser/data/in-array-non-empty.php @@ -0,0 +1,20 @@ + $array + */ + public function sayHello(array $array): void + { + if(in_array("thing", $array, true)){ + assertType('non-empty-array', $array); + } + } +}