diff --git a/packages/PostRector/Rector/NameImportingPostRector.php b/packages/PostRector/Rector/NameImportingPostRector.php index 2ddcab2eb7d..327a7fbc065 100644 --- a/packages/PostRector/Rector/NameImportingPostRector.php +++ b/packages/PostRector/Rector/NameImportingPostRector.php @@ -5,8 +5,10 @@ namespace Rector\PostRector\Rector; use PhpParser\Node; +use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Use_; +use PhpParser\Node\Stmt\UseUse; use PHPStan\Reflection\ReflectionProvider; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\CodingStyle\ClassNameImport\ClassNameImportSkipper; @@ -16,6 +18,8 @@ use Rector\Core\PhpParser\Node\BetterNodeFinder; use Rector\Core\Provider\CurrentFileProvider; use Rector\Core\ValueObject\Application\File; +use Rector\Naming\Naming\AliasNameResolver; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockNameImporter; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -30,7 +34,8 @@ public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly ReflectionProvider $reflectionProvider, private readonly CurrentFileProvider $currentFileProvider, - private readonly BetterNodeFinder $betterNodeFinder + private readonly BetterNodeFinder $betterNodeFinder, + private readonly AliasNameResolver $aliasNameResolver ) { } @@ -105,12 +110,43 @@ private function processNodeName(Name $name, File $file): ?Node $currentUses = $this->betterNodeFinder->findInstanceOf($file->getNewStmts(), Use_::class); if ($this->shouldImportName($name, $currentUses)) { + $aliasName = $this->aliasNameResolver->resolveByName($name); + $node = $name->getAttribute(AttributeKey::PARENT_NODE); + + if (is_string($aliasName) && ! $node instanceof UseUse && ! $this->hasOtherSameUseStatementWithoutAlias( + $name, + $currentUses + )) { + return new Name($aliasName); + } + return $this->nameImporter->importName($name, $file, $currentUses); } return null; } + /** + * @param Use_[] $currentUses + */ + private function hasOtherSameUseStatementWithoutAlias(Name $name, array $currentUses): bool + { + $currentName = $name->toString(); + foreach ($currentUses as $currentUse) { + foreach ($currentUse->uses as $useUse) { + if ($useUse->alias instanceof Identifier) { + continue; + } + + if ($useUse->name->toString() === $currentName) { + return true; + } + } + } + + return false; + } + /** * @param Use_[] $currentUses */ diff --git a/rules/TypeDeclaration/Rector/FunctionLike/ReturnTypeDeclarationRector.php b/rules/TypeDeclaration/Rector/FunctionLike/ReturnTypeDeclarationRector.php index b31b59e43d8..dcfdb37cb03 100644 --- a/rules/TypeDeclaration/Rector/FunctionLike/ReturnTypeDeclarationRector.php +++ b/rules/TypeDeclaration/Rector/FunctionLike/ReturnTypeDeclarationRector.php @@ -158,7 +158,7 @@ private function processType(ClassMethod | Function_ $node, Type $inferedType): return null; } - /** @var Name|NullableType|PhpParserUnionType $inferredReturnNode */ + /** @var Name|NullableType|PhpParserUnionType|IntersectionType $inferredReturnNode */ $this->addReturnType($node, $inferredReturnNode); $this->nonInformativeReturnTagRemover->removeReturnTagIfNotUseful($node); @@ -206,7 +206,7 @@ private function shouldSkipExistingReturnType(ClassMethod | Function_ $functionL private function addReturnType( ClassMethod | Function_ $functionLike, - Name|NullableType|\PhpParser\Node\UnionType|IntersectionType $inferredReturnNode + Name|NullableType|PhpParserUnionType|IntersectionType $inferredReturnNode ): void { if ($functionLike->returnType === null) { $functionLike->returnType = $inferredReturnNode; diff --git a/tests/Issues/AutoImportInAlias/AutoImportInAliasTest.php b/tests/Issues/AutoImportInAlias/AutoImportInAliasTest.php new file mode 100644 index 00000000000..996bfb41101 --- /dev/null +++ b/tests/Issues/AutoImportInAlias/AutoImportInAliasTest.php @@ -0,0 +1,32 @@ +doTestFile($filePath); + } + + /** + * @return Iterator> + */ + public function provideData(): Iterator + { + return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/tests/Issues/AutoImportInAlias/Fixture/auto_import_in_alias.php.inc b/tests/Issues/AutoImportInAlias/Fixture/auto_import_in_alias.php.inc new file mode 100644 index 00000000000..9a0c0157df1 --- /dev/null +++ b/tests/Issues/AutoImportInAlias/Fixture/auto_import_in_alias.php.inc @@ -0,0 +1,23 @@ + +----- + diff --git a/tests/Issues/AutoImportInAlias/config/configured_rule.php b/tests/Issues/AutoImportInAlias/config/configured_rule.php new file mode 100644 index 00000000000..78c22a8b209 --- /dev/null +++ b/tests/Issues/AutoImportInAlias/config/configured_rule.php @@ -0,0 +1,9 @@ +importNames(); +};