mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-20 10:02:29 +00:00
[Renaming] Handle rename template tag of class on RenameClassRector (#1318)
* Add failing test fixture for RenameClassRector # Failing Test for RenameClassRector Based on https://getrector.org/demo/1ec4e145-1672-628e-a7a2-e3aa19da6373 * Update with class from fixtures * Update rename_generic_template_of_fixture.php.inc * Use full generic example * update fixture * closes #1309 * [ci-review] Rector Rectify * [ci-review] Rector Rectify * phpstan * [ci-review] Rector Rectify * temp back * re-use class node for method get * phpstan * [ci-review] Rector Rectify * [ci-review] Rector Rectify Co-authored-by: Alexander Schranz <alexander@sulu.io> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Tomas Votruba <tomas.vot@gmail.com>
This commit is contained in:
parent
6aeef64c72
commit
5a0947d9a2
|
@ -8,6 +8,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
|
||||
|
@ -22,6 +23,7 @@ final class NodeTypes
|
|||
ReturnTagValueNode::class,
|
||||
ThrowsTagValueNode::class,
|
||||
PropertyTagValueNode::class,
|
||||
TemplateTagValueNode::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use MyNamespace\MyClass;
|
||||
|
||||
/**
|
||||
* @template T of MyClass
|
||||
*/
|
||||
interface MyServiceInterface
|
||||
{
|
||||
/**
|
||||
* @return T
|
||||
*/
|
||||
public function get(): MyClass;
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
|
||||
|
||||
use MyNamespace\MyClass;
|
||||
|
||||
/**
|
||||
* @template T of \MyNewNamespace\MyNewClass
|
||||
*/
|
||||
interface MyServiceInterface
|
||||
{
|
||||
/**
|
||||
* @return T
|
||||
*/
|
||||
public function get(): \MyNewNamespace\MyNewClass;
|
||||
}
|
||||
|
||||
?>
|
|
@ -44,8 +44,8 @@ final class PhpAttributeAnalyzer
|
|||
return false;
|
||||
}
|
||||
|
||||
$reflectionClass = $this->reflectionProvider->getClass($className);
|
||||
$ancestorClassReflections = $reflectionClass->getAncestors();
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
$ancestorClassReflections = $classReflection->getAncestors();
|
||||
foreach ($ancestorClassReflections as $ancestorClassReflection) {
|
||||
$ancestorClassName = $ancestorClassReflection->getName();
|
||||
if ($ancestorClassName === $className) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Transform\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
|
@ -7,6 +9,7 @@ use PhpParser\Node\Name\FullyQualified;
|
|||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Reflection\ReflectionProvider;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
||||
use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer;
|
||||
use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer;
|
||||
|
@ -56,7 +59,9 @@ CODE_SAMPLE
|
|||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class];
|
||||
|
@ -67,11 +72,7 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (
|
||||
$this->isDescendantOfStdclass($node) ||
|
||||
$this->hasNeededAttributeAlready($node) ||
|
||||
$this->hasMagicSetMethod($node)
|
||||
) {
|
||||
if ($this->shouldSkip($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -83,14 +84,14 @@ CODE_SAMPLE
|
|||
return PhpVersionFeature::DEPRECATE_DYNAMIC_PROPERTIES;
|
||||
}
|
||||
|
||||
private function isDescendantOfStdclass(Class_ $node): bool
|
||||
private function isDescendantOfStdclass(Class_ $class): bool
|
||||
{
|
||||
if (! $node->extends instanceof FullyQualified) {
|
||||
if (! $class->extends instanceof FullyQualified) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ancestorClassNames = $this->familyRelationsAnalyzer->getClassLikeAncestorNames($node);
|
||||
return in_array('stdClass', $ancestorClassNames);
|
||||
$ancestorClassNames = $this->familyRelationsAnalyzer->getClassLikeAncestorNames($class);
|
||||
return in_array('stdClass', $ancestorClassNames, true);
|
||||
}
|
||||
|
||||
private function hasNeededAttributeAlready(Class_ $class): bool
|
||||
|
@ -100,19 +101,13 @@ CODE_SAMPLE
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!$class->extends instanceof FullyQualified) {
|
||||
if (! $class->extends instanceof FullyQualified) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->phpAttributeAnalyzer->hasInheritedPhpAttribute($class, self::ATTRIBUTE);
|
||||
}
|
||||
|
||||
private function hasMagicSetMethod(Class_ $class): bool
|
||||
{
|
||||
$classReflection = $this->reflectionProvider->getClass($class->namespacedName);
|
||||
return $classReflection->hasMethod('__set');
|
||||
}
|
||||
|
||||
private function addAllowDynamicPropertiesAttribute(Class_ $class): Class_
|
||||
{
|
||||
$attributeGroup = $this->phpAttributeGroupFactory->createFromClass(self::ATTRIBUTE);
|
||||
|
@ -120,4 +115,24 @@ CODE_SAMPLE
|
|||
|
||||
return $class;
|
||||
}
|
||||
|
||||
private function shouldSkip(Class_ $class): bool
|
||||
{
|
||||
if ($this->isDescendantOfStdclass($class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->hasNeededAttributeAlready($class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->hasMagicSetMethod($class);
|
||||
}
|
||||
|
||||
private function hasMagicSetMethod(Class_ $class): bool
|
||||
{
|
||||
$className = (string) $this->getName($class);
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
return $classReflection->hasMethod(MethodName::__SET);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user