[PHP 8.2] Skip readonly class on property without type in ReadOnlyClassRector (#2398)

This commit is contained in:
Tomas Votruba 2022-05-31 13:35:03 +02:00 committed by GitHub
parent 3619d8bdaa
commit 967279219d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 22 deletions

View File

@ -0,0 +1,11 @@
<?php
namespace Rector\Tests\Php82\Rector\Class_\ReadOnlyClassRector\Fixture;
final class SkipMissingPromotedPropertyType
{
public function __construct(
private readonly $promotedProperty
) {
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace Rector\Tests\Php82\Rector\Class_\ReadOnlyClassRector\Fixture;
final class SkipMissingPropertyType
{
private readonly $property;
}

View File

@ -0,0 +1,8 @@
<?php
namespace Rector\Tests\Php82\Rector\Class_\ReadOnlyClassRector\Fixture;
final class SkipStaticProperties
{
private static string $property;
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\Php82\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
@ -106,20 +107,7 @@ CODE_SAMPLE
private function shouldSkip(Class_ $class): bool
{
// need to have test fixture once feature added to nikic/PHP-Parser
if ($this->visibilityManipulator->hasVisibility($class, Visibility::READONLY)) {
return true;
}
if ($this->classAnalyzer->isAnonymousClass($class)) {
return true;
}
if (! $class->isFinal()) {
return true;
}
if ($this->phpAttributeAnalyzer->hasPhpAttribute($class, self::ATTRIBUTE)) {
if ($this->shouldSkipClass($class)) {
return true;
}
@ -128,6 +116,13 @@ CODE_SAMPLE
return true;
}
foreach ($properties as $property) {
// properties of readonly class must always have type
if ($property->type === null) {
return true;
}
}
$constructClassMethod = $class->getMethod(MethodName::CONSTRUCT);
if (! $constructClassMethod instanceof ClassMethod) {
// no __construct means no property promotion, skip if class has no property defined
@ -140,14 +135,7 @@ CODE_SAMPLE
return $properties === [];
}
foreach ($params as $param) {
// has non-property promotion, skip
if (! $this->visibilityManipulator->hasVisibility($param, Visibility::READONLY)) {
return true;
}
}
return false;
return $this->shouldSkipParams($params);
}
/**
@ -163,4 +151,42 @@ CODE_SAMPLE
return false;
}
private function shouldSkipClass(Class_ $class): bool
{
// need to have test fixture once feature added to nikic/PHP-Parser
if ($this->visibilityManipulator->hasVisibility($class, Visibility::READONLY)) {
return true;
}
if ($this->classAnalyzer->isAnonymousClass($class)) {
return true;
}
if (! $class->isFinal()) {
return true;
}
return $this->phpAttributeAnalyzer->hasPhpAttribute($class, self::ATTRIBUTE);
}
/**
* @param Param[] $params
*/
private function shouldSkipParams(array $params): bool
{
foreach ($params as $param) {
// has non-property promotion, skip
if (! $this->visibilityManipulator->hasVisibility($param, Visibility::READONLY)) {
return true;
}
// type is missing, invalid syntax
if ($param->type === null) {
return true;
}
}
return false;
}
}