Skip to content

Commit f19faad

Browse files
committed
include New_
1 parent e7d1fc8 commit f19faad

File tree

4 files changed

+101
-19
lines changed

4 files changed

+101
-19
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\ScalarArgumentToExpectedParamTypeRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\ScalarArgumentToExpectedParamTypeRector\Source\ValueObjectWithConstructor;
7+
8+
final class PassFloatToNullableString extends TestCase
9+
{
10+
public function test()
11+
{
12+
$valueObject = new ValueObjectWithConstructor(123.456, '123');
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\ScalarArgumentToExpectedParamTypeRector\Fixture;
21+
22+
use PHPUnit\Framework\TestCase;
23+
use Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\ScalarArgumentToExpectedParamTypeRector\Source\ValueObjectWithConstructor;
24+
25+
final class PassFloatToNullableString extends TestCase
26+
{
27+
public function test()
28+
{
29+
$valueObject = new ValueObjectWithConstructor('123.456', 123);
30+
}
31+
}
32+
33+
?>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\ScalarArgumentToExpectedParamTypeRector\Source;
6+
7+
final class ValueObjectWithConstructor
8+
{
9+
public function __construct(?string $letter, ?int $number = null)
10+
{
11+
}
12+
}

rules/CodeQuality/Rector/MethodCall/ScalarArgumentToExpectedParamTypeRector.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PhpParser\Node;
88
use PhpParser\Node\Expr\MethodCall;
9+
use PhpParser\Node\Expr\New_;
910
use PhpParser\Node\Expr\StaticCall;
1011
use PhpParser\Node\Identifier;
1112
use PhpParser\Node\Scalar;
@@ -92,11 +93,11 @@ public function setPhone(string $phone)
9293
*/
9394
public function getNodeTypes(): array
9495
{
95-
return [MethodCall::class, StaticCall::class];
96+
return [MethodCall::class, StaticCall::class, New_::class];
9697
}
9798

9899
/**
99-
* @param MethodCall|StaticCall $node
100+
* @param MethodCall|StaticCall|New_ $node
100101
*/
101102
public function refactor(Node $node): ?Node
102103
{
@@ -156,26 +157,26 @@ public function refactor(Node $node): ?Node
156157
return $node;
157158
}
158159

159-
private function shouldSkipCall(StaticCall|MethodCall $call): bool
160+
private function shouldSkipCall(StaticCall|MethodCall|New_ $callLike): bool
160161
{
161-
if (! $this->isInTestClass($call)) {
162+
if (! $this->isInTestClass($callLike)) {
162163
return true;
163164
}
164165

165-
if ($call->isFirstClassCallable()) {
166+
if ($callLike->isFirstClassCallable()) {
166167
return true;
167168
}
168169

169-
if ($call->getArgs() === []) {
170+
if ($callLike->getArgs() === []) {
170171
return true;
171172
}
172173

173-
return ! $this->hasStringOrNumberArguments($call);
174+
return ! $this->hasStringOrNumberArguments($callLike);
174175
}
175176

176-
private function hasStringOrNumberArguments(StaticCall|MethodCall $call): bool
177+
private function hasStringOrNumberArguments(StaticCall|MethodCall|New_ $callLike): bool
177178
{
178-
foreach ($call->getArgs() as $arg) {
179+
foreach ($callLike->getArgs() as $arg) {
179180
if ($arg->value instanceof Int_) {
180181
return true;
181182
}
@@ -192,7 +193,7 @@ private function hasStringOrNumberArguments(StaticCall|MethodCall $call): bool
192193
return false;
193194
}
194195

195-
private function isInTestClass(StaticCall|MethodCall $call): bool
196+
private function isInTestClass(StaticCall|MethodCall|New_ $call): bool
196197
{
197198
$callerClassReflection = $this->reflectionResolver->resolveClassReflection($call);
198199
if (! $callerClassReflection instanceof ClassReflection) {

rules/CodeQuality/Reflection/MethodParametersAndReturnTypesResolver.php

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
namespace Rector\PHPUnit\CodeQuality\Reflection;
66

77
use PhpParser\Node\Expr\MethodCall;
8+
use PhpParser\Node\Expr\New_;
89
use PhpParser\Node\Expr\StaticCall;
910
use PhpParser\Node\Identifier;
11+
use PhpParser\Node\Name;
1012
use PHPStan\Reflection\ClassReflection;
1113
use PHPStan\Reflection\ExtendedMethodReflection;
1214
use PHPStan\Reflection\ParametersAcceptorSelector;
15+
use PHPStan\Reflection\ReflectionProvider;
1316
use PHPStan\Type\IntersectionType;
1417
use PHPStan\Type\MixedType;
1518
use PHPStan\Type\ObjectType;
@@ -23,7 +26,8 @@
2326
final readonly class MethodParametersAndReturnTypesResolver
2427
{
2528
public function __construct(
26-
private NodeTypeResolver $nodeTypeResolver
29+
private NodeTypeResolver $nodeTypeResolver,
30+
private ReflectionProvider $reflectionProvider
2731
) {
2832
}
2933

@@ -64,15 +68,31 @@ public function resolveFromReflection(
6468
/**
6569
* @return null|Type[]
6670
*/
67-
public function resolveCallParameterTypes(MethodCall|StaticCall $call): ?array
71+
public function resolveCallParameterTypes(MethodCall|StaticCall|New_ $callLike): ?array
6872
{
69-
if (! $call->name instanceof Identifier) {
73+
if ($callLike instanceof New_) {
74+
if (! $callLike->class instanceof Name) {
75+
return null;
76+
}
77+
78+
$className = $callLike->class->toString();
79+
if (! $this->reflectionProvider->hasClass($className)) {
80+
return null;
81+
}
82+
83+
$classReflection = $this->reflectionProvider->getClass($className);
84+
return $this->resolveParameterTypes($classReflection->getConstructor(), $classReflection);
85+
}
86+
87+
if (! $callLike->name instanceof Identifier) {
7088
return null;
7189
}
7290

73-
$methodName = $call->name->toString();
91+
$methodName = $callLike->name->toString();
7492

75-
$callerType = $this->nodeTypeResolver->getType($call instanceof MethodCall ? $call->var : $call->class);
93+
$callerType = $this->nodeTypeResolver->getType(
94+
$callLike instanceof MethodCall ? $callLike->var : $callLike->class
95+
);
7696
if ($callerType instanceof ThisType) {
7797
$callerType = $callerType->getStaticObjectType();
7898
}
@@ -97,15 +117,31 @@ public function resolveCallParameterTypes(MethodCall|StaticCall $call): ?array
97117
/**
98118
* @return string[]
99119
*/
100-
public function resolveCallParameterNames(MethodCall|StaticCall $call): array
120+
public function resolveCallParameterNames(MethodCall|StaticCall|New_ $callLike): array
101121
{
102-
if (! $call->name instanceof Identifier) {
122+
if ($callLike instanceof New_) {
123+
if (! $callLike->class instanceof Name) {
124+
return [];
125+
}
126+
127+
$className = $callLike->class->toString();
128+
if (! $this->reflectionProvider->hasClass($className)) {
129+
return [];
130+
}
131+
132+
$classReflection = $this->reflectionProvider->getClass($className);
133+
return $this->resolveParameterNames($classReflection->getConstructor());
134+
}
135+
136+
if (! $callLike->name instanceof Identifier) {
103137
return [];
104138
}
105139

106-
$methodName = $call->name->toString();
140+
$methodName = $callLike->name->toString();
107141

108-
$callerType = $this->nodeTypeResolver->getType($call instanceof MethodCall ? $call->var : $call->class);
142+
$callerType = $this->nodeTypeResolver->getType(
143+
$callLike instanceof MethodCall ? $callLike->var : $callLike->class
144+
);
109145
if (! $callerType instanceof ObjectType) {
110146
return [];
111147
}

0 commit comments

Comments
 (0)