add MethodNameReplacerRector

This commit is contained in:
TomasVotruba 2017-10-06 13:57:21 +02:00
parent 63c0669d7e
commit 503fe63a63
15 changed files with 188 additions and 69 deletions

View File

@ -1,20 +0,0 @@
<?php declare(strict_types=1);
namespace Rector\Rector\Contrib\Nette\Utils;
use Rector\Rector\AbstractChangeMethodNameRector;
final class HtmlAddMethodRector extends AbstractChangeMethodNameRector
{
/**
* @return string[][]
*/
protected function getPerClassOldToNewMethods(): array
{
return [
'Nette\Utils\Html' => [
'add' => 'addHtml',
],
];
}
}

View File

@ -0,0 +1,136 @@
<?php declare(strict_types=1);
namespace Rector\Rector\Dynamic;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use Rector\Node\Attribute;
use Rector\Rector\AbstractRector;
final class MethodNameReplacerRector extends AbstractRector
{
/**
* class => [
* oldMethod => newMethod
* ]
*
* @var string[][]
*/
private $perClassOldToNewMethods = [];
/**
* @param string[][]
*/
public function __construct(array $perClassOldToNewMethods)
{
$this->perClassOldToNewMethods = $perClassOldToNewMethods;
}
/**
* @var string|null
*/
private $activeType;
public function isCandidate(Node $node): bool
{
$this->activeType = null;
if ($this->isOnTypeCall($node)) {
return true;
}
if ($this->isStaticCallOnType($node)) {
return true;
}
return false;
}
/**
* @param StaticCall|MethodCall $node
*/
public function refactor(Node $node): ?Node
{
$oldToNewMethods = $this->perClassOldToNewMethods[$this->activeType];
foreach ($oldToNewMethods as $oldMethod => $newMethod) {
$methodName = $node->name->name;
if ($methodName !== $oldMethod) {
continue;
}
$node->name->name = $newMethod;
}
return $node;
}
private function isOnTypeCall(Node $node): bool
{
if (! $node instanceof MethodCall) {
return false;
}
if (! $node->var instanceof Variable) {
return false;
}
/** @var string|null $type */
$type = $node->var->getAttribute(Attribute::TYPE);
if ($type === null) {
return false;
}
if (! $this->isTypeRelevant($type)) {
return false;
}
$this->activeType = $type;
return true;
}
private function isStaticCallOnType(Node $node): bool
{
if (! $node instanceof StaticCall) {
return false;
}
if (! $node->name instanceof Identifier) {
return false;
}
if (! $node->class instanceof Name) {
return false;
}
$type = $node->class->toString();
if (! $this->isTypeRelevant($type)) {
return false;
}
$this->activeType = $type;
return true;
}
private function isTypeRelevant(string $type): bool
{
$classes = $this->getClasses();
return in_array($type, $classes, true);
}
/**
* @return string[]
*/
private function getClasses(): array
{
return array_keys($this->perClassOldToNewMethods);
}
}

View File

@ -1,9 +1,12 @@
rectors:
- Rector\Rector\Contrib\Nette\Form\FormNegativeRulesRector
- Rector\Rector\Contrib\Nette\Form\FormCallbackRector
- Rector\Rector\Contrib\Nette\Form\FormSetRequiredRector
- Rector\Rector\Contrib\Nette\Utils\HtmlAddMethodRector
- Rector\Rector\Contrib\Nette\Utils\NetteObjectToSmartTraitRector
- Rector\Rector\Contrib\Nette\PhpGenerator\PhpGeneratorDocumentMethodRector
- Rector\Rector\Contrib\Nette\Utils\MagicMethodRector
- Rector\Rector\Contrib\Nette\DI\SetEntityToStatementRector
Rector\Rector\Contrib\Nette\Form\FormNegativeRulesRector: ~
Rector\Rector\Contrib\Nette\Form\FormCallbackRector: ~
Rector\Rector\Contrib\Nette\Form\FormSetRequiredRector: ~
Rector\Rector\Contrib\Nette\Utils\NetteObjectToSmartTraitRector: ~
Rector\Rector\Contrib\Nette\PhpGenerator\PhpGeneratorDocumentMethodRector: ~
Rector\Rector\Contrib\Nette\Utils\MagicMethodRector: ~
Rector\Rector\Contrib\Nette\DI\SetEntityToStatementRector: ~
Rector\Rector\Dynamic\MethodNameReplacerRector:
'Nette\Utils\Html':
'add': 'addHtml'

View File

@ -1,41 +0,0 @@
<?php declare(strict_types=1);
namespace Rector\Tests\Rector\Contrib\Nette\Utils\HtmlAddMethodRector;
use Rector\Rector\Contrib\Nette\Utils\HtmlAddMethodRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class Test extends AbstractRectorTestCase
{
public function test(): void
{
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/Wrong/wrong.php.inc',
__DIR__ . '/Correct/correct.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/Wrong/wrong2.php.inc',
__DIR__ . '/Correct/correct2.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/Wrong/wrong3.php.inc',
__DIR__ . '/Correct/correct3.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/Wrong/wrong4.php.inc',
__DIR__ . '/Correct/correct4.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/Wrong/SomeClass.php',
__DIR__ . '/Correct/SomeClass.php'
);
}
/**
* @return string[]
*/
protected function getRectorClasses(): array
{
return [HtmlAddMethodRector::class];
}
}

View File

@ -0,0 +1,41 @@
<?php declare(strict_types=1);
namespace Rector\Tests\Rector\Dynamic\MethodNameReplacerRector;
use Rector\Rector\Dynamic\MethodNameReplacerRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class Test extends AbstractRectorTestCase
{
public function test(): void
{
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/wrong/wrong.php.inc',
__DIR__ . '/correct/correct.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/wrong/wrong2.php.inc',
__DIR__ . '/correct/correct2.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/wrong/wrong3.php.inc',
__DIR__ . '/correct/correct3.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/wrong/wrong4.php.inc',
__DIR__ . '/correct/correct4.php.inc'
);
$this->doTestFileMatchesExpectedContent(
__DIR__ . '/wrong/SomeClass.php',
__DIR__ . '/correct/SomeClass.php'
);
}
/**
* @return string[]
*/
protected function getRectorClasses(): array
{
return [MethodNameReplacerRector::class];
}
}