Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@
"Rector\\VendorLocker\\": "packages/vendor-locker/src",
"Rector\\ZendToSymfony\\": "rules/zend-to-symfony/src",
"Rector\\Performance\\": "rules/performance/src",
"Rector\\Naming\\": "rules/naming/src"
"Rector\\Naming\\": "rules/naming/src",
"Rector\\Order\\": "rules/order/src"
}
},
"autoload-dev": {
Expand Down Expand Up @@ -210,7 +211,8 @@
"Rector\\Utils\\PHPStanStaticTypeMapperChecker\\": "utils/phpstan-static-type-mapper-checker/src",
"Rector\\ZendToSymfony\\Tests\\": "rules/zend-to-symfony/tests",
"Rector\\Performance\\Tests\\": "rules/performance/tests",
"Rector\\Naming\\Tests\\": "rules/naming/tests"
"Rector\\Naming\\Tests\\": "rules/naming/tests",
"Rector\\Order\\Tests\\": "rules/order/tests"
},
"classmap": [
"rules/cakephp/tests/Rector/Name/ImplicitShortClassNameUseStatementRector/Source",
Expand Down
2 changes: 2 additions & 0 deletions config/set/order/order.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
services:
Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector: null
35 changes: 34 additions & 1 deletion docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# All 511 Rectors Overview
# All 512 Rectors Overview

- [Projects](#projects)
- [General](#general)
Expand Down Expand Up @@ -30,6 +30,7 @@
- [Nette](#nette)
- [NetteTesterToPHPUnit](#nettetestertophpunit)
- [NetteToSymfony](#nettetosymfony)
- [Order](#order)
- [Oxid](#oxid)
- [PHPOffice](#phpoffice)
- [PHPStan](#phpstan)
Expand Down Expand Up @@ -5161,6 +5162,38 @@ Adds %% to placeholder name of trans() method if missing

<br>

## Order

### `OrderPrivateMethodsByUseRector`

- class: [`Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector`](/../master/rules/order/src/Rector/Class_/OrderPrivateMethodsByUseRector.php)
- [test fixtures](/../master/rules/order/tests/Rector/Class_/OrderPrivateMethodsByUseRector/Fixture)

Order private methods in order of their use

```diff
class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}

- private function call2()
+ private function call1()
{
}

- private function call1()
+ private function call2()
{
}
}
```

<br>

## Oxid

### `OxidReplaceBackwardsCompatabilityClassRector`
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,4 @@ parameters:


- '#Use explicit return value over magic &reference#'
- '#Method Rector\\Order\\Rector\\Class_\\OrderPrivateMethodsByUseRector\:\:createOldToNewKeys\(\) should return array<int\> but returns array\|false#'
172 changes: 172 additions & 0 deletions rules/order/src/Rector/Class_/OrderPrivateMethodsByUseRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php

declare(strict_types=1);

namespace Rector\Order\Rector\Class_;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;

/**
* @see \Rector\Order\Tests\Rector\Class_\OrderPrivateMethodsByUseRector\OrderPrivateMethodsByUseRectorTest
*/
final class OrderPrivateMethodsByUseRector extends AbstractRector
{
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Order private methods in order of their use', [
new CodeSample(
<<<'PHP'
class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}

private function call2()
{
}

private function call1()
{
}
}
PHP
,
<<<'PHP'
class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}

private function call1()
{
}

private function call2()
{
}
}
PHP

),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
$desiredClassMethodOrder = $this->getLocalMethodCallOrder($node);

$privateClassMethods = [];
foreach ($node->stmts as $key => $classStmt) {
if (! $classStmt instanceof ClassMethod) {
continue;
}

if (! $classStmt->isPrivate()) {
continue;
}

/** @var string $classMethodName */
$classMethodName = $this->getName($classStmt);
$privateClassMethods[$key] = $classMethodName;
}

//$privateClassMethodsNames = array_keys($privateClassMethods);

// order is correct, nothing to change
if ($privateClassMethods === $desiredClassMethodOrder) {
return null;
}

// different private method count, one of them is dead probably
if (count($desiredClassMethodOrder) !== count($desiredClassMethodOrder)) {
return null;
}

$oldToNewKeys = $this->createOldToNewKeys($desiredClassMethodOrder, $privateClassMethods);

foreach ($node->stmts as $key => $stmt) {
if (! isset($oldToNewKeys[$key])) {
continue;
}

// reodre here
$newKey = $oldToNewKeys[$key];
$node->stmts[$newKey] = $stmt;
}

return $node;
}

/**
* @return string[]
*/
private function getLocalMethodCallOrder(Class_ $class): array
{
$localMethodCallInOrder = [];

$this->traverseNodesWithCallable($class->getMethods(), function (Node $node) use (&$localMethodCallInOrder) {
if (! $node instanceof MethodCall) {
return null;
}

if (! $this->isVariableName($node->var, 'this')) {
return null;
}

$methodName = $this->getName($node->name);
if ($methodName === null) {
return null;
}

$localMethodCallInOrder[] = $methodName;

return null;
});

return array_unique($localMethodCallInOrder);
}

/**
* @param string[] $desiredClassMethodOrder
* @return int[]
*/
private function createOldToNewKeys(array $desiredClassMethodOrder, array $privateClassMethods): array
{
$newKeys = [];
foreach ($desiredClassMethodOrder as $desiredClassMethod) {
foreach ($privateClassMethods as $currentKey => $classMethodName) {
if ($classMethodName === $desiredClassMethod) {
$newKeys[] = $currentKey;
}
}
}

$oldKeys = array_values($newKeys);
sort($oldKeys);

return array_combine($oldKeys, $newKeys);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Rector\Order\Tests\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;

class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}

private function call2()
{
}

private function call1()
{
}
}

?>
-----
<?php

namespace Rector\Order\Tests\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;

class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}

private function call1()
{
}
private function call2()
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Rector\Order\Tests\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;

class MultiCall
{
public function run()
{
$this->call3();
}

private function call2()
{
}

private function call1()
{
}

private function call3()
{
$this->call1();
$this->call2();
}
}

?>
-----
<?php

namespace Rector\Order\Tests\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;

class MultiCall
{
public function run()
{
$this->call3();
}

private function call3()
{
$this->call1();
$this->call2();
}
private function call1()
{
}
private function call2()
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Rector\Order\Tests\Rector\Class_\OrderPrivateMethodsByUseRector;

use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector;

final class OrderPrivateMethodsByUseRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}

public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

protected function getRectorClass(): string
{
return OrderPrivateMethodsByUseRector::class;
}
}