mirror of https://github.com/rectorphp/rector.git
[Renaming] Skip docblock rename different namespace on RenameClassRector (#2419)
* [Renaming] Skip docblock rename different namespace on RenameClassRector
* debug
* [ci-review] Rector Rectify
* debug
* [ci-review] Rector Rectify
* \ between namespace and name
* up
* debug
* debug
* check no namespace
* up
* Fixed 🎉
* final touch: add GroupUse_ support
* final touch: add GroupUse_ support
* final touch: clean up
* really final touch: clean up
* final touch: ensure no subnamespace check as check against getLast()
* final touch: remove unnneeded string cast
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
parent
e8f058a6e4
commit
283a9af3f0
|
@ -4,6 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\NodeTypeResolver\PhpDocNodeVisitor;
|
||||
|
||||
use PhpParser\Node as PhpParserNode;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\GroupUse;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
@ -11,6 +16,11 @@ use PHPStan\Type\ObjectType;
|
|||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
use Rector\Core\Configuration\CurrentNodeProvider;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\Comparing\NodeComparator;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\Naming\Naming\UseImportsResolver;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\ValueObject\OldToNewType;
|
||||
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
|
@ -26,7 +36,11 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
|
||||
public function __construct(
|
||||
private readonly StaticTypeMapper $staticTypeMapper,
|
||||
private readonly CurrentNodeProvider $currentNodeProvider
|
||||
private readonly CurrentNodeProvider $currentNodeProvider,
|
||||
private readonly UseImportsResolver $useImportsResolver,
|
||||
private readonly BetterNodeFinder $betterNodeFinder,
|
||||
private readonly NodeNameResolver $nodeNameResolver,
|
||||
private readonly NodeComparator $nodeComparator
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -48,7 +62,11 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$staticType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($node, $phpParserNode);
|
||||
$identifier = clone $node;
|
||||
|
||||
$namespacedName = $this->resolveNamespacedName($phpParserNode, $identifier->name);
|
||||
$identifier->name = $namespacedName;
|
||||
$staticType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($identifier, $phpParserNode);
|
||||
|
||||
// make sure to compare FQNs
|
||||
if ($staticType instanceof ShortenedObjectType) {
|
||||
|
@ -84,4 +102,59 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
{
|
||||
$this->oldToNewTypes = $oldToNewTypes;
|
||||
}
|
||||
|
||||
private function resolveNamespacedName(PhpParserNode $phpParserNode, string $name): string
|
||||
{
|
||||
if (str_starts_with($name, '\\')) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if (str_contains($name, '\\')) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$namespace = $this->betterNodeFinder->findParentType($phpParserNode, Namespace_::class);
|
||||
$uses = $this->useImportsResolver->resolveForNode($phpParserNode);
|
||||
|
||||
if (! $namespace instanceof Namespace_) {
|
||||
return $this->resolveNamefromUse($uses, $name);
|
||||
}
|
||||
|
||||
$originalNode = $namespace->getAttribute(AttributeKey::ORIGINAL_NODE);
|
||||
if (! $this->nodeComparator->areNodesEqual($originalNode, $namespace)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if ($uses === []) {
|
||||
$namespaceName = $this->nodeNameResolver->getName($namespace);
|
||||
return $namespaceName . '\\' . $name;
|
||||
}
|
||||
|
||||
return $this->resolveNamefromUse($uses, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Use_[]|GroupUse[] $uses
|
||||
*/
|
||||
private function resolveNamefromUse(array $uses, string $name): string
|
||||
{
|
||||
foreach ($uses as $use) {
|
||||
$prefix = $use instanceof GroupUse
|
||||
? $use->prefix . '\\'
|
||||
: '';
|
||||
|
||||
foreach ($use->uses as $useUse) {
|
||||
if ($useUse->alias instanceof Identifier) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lastName = $useUse->name->getLast();
|
||||
if ($lastName === $name) {
|
||||
return $prefix . $useUse->name->toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Future note: Not inside namespace on purpose to check last name Use_ used
|
||||
*/
|
||||
use \Company2\Bar;
|
||||
|
||||
final class SkipDocblockRenameDifferentNamespace
|
||||
{
|
||||
/**
|
||||
* @param Bar $foo
|
||||
*/
|
||||
public function importedClassesReferencedViaAlias($foo)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
final class SkipDocblockRenameDifferentNamespace2
|
||||
{
|
||||
/**
|
||||
* @param Bar $foo
|
||||
*/
|
||||
public function importedClassViaSameNamespace($foo)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use \Company2\{ Bar };
|
||||
|
||||
final class SkipDocblockRenameDifferentNamespace3
|
||||
{
|
||||
/**
|
||||
* @param Bar $foo
|
||||
*/
|
||||
public function importedClassViaSameNamespace($foo)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Future note: Not inside namespace on purpose to check last name GroupUse_ used
|
||||
*/
|
||||
|
||||
use \Company2\{ Bar };
|
||||
|
||||
final class SkipDocblockRenameDifferentNamespace4
|
||||
{
|
||||
/**
|
||||
* @param Bar $foo
|
||||
*/
|
||||
public function importedClassViaSameNamespace($foo)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -45,5 +45,6 @@ return static function (RectorConfig $rectorConfig): void {
|
|||
SomeNonFinalClass::class => SomeFinalClass::class,
|
||||
'Foo\Bar' => 'Foo\Bar\BarInterface',
|
||||
'Doctrine\DBAL\DBALException' => 'Doctrine\DBAL\Exception',
|
||||
'Bar' => 'BarInterface',
|
||||
]);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue