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