Skip to content

Commit 79bf991

Browse files
committed
Fix
1 parent 2cad0c6 commit 79bf991

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

rules/CodeQuality/NodeAnalyser/MockObjectExprDetector.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,28 @@
44

55
namespace Rector\PHPUnit\CodeQuality\NodeAnalyser;
66

7+
use PhpParser\Node\Arg;
78
use PhpParser\Node\Expr;
89
use PhpParser\Node\Expr\MethodCall;
910
use PhpParser\Node\Expr\PropertyFetch;
1011
use PhpParser\Node\Expr\Variable;
1112
use PhpParser\Node\Stmt\Class_;
1213
use PhpParser\Node\Stmt\ClassMethod;
14+
use PHPStan\Reflection\MethodReflection;
15+
use PHPStan\Type\ObjectType;
1316
use Rector\NodeNameResolver\NodeNameResolver;
1417
use Rector\PhpParser\Node\BetterNodeFinder;
1518
use Rector\PHPUnit\CodeQuality\NodeFinder\VariableFinder;
19+
use Rector\PHPUnit\Enum\PHPUnitClassName;
20+
use Rector\Reflection\ReflectionResolver;
1621

1722
final readonly class MockObjectExprDetector
1823
{
1924
public function __construct(
2025
private BetterNodeFinder $betterNodeFinder,
2126
private NodeNameResolver $nodeNameResolver,
2227
private VariableFinder $variableFinder,
28+
private ReflectionResolver $reflectionResolver,
2329
) {
2430
}
2531

@@ -67,6 +73,8 @@ public function isUsedForMocking(Expr $expr, ClassMethod $classMethod): bool
6773
/** @var array<Expr\MethodCall> $methodCalls */
6874
$methodCalls = $this->betterNodeFinder->findInstancesOfScoped((array) $classMethod->stmts, [MethodCall::class]);
6975

76+
$mockObjectType = new ObjectType(PHPUnitClassName::MOCK_OBJECT);
77+
7078
foreach ($methodCalls as $methodCall) {
7179
if (! $methodCall->var instanceof Variable) {
7280
continue;
@@ -76,6 +84,41 @@ public function isUsedForMocking(Expr $expr, ClassMethod $classMethod): bool
7684
// variable is being called on, most like mocking, lets skip
7785
return true;
7886
}
87+
88+
if ($methodCall->isFirstClassCallable()) {
89+
continue;
90+
}
91+
92+
// check if variable is passed as arg to a method that declares MockObject type parameter
93+
foreach ($methodCall->getArgs() as $position => $arg) {
94+
if (! $arg instanceof Arg) {
95+
continue;
96+
}
97+
98+
if (! $arg->value instanceof Variable) {
99+
continue;
100+
}
101+
102+
if (! $this->nodeNameResolver->isName($arg->value, $variableName)) {
103+
continue;
104+
}
105+
106+
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromMethodCall($methodCall);
107+
if (! $methodReflection instanceof MethodReflection) {
108+
continue;
109+
}
110+
111+
$parameters = $methodReflection->getVariants()[0]
112+
->getParameters();
113+
if (! isset($parameters[$position])) {
114+
continue;
115+
}
116+
117+
$paramType = $parameters[$position]->getType();
118+
if ($mockObjectType->isSuperTypeOf($paramType)->yes()) {
119+
return true;
120+
}
121+
}
79122
}
80123

81124
return false;

0 commit comments

Comments
 (0)