mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-28 23:10:51 +00:00
[CodeQuality] Remove MoveVariableDeclarationNearReferenceRector for too wide domain, not capable on most of real projects (#587)
This commit is contained in:
parent
aff0c5d90c
commit
0a51a73ad6
|
@ -3,7 +3,6 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector;
|
||||
use Rector\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector;
|
||||
use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector;
|
||||
use Rector\CodingStyle\Rector\MethodCall\UseMessageVariableForSprintfInSymfonyStyleRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
@ -11,7 +10,6 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
|
|||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(CountArrayToEmptyArrayComparisonRector::class);
|
||||
$services->set(MoveVariableDeclarationNearReferenceRector::class);
|
||||
$services->set(UseMessageVariableForSprintfInSymfonyStyleRector::class);
|
||||
$services->set(FlipTypeControlToUseExclusiveTypeRector::class);
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ final class SetList implements SetListInterface
|
|||
public const CODE_QUALITY = __DIR__ . '/../../../config/set/code-quality.php';
|
||||
|
||||
/**
|
||||
* @deprecated Use only/directly CODE_QUALITY instead
|
||||
* @var string
|
||||
*/
|
||||
public const CODE_QUALITY_STRICT = __DIR__ . '/../../../config/set/code-quality-strict.php';
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class Fixture
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class Fixture
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
if (mktime() === false) {
|
||||
$var = 1;
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class FixtureUsedOnlyAfterIf
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
null;
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class FixtureUsedOnlyAfterIf
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
if (mktime() === false) {
|
||||
null;
|
||||
}
|
||||
$var = 1;
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function variableInClosure()
|
||||
{
|
||||
$closure = function () {
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
return $var;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function variableInClosure()
|
||||
{
|
||||
$closure = function () {
|
||||
if (mktime() === false) {
|
||||
$var = 1;
|
||||
return $var;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function variableInClosureWithReturn()
|
||||
{
|
||||
return function () {
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
return $var;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function variableInClosureWithReturn()
|
||||
{
|
||||
return function () {
|
||||
if (mktime() === false) {
|
||||
$var = 1;
|
||||
return $var;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function variableWithMultipleUsages()
|
||||
{
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
echo $var;
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function variableWithMultipleUsages()
|
||||
{
|
||||
if (mktime() === false) {
|
||||
$var = 1;
|
||||
echo $var;
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipArrayDimFetchNext
|
||||
{
|
||||
private function createArgsFromItems(array $items, ?string $silentKey = null): array
|
||||
{
|
||||
$args = [];
|
||||
|
||||
if ($silentKey !== null && isset($items[$silentKey])) {
|
||||
$args[] = 1;
|
||||
}
|
||||
|
||||
if (true) {
|
||||
foreach ($items as $key => $value) {
|
||||
$args[] = 2;
|
||||
}
|
||||
} else {
|
||||
foreach ($items as $value) {
|
||||
$args[] = 3;
|
||||
}
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipArrayDimFetchNextAsKey
|
||||
{
|
||||
private function foo($data, $aliasName)
|
||||
{
|
||||
$loweredAliasName = strtolower($aliasName);
|
||||
|
||||
if (isset($data[$loweredAliasName])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $loweredAliasName;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,13 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
final class SkipAssignExprArrayDimFetch
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$value = $values[$i];
|
||||
++$i;
|
||||
return $value;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipDeclaredInExtraParentPrevious
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$absoluteDirectories = [];
|
||||
|
||||
foreach ($directories as $directory) {
|
||||
if (Strings::contains($directory, '*')) {
|
||||
$absoluteDirectories = array_merge($absoluteDirectories, glob($directory, GLOB_ONLYDIR));
|
||||
} else {
|
||||
$this->ensureDirectoryExists($directory);
|
||||
$absoluteDirectories[] = $directory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipExprReused
|
||||
{
|
||||
function myMethod($x)
|
||||
{
|
||||
$var = $x;
|
||||
$x = 1;
|
||||
echo $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipExprVarUsed
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = run($a, $b);
|
||||
$a = 1;
|
||||
$b = 2;
|
||||
|
||||
if (mktime() === false) {
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipInsideCondition
|
||||
{
|
||||
function myMethod($node)
|
||||
{
|
||||
if (mktime() === false) {
|
||||
$node = 1;
|
||||
} else {
|
||||
echo $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipInsideLoop
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = rand(0, 1);
|
||||
|
||||
for ($i = 0; $i <= 10; $i++) {
|
||||
echo $var + $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
function test() {
|
||||
$title = 'abc';
|
||||
?>
|
||||
<h1>
|
||||
<?php echo $title; ?>
|
||||
</h1>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
/**
|
||||
* @see https://github.com/codeigniter4/CodeIgniter4/blob/2c3f9897762fba3c18f95237686c1297822cdff4/tests/system/Database/Live/FabricatorLiveTest.php#L68-L72
|
||||
*/
|
||||
class SkipNonNativeFunction
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$count = Fabricator::getCount('user');
|
||||
fake(UserModel::class, ['country' => 'Italy']);
|
||||
|
||||
$count !== Fabricator::getCount('user');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipNotUsed
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = 1;
|
||||
|
||||
if (mktime() === false) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
final class SkipObGetContents
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
ob_start();
|
||||
$git->status();
|
||||
$contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $contents;
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
final class SkipPassBcdiv
|
||||
{
|
||||
public function run($data, $options)
|
||||
{
|
||||
$a = bcscale(3);
|
||||
echo bcdiv('105', '6.55957');
|
||||
echo $a;
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
final class SkipPassJsonLastError
|
||||
{
|
||||
public function run($data, $options)
|
||||
{
|
||||
$result = json_encode($data, $options, 512);
|
||||
|
||||
if (json_last_error()) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
echo $result;
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipPropertyInExpr
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = $this->run($this->a->b, $this->c->d);
|
||||
|
||||
if (true) {
|
||||
$this->a = new \stdClass;
|
||||
$this->b = new \stdClass;
|
||||
|
||||
echo $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipReassign
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
$var = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsageInMethodCall
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$crawler = $kernelBrowser->request('GET', '/');
|
||||
$this->assertResponseIsSuccessful();
|
||||
$this->assertStringContainsString('Hello World', $crawler->filter('h1, h2, h3')->text());
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsageInMultipleLevels
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$varused = 1;
|
||||
|
||||
if (mktime() === false) {
|
||||
if (true) {
|
||||
if (false) {
|
||||
return $varused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $varused;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsageInMultipleLevelsHasStmtBetween
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$varused = 1;
|
||||
|
||||
if (mktime() === false) {
|
||||
if (true) {
|
||||
if (false) {
|
||||
return $varused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo 'STATEMENT HERE';
|
||||
|
||||
echo $varused;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsageInStaticCall
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$crawler = $kernelBrowser->request('GET', '/');
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertStringContainsString('Hello World', $crawler->filter('h1, h2, h3')->text());
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsedInCatch
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$position = getPosition();
|
||||
|
||||
try {
|
||||
execute();
|
||||
echo $position;
|
||||
} catch (\Exception $e) {
|
||||
echo $position + 1;
|
||||
} finally {
|
||||
echo $position + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsedInNextCaseOfSwitch
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$do_sfe = $do_trt->get_sfe_do();
|
||||
|
||||
switch($do_trt->get_mar_do()->get_cod_s()) {
|
||||
case 'MAR1':
|
||||
return class1::get_price_all($do_sfe);
|
||||
case 'MAR2':
|
||||
return class1::get_price_all2($do_sfe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsedInNextElse
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$position = getPosition();
|
||||
|
||||
if (rand(0, 1) === 1) {
|
||||
echo $position;
|
||||
} elseif (rand(0, 1) === 0) {
|
||||
echo $position + 1;
|
||||
} else {
|
||||
echo $position + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsedInNextTernary
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$position = getPosition();
|
||||
|
||||
rand(0, 1) === 1
|
||||
? $position
|
||||
: $position + 1;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
class SkipUsedMultipleTimes
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = 1;
|
||||
if (mktime() === false) {
|
||||
return $var;
|
||||
}
|
||||
|
||||
if (mktime() === true) {
|
||||
return $var + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
use Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Source\MyException;
|
||||
|
||||
class StaticCallNextException
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
$var = do_something();
|
||||
if (mktime() === false) {
|
||||
throw MyException::notFound();
|
||||
}
|
||||
echo $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Fixture;
|
||||
|
||||
use Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Source\MyException;
|
||||
|
||||
class StaticCallNextException
|
||||
{
|
||||
function myMethod()
|
||||
{
|
||||
if (mktime() === false) {
|
||||
throw MyException::notFound();
|
||||
}
|
||||
$var = do_something();
|
||||
echo $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class MoveVariableDeclarationNearReferenceRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/configured_rule.php';
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\Source;
|
||||
|
||||
class MyException extends \Exception
|
||||
{
|
||||
public static function notFound()
|
||||
{
|
||||
return new self('Page not found');
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(MoveVariableDeclarationNearReferenceRector::class);
|
||||
};
|
|
@ -1,244 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Rector\Variable;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticPropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Do_;
|
||||
use PhpParser\Node\Stmt\Else_;
|
||||
use PhpParser\Node\Stmt\ElseIf_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\For_;
|
||||
use PhpParser\Node\Stmt\Foreach_;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use PhpParser\Node\Stmt\While_;
|
||||
use Rector\CodeQuality\UsageFinder\UsageInNextStmtFinder;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeNestingScope\NodeFinder\ScopeAwareNodeFinder;
|
||||
use Rector\NodeNestingScope\ParentFinder;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\CodeQuality\Rector\Variable\MoveVariableDeclarationNearReferenceRector\MoveVariableDeclarationNearReferenceRectorTest
|
||||
*/
|
||||
final class MoveVariableDeclarationNearReferenceRector extends AbstractRector
|
||||
{
|
||||
public function __construct(
|
||||
private ScopeAwareNodeFinder $scopeAwareNodeFinder,
|
||||
private ParentFinder $parentFinder,
|
||||
private UsageInNextStmtFinder $usageInNextStmtFinder
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Move variable declaration near its reference',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
$var = 1;
|
||||
if ($condition === null) {
|
||||
return $var;
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
if ($condition === null) {
|
||||
$var = 1;
|
||||
return $var;
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Variable::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Variable $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! ($parent instanceof Assign && $parent->var === $node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($parent->expr instanceof ArrayDimFetch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$expression = $parent->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $expression instanceof Expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->isUsedAsArraykeyOrInsideIfCondition($expression, $node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->hasPropertyInExpr($parent->expr)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->shouldSkipReAssign($expression, $parent)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$usageStmt = $this->findUsageStmt($expression, $node);
|
||||
if (! $usageStmt instanceof Node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->isInsideLoopStmts($usageStmt)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->addNodeBeforeNode($expression, $usageStmt);
|
||||
$this->removeNode($expression);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function isUsedAsArraykeyOrInsideIfCondition(Expression $expression, Variable $variable): bool
|
||||
{
|
||||
$parentExpression = $expression->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($this->isUsedAsArrayKey($parentExpression, $variable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->isInsideCondition($expression);
|
||||
}
|
||||
|
||||
private function hasPropertyInExpr(Expr $expr): bool
|
||||
{
|
||||
return (bool) $this->betterNodeFinder->findFirst(
|
||||
$expr,
|
||||
fn (Node $node): bool => $node instanceof PropertyFetch || $node instanceof StaticPropertyFetch
|
||||
);
|
||||
}
|
||||
|
||||
private function shouldSkipReAssign(Expression $expression, Assign $assign): bool
|
||||
{
|
||||
if ($this->hasReAssign($expression, $assign->var)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->hasReAssign($expression, $assign->expr);
|
||||
}
|
||||
|
||||
private function isInsideLoopStmts(Node $node): bool
|
||||
{
|
||||
$loopNode = $this->parentFinder->findByTypes(
|
||||
$node,
|
||||
[For_::class, While_::class, Foreach_::class, Do_::class]
|
||||
);
|
||||
return (bool) $loopNode;
|
||||
}
|
||||
|
||||
private function isUsedAsArrayKey(?Node $node, Variable $variable): bool
|
||||
{
|
||||
if (! $node instanceof Node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var ArrayDimFetch[] $arrayDimFetches */
|
||||
$arrayDimFetches = $this->betterNodeFinder->findInstanceOf($node, ArrayDimFetch::class);
|
||||
|
||||
foreach ($arrayDimFetches as $arrayDimFetch) {
|
||||
/** @var Node|null $dim */
|
||||
$dim = $arrayDimFetch->dim;
|
||||
if (! $dim instanceof Node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isFoundInKey = (bool) $this->betterNodeFinder->findFirst(
|
||||
$dim,
|
||||
fn (Node $node): bool => $this->nodeComparator->areNodesEqual($node, $variable)
|
||||
);
|
||||
if ($isFoundInKey) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function isInsideCondition(Expression $expression): bool
|
||||
{
|
||||
return (bool) $this->scopeAwareNodeFinder->findParentType(
|
||||
$expression,
|
||||
[If_::class, Else_::class, ElseIf_::class]
|
||||
);
|
||||
}
|
||||
|
||||
private function hasReAssign(Expression $expression, Expr $expr): bool
|
||||
{
|
||||
$next = $expression->getAttribute(AttributeKey::NEXT_NODE);
|
||||
$exprValues = $this->betterNodeFinder->find($expr, fn (Node $node): bool => $node instanceof Variable);
|
||||
|
||||
if ($exprValues === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while ($next) {
|
||||
foreach ($exprValues as $exprValue) {
|
||||
$isReAssign = (bool) $this->betterNodeFinder->findFirst($next, function (Node $node): bool {
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parent instanceof Assign) {
|
||||
return false;
|
||||
}
|
||||
$node = $this->mayBeArrayDimFetch($node);
|
||||
return (string) $this->getName($node) === (string) $this->getName($parent->var);
|
||||
});
|
||||
|
||||
if (! $isReAssign) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$next = $next->getAttribute(AttributeKey::NEXT_NODE);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function mayBeArrayDimFetch(Node $node): Node
|
||||
{
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parent instanceof ArrayDimFetch) {
|
||||
$node = $parent->var;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function findUsageStmt(Expression $expression, Variable $variable): Node | null
|
||||
{
|
||||
$nextVariable = $this->usageInNextStmtFinder->getUsageInNextStmts($expression, $variable);
|
||||
if (! $nextVariable instanceof Variable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $nextVariable->getAttribute(AttributeKey::CURRENT_STATEMENT);
|
||||
}
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\UsageFinder;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use PhpParser\Node\Stmt\InlineHTML;
|
||||
use PhpParser\Node\Stmt\Switch_;
|
||||
use PhpParser\Node\Stmt\TryCatch;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\DeadCode\SideEffect\SideEffectNodeDetector;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class UsageInNextStmtFinder
|
||||
{
|
||||
public function __construct(
|
||||
private SideEffectNodeDetector $sideEffectNodeDetector,
|
||||
private BetterNodeFinder $betterNodeFinder,
|
||||
private NodeNameResolver $nodeNameResolver
|
||||
) {
|
||||
}
|
||||
|
||||
public function getUsageInNextStmts(Expression $expression, Variable $variable): ?Variable
|
||||
{
|
||||
/** @var Node|null $next */
|
||||
$next = $expression->getAttribute(AttributeKey::NEXT_NODE);
|
||||
if (! $next instanceof Node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($next instanceof InlineHTML) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->hasCall($next)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$countFound = $this->getCountFound($next, $variable);
|
||||
if ($countFound === 0) {
|
||||
return null;
|
||||
}
|
||||
if ($countFound >= 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$nextVariable = $this->getSameVarName([$next], $variable);
|
||||
|
||||
if ($nextVariable instanceof Variable) {
|
||||
return $nextVariable;
|
||||
}
|
||||
|
||||
return $this->getSameVarNameInNexts($next, $variable);
|
||||
}
|
||||
|
||||
private function hasCall(Node $node): bool
|
||||
{
|
||||
return (bool) $this->betterNodeFinder->findFirst(
|
||||
$node,
|
||||
fn (Node $n): bool => $this->sideEffectNodeDetector->detectCallExpr($n)
|
||||
);
|
||||
}
|
||||
|
||||
private function getCountFound(Node $node, Variable $variable): int
|
||||
{
|
||||
$countFound = 0;
|
||||
while ($node) {
|
||||
$isFound = (bool) $this->getSameVarName([$node], $variable);
|
||||
|
||||
if ($isFound) {
|
||||
++$countFound;
|
||||
}
|
||||
|
||||
$countFound = $this->countWithElseIf($node, $variable, $countFound);
|
||||
$countFound = $this->countWithTryCatch($node, $variable, $countFound);
|
||||
$countFound = $this->countWithSwitchCase($node, $variable, $countFound);
|
||||
|
||||
/** @var Node|null $node */
|
||||
$node = $node->getAttribute(AttributeKey::NEXT_NODE);
|
||||
}
|
||||
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
private function getSameVarNameInNexts(Node $node, Variable $variable): ?Variable
|
||||
{
|
||||
while ($node) {
|
||||
$found = $this->getSameVarName([$node], $variable);
|
||||
|
||||
if ($found instanceof Variable) {
|
||||
return $found;
|
||||
}
|
||||
|
||||
/** @var Node|null $node */
|
||||
$node = $node->getAttribute(AttributeKey::NEXT_NODE);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function countWithElseIf(Node $node, Variable $variable, int $countFound): int
|
||||
{
|
||||
if (! $node instanceof If_) {
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
$isFoundElseIf = (bool) $this->getSameVarName($node->elseifs, $variable);
|
||||
$isFoundElse = (bool) $this->getSameVarName([$node->else], $variable);
|
||||
|
||||
if ($isFoundElseIf || $isFoundElse) {
|
||||
++$countFound;
|
||||
}
|
||||
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
private function countWithTryCatch(Node $node, Variable $variable, int $countFound): int
|
||||
{
|
||||
if (! $node instanceof TryCatch) {
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
$isFoundInCatch = (bool) $this->getSameVarName($node->catches, $variable);
|
||||
$isFoundInFinally = (bool) $this->getSameVarName([$node->finally], $variable);
|
||||
|
||||
if ($isFoundInCatch || $isFoundInFinally) {
|
||||
++$countFound;
|
||||
}
|
||||
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
private function countWithSwitchCase(Node $node, Variable $variable, int $countFound): int
|
||||
{
|
||||
if (! $node instanceof Switch_) {
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
$isFoundInCases = (bool) $this->getSameVarName($node->cases, $variable);
|
||||
|
||||
if ($isFoundInCases) {
|
||||
++$countFound;
|
||||
}
|
||||
|
||||
return $countFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Node|null> $multiNodes
|
||||
*/
|
||||
private function getSameVarName(array $multiNodes, Variable $variable): ?Variable
|
||||
{
|
||||
foreach ($multiNodes as $multiNode) {
|
||||
if ($multiNode === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var Variable|null $found */
|
||||
$found = $this->betterNodeFinder->findFirst($multiNode, function (Node $currentNode) use ($variable): bool {
|
||||
$currentNode = $this->unwrapArrayDimFetch($currentNode);
|
||||
if (! $currentNode instanceof Variable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->nodeNameResolver->isName(
|
||||
$currentNode,
|
||||
(string) $this->nodeNameResolver->getName($variable)
|
||||
);
|
||||
});
|
||||
|
||||
if ($found !== null) {
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function unwrapArrayDimFetch(Node $node): Node
|
||||
{
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
while ($parent instanceof ArrayDimFetch) {
|
||||
$node = $parent->var;
|
||||
$parent = $parent->getAttribute(AttributeKey::PARENT_NODE);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user