diff --git a/src/Application/ChangedNodeScopeRefresher.php b/src/Application/ChangedNodeScopeRefresher.php index c90a8b25e4f..d79eb149b81 100644 --- a/src/Application/ChangedNodeScopeRefresher.php +++ b/src/Application/ChangedNodeScopeRefresher.php @@ -36,6 +36,7 @@ use PHPStan\Analyser\MutatingScope; use Rector\Exception\ShouldNotHappenException; use Rector\NodeAnalyzer\ScopeAnalyzer; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\Scope\PHPStanNodeScopeResolver; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; @@ -80,6 +81,8 @@ public function refresh(Node $node, string $filePath, ?MutatingScope $mutatingSc // a class-like scope is already inside the class, so PHPStan cannot enter it again and would fail // on the class node, leaving its methods with the class scope; process the class stmts directly instead if ($node instanceof ClassLike && $mutatingScope->isInClass()) { + // the class node itself is not part of its stmts, e.g. an Enum_ replaced by a new Class_ has no scope yet + $node->setAttribute(AttributeKey::SCOPE, $mutatingScope); $this->phpStanNodeScopeResolver->processNodes($node->stmts, $filePath, $mutatingScope); return; } diff --git a/tests/Issues/EnumToClassScopeRefresh/EnumToClassScopeRefreshTest.php b/tests/Issues/EnumToClassScopeRefresh/EnumToClassScopeRefreshTest.php new file mode 100644 index 00000000000..7806e81362b --- /dev/null +++ b/tests/Issues/EnumToClassScopeRefresh/EnumToClassScopeRefreshTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/tests/Issues/EnumToClassScopeRefresh/Fixture/scope_on_class_from_enum.php.inc b/tests/Issues/EnumToClassScopeRefresh/Fixture/scope_on_class_from_enum.php.inc new file mode 100644 index 00000000000..66fa6eee5e2 --- /dev/null +++ b/tests/Issues/EnumToClassScopeRefresh/Fixture/scope_on_class_from_enum.php.inc @@ -0,0 +1,23 @@ + +----- + diff --git a/tests/Issues/EnumToClassScopeRefresh/config/configured_rule.php b/tests/Issues/EnumToClassScopeRefresh/config/configured_rule.php new file mode 100644 index 00000000000..bb745af6e5f --- /dev/null +++ b/tests/Issues/EnumToClassScopeRefresh/config/configured_rule.php @@ -0,0 +1,14 @@ +withRules([DowngradeEnumToConstantListClassRector::class]) + ->withConfiguredRule(RenameMethodRector::class, [ + new MethodCallRename('SomeClass', 'oldMethod', 'newMethod'), + ]);