[Naming] Skip used by trait on RenamePropertyToMatchTypeRector (#2077)

* [Naming] Skip used by trait on RenamePropertyToMatchTypeRector

* Fixed 🎉

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Abdul Malik Ikhsan 2022-04-15 14:21:53 +07:00 committed by GitHub
parent 4519646150
commit 8be11db297
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 31 deletions

View File

@ -0,0 +1,21 @@
<?php
namespace Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
use Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Source\EliteManager;
use Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Source\UseEliteManagerTrait;
class SkipUsedByTrait
{
use UseEliteManagerTrait;
/**
* @var EliteManager
*/
private $eventManager;
public function __construct(EliteManager $eventManager)
{
$this->eventManager = $eventManager;
}
}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Source;
trait UseEliteManagerTrait
{
public function trigger($name)
{
$this->eventManager->trigger($name);
}
}

View File

@ -4,8 +4,11 @@ declare(strict_types=1);
namespace Rector\Naming\ExpectedNameResolver;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\NodeManipulator\PropertyManipulator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Naming\Naming\PropertyNaming;
use Rector\Naming\ValueObject\ExpectedName;
use Rector\NodeNameResolver\NodeNameResolver;
@ -15,12 +18,24 @@ final class MatchPropertyTypeExpectedNameResolver
public function __construct(
private readonly PropertyNaming $propertyNaming,
private readonly PhpDocInfoFactory $phpDocInfoFactory,
private readonly NodeNameResolver $nodeNameResolver
private readonly NodeNameResolver $nodeNameResolver,
private readonly BetterNodeFinder $betterNodeFinder,
private readonly PropertyManipulator $propertyManipulator
) {
}
public function resolve(Property $property): ?string
{
$class = $this->betterNodeFinder->findParentType($property, Class_::class);
if (! $class instanceof Class_) {
return null;
}
$propertyName = $this->nodeNameResolver->getName($property);
if ($this->propertyManipulator->isUsedByTrait($class, $propertyName)) {
return null;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
$expectedName = $this->propertyNaming->getExpectedNameFromType($phpDocInfo->getVarType());

View File

@ -7,12 +7,10 @@ namespace Rector\Php74\Guard;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Trait_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use Rector\Core\NodeAnalyzer\PropertyAnalyzer;
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\NodeManipulator\PropertyManipulator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -22,9 +20,8 @@ final class MakePropertyTypedGuard
public function __construct(
private readonly BetterNodeFinder $betterNodeFinder,
private readonly NodeNameResolver $nodeNameResolver,
private readonly AstResolver $astResolver,
private readonly PropertyFetchAnalyzer $propertyFetchAnalyzer,
private readonly PropertyAnalyzer $propertyAnalyzer
private readonly PropertyAnalyzer $propertyAnalyzer,
private readonly PropertyManipulator $propertyManipulator
) {
}
@ -59,7 +56,7 @@ final class MakePropertyTypedGuard
$propertyName = $this->nodeNameResolver->getName($property);
if ($this->isModifiedByTrait($class, $propertyName)) {
if ($this->propertyManipulator->isUsedByTrait($class, $propertyName)) {
return false;
}
@ -74,24 +71,6 @@ final class MakePropertyTypedGuard
return $this->isSafeProtectedProperty($property, $class);
}
private function isModifiedByTrait(Class_ $class, string $propertyName): bool
{
foreach ($class->getTraitUses() as $traitUse) {
foreach ($traitUse->traits as $traitName) {
$trait = $this->astResolver->resolveClassFromName($traitName->toString());
if (! $trait instanceof Trait_) {
continue;
}
if ($this->propertyFetchAnalyzer->containsLocalPropertyFetchName($trait, $propertyName)) {
return true;
}
}
}
return false;
}
private function isSafeProtectedProperty(Property $property, Class_ $class): bool
{
if (! $property->isProtected()) {

View File

@ -25,9 +25,14 @@ final class VersionResolver
*/
public const RELEASE_DATE = '@release_date@';
/**
* @var string
*/
private const GIT = 'git';
public static function resolvePackageVersion(): string
{
$pointsAtProcess = new Process(['git', 'tag', '--points-at'], __DIR__);
$pointsAtProcess = new Process([self::GIT, 'tag', '--points-at'], __DIR__);
if ($pointsAtProcess->run() !== Command::SUCCESS) {
throw new VersionException(
'You must ensure to run compile from composer git repository clone and that git binary is available.'
@ -35,11 +40,11 @@ final class VersionResolver
}
$tag = trim($pointsAtProcess->getOutput());
if ($tag) {
if ($tag !== '' && $tag !== '0') {
return $tag;
}
$process = new Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);
$process = new Process([self::GIT, 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);
if ($process->run() !== Command::SUCCESS) {
throw new VersionException(
'You must ensure to run compile from composer git repository clone and that git binary is available.'
@ -52,7 +57,7 @@ final class VersionResolver
public static function resolverReleaseDateTime(): DateTime
{
$process = new Process(['git', 'log', '-n1', '--pretty=%ci', 'HEAD'], __DIR__);
$process = new Process([self::GIT, 'log', '-n1', '--pretty=%ci', 'HEAD'], __DIR__);
if ($process->run() !== Command::SUCCESS) {
throw new VersionException(
'You must ensure to run compile from composer git repository clone and that git binary is available.'

View File

@ -24,11 +24,14 @@ use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Trait_;
use PhpParser\Node\Stmt\Unset_;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder;
use Rector\Core\Reflection\ReflectionResolver;
@ -83,7 +86,9 @@ final class PropertyManipulator
private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer,
private readonly NodeTypeResolver $nodeTypeResolver,
private readonly PromotedPropertyResolver $promotedPropertyResolver,
private readonly ConstructorAssignDetector $constructorAssignDetector
private readonly ConstructorAssignDetector $constructorAssignDetector,
private readonly AstResolver $astResolver,
private readonly PropertyFetchAnalyzer $propertyFetchAnalyzer
) {
}
@ -229,6 +234,24 @@ final class PropertyManipulator
return null;
}
public function isUsedByTrait(Class_ $class, string $propertyName): bool
{
foreach ($class->getTraitUses() as $traitUse) {
foreach ($traitUse->traits as $traitName) {
$trait = $this->astResolver->resolveClassFromName($traitName->toString());
if (! $trait instanceof Trait_) {
continue;
}
if ($this->propertyFetchAnalyzer->containsLocalPropertyFetchName($trait, $propertyName)) {
return true;
}
}
}
return false;
}
private function isPropertyAssignedOnlyInConstructor(
ClassLike $classLike,
string $propertyName,