Skip to content

Commit

Permalink
[NodeTypeResolver] Use Scope->getType() on ArrayDimFetch on NodeTypeR…
Browse files Browse the repository at this point in the history
…esolver::getNativeType() (#5037)

* [NodeTypeResolver] Use Scope->getType() on ArrayDimFetch on NodeTypeResolver::getNativeType()

* Fix

* Fix

* final touch: more clear usage of ArrayDimFetch on empty

* add array dim fetch from docblock
  • Loading branch information
samsonasik committed Sep 18, 2023
1 parent 308178a commit a3d2fcd
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 20 deletions.
42 changes: 27 additions & 15 deletions packages/NodeTypeResolver/NodeTypeResolver.php
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\ConstFetch;
Expand Down Expand Up @@ -234,7 +235,13 @@ public function getNativeType(Expr $expr): Type
}
}

$type = $scope->getNativeType($expr);
/**
* ArrayDimFetch got type by its Scope->getType(), otherwise, it got MixedType
*/
$type = $expr instanceof ArrayDimFetch
? $scope->getType($expr)
: $scope->getNativeType($expr);

if (! $type instanceof UnionType) {
if ($this->isAnonymousObjectType($type)) {
return new ObjectWithoutClassType();
Expand All @@ -243,20 +250,7 @@ public function getNativeType(Expr $expr): Type
return $this->accessoryNonEmptyStringTypeCorrector->correct($type);
}

$hasChanged = false;
$types = $type->getTypes();
foreach ($types as $key => $childType) {
if ($this->isAnonymousObjectType($childType)) {
$types[$key] = new ObjectWithoutClassType();
$hasChanged = true;
}
}

if ($hasChanged) {
return $this->accessoryNonEmptyStringTypeCorrector->correct(new UnionType($types));
}

return $this->accessoryNonEmptyStringTypeCorrector->correct($type);
return $this->resolveNativeUnionType($type);
}

public function isNumberType(Expr $expr): bool
Expand Down Expand Up @@ -331,6 +325,24 @@ public function isMethodStaticCallOrClassMethodObjectType(Node $node, ObjectType
return $classReflection->isSubclassOf($objectType->getClassName());
}

private function resolveNativeUnionType(UnionType $unionType): Type
{
$hasChanged = false;
$types = $unionType->getTypes();
foreach ($types as $key => $childType) {
if ($this->isAnonymousObjectType($childType)) {
$types[$key] = new ObjectWithoutClassType();
$hasChanged = true;
}
}

if ($hasChanged) {
return $this->accessoryNonEmptyStringTypeCorrector->correct(new UnionType($types));
}

return $this->accessoryNonEmptyStringTypeCorrector->correct($unionType);
}

private function isMatchObjectWithoutClassType(
ObjectWithoutClassType $objectWithoutClassType,
ObjectType $requiredObjectType
Expand Down
10 changes: 5 additions & 5 deletions rules/Strict/Rector/Empty_/DisallowedEmptyRuleFixerRector.php
Expand Up @@ -97,7 +97,7 @@ private function refactorBooleanNot(BooleanNot $booleanNot, Scope $scope): Expr|

$empty = $booleanNot->expr;
if ($empty->expr instanceof ArrayDimFetch) {
return $this->createDimFetchBooleanAnd($empty);
return $this->createDimFetchBooleanAnd($empty->expr);
}

if ($this->exprAnalyzer->isNonTypedFromParam($empty->expr)) {
Expand All @@ -123,12 +123,12 @@ private function refactorEmpty(Empty_ $empty, Scope $scope, bool $treatAsNonEmpt
return $this->exactCompareFactory->createIdenticalFalsyCompare($exprType, $empty->expr, $treatAsNonEmpty);
}

private function createDimFetchBooleanAnd(Empty_ $empty): ?BooleanAnd
private function createDimFetchBooleanAnd(ArrayDimFetch $arrayDimFetch): ?BooleanAnd
{
$exprType = $this->getType($empty->expr);
$exprType = $this->nodeTypeResolver->getNativeType($arrayDimFetch);

$isset = new Isset_([$empty->expr]);
$compareExpr = $this->exactCompareFactory->createNotIdenticalFalsyCompare($exprType, $empty->expr, false);
$isset = new Isset_([$arrayDimFetch]);
$compareExpr = $this->exactCompareFactory->createNotIdenticalFalsyCompare($exprType, $arrayDimFetch, false);

if (! $compareExpr instanceof Expr) {
return null;
Expand Down
@@ -0,0 +1,41 @@
<?php

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

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

return null;
}
}

?>
-----
<?php

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

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

return null;
}
}

?>

0 comments on commit a3d2fcd

Please sign in to comment.