Skip to content

Commit

Permalink
Cover non-empty-array in array_merge
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm authored Jul 19, 2021
1 parent 9ee914b commit 0be769d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
16 changes: 15 additions & 1 deletion src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\Type;
Expand All @@ -29,6 +30,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,

$keyTypes = [];
$valueTypes = [];
$nonEmpty = false;
foreach ($functionCall->args as $arg) {
$argType = $scope->getType($arg->value);
if ($arg->unpack) {
Expand All @@ -42,12 +44,24 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,

$keyTypes[] = TypeUtils::generalizeType($argType->getIterableKeyType(), GeneralizePrecision::moreSpecific());
$valueTypes[] = $argType->getIterableValueType();

if (!$argType->isIterableAtLeastOnce()->yes()) {
continue;
}

$nonEmpty = true;
}

return new ArrayType(
$arrayType = new ArrayType(
TypeCombinator::union(...$keyTypes),
TypeCombinator::union(...$valueTypes)
);

if ($nonEmpty) {
$arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType());
}

return $arrayType;
}

}
12 changes: 6 additions & 6 deletions tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5129,31 +5129,31 @@ public function dataArrayFunctions(): array
'array_values($generalStringKeys)',
],
[
'array<int|non-empty-string, stdClass>',
'array<int|non-empty-string, stdClass>&nonEmpty',
'array_merge($stringOrIntegerKeys)',
],
[
'array<int|string, DateTimeImmutable|int>',
'array_merge($generalStringKeys, $generalDateTimeValues)',
],
[
'array<int|string, int|stdClass>',
'array<int|string, int|stdClass>&nonEmpty',
'array_merge($generalStringKeys, $stringOrIntegerKeys)',
],
[
'array<int|string, int|stdClass>',
'array<int|string, int|stdClass>&nonEmpty',
'array_merge($stringOrIntegerKeys, $generalStringKeys)',
],
[
'array<int|non-empty-string, \'foo\'|stdClass>',
'array<int|non-empty-string, \'foo\'|stdClass>&nonEmpty',
'array_merge($stringKeys, $stringOrIntegerKeys)',
],
[
'array<int|non-empty-string, \'foo\'|stdClass>',
'array<int|non-empty-string, \'foo\'|stdClass>&nonEmpty',
'array_merge($stringOrIntegerKeys, $stringKeys)',
],
[
'array<int|non-empty-string, 2|4|\'a\'|\'b\'|\'green\'|\'red\'|\'trapezoid\'>',
'array<int|non-empty-string, 2|4|\'a\'|\'b\'|\'green\'|\'red\'|\'trapezoid\'>&nonEmpty',
'array_merge(array("color" => "red", 2, 4), array("a", "b", "color" => "green", "shape" => "trapezoid", 4))',
],
[
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Analyser/data/non-empty-array.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,10 @@ public function arrayFunctions($array, $list): void
{
assertType('array&nonEmpty', array_combine($array, $array));
assertType('array&nonEmpty', array_combine($list, $list));

assertType('array&nonEmpty', array_merge($array));
assertType('array&nonEmpty', array_merge([], $array));
assertType('array&nonEmpty', array_merge($array, []));
assertType('array&nonEmpty', array_merge($array, $array));
}
}

0 comments on commit 0be769d

Please sign in to comment.