Skip to content

Commit bf193a4

Browse files
[Phpunit12] Skip as Argument with required MockObject Type on CreateStubOverCreateMockArgRector (#662)
* [Phpunit12] Skip as Argument with required MockObject Type on CreateStubOverCreateMockArgRector * [rector] Rector fixes * fix * fix phpstan --------- Co-authored-by: GitHub Action <actions@github.com>
1 parent 4f2e799 commit bf193a4

File tree

9 files changed

+104
-10
lines changed

9 files changed

+104
-10
lines changed

rules-tests/PHPUnit120/Rector/CallLike/CreateStubOverCreateMockArgRector/Fixture/handle_static_call.php.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Fixture;
44

55
use PHPUnit\Framework\TestCase;
6-
use Utils\PHPStan\Tests\Rule\PHPUnit\StubOverMockArgRule\Source\AnyClass;
6+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source\AnyClass;
77

88
class HandleStaticCall extends TestCase
99
{
@@ -22,7 +22,7 @@ class HandleStaticCall extends TestCase
2222
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Fixture;
2323

2424
use PHPUnit\Framework\TestCase;
25-
use Utils\PHPStan\Tests\Rule\PHPUnit\StubOverMockArgRule\Source\AnyClass;
25+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source\AnyClass;
2626

2727
class HandleStaticCall extends TestCase
2828
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Fixture;
4+
5+
use DateTime;
6+
use PHPUnit\Framework\TestCase;
7+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source\SomeMockHelper;
8+
9+
class SkipAsArgumentWithMockObjectType extends TestCase {
10+
public function testFoo(): void
11+
{
12+
new SomeMockHelper($this->createMock(DateTime::class));
13+
}
14+
}

rules-tests/PHPUnit120/Rector/CallLike/CreateStubOverCreateMockArgRector/Fixture/skip_first_class_callable.php.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Fixture;
44

55
use PHPUnit\Framework\TestCase;
6-
use Utils\PHPStan\Tests\Rule\PHPUnit\StubOverMockArgRule\Source\AnyClass;
6+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source\AnyClass;
77

88
class SkipFirstClassCallable extends TestCase
99
{

rules-tests/PHPUnit120/Rector/CallLike/CreateStubOverCreateMockArgRector/Fixture/some_file_with_mocks.php.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Fixture;
44

55
use PHPUnit\Framework\TestCase;
6-
use Utils\PHPStan\Tests\Rule\PHPUnit\StubOverMockArgRule\Source\AnyClass;
6+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source\AnyClass;
77

88
class SomeFileWithMocks extends TestCase
99
{
@@ -24,7 +24,7 @@ class SomeFileWithMocks extends TestCase
2424
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Fixture;
2525

2626
use PHPUnit\Framework\TestCase;
27-
use Utils\PHPStan\Tests\Rule\PHPUnit\StubOverMockArgRule\Source\AnyClass;
27+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source\AnyClass;
2828

2929
class SomeFileWithMocks extends TestCase
3030
{
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source;
4+
5+
final class AnyClass
6+
{
7+
public function run(...$params)
8+
{
9+
}
10+
11+
public static function staticRun(...$params)
12+
{
13+
}
14+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector\Source;
4+
5+
use DateTime;
6+
use PHPUnit\Framework\MockObject\MockObject;
7+
8+
class SomeMockHelper {
9+
public function __construct(
10+
public MockObject&DateTime $i
11+
) {}
12+
13+
public function configureMock(array $data): void
14+
{
15+
}
16+
}

rules/CodeQuality/NodeAnalyser/AssertMethodAnalyzer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function detectTestCaseCall(MethodCall|StaticCall $call): bool
5656
$declaringClassName = $extendedMethodReflection->getDeclaringClass()
5757
->getName();
5858

59-
return in_array($declaringClassName, [PHPUnitClassName::TEST_CASE, PHPUnitClassName::ASSERT]);
59+
return in_array($declaringClassName, [PHPUnitClassName::TEST_CASE, PHPUnitClassName::ASSERT], true);
6060
}
6161

6262
public function detectTestCaseCallForStatic(MethodCall $methodCall): bool

rules/PHPUnit120/Rector/CallLike/CreateStubOverCreateMockArgRector.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Rector\PHPUnit\PHPUnit120\Rector\CallLike;
66

77
use PhpParser\Node;
8+
use PhpParser\Node\Arg;
89
use PhpParser\Node\ArrayItem;
910
use PhpParser\Node\Expr;
1011
use PhpParser\Node\Expr\Assign;
@@ -15,9 +16,19 @@
1516
use PhpParser\Node\Identifier;
1617
use PhpParser\Node\Stmt\ClassMethod;
1718
use PhpParser\Node\Stmt\Expression;
19+
use PHPStan\Reflection\FunctionReflection;
20+
use PHPStan\Reflection\MethodReflection;
21+
use PHPStan\Reflection\ParametersAcceptor;
22+
use PHPStan\Type\MixedType;
23+
use PHPStan\Type\ObjectType;
24+
use PHPStan\Type\Type;
25+
use Rector\NodeTypeResolver\PHPStan\ParametersAcceptorSelectorVariantsWrapper;
26+
use Rector\PHPStan\ScopeFetcher;
1827
use Rector\PHPUnit\CodeQuality\NodeAnalyser\MockObjectExprDetector;
28+
use Rector\PHPUnit\Enum\PHPUnitClassName;
1929
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
2030
use Rector\Rector\AbstractRector;
31+
use Rector\Reflection\ReflectionResolver;
2132
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2233
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2334

@@ -31,6 +42,7 @@ final class CreateStubOverCreateMockArgRector extends AbstractRector
3142
public function __construct(
3243
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
3344
private readonly MockObjectExprDetector $mockObjectExprDetector,
45+
private readonly ReflectionResolver $reflectionResolver
3446
) {
3547
}
3648

@@ -107,11 +119,27 @@ public function refactor(Node $node): MethodCall|StaticCall|New_|ArrayItem|Class
107119
return null;
108120
}
109121

110-
foreach ($node->getArgs() as $arg) {
122+
$scope = ScopeFetcher::fetch($node);
123+
$reflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
124+
125+
if (! $reflection instanceof FunctionReflection && ! $reflection instanceof MethodReflection) {
126+
return null;
127+
}
128+
129+
$parametersAcceptor = ParametersAcceptorSelectorVariantsWrapper::select($reflection, $node, $scope);
130+
131+
foreach ($node->getArgs() as $key => $arg) {
111132
if (! $arg->value instanceof MethodCall) {
112133
continue;
113134
}
114135

136+
$type = $this->resolveTypeFromArgumentAndKey($parametersAcceptor, $arg, $key);
137+
$superType = new ObjectType(PHPUnitClassName::MOCK_OBJECT);
138+
139+
if ($superType->isSuperTypeOf($type)->yes()) {
140+
continue;
141+
}
142+
115143
$methodCall = $arg->value;
116144
if (! $this->isName($methodCall->name, 'createMock')) {
117145
continue;
@@ -128,6 +156,28 @@ public function refactor(Node $node): MethodCall|StaticCall|New_|ArrayItem|Class
128156
return null;
129157
}
130158

159+
private function resolveTypeFromArgumentAndKey(ParametersAcceptor $parametersAcceptor, Arg $arg, int $key): Type
160+
{
161+
$parameters = $parametersAcceptor->getParameters();
162+
if (! $arg->name instanceof Identifier) {
163+
if (! isset($parameters[$key])) {
164+
return new MixedType();
165+
}
166+
167+
return $parameters[$key]->getType();
168+
}
169+
170+
foreach ($parameters as $parameter) {
171+
if ($parameter->getName() !== $arg->name->toString()) {
172+
continue;
173+
}
174+
175+
return $parameter->getType();
176+
}
177+
178+
return new MixedType();
179+
}
180+
131181
private function matchCreateMockMethodCall(Expr $expr): null|MethodCall
132182
{
133183
if (! $expr instanceof MethodCall) {

rules/PHPUnit120/Rector/Class_/PropertyCreateMockToCreateStubRector.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,11 @@ private function shouldSkipClass(Class_ $class): bool
152152
return ! $setUpClassMethod instanceof ClassMethod;
153153
}
154154

155-
private function updatePropertyType(?Node $type): IntersectionType|FullyQualified
155+
private function updatePropertyType(?Node $node): IntersectionType|FullyQualified
156156
{
157-
if ($type instanceof IntersectionType) {
157+
if ($node instanceof IntersectionType) {
158158
$newTypes = [];
159-
foreach ($type->types as $innerType) {
159+
foreach ($node->types as $innerType) {
160160
if ($innerType instanceof FullyQualified && $innerType->toString() === PHPUnitClassName::MOCK_OBJECT) {
161161
$newTypes[] = new FullyQualified(PHPUnitClassName::STUB);
162162
} else {

0 commit comments

Comments
 (0)