Skip to content

Commit

Permalink
[NodeTypeResolver] pull getType() on ArrayDimFetch when not mixed typ…
Browse files Browse the repository at this point in the history
…e from its variable native definition (#5056)

* [NodeTypeResolver] pull getType() on ArrayDimFetch when not mixed type from its variable native definition

* also skip mixed

* clean up

* more fixture

* on array object
  • Loading branch information
samsonasik committed Sep 21, 2023
1 parent 884a47e commit ad96b1f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 16 deletions.
30 changes: 24 additions & 6 deletions packages/NodeTypeResolver/NodeTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use PHPStan\Broker\ClassAutoloadingException;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
Expand Down Expand Up @@ -235,12 +236,29 @@ public function getNativeType(Expr $expr): Type
}
}

/**
* ArrayDimFetch got type by its Scope->getType(), otherwise, it got MixedType
*/
$type = $expr instanceof ArrayDimFetch
? $scope->getType($expr)
: $scope->getNativeType($expr);
$type = $scope->getNativeType($expr);
if ($expr instanceof ArrayDimFetch) {
/**
* Allow pull type from
*
* - native function
* - always defined by assignment
*
* eg:
*
* $parts = parse_url($url);
* if (!empty($parts['host'])) { }
*
* or
*
* $parts = ['host' => 'foo'];
* if (!empty($parts['host'])) { }
*/
$variableType = $scope->getNativeType($expr->var);
if (! $variableType instanceof ArrayType || ! $variableType->getItemType() instanceof MixedType) {
$type = $scope->getType($expr);
}
}

if (! $type instanceof UnionType) {
if ($this->isAnonymousObjectType($type)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Rector\Core\Tests\Issues\EmptyBooleanCompare\Fixture;

final class AlwaysExistsArrayDimFetchItem
{
public function checkUrl(string $url)
{
if (rand(0, 1)) {
$parts = [
'host' => 'foo',
];
} else {
$parts = [
'host' => '',
];
}

if (!empty($parts['host'])) {
return $parts['host'];
}

return null;
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\EmptyBooleanCompare\Fixture;

final class AlwaysExistsArrayDimFetchItem
{
public function checkUrl(string $url)
{
if (rand(0, 1) !== 0) {
$parts = [
'host' => 'foo',
];
} else {
$parts = [
'host' => '',
];
}

if (isset($parts['host']) && $parts['host'] !== '') {
return $parts['host'];
}

return null;
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

namespace Rector\Core\Tests\Issues\EmptyBooleanCompare\Fixture;

final class ArrayDimFetchFromDocblock
final class OnArrayObject
{
/**
* @param array{host: string} $parts
*/
public function checkUrl(array $parts)
public function checkUrl()
{
$parts = new \ArrayObject(['host' => 'test'], \ArrayObject::ARRAY_AS_PROPS);

if (!empty($parts['host'])) {
return $parts['host'];
}
Expand All @@ -23,13 +22,12 @@ final class ArrayDimFetchFromDocblock

namespace Rector\Core\Tests\Issues\EmptyBooleanCompare\Fixture;

final class ArrayDimFetchFromDocblock
final class OnArrayObject
{
/**
* @param array{host: string} $parts
*/
public function checkUrl(array $parts)
public function checkUrl()
{
$parts = new \ArrayObject(['host' => 'test'], \ArrayObject::ARRAY_AS_PROPS);

if (isset($parts['host']) && $parts['host'] !== '') {
return $parts['host'];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Rector\Core\Tests\Issues\EmptyBooleanCompare\Fixture;

final class SkipArrayDimFetchFromDocblock
{
/**
* @param array{host: string} $parts
*/
public function checkUrl(array $parts)
{
if (!empty($parts['host'])) {
return $parts['host'];
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\Core\Tests\Issues\EmptyBooleanCompare\Fixture;

final class SkipMixedArrayDimFetch
{
public function checkUrl(array $parts)
{
if (!empty($parts['host'])) {
return $parts['host'];
}

return null;
}
}

0 comments on commit ad96b1f

Please sign in to comment.