From a92f64e7a0b918bf0e4f5b05d8458ad98d01251f Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 27 Aug 2026 18:45:25 +0100 Subject: [PATCH] [CodeQuality] Skip DirectInstanceOverMockArgRector outside test classes Gate the rule on TestsNodeAnalyzer::isInTestClass() before fetching scope. Non-test app code with a spread + named-arg new expression has no scope on the arg, so the eager ScopeFetcher::fetch() threw "Scope not available" and crashed the whole Rector run. The rule only handles Symfony Request mocks in tests anyway. Claude-Session: https://claude.ai/code/session_018faFsAZPx2pm78KBAwortK --- .../skip_non_test_class_spread_named_arg.php.inc | 14 ++++++++++++++ .../CallLike/DirectInstanceOverMockArgRector.php | 15 +++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector/Fixture/skip_non_test_class_spread_named_arg.php.inc diff --git a/rules-tests/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector/Fixture/skip_non_test_class_spread_named_arg.php.inc b/rules-tests/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector/Fixture/skip_non_test_class_spread_named_arg.php.inc new file mode 100644 index 00000000..a1a6552b --- /dev/null +++ b/rules-tests/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector/Fixture/skip_non_test_class_spread_named_arg.php.inc @@ -0,0 +1,14 @@ +updateData(), + user: (string) $request->user()->getKey(), + ); + } +} diff --git a/rules/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector.php b/rules/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector.php index ec90e9d1..a31b61aa 100644 --- a/rules/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector.php +++ b/rules/CodeQuality/Rector/CallLike/DirectInstanceOverMockArgRector.php @@ -13,8 +13,7 @@ use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Name\FullyQualified; use Rector\PhpParser\Node\Value\ValueResolver; -use Rector\PHPStan\ScopeFetcher; -use Rector\PHPUnit\Enum\PHPUnitClassName; +use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer; use Rector\Rector\AbstractRector; use Rector\Symfony\Enum\SymfonyClass; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -26,7 +25,8 @@ final class DirectInstanceOverMockArgRector extends AbstractRector { public function __construct( - private readonly ValueResolver $valueResolver + private readonly ValueResolver $valueResolver, + private readonly TestsNodeAnalyzer $testsNodeAnalyzer ) { } @@ -88,13 +88,8 @@ public function getNodeTypes(): array */ public function refactor(Node $node): MethodCall|StaticCall|New_|ArrayItem|null { - $scope = ScopeFetcher::fetch($node); - if (! $scope->isInClass()) { - return null; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection->is(PHPUnitClassName::TEST_CASE)) { + // run on test classes only, non-test code may lack scope on args and crash the whole run + if (! $this->testsNodeAnalyzer->isInTestClass($node)) { return null; }