forked from rectorphp/rector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRemoveFuncCallRector.php
131 lines (113 loc) · 3.58 KB
/
RemoveFuncCallRector.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?php
declare(strict_types=1);
namespace Rector\Removing\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeRemoval\BreakingRemovalGuard;
use Rector\Removing\ValueObject\RemoveFuncCall;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Webmozart\Assert\Assert;
/**
* @see \Rector\Tests\Removing\Rector\FuncCall\RemoveFuncCallRector\RemoveFuncCallRectorTest
*/
final class RemoveFuncCallRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const REMOVE_FUNC_CALLS = 'remove_func_calls';
/**
* @var RemoveFuncCall[]
*/
private $removeFuncCalls = [];
/**
* @var BreakingRemovalGuard
*/
private $breakingRemovalGuard;
public function __construct(BreakingRemovalGuard $breakingRemovalGuard)
{
$this->breakingRemovalGuard = $breakingRemovalGuard;
}
public function getRuleDefinition(): RuleDefinition
{
$configuration = [
self::REMOVE_FUNC_CALLS => [
new RemoveFuncCall('ini_get', [
1 => ['y2k_compliance'],
]),
],
];
return new RuleDefinition('Remove ini_get by configuration', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
ini_get('y2k_compliance');
ini_get('keep_me');
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
ini_get('keep_me');
CODE_SAMPLE
,
$configuration
), ]
);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [FuncCall::class];
}
/**
* @param FuncCall $node
*/
public function refactor(Node $node): ?Node
{
foreach ($this->removeFuncCalls as $removeFuncCall) {
if (! $this->isName($node, $removeFuncCall->getFuncCall())) {
continue;
}
if ($removeFuncCall->getArgumentPositionAndValues() === []) {
$this->removeNode($node);
return null;
}
$this->refactorFuncCallsWithPositions($node, $removeFuncCall);
}
return null;
}
/**
* @param array<string, RemoveFuncCall[]> $configuration
*/
public function configure(array $configuration): void
{
$removeFuncCalls = $configuration[self::REMOVE_FUNC_CALLS] ?? [];
Assert::allIsInstanceOf($removeFuncCalls, RemoveFuncCall::class);
$this->removeFuncCalls = $removeFuncCalls;
}
private function refactorFuncCallsWithPositions(FuncCall $funcCall, RemoveFuncCall $removeFuncCall): void
{
foreach ($removeFuncCall->getArgumentPositionAndValues() as $argumentPosition => $values) {
if (! $this->isArgumentPositionValueMatch($funcCall, $argumentPosition, $values)) {
continue;
}
if ($this->breakingRemovalGuard->isLegalNodeRemoval($funcCall)) {
$this->removeNode($funcCall);
}
}
}
/**
* @param mixed[] $values
*/
private function isArgumentPositionValueMatch(FuncCall $funcCall, int $argumentPosition, array $values): bool
{
if (! isset($funcCall->args[$argumentPosition])) {
return false;
}
return $this->valueResolver->isValues($funcCall->args[$argumentPosition]->value, $values);
}
}