Skip to content

Commit a46cf1e

Browse files
author
Michael Petri
committed
Added rector rule
1 parent 0d057f1 commit a46cf1e

File tree

4 files changed

+159
-1
lines changed

4 files changed

+159
-1
lines changed

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"require-dev": {
1717
"friendsofphp/php-cs-fixer": "^3.15.1",
1818
"roave/security-advisories": "dev-latest",
19-
"vimeo/psalm": "^5.8.0"
19+
"vimeo/psalm": "^5.8.0",
20+
"rector/rector": "^0.17.6"
2021
},
2122
"autoload": {
2223
"psr-4": {
@@ -45,6 +46,8 @@
4546
"security": "composer update --dry-run roave/security-advisories",
4647
"phpunit": "vendor/bin/phpunit --testdox --order-by=random",
4748
"phpunit-coverage-report": "vendor/bin/phpunit --coverage-html=.phpunit-coverage-report",
49+
"rector-test": "vendor/bin/rector --dry-run",
50+
"rector-debug": "vendor/bin/rector --dry-run --xdebug",
4851
"bash": "bash"
4952
}
5053
}

rector-test/ExampleTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PhpParser\Node;
6+
use PHPUnit\Framework\TestCase;
7+
8+
final class ExampleTest extends TestCase
9+
{
10+
public function testExample(): void
11+
{
12+
$mock = $this->createMock(Node::class);
13+
14+
$mock
15+
->expects(self::exactly(2))
16+
->method('hasAttribute')
17+
->withConsecutive(
18+
['foo'],
19+
['bar']
20+
)
21+
->willReturn(true);
22+
23+
$mock->hasAttribute('foo');
24+
$mock->hasAttribute('bar');
25+
}
26+
}

rector.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use MichaelPetri\PhpunitConsecutiveArguments\ConsecutiveArgumentsRectorRule;
6+
use Rector\Config\RectorConfig;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->paths([
10+
__DIR__ . '/rector-test',
11+
]);
12+
13+
$rectorConfig->rule(ConsecutiveArgumentsRectorRule::class);
14+
};
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MichaelPetri\PhpunitConsecutiveArguments;
6+
7+
use PhpParser\Node;
8+
use Rector\Core\Rector\AbstractRector;
9+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
10+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
11+
12+
final class ConsecutiveArgumentsRectorRule extends AbstractRector
13+
{
14+
/**
15+
* @return array<class-string<Node>>
16+
*/
17+
public function getNodeTypes(): array
18+
{
19+
return [
20+
Node\Expr\MethodCall::class
21+
];
22+
}
23+
24+
public function refactor(Node $node): ?Node
25+
{
26+
if (!$node instanceof Node\Expr\MethodCall) {
27+
return null;
28+
}
29+
30+
if (
31+
$node->name instanceof Node\Identifier &&
32+
$node->name->name !== 'withConsecutive'
33+
) {
34+
return null;
35+
}
36+
37+
$node->name = new Node\Identifier('with');
38+
39+
$node->args = [
40+
new Node\Arg(
41+
new Node\Expr\StaticCall(
42+
new Node\Name(
43+
'\\' . ConsecutiveArguments::class
44+
),
45+
new Node\Identifier('of'),
46+
$node->args,
47+
)
48+
)
49+
];
50+
51+
return $node;
52+
}
53+
54+
public function getRuleDefinition(): RuleDefinition
55+
{
56+
return new RuleDefinition(
57+
'Use $mock->with(ConsecutiveArguments::of(...)) instead of $mock->withConsecutive(...)',
58+
[
59+
new CodeSample(
60+
<<<PHP
61+
use MichaelPetri\PhpunitConsecutiveArguments\ConsecutiveArguments;
62+
use PhpParser\Node;
63+
use PHPUnit\Framework\TestCase;
64+
65+
final class GoodExample extends TestCase
66+
{
67+
public function testExample(): void
68+
{
69+
\$mock = \$this->createMock(Node::class);
70+
71+
\$mock
72+
->expects(self::exactly(2))
73+
->method('hasAttribute')
74+
->with(
75+
ConsecutiveArguments::of(
76+
['foo'],
77+
['bar']
78+
)
79+
)
80+
->willReturn(true);
81+
82+
\$mock->hasAttribute('foo');
83+
\$mock->hasAttribute('bar');
84+
}
85+
}
86+
PHP,
87+
<<<PHP
88+
use PhpParser\Node;
89+
use PHPUnit\Framework\TestCase;
90+
91+
final class BadExample extends TestCase
92+
{
93+
public function testExample(): void
94+
{
95+
\$mock = \$this->createMock(Node::class);
96+
97+
\$mock
98+
->expects(self::exactly(2))
99+
->method('hasAttribute')
100+
->withConsecutive(
101+
['foo'],
102+
['bar']
103+
)
104+
->willReturn(true);
105+
106+
\$mock->hasAttribute('foo');
107+
\$mock->hasAttribute('bar');
108+
}
109+
}
110+
PHP
111+
)
112+
]
113+
);
114+
}
115+
}

0 commit comments

Comments
 (0)