From d9bbb9a16897a261262e417a30135de9064a2026 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 10 Sep 2025 00:30:22 +0700 Subject: [PATCH 1/5] [AutoImport] Allow FQCN current same class --- rules/CodingStyle/Node/NameImporter.php | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/rules/CodingStyle/Node/NameImporter.php b/rules/CodingStyle/Node/NameImporter.php index 945255bc378..6815d6874b5 100644 --- a/rules/CodingStyle/Node/NameImporter.php +++ b/rules/CodingStyle/Node/NameImporter.php @@ -9,6 +9,7 @@ use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\GroupUse; use PhpParser\Node\Stmt\Use_; +use PHPStan\Analyser\Scope; use Rector\CodingStyle\ClassNameImport\ClassNameImportSkipper; use Rector\Naming\Naming\AliasNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -90,6 +91,12 @@ private function importNameAndCollectNewUseStatement( return $nameInUse; } + $nameInNamespacedScope = $this->resolveNameInNamespacedScope($fullyQualified); + if ($nameInNamespacedScope instanceof Name) { + $nameInNamespacedScope->setAttribute(AttributeKey::NAMESPACED_NAME, $fullyQualified->toString()); + return $nameInNamespacedScope; + } + // the same end is already imported → skip if ($this->classNameImportSkipper->shouldSkipNameForFullyQualifiedObjectType( $file, @@ -111,6 +118,29 @@ private function importNameAndCollectNewUseStatement( return $fullyQualifiedObjectType->getShortNameNode(); } + private function resolveNameInNamespacedScope(FullyQualified $fullyQualified): ?Name + { + $scope = $fullyQualified->getAttribute(AttributeKey::SCOPE); + + if (! $scope instanceof Scope) { + return null; + } + + $namespace = $scope->getNamespace(); + if ($namespace === null) { + return null; + } + + $shortName = $fullyQualified->getLast(); + $namepaceFullyQualifiedName = substr($fullyQualified->toString(), 0, -strlen($shortName) - 1); + + if ($namepaceFullyQualifiedName === $namespace) { + return new Name($shortName); + } + + return null; + } + private function addUseImport( File $file, FullyQualified $fullyQualified, From 6c4aa58607056f78dbb4860cf6e3c3844ebc5809 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 10 Sep 2025 00:30:29 +0700 Subject: [PATCH 2/5] [AutoImport] Allow FQCN current same class --- .../Fixture/fqcn_current_same_class.php.inc | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/Issues/AutoImport/Fixture/fqcn_current_same_class.php.inc diff --git a/tests/Issues/AutoImport/Fixture/fqcn_current_same_class.php.inc b/tests/Issues/AutoImport/Fixture/fqcn_current_same_class.php.inc new file mode 100644 index 00000000000..bdab86555ff --- /dev/null +++ b/tests/Issues/AutoImport/Fixture/fqcn_current_same_class.php.inc @@ -0,0 +1,21 @@ + +----- + From e001388a22d5bc8d72a4aaa85993e7ce522133ab Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 10 Sep 2025 00:35:18 +0700 Subject: [PATCH 3/5] future note --- rules/CodingStyle/Node/NameImporter.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rules/CodingStyle/Node/NameImporter.php b/rules/CodingStyle/Node/NameImporter.php index 6815d6874b5..c40a5b4a0da 100644 --- a/rules/CodingStyle/Node/NameImporter.php +++ b/rules/CodingStyle/Node/NameImporter.php @@ -122,6 +122,10 @@ private function resolveNameInNamespacedScope(FullyQualified $fullyQualified): ? { $scope = $fullyQualified->getAttribute(AttributeKey::SCOPE); + // Note: Don't use ScopeFetcher::fetch, + // Scope can be null on Name + // This is part of ScopeAnalyzer::NON_REFRESHABLE_NODES + // @see https://github.com/rectorphp/rector-src/blob/9929af7c0179929b4fde6915cb7a06c3141dde6c/src/NodeAnalyzer/ScopeAnalyzer.php#L17 if (! $scope instanceof Scope) { return null; } From c04f7113b6e01ea312e950421ae96e95d22879c1 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 10 Sep 2025 00:36:52 +0700 Subject: [PATCH 4/5] future note --- rules/CodingStyle/Node/NameImporter.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rules/CodingStyle/Node/NameImporter.php b/rules/CodingStyle/Node/NameImporter.php index c40a5b4a0da..b448fde79a5 100644 --- a/rules/CodingStyle/Node/NameImporter.php +++ b/rules/CodingStyle/Node/NameImporter.php @@ -120,12 +120,13 @@ private function importNameAndCollectNewUseStatement( private function resolveNameInNamespacedScope(FullyQualified $fullyQualified): ?Name { + /** + * Note: Don't use ScopeFetcher::fetch(), + * Scope can be null on Name + * This is part of ScopeAnalyzer::NON_REFRESHABLE_NODES + * @see https://github.com/rectorphp/rector-src/blob/9929af7c0179929b4fde6915cb7a06c3141dde6c/src/NodeAnalyzer/ScopeAnalyzer.php#L17 + */ $scope = $fullyQualified->getAttribute(AttributeKey::SCOPE); - - // Note: Don't use ScopeFetcher::fetch, - // Scope can be null on Name - // This is part of ScopeAnalyzer::NON_REFRESHABLE_NODES - // @see https://github.com/rectorphp/rector-src/blob/9929af7c0179929b4fde6915cb7a06c3141dde6c/src/NodeAnalyzer/ScopeAnalyzer.php#L17 if (! $scope instanceof Scope) { return null; } From 9a5705a36d629061203cb90349de1ff3b91168b9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 10 Sep 2025 00:37:16 +0700 Subject: [PATCH 5/5] future note --- rules/CodingStyle/Node/NameImporter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/CodingStyle/Node/NameImporter.php b/rules/CodingStyle/Node/NameImporter.php index b448fde79a5..dc5821210aa 100644 --- a/rules/CodingStyle/Node/NameImporter.php +++ b/rules/CodingStyle/Node/NameImporter.php @@ -121,7 +121,7 @@ private function importNameAndCollectNewUseStatement( private function resolveNameInNamespacedScope(FullyQualified $fullyQualified): ?Name { /** - * Note: Don't use ScopeFetcher::fetch(), + * Note: Don't use ScopeFetcher::fetch() on Name instance, * Scope can be null on Name * This is part of ScopeAnalyzer::NON_REFRESHABLE_NODES * @see https://github.com/rectorphp/rector-src/blob/9929af7c0179929b4fde6915cb7a06c3141dde6c/src/NodeAnalyzer/ScopeAnalyzer.php#L17