-
Notifications
You must be signed in to change notification settings - Fork 65
Expand file tree
/
Copy pathUseSpecificWillMethodRector.php
More file actions
141 lines (120 loc) · 3.94 KB
/
UseSpecificWillMethodRector.php
File metadata and controls
141 lines (120 loc) · 3.94 KB
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
132
133
134
135
136
137
138
139
140
141
<?php
declare(strict_types=1);
namespace Rector\PHPUnit\CodeQuality\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://github.com/symfony/symfony/pull/29685/files
* @see \Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\UseSpecificWillMethodRector\UseSpecificWillMethodRectorTest
*/
final class UseSpecificWillMethodRector extends AbstractRector
{
/**
* @var array<string, string>
*/
private const array NESTED_METHOD_TO_RENAME_MAP = [
'returnArgument' => 'willReturnArgument',
'returnCallback' => 'willReturnCallback',
'returnSelf' => 'willReturnSelf',
'returnValue' => 'willReturn',
'returnValueMap' => 'willReturnMap',
'onConsecutiveCalls' => 'willReturnOnConsecutiveCalls',
'throwException' => 'willThrowException',
];
public function __construct(
private readonly TestsNodeAnalyzer $testsNodeAnalyzer
) {
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Changes $mock->will() call to more specific method',
[
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass extends PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->createMock('SomeClass');
$translator->expects($this->any())
->method('trans')
->will($this->returnValue('translated max {{ max }}!'));
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass extends PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->createMock('SomeClass');
$translator->expects($this->any())
->method('trans')
->willReturnValue('translated max {{ max }}!');
}
}
CODE_SAMPLE
),
]
);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [MethodCall::class, StaticCall::class];
}
/**
* @param MethodCall|StaticCall $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->testsNodeAnalyzer->isInTestClass($node)) {
return null;
}
// we cannot check caller types, as on old PHPUnit version, this the magic ->method() call result to a mixed type
if (! $this->isName($node->name, 'will')) {
return null;
}
if ($node->isFirstClassCallable()) {
return null;
}
$firstArg = $node->getArgs()[0];
// special case for new map
if ($firstArg->value instanceof New_) {
return $this->refactorNew($firstArg->value, $node);
}
if (! $firstArg->value instanceof MethodCall && ! $firstArg->value instanceof StaticCall) {
return null;
}
$nestedMethodCall = $firstArg->value;
foreach (self::NESTED_METHOD_TO_RENAME_MAP as $oldMethodName => $newParentMethodName) {
if (! $this->isName($nestedMethodCall->name, $oldMethodName)) {
continue;
}
$node->name = new Identifier($newParentMethodName);
$node->args = $nestedMethodCall->args;
return $node;
}
return null;
}
private function refactorNew(New_ $new, StaticCall|MethodCall $call): null|MethodCall|StaticCall
{
if (! $this->isName($new->class, 'PHPUnit\Framework\MockObject\Stub\ReturnValueMap')) {
return null;
}
$call->name = new Identifier('willReturnMap');
$call->args = $new->args;
return $call;
}
}