Skip to content

Commit 89c94de

Browse files
authored
[DowngradePhp74][DowngradePhp81] Handle ArrowFunctionToAnonymousFunctionRector+DowngradeArrayIsListRector (#206)
* [DowngradePhp74][DowngradePhp81] Handle ArrowFunctionToAnonymousFunctionRector+DowngradeArrayIsListRector * emove debug
1 parent 4056166 commit 89c94de

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed

rules/DowngradePhp74/Rector/ArrowFunction/ArrowFunctionToAnonymousFunctionRector.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
namespace Rector\DowngradePhp74\Rector\ArrowFunction;
66

77
use PhpParser\Node;
8+
use PhpParser\Node\Expr;
89
use PhpParser\Node\Expr\ArrowFunction;
910
use PhpParser\Node\Expr\Assign;
1011
use PhpParser\Node\Expr\Closure;
1112
use PhpParser\Node\Expr\ClosureUse;
1213
use PhpParser\Node\Expr\Variable;
1314
use PhpParser\Node\Stmt\Return_;
1415
use PhpParser\Node\Stmt\Throw_;
16+
use PHPStan\Analyser\Scope;
1517
use Rector\Core\PhpParser\Node\BetterNodeFinder;
1618
use Rector\Core\Rector\AbstractRector;
19+
use Rector\NodeTypeResolver\Node\AttributeKey;
1720
use Rector\Php72\NodeFactory\AnonymousFunctionFactory;
1821
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1922
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@@ -114,6 +117,35 @@ public function refactor(Node $node): Closure
114117
return new Throw_($throw->expr);
115118
});
116119

120+
$this->appendUsesFromInsertedVariable($node->expr, $anonymousFunctionFactory);
121+
117122
return $anonymousFunctionFactory;
118123
}
124+
125+
private function appendUsesFromInsertedVariable(Expr $expr, Closure $anonymousFunctionFactory): void
126+
{
127+
$this->traverseNodesWithCallable($expr, function (Node $subNode) use ($anonymousFunctionFactory) {
128+
if (! $subNode instanceof Variable) {
129+
return null;
130+
}
131+
132+
$variableName = $this->getName($subNode);
133+
if ($variableName === null) {
134+
return null;
135+
}
136+
137+
if ($subNode->hasAttribute(AttributeKey::ORIGINAL_NODE)) {
138+
return null;
139+
}
140+
141+
$scope = $subNode->getAttribute(AttributeKey::SCOPE);
142+
if (! $scope instanceof Scope) {
143+
return null;
144+
}
145+
146+
if (! $scope->hasVariableType($variableName)->yes()) {
147+
$anonymousFunctionFactory->uses[] = new ClosureUse(new Variable($variableName));
148+
}
149+
});
150+
}
119151
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Issues\DowngradeArrayIsListArrowFunction;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class DowngradeArrayIsListArrowFunctionTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace Rector\Tests\Issues\DowngradeArrayIsListArrowFunction\Fixture;
4+
5+
class Fixture
6+
{
7+
public function run($items)
8+
{
9+
return array_map(
10+
fn($item) => is_array($item) && !array_is_list($item)? (object) $this->convertToObject($item) : ($item),
11+
$items
12+
);
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\Tests\Issues\DowngradeArrayIsListArrowFunction\Fixture;
21+
22+
class Fixture
23+
{
24+
public function run($items)
25+
{
26+
$arrayIsListFunction = function (array $array) : bool {
27+
if (function_exists('array_is_list')) {
28+
return array_is_list($array);
29+
}
30+
if ($array === []) {
31+
return true;
32+
}
33+
$current_key = 0;
34+
foreach ($array as $key => $noop) {
35+
if ($key !== $current_key) {
36+
return false;
37+
}
38+
++$current_key;
39+
}
40+
return true;
41+
};
42+
return array_map(
43+
function ($item) use ($arrayIsListFunction) {
44+
return is_array($item) && !$arrayIsListFunction($item)? (object) $this->convertToObject($item) : ($item);
45+
},
46+
$items
47+
);
48+
}
49+
}
50+
51+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\DowngradePhp74\Rector\ArrowFunction\ArrowFunctionToAnonymousFunctionRector;
7+
use Rector\DowngradePhp81\Rector\FuncCall\DowngradeArrayIsListRector;
8+
9+
return static function (RectorConfig $rectorConfig): void {
10+
$rectorConfig->rules([DowngradeArrayIsListRector::class, ArrowFunctionToAnonymousFunctionRector::class]);
11+
};

0 commit comments

Comments
 (0)