mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-08 12:20:52 +00:00
[Renaming] Handle var static docblock in union on RenameClassRector (#1248)
* [Renaming] Handle var sstatic docblock in union on RenameClassRector * update fixture * more fixture * more fixture * more fixture * Fixed 🎉 * add array static * Fixed 🎉 * Fixed 🎉 * add failing fixture for array<static> * Fixed 🎉 * better to return early on MethodTagValueNode * move check to IdentifierTypeMapper * clean up * final touch: rename method * final touch: clean up resolve class name * final touch: verify if not already a ClassLike
This commit is contained in:
parent
5d637a8040
commit
50096d7955
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Name;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\NodeTypeResolver\PhpDoc\PhpDocNodeTraverser\RenamingPhpDocNodeVisitorFactory;
|
||||
use Rector\NodeTypeResolver\PhpDocNodeVisitor\ClassRenamePhpDocNodeVisitor;
|
||||
|
@ -27,26 +26,6 @@ final class DocBlockClassRenamer
|
|||
return;
|
||||
}
|
||||
|
||||
$phpDocNode = $phpDocInfo->getPhpDocNode();
|
||||
$tags = $phpDocNode->getTags();
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$tagValueNode = $tag->value;
|
||||
$tagName = $phpDocInfo->resolveNameForPhpDocTagValueNode($tagValueNode);
|
||||
|
||||
if (! is_string($tagName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tagValues = $phpDocInfo->getTagsByName($tagName);
|
||||
foreach ($tagValues as $tagValue) {
|
||||
$name = new Name((string) $tagValue->value);
|
||||
if ($name->isSpecialClassName()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$phpDocNodeTraverser = $this->renamingPhpDocNodeVisitorFactory->create();
|
||||
$this->classRenamePhpDocNodeVisitor->setOldToNewTypes($oldToNewTypes);
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@ namespace Rector\StaticTypeMapper\PhpDocParser;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PHPStan\Analyser\NameScope;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use PHPStan\Reflection\ReflectionProvider;
|
||||
use PHPStan\Type\ClassStringType;
|
||||
use PHPStan\Type\IterableType;
|
||||
use PHPStan\Type\MixedType;
|
||||
|
@ -19,7 +19,6 @@ use PHPStan\Type\StaticType;
|
|||
use PHPStan\Type\Type;
|
||||
use Rector\Core\Enum\ObjectReference;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\NodeCollector\ScopeResolver\ParentClassScopeResolver;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\StaticTypeMapper\Contract\PhpDocParser\PhpDocTypeMapperInterface;
|
||||
|
@ -33,9 +32,9 @@ final class IdentifierTypeMapper implements PhpDocTypeMapperInterface
|
|||
public function __construct(
|
||||
private ObjectTypeSpecifier $objectTypeSpecifier,
|
||||
private ScalarStringToTypeMapper $scalarStringToTypeMapper,
|
||||
private ParentClassScopeResolver $parentClassScopeResolver,
|
||||
private BetterNodeFinder $betterNodeFinder,
|
||||
private NodeNameResolver $nodeNameResolver
|
||||
private NodeNameResolver $nodeNameResolver,
|
||||
private ReflectionProvider $reflectionProvider
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -67,18 +66,16 @@ final class IdentifierTypeMapper implements PhpDocTypeMapperInterface
|
|||
return new ClassStringType();
|
||||
}
|
||||
|
||||
$scope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
if ($loweredName === ObjectReference::SELF()->getValue()) {
|
||||
return $this->mapSelf($node);
|
||||
}
|
||||
|
||||
if ($loweredName === ObjectReference::PARENT()->getValue()) {
|
||||
return $this->mapParent($scope);
|
||||
return $this->mapParent($node);
|
||||
}
|
||||
|
||||
if ($loweredName === ObjectReference::STATIC()->getValue()) {
|
||||
return $this->mapStatic($scope);
|
||||
return $this->mapStatic($node);
|
||||
}
|
||||
|
||||
if ($loweredName === 'iterable') {
|
||||
|
@ -93,13 +90,8 @@ final class IdentifierTypeMapper implements PhpDocTypeMapperInterface
|
|||
|
||||
private function mapSelf(Node $node): MixedType | SelfObjectType
|
||||
{
|
||||
$classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);
|
||||
if (! $classLike instanceof ClassLike) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
// @todo check FQN
|
||||
$className = $this->nodeNameResolver->getName($classLike);
|
||||
$className = $this->resolveClassName($node);
|
||||
if (! is_string($className)) {
|
||||
// self outside the class, e.g. in a function
|
||||
return new MixedType();
|
||||
|
@ -108,9 +100,18 @@ final class IdentifierTypeMapper implements PhpDocTypeMapperInterface
|
|||
return new SelfObjectType($className);
|
||||
}
|
||||
|
||||
private function mapParent(Scope $scope): ParentStaticType | MixedType
|
||||
private function mapParent(Node $node): ParentStaticType | MixedType
|
||||
{
|
||||
$parentClassReflection = $this->parentClassScopeResolver->resolveParentClassReflection($scope);
|
||||
$className = $this->resolveClassName($node);
|
||||
if (! is_string($className)) {
|
||||
// parent outside the class, e.g. in a function
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
/** @var ClassReflection $classReflection */
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
$parentClassReflection = $classReflection->getParentClass();
|
||||
|
||||
if (! $parentClassReflection instanceof ClassReflection) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
@ -118,13 +119,38 @@ final class IdentifierTypeMapper implements PhpDocTypeMapperInterface
|
|||
return new ParentStaticType($parentClassReflection);
|
||||
}
|
||||
|
||||
private function mapStatic(Scope $scope): MixedType | StaticType
|
||||
private function mapStatic(Node $node): MixedType | StaticType
|
||||
{
|
||||
$classReflection = $scope->getClassReflection();
|
||||
if (! $classReflection instanceof ClassReflection) {
|
||||
$className = $this->resolveClassName($node);
|
||||
if (! is_string($className)) {
|
||||
// static outside the class, e.g. in a function
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
/** @var ClassReflection $classReflection */
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
return new StaticType($classReflection);
|
||||
}
|
||||
|
||||
private function resolveClassName(Node $node): ?string
|
||||
{
|
||||
$classLike = $node instanceof ClassLike
|
||||
? $node
|
||||
: $this->betterNodeFinder->findParentType($node, ClassLike::class);
|
||||
|
||||
if (! $classLike instanceof ClassLike) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$className = $this->nodeNameResolver->getName($classLike);
|
||||
if (! is_string($className)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->reflectionProvider->hasClass($className)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $className;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class ArrayStatic extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var static[]|null
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? [$dateTime]
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class ArrayStatic extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var static[]|null
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(\DateTimeInterface $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? [$dateTime]
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class ArrayStatic2 extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var static[]
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime)
|
||||
{
|
||||
$this->dateTime = [$dateTime];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class ArrayStatic2 extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var static[]
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(\DateTimeInterface $dateTime)
|
||||
{
|
||||
$this->dateTime = [$dateTime];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class ArrayStatic3 extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var array<static>
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime)
|
||||
{
|
||||
$this->dateTime = [$dateTime];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class ArrayStatic3 extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var array<static>
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(\DateTimeInterface $dateTime)
|
||||
{
|
||||
$this->dateTime = [$dateTime];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class VarStaticInNullable extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var static|null
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? $dateTime
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class VarStaticInNullable extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var static|null
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(\DateTimeInterface $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? $dateTime
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class VarStaticInNullable extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var ?static
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? $dateTime
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class VarStaticInNullable extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var ?static
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(\DateTimeInterface $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? $dateTime
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class VarStaticInUnion extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var DateTimeInterface|static|null
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(DateTime $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? $dateTime
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
class VarStaticInUnion extends \DateTime
|
||||
{
|
||||
/**
|
||||
* @var DateTimeInterface|static|null
|
||||
*/
|
||||
private $dateTime;
|
||||
|
||||
public function __construct(\DateTimeInterface $dateTime)
|
||||
{
|
||||
$this->dateTime = rand(0,1)
|
||||
? $dateTime
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user