Skip to content

Commit b75c030

Browse files
[CodeQuality] Handle createMock as well in PreferPHPUnitThisCallRector (#407)
* [CodeQuality] Handle createMock as well in PreferPHPUnitThisCallRector * Covert expectations mock invoke as well * [ci-review] Rector Rectify --------- Co-authored-by: GitHub Action <[email protected]>
1 parent d991406 commit b75c030

File tree

5 files changed

+87
-16
lines changed

5 files changed

+87
-16
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"php": ">=8.2"
88
},
99
"require-dev": {
10-
"rector/rector-src": "dev-main#e3ba39d",
10+
"rector/rector-src": "dev-main",
1111
"phpunit/phpunit": "^10.5",
1212
"phpstan/phpstan": "^1.12",
1313
"symplify/phpstan-rules": "^13.0",
@@ -17,7 +17,7 @@
1717
"phpstan/phpstan-webmozart-assert": "^1.2",
1818
"symplify/vendor-patches": "^11.3",
1919
"tracy/tracy": "^2.10",
20-
"tomasvotruba/class-leak": "^1.1.2",
20+
"tomasvotruba/class-leak": "^1.2",
2121
"rector/type-perfect": "^1.0",
2222
"rector/swiss-knife": "^1.0"
2323
},

rector.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Rector\Config\RectorConfig;
66
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
7-
use Rector\PHPUnit\Set\PHPUnitSetList;
87

98
return RectorConfig::configure()
109
->withImportNames(removeUnusedImports: true)
@@ -30,7 +29,8 @@
3029
__DIR__ . '/src/NodeFinder/DataProviderClassMethodFinder.php',
3130
],
3231
])
33-
->withPhpSets(php82: true)
32+
->withPhpSets()
33+
->withAttributesSets(all: true)
3434
->withPreparedSets(
3535
deadCode: true,
3636
codeQuality: true,
@@ -39,12 +39,9 @@
3939
naming: true,
4040
typeDeclarations: true,
4141
privatization: true,
42-
rectorPreset: true
42+
rectorPreset: true,
43+
phpunitCodeQuality: true
4344
)
44-
->withSets([
45-
PHPUnitSetList::PHPUNIT_100,
46-
PHPUnitSetList::PHPUNIT_CODE_QUALITY,
47-
])
4845
->withConfiguredRule(StringClassNameToClassConstantRector::class, [
4946
// keep unprefixed to protected from downgrade
5047
'PHPUnit\Framework\*',
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
final class AtLeastOnce extends TestCase
8+
{
9+
public function testMe()
10+
{
11+
$matcher = self::once();
12+
$matcher = self::atLeast(5);
13+
$matcher = self::never();
14+
$matcher = self::atLeastOnce();
15+
}
16+
}
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector\Fixture;
23+
24+
use PHPUnit\Framework\TestCase;
25+
26+
final class AtLeastOnce extends TestCase
27+
{
28+
public function testMe()
29+
{
30+
$matcher = $this->once();
31+
$matcher = $this->atLeast(5);
32+
$matcher = $this->never();
33+
$matcher = $this->atLeastOnce();
34+
}
35+
}
36+
37+
?>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
final class CreateMock extends TestCase
8+
{
9+
public function testMe()
10+
{
11+
$someMock = self::createMock('stdClass');
12+
}
13+
}
14+
15+
?>
16+
-----
17+
<?php
18+
19+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector\Fixture;
20+
21+
use PHPUnit\Framework\TestCase;
22+
23+
final class CreateMock extends TestCase
24+
{
25+
public function testMe()
26+
{
27+
$someMock = $this->createMock('stdClass');
28+
}
29+
}
30+
31+
?>

rules/CodeQuality/Rector/Class_/PreferPHPUnitThisCallRector.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
*/
2222
final class PreferPHPUnitThisCallRector extends AbstractRector
2323
{
24+
/**
25+
* @var string[]
26+
*/
27+
private const NON_ASSERT_STATIC_METHODS = ['createMock', 'atLeast', 'atLeastOnce', 'once', 'never'];
28+
2429
public function __construct(
2530
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
2631
) {
@@ -75,30 +80,31 @@ public function refactor(Node $node): ?Node
7580
}
7681

7782
$hasChanged = false;
83+
7884
$this->traverseNodesWithCallable($node, function (Node $node) use (&$hasChanged): int|null|MethodCall {
79-
$isStatic = ($node instanceof ClassMethod && $node->isStatic()) || ($node instanceof Closure && $node->static);
80-
if ($isStatic) {
85+
$isInsideStaticFunctionLike = ($node instanceof ClassMethod && $node->isStatic()) || ($node instanceof Closure && $node->static);
86+
if ($isInsideStaticFunctionLike) {
8187
return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
8288
}
8389

8490
if (! $node instanceof StaticCall) {
8591
return null;
8692
}
8793

88-
$methodName = $this->getName($node->name);
89-
if (! is_string($methodName)) {
94+
if ($node->isFirstClassCallable()) {
9095
return null;
9196
}
9297

93-
if (! $this->isNames($node->class, ['static', 'self'])) {
98+
$methodName = $this->getName($node->name);
99+
if (! is_string($methodName)) {
94100
return null;
95101
}
96102

97-
if (! str_starts_with($methodName, 'assert')) {
103+
if (! $this->isNames($node->class, ['static', 'self'])) {
98104
return null;
99105
}
100106

101-
if ($node->isFirstClassCallable()) {
107+
if (! str_starts_with($methodName, 'assert') && ! in_array($methodName, self::NON_ASSERT_STATIC_METHODS)) {
102108
return null;
103109
}
104110

0 commit comments

Comments
 (0)