diff --git a/packages/CodingStyle/src/Imports/ShortNameResolver.php b/packages/CodingStyle/src/Imports/ShortNameResolver.php index fd376aff2275..50cddfb11b93 100644 --- a/packages/CodingStyle/src/Imports/ShortNameResolver.php +++ b/packages/CodingStyle/src/Imports/ShortNameResolver.php @@ -16,6 +16,11 @@ final class ShortNameResolver */ private $callableNodeTraverser; + /** + * @var string[][] + */ + private $shortNamesByNamespaceObjectHash = []; + public function __construct(CallableNodeTraverser $callableNodeTraverser) { $this->callableNodeTraverser = $callableNodeTraverser; @@ -26,10 +31,22 @@ public function __construct(CallableNodeTraverser $callableNodeTraverser) */ public function resolveForNode(Node $node): array { + /** @var Namespace_|null $namespace */ $namespace = $node->getAttribute(AttributeKey::NAMESPACE_NODE); + if ($namespace === null) { + return []; + } + + $namespaceHash = spl_object_hash($namespace); + if (isset($this->shortNamesByNamespaceObjectHash[$namespaceHash])) { + return $this->shortNamesByNamespaceObjectHash[$namespaceHash]; + } + if ($namespace instanceof Namespace_) { - return $this->resolveForNamespace($namespace); + $shortNames = $this->resolveForNamespace($namespace); + $this->shortNamesByNamespaceObjectHash[$namespaceHash] = $shortNames; + return $shortNames; } return []; diff --git a/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php b/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php index 078302ad18f5..f79168730893 100644 --- a/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php +++ b/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php @@ -16,6 +16,8 @@ use PhpParser\Node\Stmt\Use_; use PhpParser\Node\Stmt\UseUse; use PhpParser\NodeVisitor\NameResolver; +use Rector\CodingStyle\Imports\ShortNameResolver; +use Rector\CodingStyle\Naming\ClassNaming; use Rector\Exception\ShouldNotHappenException; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\PhpParser\NodeTraverser\CallableNodeTraverser; @@ -40,9 +42,24 @@ final class RemoveUnusedAliasRector extends AbstractRector */ private $callableNodeTraverser; - public function __construct(CallableNodeTraverser $callableNodeTraverser) - { + /** + * @var ShortNameResolver + */ + private $shortNameResolver; + + /** + * @var ClassNaming + */ + private $classNaming; + + public function __construct( + CallableNodeTraverser $callableNodeTraverser, + ShortNameResolver $shortNameResolver, + ClassNaming $classNaming + ) { $this->callableNodeTraverser = $callableNodeTraverser; + $this->shortNameResolver = $shortNameResolver; + $this->classNaming = $classNaming; } public function getDefinition(): RectorDefinition @@ -83,8 +100,14 @@ public function refactor(Node $node): ?Node { $this->resolvedNodeNames = []; $this->resolveUsedNameNodes($node); - if ($this->resolvedNodeNames === []) { - return null; + + // collect differentiated aliases + $useNamesAliasToName = []; + + $shortNames = $this->shortNameResolver->resolveForNode($node); + foreach ($shortNames as $alias => $useImport) { + $shortName = $this->classNaming->getShortName($useImport); + $useNamesAliasToName[$shortName][] = $alias; } foreach ($node->uses as $use) { @@ -96,7 +119,7 @@ public function refactor(Node $node): ?Node $aliasName = $this->getName($use->alias); // both are used → nothing to remove - if (isset($this->resolvedNodeNames[$lastName]) && isset($this->resolvedNodeNames[$aliasName])) { + if (isset($this->resolvedNodeNames[$lastName], $this->resolvedNodeNames[$aliasName])) { continue; } @@ -113,6 +136,11 @@ public function refactor(Node $node): ?Node // only alias name is used → use last name directly if (isset($this->resolvedNodeNames[$aliasName])) { + // keep to differentiate 2 alaises classes + if (isset($useNamesAliasToName[$lastName]) && count($useNamesAliasToName[$lastName]) > 1) { + continue; + } + $this->renameNameNode($this->resolvedNodeNames[$aliasName], $lastName); $use->alias = null; } diff --git a/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/Fixture/different_namespaces_same_name.php.inc b/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/Fixture/skip_different_namespaces_same_name.php.inc similarity index 99% rename from packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/Fixture/different_namespaces_same_name.php.inc rename to packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/Fixture/skip_different_namespaces_same_name.php.inc index a09126fe1234..7119d6c94a8c 100644 --- a/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/Fixture/different_namespaces_same_name.php.inc +++ b/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/Fixture/skip_different_namespaces_same_name.php.inc @@ -13,6 +13,3 @@ class DifferentNamespacesSameClass $secondStandalone = new SecondStandalone; } } - -?> - diff --git a/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/RemoveUnusedAliasRectorTest.php b/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/RemoveUnusedAliasRectorTest.php index 047cb694d572..fc2f11d8a69e 100644 --- a/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/RemoveUnusedAliasRectorTest.php +++ b/packages/CodingStyle/tests/Rector/Use_/RemoveUnusedAliasRector/RemoveUnusedAliasRectorTest.php @@ -13,7 +13,6 @@ public function test(): void __DIR__ . '/Fixture/fixture.php.inc', __DIR__ . '/Fixture/used.php.inc', __DIR__ . '/Fixture/class_name.php.inc', - __DIR__ . '/Fixture/different_namespaces_same_name.php.inc', # no namespace __DIR__ . '/Fixture/no_namespace.php.inc', __DIR__ . '/Fixture/no_namespace_class_name.php.inc', @@ -23,6 +22,8 @@ public function test(): void # interfaces __DIR__ . '/Fixture/interace_extending.php.inc', __DIR__ . '/Fixture/doc_block.php.inc', + # skip + __DIR__ . '/Fixture/skip_different_namespaces_same_name.php.inc', ]); } diff --git a/packages/Php/src/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php b/packages/Php/src/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php index b04f47a5d39c..316963f9449e 100644 --- a/packages/Php/src/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php +++ b/packages/Php/src/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php @@ -121,7 +121,7 @@ public function refactor(Node $node): ?Node $this->undefinedVariables[] = $variableName; }); } catch (BreakScopeException $breakScopeException) { - // nothing + // @ignoreException } if ($this->undefinedVariables === []) { diff --git a/phpstan.neon b/phpstan.neon index 68e2d19c3824..a33fba8db50e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -168,3 +168,6 @@ parameters: - '#Cannot cast array\|bool\|string\|null to string#' - '#Method Rector\\ContributorTools\\Configuration\\ConfigurationFactory\:\:resolveCategoryFromFqnNodeTypes\(\) should return string but returns string\|null#' - '#Method Rector\\Legacy\\Rector\\ClassMethod\\ChangeSingletonToServiceRector\:\:matchStaticPropertyFetchAndGetSingletonMethodName\(\) should return array\|null but returns array#' + + # future compat + - '#Call to function method_exists\(\) with (.*?) will always evaluate to false#' diff --git a/src/EventDispatcher/AutowiredEventDispatcher.php b/src/EventDispatcher/AutowiredEventDispatcher.php index 4f3fa0c95a16..19ae27f5cdf7 100644 --- a/src/EventDispatcher/AutowiredEventDispatcher.php +++ b/src/EventDispatcher/AutowiredEventDispatcher.php @@ -16,7 +16,7 @@ public function __construct(array $eventSubscribers) $this->addSubscriber($eventSubscriber); } - if (method_exists(get_parent_class($this), '__construct')) { + if (method_exists(parent::class, '__construct')) { parent::__construct(); } }