diff --git a/rules-tests/Php81/Rector/Property/ReadOnlyPropertyRector/Fixture/skip_assigned_in_named_constructor.php.inc b/rules-tests/Php81/Rector/Property/ReadOnlyPropertyRector/Fixture/skip_assigned_in_named_constructor.php.inc new file mode 100644 index 00000000000..fa210cfa78a --- /dev/null +++ b/rules-tests/Php81/Rector/Property/ReadOnlyPropertyRector/Fixture/skip_assigned_in_named_constructor.php.inc @@ -0,0 +1,25 @@ +date = new \DateTime(); + } + + public function getDate(): \DateTimeInterface + { + return $this->date; + } + + public static function create(\DateTimeInterface $date): self + { + $ack = new self(); + $ack->date = $date; + + return $ack; + } +} diff --git a/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php b/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php index 0a410a99d1d..1f5d45945ad 100644 --- a/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php +++ b/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php @@ -153,7 +153,7 @@ private function shouldSkipClass(Class_ $class): bool private function removePropertyAssigns(Class_ $class, string $propertyName): void { - $this->traverseNodesWithCallable($class, function (Node $node) use ($propertyName): ?int { + $this->traverseNodesWithCallable($class, function (Node $node) use ($class, $propertyName): ?int { if (! $node instanceof Expression) { return null; } @@ -163,7 +163,7 @@ private function removePropertyAssigns(Class_ $class, string $propertyName): voi } $assign = $node->expr; - if (! $this->propertyFetchFinder->isLocalPropertyFetchByName($assign->var, $propertyName)) { + if (! $this->propertyFetchFinder->isLocalPropertyFetchByName($assign->var, $class, $propertyName)) { return null; } diff --git a/src/PhpParser/NodeFinder/PropertyFetchFinder.php b/src/PhpParser/NodeFinder/PropertyFetchFinder.php index 604a2db4793..ca963ced932 100644 --- a/src/PhpParser/NodeFinder/PropertyFetchFinder.php +++ b/src/PhpParser/NodeFinder/PropertyFetchFinder.php @@ -24,6 +24,7 @@ use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\NodeTypeResolver; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; +use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType; final class PropertyFetchFinder { @@ -120,7 +121,7 @@ function (Node $subNode) use (&$propertyArrayDimFetches, $propertyName) { return $propertyArrayDimFetches; } - public function isLocalPropertyFetchByName(Expr $expr, string $propertyName): bool + public function isLocalPropertyFetchByName(Expr $expr, Class_|Trait_ $class, string $propertyName): bool { if (! $expr instanceof PropertyFetch) { return false; @@ -130,7 +131,15 @@ public function isLocalPropertyFetchByName(Expr $expr, string $propertyName): bo return false; } - return $this->nodeNameResolver->isName($expr->var, 'this'); + if ($this->nodeNameResolver->isName($expr->var, 'this')) { + return true; + } + + $type = $this->nodeTypeResolver->getType($expr->var); + return $type instanceof FullyQualifiedObjectType && $this->nodeNameResolver->isName( + $class, + $type->getClassName() + ); } /** @@ -187,7 +196,7 @@ private function isNamePropertyNameEquals( ): bool { // 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->isLocalPropertyFetchByName($propertyFetch, $propertyName)) { + if (! $this->isLocalPropertyFetchByName($propertyFetch, $class, $propertyName)) { return false; }