Skip to content

Commit

Permalink
[Php81] Skip ReadOnlyPropertyRector on Clone $this (#1599)
Browse files Browse the repository at this point in the history
* add failing test for cloned properties

Signed-off-by: Gary Lockett <[email protected]>

* [Php81] Skip ReadOnlyPropertyRector on Clone $this

* final touch: ensure name is equal

* final touch: ensure use TypeWithClassName with check class name is equal

* phpstan

* flip if to reduce deep if

* final touch: early check name not equals, then check type

* comment

* comment

* comment

* comment

* final touch: re-use found Class_

Co-authored-by: Gary Lockett <[email protected]>
  • Loading branch information
samsonasik and Gary Lockett authored Dec 31, 2021
1 parent bc09bdc commit 311ffc6
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Rector\Tests\Php81\Rector\Property\ReadOnlyPropertyRector\Fixture;

final class SkipWriteAlsoClonedProperty
{
private string $name;

public function __construct(string $name)
{
$this->name = $name;
}

public function withName(string $name): self
{
$clone = clone $this;
$clone->name = $name;

return $clone;
}

public function getName()
{
return $this->name;
}
}
25 changes: 21 additions & 4 deletions src/PhpParser/NodeFinder/PropertyFetchFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\Enum\ObjectReference;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\NodeTypeResolver;

final class PropertyFetchFinder
{
Expand All @@ -29,6 +31,7 @@ public function __construct(
private readonly NodeNameResolver $nodeNameResolver,
private readonly ReflectionResolver $reflectionResolver,
private readonly AstResolver $astResolver,
private readonly NodeTypeResolver $nodeTypeResolver
) {
}

Expand Down Expand Up @@ -118,7 +121,7 @@ private function findPropertyFetchesInClassLike(
return false;
}

return $this->isNamePropertyNameEquals($propertyFetch, $propertyName);
return $this->isNamePropertyNameEquals($propertyFetch, $propertyName, $class);
});

/** @var StaticPropertyFetch[] $staticPropertyFetches */
Expand Down Expand Up @@ -146,13 +149,27 @@ private function isInAnonymous(PropertyFetch $propertyFetch, Class_ $class, bool
return $parent !== $class && ! $hasTrait;
}

private function isNamePropertyNameEquals(PropertyFetch $propertyFetch, string $propertyName): bool
private function isNamePropertyNameEquals(PropertyFetch $propertyFetch, string $propertyName, Class_ $class): bool
{
if (! $this->nodeNameResolver->isName($propertyFetch->var, self::THIS)) {
// early check if property fetch name is not equals with property name
// so next check is check var name and var type only
if (! $this->nodeNameResolver->isName($propertyFetch->name, $propertyName)) {
return false;
}

return $this->nodeNameResolver->isName($propertyFetch->name, $propertyName);
if ($this->nodeNameResolver->isName($propertyFetch->var, self::THIS)) {
return true;
}

$propertyFetchVarType = $this->nodeTypeResolver->getType($propertyFetch->var);
if (! $propertyFetchVarType instanceof TypeWithClassName) {
return false;
}

$propertyFetchVarTypeClassName = $propertyFetchVarType->getClassName();
$classLikeName = $this->nodeNameResolver->getName($class);

return $propertyFetchVarTypeClassName === $classLikeName;
}

private function resolvePropertyName(Property | Param $propertyOrPromotedParam): ?string
Expand Down

0 comments on commit 311ffc6

Please sign in to comment.