Skip to content

Commit

Permalink
[PostRector][AutoImport] Handle remove unused import with auto import…
Browse files Browse the repository at this point in the history
… enabled on conflict with existing use statement (#5912)

* [PostRector][AutoImport] Handle remove unused import with auto import enabled on conflict with existing use statement

* more tests

* fix

* fix

* fix
  • Loading branch information
samsonasik committed May 25, 2024
1 parent 650ae6a commit c431eae
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 13 deletions.
45 changes: 32 additions & 13 deletions src/PostRector/Rector/UnusedImportRemovingPostRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public function enterNode(Node $node): ?Node

$hasChanged = false;

$namespaceName = $node instanceof Namespace_ && $node->name instanceof Name
? $node->name
: null;

$names = $this->resolveUsedPhpAndDocNames($node);

foreach ($node->stmts as $key => $namespaceStmt) {
Expand All @@ -57,7 +61,7 @@ public function enterNode(Node $node): ?Node
}

$useUse = $namespaceStmt->uses[0];
if ($this->isUseImportUsed($useUse, $names)) {
if ($this->isUseImportUsed($useUse, $names, $namespaceName)) {
continue;
}

Expand Down Expand Up @@ -174,7 +178,7 @@ private function resolveAliasName(UseUse $useUse): ?string
/**
* @param string[] $names
*/
private function isUseImportUsed(UseUse $useUse, array $names): bool
private function isUseImportUsed(UseUse $useUse, array $names, ?Name $namespaceName): bool
{
$comparedName = $useUse->name->toString();
if (in_array($comparedName, $names, true)) {
Expand All @@ -188,40 +192,55 @@ private function isUseImportUsed(UseUse $useUse, array $names): bool
}

$alias = $this->resolveAliasName($useUse);
$lastName = $useUse->name->getLast();
$namespaceName = $namespaceName instanceof Name ? $namespaceName->toString() : null;

// match partial import
foreach ($names as $name) {
if (str_ends_with($comparedName, '\\' . $name)) {
if ($this->isSubNamespace($name, $comparedName, $namespacedPrefix)) {
return true;
}

if ($this->isSubNamespace($name, $namespacedPrefix)) {
if (is_string($alias) && $this->isUsedAlias($alias, $name)) {
return true;
}

if (! is_string($alias)) {
if (! str_starts_with($name, $lastName . '\\')) {
continue;
}

if ($alias === $name) {
if ($namespaceName === null) {
return true;
}

if (! str_contains($name, '\\')) {
continue;
}

$namePrefix = Strings::before($name, '\\', 1);
if ($alias === $namePrefix) {
if (! str_starts_with($name, $namespaceName . '\\')) {
return true;
}
}

return false;
}

private function isSubNamespace(string $name, string $namespacedPrefix): bool
private function isUsedAlias(string $alias, string $name): bool
{
if ($alias === $name) {
return true;
}

if (! str_contains($name, '\\')) {
return false;
}

$namePrefix = Strings::before($name, '\\', 1);
return $alias === $namePrefix;
}

private function isSubNamespace(string $name, string $comparedName, string $namespacedPrefix): bool
{
if (str_ends_with($comparedName, '\\' . $name)) {
return true;
}

if (str_starts_with($name, $namespacedPrefix)) {
$subNamespace = substr($name, strlen($namespacedPrefix));
return ! str_contains($subNamespace, '\\');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use Some\Class_ as ClassOrig;
use PhpParser\Node;

final class ConflictLastNameAliased
{
/**
* @param Node\Stmt\Class_ $param
*/
public function run($param): void
{
}
}

?>
-----
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use PhpParser\Node\Stmt\Class_;
final class ConflictLastNameAliased
{
/**
* @param Class_ $param
*/
public function run($param): void
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use Some\Class_;
use PhpParser\Node;

final class ConflictLastNameUnused
{
/**
* @param Node\Stmt\Class_ $param
*/
public function run($param): void
{
}
}

?>
-----
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use PhpParser\Node\Stmt\Class_;
final class ConflictLastNameUnused
{
/**
* @param Class_ $param
*/
public function run($param): void
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use Some\Class_;
use PhpParser\Node;

final class SkipNonDocblockConflictLastName
{
public function run(Node\Stmt\Class_ $param): void
{
new Class_();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use Some\Class_ as ClassOrig;
use PhpParser\Node;

final class SkipConflictLastNameAliasedUsed
{
/**
* @param Node\Stmt\Class_ $param
*/
public function run($param): void
{
new ClassOrig();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Tests\Issues\NamespacedUseAutoImport\Fixture;

use Some\Class_;
use PhpParser\Node;

final class SkipConflictLastNameUsed
{
/**
* @param Node\Stmt\Class_ $param
*/
public function run($param): void
{
new Class_();
}
}

0 comments on commit c431eae

Please sign in to comment.