rector/rules/generic/src/Rector/ClassMethod/ArgumentRemoverRector.php

164 lines
4.7 KiB
PHP
Raw Normal View History

2019-10-13 05:59:52 +00:00
<?php
declare(strict_types=1);
namespace Rector\Generic\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
2020-07-29 23:39:41 +00:00
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
2019-09-03 09:11:45 +00:00
/**
* @see \Rector\Generic\Tests\Rector\ClassMethod\ArgumentRemoverRector\ArgumentRemoverRectorTest
2019-09-03 09:11:45 +00:00
*/
2020-07-29 23:39:41 +00:00
final class ArgumentRemoverRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
2020-07-29 23:39:41 +00:00
* @var string
*/
2020-07-29 23:39:41 +00:00
public const POSITIONS_BY_METHOD_NAME_BY_CLASS_TYPE = '$positionsByMethodNameByClassType';
/**
2020-07-29 23:39:41 +00:00
* @var mixed[]
*/
2020-07-29 23:39:41 +00:00
private $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(
2019-09-18 06:14:35 +00:00
<<<'PHP'
$someObject = new SomeClass;
$someObject->someMethod(true);
2019-09-18 06:14:35 +00:00
PHP
,
2019-09-18 06:14:35 +00:00
<<<'PHP'
$someObject = new SomeClass;
$someObject->someMethod();'
2019-09-18 06:14:35 +00:00
PHP
2018-08-01 19:52:44 +00:00
,
[
self::POSITIONS_BY_METHOD_NAME_BY_CLASS_TYPE => [
'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) {
2019-09-04 12:10:29 +00:00
if (! $this->isMethodStaticCallOrClassMethodObjectType($node, $type)) {
continue;
}
foreach ($positionByMethodName as $methodName => $positions) {
if (! $this->isName($node->name, $methodName)) {
continue;
}
foreach ($positions as $position => $match) {
$this->processPosition($node, $position, $match);
}
}
}
return $node;
}
2020-07-29 23:39:41 +00:00
public function configure(array $configuration): void
{
$this->positionsByMethodNameByClassType = $configuration[self::POSITIONS_BY_METHOD_NAME_BY_CLASS_TYPE] ?? [];
}
/**
* @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]);
}
}
}
/**
* @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)) {
2020-03-19 11:23:00 +00:00
$this->removeArg($node, $position);
}
return;
}
if ($node instanceof ClassMethod) {
if (isset($node->params[$position]) && $this->isName($node->params[$position], $name)) {
2020-03-19 11:23:00 +00:00
$this->removeParam($node, $position);
}
return;
}
}
/**
* @param mixed[] $values
*/
private function isArgumentValueMatch(Arg $arg, array $values): bool
{
$nodeValue = $this->getValue($arg->value);
return in_array($nodeValue, $values, true);
}
}