rector/src/Rector/Argument/ArgumentRemoverRector.php

154 lines
4.2 KiB
PHP
Raw Normal View History

<?php declare(strict_types=1);
namespace Rector\Rector\Argument;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Rector\AbstractRector;
2018-08-01 19:52:44 +00:00
use Rector\RectorDefinition\ConfiguredCodeSample;
use Rector\RectorDefinition\RectorDefinition;
final class ArgumentRemoverRector extends AbstractRector
{
/**
* @var mixed[]
*/
private $positionsByMethodNameByClassType = [];
/**
* @param mixed[] $positionsByMethodNameByClassType
*/
public function __construct(array $positionsByMethodNameByClassType = [])
{
$this->positionsByMethodNameByClassType = $positionsByMethodNameByClassType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
'Removes defined arguments in defined methods and their calls.',
[
2018-08-01 19:52:44 +00:00
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
$someObject = new SomeClass;
$someObject->someMethod(true);
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$someObject = new SomeClass;
$someObject->someMethod();'
CODE_SAMPLE
2018-08-01 19:52:44 +00:00
,
[
'ExampleClass' => [
'someMethod' => [
0 => [
'value' => 'true',
],
],
2018-08-01 19:52:44 +00:00
],
]
),
]
);
}
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
{
foreach ($this->positionsByMethodNameByClassType as $type => $positionByMethodName) {
if (! $this->isType($node, $type)) {
continue;
}
foreach ($positionByMethodName as $methodName => $positions) {
if (! $this->isName($node, $methodName)) {
continue;
}
foreach ($positions as $position => $match) {
$this->processPosition($node, $position, $match);
}
}
}
return $node;
}
/**
* @param ClassMethod|StaticCall|MethodCall $node
* @param mixed[]|null $match
*/
private function processPosition(Node $node, int $position, ?array $match): void
{
if ($match === null) {
if ($node instanceof MethodCall || $node instanceof StaticCall) {
unset($node->args[$position]);
2018-12-16 23:00:16 +00:00
} else {
unset($node->params[$position]);
}
}
if ($match) {
if (isset($match['name'])) {
$this->removeByName($node, $position, $match['name']);
return;
}
// only argument specific value can be removed
if ($node instanceof ClassMethod || ! isset($node->args[$position])) {
return;
}
if ($this->isArgumentValueMatch($node->args[$position], $match)) {
unset($node->args[$position]);
}
}
}
2018-07-17 20:52:46 +00:00
/**
* @param mixed[] $values
2018-07-17 20:52:46 +00:00
*/
2019-02-22 17:25:31 +00:00
private function isArgumentValueMatch(Arg $arg, array $values): bool
{
2019-02-22 17:25:31 +00:00
$nodeValue = $this->getValue($arg->value);
2018-10-22 02:02:53 +00:00
return in_array($nodeValue, $values, true);
}
/**
* @param ClassMethod|StaticCall|MethodCall $node
*/
private function removeByName(Node $node, int $position, string $name): void
{
if ($node instanceof MethodCall || $node instanceof StaticCall) {
if (isset($node->args[$position]) && $this->isName($node->args[$position], $name)) {
unset($node->args[$position]);
}
return;
}
if ($node instanceof ClassMethod) {
if (isset($node->params[$position]) && $this->isName($node->params[$position], $name)) {
unset($node->params[$position]);
}
return;
}
}
}