Skip to content

Commit

Permalink
Support non-empty-array in InArrayFunctionTypeSpecifyingExtension
Browse files Browse the repository at this point in the history
  • Loading branch information
clxmstaab committed Mar 23, 2022
1 parent 2b9d212 commit 0f6720e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
24 changes: 20 additions & 4 deletions src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php
Expand Up @@ -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;
Expand Down Expand Up @@ -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->true()) {
$arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType());

$specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create(
$node->getArgs()[1]->value,
$arrayType,
$context,
false,
$scope,
));
}

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,
);
));
}

return new SpecifiedTypes([], []);
return $specifiedTypes;
}

}
5 changes: 5 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -810,6 +810,11 @@ public function dataFileAsserts(): iterable
if (PHP_VERSION_ID >= 80100) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/value-of-enum.php');
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/in-array-non-empty.php');
if (PHP_VERSION_ID >= 80000) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/in-array-non-empty-php8.php');
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6584.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6439.php');
Expand Down
20 changes: 20 additions & 0 deletions tests/PHPStan/Analyser/data/in-array-non-empty-php8.php
@@ -0,0 +1,20 @@
<?php // lint >= 8.0

declare(strict_types = 1);

namespace InArrayNonEmptyPhp8;

use function PHPStan\Testing\assertType;

class HelloWorld
{
/**
* @phpstan-param list<string> $array
*/
public function sayHello(array $array): void
{
if(in_array(haystack: $array, needle: "thing", strict: true)){
assertType('non-empty-array<int, string>', $array);
}
}
}
20 changes: 20 additions & 0 deletions tests/PHPStan/Analyser/data/in-array-non-empty.php
@@ -0,0 +1,20 @@
<?php

declare(strict_types = 1);

namespace InArrayNonEmpty;

use function PHPStan\Testing\assertType;

class HelloWorld
{
/**
* @phpstan-param list<string> $array
*/
public function sayHello(array $array): void
{
if(in_array("thing", $array, true)){
assertType('non-empty-array<int, string>', $array);
}
}
}

0 comments on commit 0f6720e

Please sign in to comment.