Skip to content

Commit 1033c38

Browse files
Support array_values in ArrayFirstLastRector
1 parent 17e1297 commit 1033c38

3 files changed

Lines changed: 132 additions & 2 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector\Fixture;
6+
7+
final class ArrayValuesPattern
8+
{
9+
public function run(array $array)
10+
{
11+
echo array_values($array)[0];
12+
echo array_values($array)[count($array) - 1];
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
declare(strict_types=1);
21+
22+
namespace Rector\Tests\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector\Fixture;
23+
24+
final class ArrayValuesPattern
25+
{
26+
public function run(array $array)
27+
{
28+
echo array_first($array);
29+
echo array_last($array);
30+
}
31+
}
32+
33+
?>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector\Fixture;
6+
7+
final class SkipArrayValuesDifferentVariable
8+
{
9+
public function run(array $array, array $differentVariable)
10+
{
11+
echo array_values($array)[count($differentVariable) - 1];
12+
}
13+
}

rules/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector.php

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
use PhpParser\Node;
88
use PhpParser\Node\Expr\ArrayDimFetch;
9+
use PhpParser\Node\Expr\BinaryOp\Minus;
910
use PhpParser\Node\Expr\FuncCall;
11+
use PhpParser\Node\Scalar\Int_;
1012
use Rector\NodeTypeResolver\Node\AttributeKey;
1113
use Rector\PHPStan\ScopeFetcher;
1214
use Rector\Rector\AbstractRector;
@@ -40,11 +42,15 @@ public function getRuleDefinition(): RuleDefinition
4042
<<<'CODE_SAMPLE'
4143
echo $array[array_key_first($array)];
4244
echo $array[array_key_last($array)];
45+
echo array_values($array)[0];
46+
echo array_values($array)[count($array) - 1];
4347
CODE_SAMPLE
4448
,
4549
<<<'CODE_SAMPLE'
4650
echo array_first($array);
4751
echo array_last($array);
52+
echo array_first($array);
53+
echo array_last($array);
4854
CODE_SAMPLE
4955
),
5056
]
@@ -63,6 +69,24 @@ public function getNodeTypes(): array
6369
* @param ArrayDimFetch $node
6470
*/
6571
public function refactor(Node $node): ?FuncCall
72+
{
73+
if ($node->dim instanceof FuncCall) {
74+
return $this->refactorArrayKeyPattern($node);
75+
}
76+
77+
if ($node->var instanceof FuncCall && ($node->dim instanceof Int_ || $node->dim instanceof Minus)) {
78+
return $this->refactorArrayValuesPattern($node);
79+
}
80+
81+
return null;
82+
}
83+
84+
public function provideMinPhpVersion(): int
85+
{
86+
return PhpVersionFeature::ARRAY_FIRST_LAST;
87+
}
88+
89+
private function refactorArrayKeyPattern(ArrayDimFetch $node): ?FuncCall
6690
{
6791
if (! $node->dim instanceof FuncCall) {
6892
return null;
@@ -100,8 +124,68 @@ public function refactor(Node $node): ?FuncCall
100124
return $this->nodeFactory->createFuncCall($functionName, [$node->var]);
101125
}
102126

103-
public function provideMinPhpVersion(): int
127+
private function refactorArrayValuesPattern(ArrayDimFetch $node): ?FuncCall
104128
{
105-
return PhpVersionFeature::ARRAY_FIRST_LAST;
129+
if (! $node->var instanceof FuncCall) {
130+
return null;
131+
}
132+
133+
if (! $this->isName($node->var, 'array_values')) {
134+
return null;
135+
}
136+
137+
if ($node->var->isFirstClassCallable()) {
138+
return null;
139+
}
140+
141+
if (count($node->var->getArgs()) !== 1) {
142+
return null;
143+
}
144+
145+
$scope = ScopeFetcher::fetch($node);
146+
if ($scope->isInExpressionAssign($node)) {
147+
return null;
148+
}
149+
150+
if ($node->getAttribute(AttributeKey::IS_UNSET_VAR)) {
151+
return null;
152+
}
153+
154+
$arrayArg = $node->var->getArgs()[0]
155+
->value;
156+
157+
if ($node->dim instanceof Int_ && $node->dim->value === 0) {
158+
return $this->nodeFactory->createFuncCall('array_first', [$arrayArg]);
159+
}
160+
161+
if ($node->dim instanceof Minus) {
162+
if (! $node->dim->left instanceof FuncCall) {
163+
return null;
164+
}
165+
166+
if (! $this->isName($node->dim->left, 'count')) {
167+
return null;
168+
}
169+
170+
if ($node->dim->left->isFirstClassCallable()) {
171+
return null;
172+
}
173+
174+
if (count($node->dim->left->getArgs()) !== 1) {
175+
return null;
176+
}
177+
178+
if (! $node->dim->right instanceof Int_ || $node->dim->right->value !== 1) {
179+
return null;
180+
}
181+
182+
if (! $this->nodeComparator->areNodesEqual($arrayArg, $node->dim->left->getArgs()[0]->value)) {
183+
return null;
184+
}
185+
186+
return $this->nodeFactory->createFuncCall('array_last', [$arrayArg]);
187+
}
188+
189+
return null;
106190
}
107191
}

0 commit comments

Comments
 (0)