Make PropertyToMethodRector work with getter with arg

This commit is contained in:
Tomas Votruba 2018-09-20 00:45:34 +02:00
parent 065ca5cefe
commit bff2dfb805
9 changed files with 173 additions and 43 deletions

View File

@ -0,0 +1,4 @@
# source: https://book.cakephp.org/3.0/en/appendices/3-4-migration-guide.html
services:
# ...

View File

@ -0,0 +1,36 @@
# source: https://book.cakephp.org/3.0/en/appendices/3-5-migration-guide.html
services:
Rector\Rector\Property\PropertyToMethodRector:
$perClassPropertyToMethods:
'Cake\Network\Request':
'params':
'get':
method: 'getAttribute'
arguments:
- 'params'
'data':
'get': 'getData'
'query':
'get': 'getQueryParams'
'cookies':
'get': 'getCookie'
'base':
'get':
method: 'getAttribute'
arguments:
- 'base'
'webroot':
'get':
method: 'getAttribute'
arguments:
- 'webroot'
Rector\Rector\Class_\ClassReplacerRector:
$oldToNewClasses:
'Cake\Http\Client\CookieCollection ': 'Cake\Http\Cookie\CookieCollection'
Rector\Rector\Property\PropertyNameReplacerRector:
$perClassOldToNewProperties:
'Cake\Network\Request':
'_session': 'session'

View File

@ -71,11 +71,11 @@ final class MethodCallNodeFactory
* @param mixed[] $arguments
*/
public function createWithVariableMethodNameAndArguments(
Variable $variableNode,
Expr $exprNode,
string $method,
array $arguments
): MethodCall {
$methodCall = $this->createWithVariableAndMethodName($variableNode, $method);
$methodCall = $this->createWithVariableAndMethodName($exprNode, $method);
$methodCall->args = $this->nodeFactory->createArgs($arguments);
return $methodCall;

View File

@ -21,11 +21,6 @@ final class PropertyToMethodRector extends AbstractRector
*/
private $perClassPropertyToMethods = [];
/**
* @var string
*/
private $activeMethod;
/**
* @var PropertyFetchAnalyzer
*/
@ -73,7 +68,32 @@ CODE_SAMPLE
[
'$perClassPropertyToMethods' => [
'SomeObject' => [
'property' => ['getProperty', 'setProperty'],
'property' => [
'get' => 'getProperty',
'set' => 'setProperty',
],
],
],
]
),
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
$result = $object->property;
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$result = $object->getProperty('someArg');
CODE_SAMPLE
,
[
'$perClassPropertyToMethods' => [
'SomeObject' => [
'property' => [
'get' => [
'method' => 'getConfig',
'arguments' => ['someArg'],
],
],
],
],
]
@ -94,45 +114,80 @@ CODE_SAMPLE
*/
public function refactor(Node $assignNode): ?Node
{
// setter
if ($assignNode->var instanceof PropertyFetch) {
if ($this->processPropertyFetchCandidate($assignNode->var, 'set') === false) {
return null;
}
return $this->processSetter($assignNode);
}
// getter
if ($assignNode->expr instanceof PropertyFetch) {
if ($this->processPropertyFetchCandidate($assignNode->expr, 'get') === false) {
return null;
}
}
// setter
if ($assignNode->var instanceof PropertyFetch) {
$args = $this->nodeFactory->createArgs([$assignNode->expr]);
/** @var Variable $variable */
$variable = $assignNode->var->var;
return $this->methodCallNodeFactory->createWithVariableMethodNameAndArguments(
$variable,
$this->activeMethod,
$args
);
}
// getter
if ($assignNode->expr instanceof PropertyFetch) {
$assignNode->expr = $this->methodCallNodeFactory->createWithVariableAndMethodName(
$assignNode->expr->var,
$this->activeMethod
);
return $this->processGetter($assignNode);
}
return null;
}
private function processPropertyFetchCandidate(PropertyFetch $propertyFetchNode, string $type): bool
private function processSetter(Assign $assignNode): ?Node
{
/** @var PropertyFetch $propertyFetchNode */
$propertyFetchNode = $assignNode->var;
$newMethodMatch = $this->matchPropertyFetchCandidate($propertyFetchNode);
if ($newMethodMatch === null) {
return null;
}
$args = $this->nodeFactory->createArgs([$assignNode->expr]);
/** @var Variable $variable */
$variable = $propertyFetchNode->var;
return $this->methodCallNodeFactory->createWithVariableMethodNameAndArguments(
$variable,
$newMethodMatch['set'],
$args
);
}
private function processGetter(Assign $assignNode): ?Node
{
/** @var PropertyFetch $propertyFetchNode */
$propertyFetchNode = $assignNode->expr;
$newMethodMatch = $this->matchPropertyFetchCandidate($propertyFetchNode);
if ($newMethodMatch === null) {
return null;
}
// simple method name
if (is_string($newMethodMatch['get'])) {
$assignNode->expr = $this->methodCallNodeFactory->createWithVariableAndMethodName(
$propertyFetchNode->var,
$newMethodMatch['get']
);
return $assignNode;
// method with argument
}
if (is_array($newMethodMatch['get'])) {
$args = $this->nodeFactory->createArgs($newMethodMatch['get']['arguments']);
$assignNode->expr = $this->methodCallNodeFactory->createWithVariableMethodNameAndArguments(
$propertyFetchNode->var,
$newMethodMatch['get']['method'],
$args
);
return $assignNode;
}
return $assignNode;
}
/**
* @return mixed[]|null
*/
private function matchPropertyFetchCandidate(PropertyFetch $propertyFetchNode): ?array
{
foreach ($this->perClassPropertyToMethods as $class => $propertyToMethods) {
$properties = array_keys($propertyToMethods);
@ -141,12 +196,10 @@ CODE_SAMPLE
/** @var Identifier $identifierNode */
$identifierNode = $propertyFetchNode->name;
$this->activeMethod = $propertyToMethods[$identifierNode->toString()][$type];
return true;
return $propertyToMethods[$identifierNode->toString()]; //[$type];
}
}
return false;
return null;
}
}

View File

@ -5,6 +5,9 @@ namespace Rector\Tests\Rector\Property\PropertyNameReplacerRector;
use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
/**
* @covers \Rector\Rector\Property\PropertyNameReplacerRector
*/
final class PropertyNameReplacerRectorTest extends AbstractRectorTestCase
{
/**

View File

@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace Rector\Tests\Rector\Property\PropertyToMethodRector\Wrong;
final class SomeClassWithParameters
{
private $parameter;
public function run()
{
$value = $this->getConfig('parameter');
}
}

View File

@ -21,6 +21,7 @@ final class PropertyToMethodRectorTest extends AbstractRectorTestCase
public function provideWrongToFixedFiles(): Iterator
{
yield [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc'];
yield [__DIR__ . '/Wrong/wrong2.php.inc', __DIR__ . '/Correct/correct2.php.inc'];
}
protected function provideConfig(): string

View File

@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace Rector\Tests\Rector\Property\PropertyToMethodRector\Wrong;
final class SomeClassWithParameters
{
private $parameter;
public function run()
{
$value = $this->parameter;
}
}

View File

@ -5,3 +5,10 @@ services:
'locale':
'get': 'getLocale'
'set': 'setLocale'
'Rector\Tests\Rector\Property\PropertyToMethodRector\Wrong\SomeClassWithParameters':
'parameter':
'get':
method: 'getConfig'
arguments:
- 'parameter'