Merge pull request #12 from TomasVotruba/nette-php-generator-rector

[Rector] allow AbstractChangeMethodNameRector work with multiple objects and methods
This commit is contained in:
Tomáš Votruba 2017-08-24 12:17:21 +02:00 committed by GitHub
commit 6a68cd490b
7 changed files with 175 additions and 43 deletions

View File

@ -34,10 +34,8 @@ parameters:
skip:
Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer:
# class might not exist
- src/Rector/Contrib/Nette/RemoveConfiguratorConstantsRector.php
- src/Rector/Contrib/Nette/NetteObjectToSmartTraitRector.php
- src/Rector/Contrib/Nette/HtmlAddMethodRector.php
# classes might not exist
- */src/Rector/Contrib/Nette/*Rector.php
Symplify\CodingStandard\Sniffs\Debug\CommentedOutCodeSniff:
# examples of code to be found
- src/Rector/Contrib/Symfony/GetterToPropertyRector.php

View File

@ -10,13 +10,20 @@ use PhpParser\Node\Identifier;
abstract class AbstractChangeMethodNameRector extends AbstractRector
{
/**
* @var string|null
*/
private $activeType;
public function isCandidate(Node $node): bool
{
if ($this->isOnTypeCall($node, $this->getClassName())) {
$this->activeType = null;
if ($this->isOnTypeCall($node)) {
return true;
}
if ($this->isStaticCall($node)) {
if ($this->isStaticCallOnType($node)) {
return true;
}
@ -28,35 +35,26 @@ abstract class AbstractChangeMethodNameRector extends AbstractRector
*/
public function refactor(Node $node): ?Node
{
$node->name->name = $this->getNewMethodName();
$oldToNewMethods = $this->getPerClassOldToNewMethods()[$this->activeType];
foreach ($oldToNewMethods as $oldMethod => $newMethod) {
$methodName = $node->name->name;
if ($methodName !== $oldMethod) {
continue;
}
$node->name->name = $newMethod;
}
return $node;
}
abstract protected function getClassName(): string;
/**
* @return string[][] { class => [ oldMethod => newMethod ] }
*/
abstract protected function getPerClassOldToNewMethods(): array;
abstract protected function getOldMethodName(): string;
abstract protected function getNewMethodName(): string;
private function isStaticCall(Node $node): bool
{
if (! $node instanceof StaticCall) {
return false;
}
if (! $node->name instanceof Identifier) {
return false;
}
if ($node->class->toString() !== $this->getClassName()) {
return false;
}
return (string) $node->name === $this->getOldMethodName();
}
private function isOnTypeCall(Node $node, string $class): bool
private function isOnTypeCall(Node $node): bool
{
if (! $node instanceof MethodCall) {
return false;
@ -66,6 +64,51 @@ abstract class AbstractChangeMethodNameRector extends AbstractRector
return false;
}
return $node->var->getAttribute('type') === $class;
/** @var string $type */
$type = $node->var->getAttribute('type');
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;
}
$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->getPerClassOldToNewMethods());
}
}

View File

@ -17,18 +17,15 @@ final class HtmlAddMethodRector extends AbstractChangeMethodNameRector
return 2.4;
}
protected function getClassName(): string
/**
* @return string[][]
*/
protected function getPerClassOldToNewMethods(): array
{
return 'Nette\Utils\Html';
}
protected function getOldMethodName(): string
{
return 'add';
}
protected function getNewMethodName(): string
{
return 'addHtml';
return [
'Nette\Utils\Html' => [
'add' => 'addHtml',
],
];
}
}

View File

@ -0,0 +1,41 @@
<?php declare(strict_types=1);
namespace Rector\Rector\Contrib\Nette;
use Rector\Deprecation\SetNames;
use Rector\Rector\AbstractChangeMethodNameRector;
final class PhpGeneratorDocumentMethodRector extends AbstractChangeMethodNameRector
{
/**
* @var string[]
*/
private $commonMethods = [
'addDocument' => 'addComment',
'setDocuments' => 'setComment',
'getDocuments' => 'getComment',
];
public function getSetName(): string
{
return SetNames::NETTE;
}
public function sinceVersion(): float
{
return 2.4;
}
/**
* @return string[][]
*/
protected function getPerClassOldToNewMethods(): array
{
return [
'Nette\PhpGenerator\ClassType' => $this->commonMethods,
'Nette\PhpGenerator\Method' => $this->commonMethods,
'Nette\PhpGenerator\PhpFile' => $this->commonMethods,
'Nette\PhpGenerator\Property' => $this->commonMethods,
];
}
}

View File

@ -0,0 +1,14 @@
<?php declare (strict_types=1);
$classType = new Nette\PhpGenerator\ClassType;
$classType->addComment('...');
$method = new Nette\PhpGenerator\Method('someMethod');
$method->setComment('...');
$phpFile = new Nette\PhpGenerator\PhpFile;
$phpFile->getComment('...');
$property = new Nette\PhpGenerator\Property('someProperty');
$property->addComment('...');

View File

@ -0,0 +1,25 @@
<?php declare(strict_types=1);
namespace Rector\Tests\Rector\Contrib\Nette\PhpGeneratorDocumentMethod;
use Rector\Rector\Contrib\Nette\PhpGeneratorDocumentMethodRector;
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'
);
}
/**
* @return string[]
*/
protected function getRectorClasses(): array
{
return [PhpGeneratorDocumentMethodRector::class];
}
}

View File

@ -0,0 +1,14 @@
<?php declare (strict_types=1);
$classType = new Nette\PhpGenerator\ClassType;
$classType->addDocument('...');
$method = new Nette\PhpGenerator\Method('someMethod');
$method->setDocuments('...');
$phpFile = new Nette\PhpGenerator\PhpFile;
$phpFile->getDocuments('...');
$property = new Nette\PhpGenerator\Property('someProperty');
$property->addDocument('...');