rector/src/Rector/Argument/ArgumentAdderRector.php

146 lines
4.1 KiB
PHP
Raw Normal View History

<?php declare(strict_types=1);
namespace Rector\Rector\Argument;
use PhpParser\BuilderHelpers;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Configuration\Rector\ArgumentAdderRecipe;
2018-08-01 19:52:44 +00:00
use Rector\RectorDefinition\ConfiguredCodeSample;
use Rector\RectorDefinition\RectorDefinition;
final class ArgumentAdderRector extends AbstractArgumentRector
{
/**
* @var ArgumentAdderRecipe[]
*/
2018-08-01 19:52:44 +00:00
private $recipes = [];
/**
* @param mixed[] $argumentChangesByMethodAndType
*/
public function __construct(array $argumentChangesByMethodAndType)
{
foreach ($argumentChangesByMethodAndType as $configurationArray) {
2018-08-01 19:52:44 +00:00
$this->recipes[] = ArgumentAdderRecipe::createFromArray($configurationArray);
}
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
'This Rector adds new default arguments in calls of defined methods and class types.',
[
2018-08-01 19:52:44 +00:00
new ConfiguredCodeSample(
2018-05-04 12:52:17 +00:00
<<<'CODE_SAMPLE'
$someObject = new SomeClass;
$someObject->someMethod();
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$someObject = new SomeClass;
$someObject->someMethod(true);
CODE_SAMPLE
2018-08-01 19:52:44 +00:00
,
[
'$argumentChangesByMethodAndType' => [
'class' => 'SomeClass',
2018-08-01 19:52:44 +00:00
'method' => 'someMethod',
'position' => 0,
'default_value' => 'true',
],
]
),
2018-08-01 19:52:44 +00:00
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
class MyCustomClass extends SomeClass
{
public function someMethod()
{
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class MyCustomClass extends SomeClass
{
public function someMethod($value = true)
{
}
}
2018-05-04 12:52:17 +00:00
CODE_SAMPLE
2018-08-01 19:52:44 +00:00
,
[
'$argumentChangesByMethodAndType' => [
'class' => 'SomeClass',
2018-08-01 19:52:44 +00:00
'method' => 'someMethod',
'position' => 0,
'default_value' => 'true',
],
]
),
]
);
}
2018-08-14 22:12:41 +00:00
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [MethodCall::class, StaticCall::class, ClassMethod::class];
}
/**
* @param MethodCall|StaticCall|ClassMethod $node
*/
2018-08-14 22:12:41 +00:00
public function refactor(Node $node): ?Node
{
2018-08-14 22:12:41 +00:00
$matchedRecipes = $this->matchArgumentChanges($node);
2018-10-15 13:55:01 +00:00
if (! $matchedRecipes) {
return null;
}
2018-08-14 22:12:41 +00:00
$argumentsOrParameters = $this->getNodeArgumentsOrParameters($node);
2018-08-14 22:12:41 +00:00
$argumentsOrParameters = $this->processArgumentNodes($argumentsOrParameters, $matchedRecipes);
$this->setNodeArgumentsOrParameters($node, $argumentsOrParameters);
return $node;
}
/**
* @return ArgumentAdderRecipe[]
*/
private function matchArgumentChanges(Node $node): array
{
$argumentReplacerRecipes = [];
2018-08-01 19:52:44 +00:00
foreach ($this->recipes as $argumentReplacerRecipe) {
if ($this->isNodeToRecipeMatch($node, $argumentReplacerRecipe)) {
$argumentReplacerRecipes[] = $argumentReplacerRecipe;
}
}
return $argumentReplacerRecipes;
}
/**
* @param mixed[] $argumentNodes
2018-08-14 22:12:41 +00:00
* @param ArgumentAdderRecipe[] $argumentAdderRecipes
* @return mixed[]
*/
2018-08-14 22:12:41 +00:00
private function processArgumentNodes(array $argumentNodes, array $argumentAdderRecipes): array
{
2018-08-14 22:12:41 +00:00
foreach ($argumentAdderRecipes as $argumentReplacerRecipe) {
$position = $argumentReplacerRecipe->getPosition();
$argumentNodes[$position] = BuilderHelpers::normalizeValue($argumentReplacerRecipe->getDefaultValue());
}
return $argumentNodes;
}
}