rector/rules/Naming/Rector/Class_/RenamePropertyToMatchTypeRe...

129 lines
4.1 KiB
PHP

<?php
declare (strict_types=1);
namespace Rector\Naming\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Property;
use Rector\Naming\ExpectedNameResolver\MatchPropertyTypeExpectedNameResolver;
use Rector\Naming\PropertyRenamer\MatchTypePropertyRenamer;
use Rector\Naming\PropertyRenamer\PropertyPromotionRenamer;
use Rector\Naming\ValueObject\PropertyRename;
use Rector\Naming\ValueObjectFactory\PropertyRenameFactory;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\RenamePropertyToMatchTypeRectorTest
*/
final class RenamePropertyToMatchTypeRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Naming\PropertyRenamer\MatchTypePropertyRenamer
*/
private $matchTypePropertyRenamer;
/**
* @readonly
* @var \Rector\Naming\ValueObjectFactory\PropertyRenameFactory
*/
private $propertyRenameFactory;
/**
* @readonly
* @var \Rector\Naming\ExpectedNameResolver\MatchPropertyTypeExpectedNameResolver
*/
private $matchPropertyTypeExpectedNameResolver;
/**
* @readonly
* @var \Rector\Naming\PropertyRenamer\PropertyPromotionRenamer
*/
private $propertyPromotionRenamer;
/**
* @var bool
*/
private $hasChanged = \false;
public function __construct(MatchTypePropertyRenamer $matchTypePropertyRenamer, PropertyRenameFactory $propertyRenameFactory, MatchPropertyTypeExpectedNameResolver $matchPropertyTypeExpectedNameResolver, PropertyPromotionRenamer $propertyPromotionRenamer)
{
$this->matchTypePropertyRenamer = $matchTypePropertyRenamer;
$this->propertyRenameFactory = $propertyRenameFactory;
$this->matchPropertyTypeExpectedNameResolver = $matchPropertyTypeExpectedNameResolver;
$this->propertyPromotionRenamer = $propertyPromotionRenamer;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Rename property and method param to match its type', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
/**
* @var EntityManager
*/
private $eventManager;
public function __construct(EntityManager $eventManager)
{
$this->eventManager = $eventManager;
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
/**
* @var EntityManager
*/
private $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Class_::class, Interface_::class];
}
/**
* @param Class_|Interface_ $node
*/
public function refactor(Node $node) : ?Node
{
$this->hasChanged = \false;
$this->refactorClassProperties($node);
$hasPromotedPropertyChanged = $this->propertyPromotionRenamer->renamePropertyPromotion($node);
if ($this->hasChanged) {
return $node;
}
if ($hasPromotedPropertyChanged) {
return $node;
}
return null;
}
private function refactorClassProperties(ClassLike $classLike) : void
{
foreach ($classLike->getProperties() as $property) {
$expectedPropertyName = $this->matchPropertyTypeExpectedNameResolver->resolve($property, $classLike);
if ($expectedPropertyName === null) {
continue;
}
$propertyRename = $this->propertyRenameFactory->createFromExpectedName($classLike, $property, $expectedPropertyName);
if (!$propertyRename instanceof PropertyRename) {
continue;
}
$renameProperty = $this->matchTypePropertyRenamer->rename($propertyRename);
if (!$renameProperty instanceof Property) {
continue;
}
$this->hasChanged = \true;
}
}
}