[DowngradePhp73] Handle (array) cast on DowngradeArrayKeyFirstLastRector (#1478)

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Abdul Malik Ikhsan 2021-12-13 23:34:56 +07:00 committed by GitHub
parent 41caea7156
commit 4214801263
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 154 additions and 2 deletions

View File

@ -0,0 +1,33 @@
<?php
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
use PhpParser\Node\Stmt\ClassMethod;
class CastArrayKeyFirstValue
{
public function run(ClassMethod $classMethod)
{
$firstItemKey = array_key_first((array) $classMethod->stmts);
}
}
?>
-----
<?php
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
use PhpParser\Node\Stmt\ClassMethod;
class CastArrayKeyFirstValue
{
public function run(ClassMethod $classMethod)
{
$stmts = (array) $classMethod->stmts;
reset($stmts);
$firstItemKey = key($stmts);
}
}
?>

View File

@ -0,0 +1,33 @@
<?php
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
use PhpParser\Node\Stmt\ClassMethod;
class CastArrayKeyLastValue
{
public function run(ClassMethod $classMethod)
{
$lastItemKey = array_key_last((array) $classMethod->stmts);
}
}
?>
-----
<?php
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
use PhpParser\Node\Stmt\ClassMethod;
class CastArrayKeyLastValue
{
public function run(ClassMethod $classMethod)
{
$stmts = (array) $classMethod->stmts;
end($stmts);
$lastItemKey = key($stmts);
}
}
?>

View File

@ -0,0 +1,33 @@
<?php
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
use PhpParser\Node\Stmt\ClassMethod;
class DoubleCast
{
public function run(ClassMethod $classMethod)
{
$lastItemKey = array_key_last((array)(array) $classMethod->stmts);
}
}
?>
-----
<?php
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
use PhpParser\Node\Stmt\ClassMethod;
class DoubleCast
{
public function run(ClassMethod $classMethod)
{
$stmts = (array)(array) $classMethod->stmts;
end($stmts);
$lastItemKey = key($stmts);
}
}
?>

View File

@ -6,9 +6,16 @@ namespace Rector\DowngradePhp73\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Cast\Array_;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\Rector\AbstractRector;
use Rector\Naming\Naming\VariableNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -19,6 +26,11 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
*/
final class DowngradeArrayKeyFirstLastRector extends AbstractRector
{
public function __construct(
private readonly VariableNaming $variableNaming
) {
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Downgrade array_key_first() and array_key_last() functions', [
@ -82,12 +94,20 @@ CODE_SAMPLE
return null;
}
$array = $funcCall->args[0]->value;
$originalArray = $funcCall->args[0]->value;
$array = $this->resolveCastedArray($originalArray);
if ($originalArray !== $array) {
$this->addAssignNewVariable($funcCall, $originalArray, $array);
}
$resetFuncCall = $this->nodeFactory->createFuncCall('reset', [$array]);
$this->nodesToAddCollector->addNodeBeforeNode($resetFuncCall, $funcCall);
$funcCall->name = new Name('key');
if ($originalArray !== $array) {
$funcCall->args[0]->value = $array;
}
return $funcCall;
}
@ -102,12 +122,45 @@ CODE_SAMPLE
return null;
}
$array = $funcCall->args[0]->value;
$originalArray = $funcCall->args[0]->value;
$array = $this->resolveCastedArray($originalArray);
if ($originalArray !== $array) {
$this->addAssignNewVariable($funcCall, $originalArray, $array);
}
$resetFuncCall = $this->nodeFactory->createFuncCall('end', [$array]);
$this->nodesToAddCollector->addNodeBeforeNode($resetFuncCall, $funcCall);
$funcCall->name = new Name('key');
if ($originalArray !== $array) {
$funcCall->args[0]->value = $array;
}
return $funcCall;
}
private function addAssignNewVariable(FuncCall $funcCall, Expr $expr, Expr|Variable $variable): void
{
$this->addNodeBeforeNode(new Expression(new Assign($variable, $expr)), $funcCall);
}
private function resolveCastedArray(Expr $expr): Expr|Variable
{
if (! $expr instanceof Array_) {
return $expr;
}
if ($expr->expr instanceof Array_) {
return $this->resolveCastedArray($expr->expr);
}
$scope = $expr->getAttribute(AttributeKey::SCOPE);
$variableName = $this->variableNaming->createCountedValueName(
(string) $this->nodeNameResolver->getName($expr->expr),
$scope
);
return new Variable($variableName);
}
}