Skip to content

Commit

Permalink
[Downgrade] Add class method param to DowngradeEnumToConstantListClas…
Browse files Browse the repository at this point in the history
…sRector (#2417)

* add param enum downgrade

* [ci-review] Rector Rectify

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
TomasVotruba and actions-user committed Jun 2, 2022
1 parent 340f5b9 commit e368dab
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 16 deletions.
75 changes: 70 additions & 5 deletions build/target-repository/docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 513 Rules Overview
# 516 Rules Overview

<br>

Expand Down Expand Up @@ -38,10 +38,12 @@

- [DowngradePhp74](#downgradephp74) (12)

- [DowngradePhp80](#downgradephp80) (28)
- [DowngradePhp80](#downgradephp80) (29)

- [DowngradePhp81](#downgradephp81) (9)

- [DowngradePhp82](#downgradephp82) (1)

- [EarlyReturn](#earlyreturn) (11)

- [MysqlToMysqli](#mysqltomysqli) (4)
Expand Down Expand Up @@ -70,7 +72,7 @@

- [Php74](#php74) (14)

- [Php80](#php80) (17)
- [Php80](#php80) (18)

- [Php81](#php81) (9)

Expand Down Expand Up @@ -2192,13 +2194,12 @@ Changes `$this->...` and static:: to self:: or vise versa for given types

```php
use PHPUnit\Framework\TestCase;
use Rector\CodingStyle\Enum\PreferenceSelfThis;
use Rector\CodingStyle\Rector\MethodCall\PreferThisOrSelfMethodCallRector;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(PreferThisOrSelfMethodCallRector::class, [
TestCase::class => PreferenceSelfThis::PREFER_SELF(),
TestCase::class => 'prefer_self',
]);
};
```
Expand Down Expand Up @@ -5413,6 +5414,26 @@ Add parentheses around non-dereferenceable expressions.

<br>

### DowngradeEnumToConstantListClassRector

Downgrade enum to constant list class

- class: [`Rector\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector`](../rules/DowngradePhp80/Rector/Enum_/DowngradeEnumToConstantListClassRector.php)

```diff
-enum Direction
+class Direction
{
- case LEFT;
+ public const LEFT = 'left';

- case RIGHT;
+ public const RIGHT = 'right';
}
```

<br>

### DowngradeMatchToSwitchRector

Downgrade `match()` to `switch()`
Expand Down Expand Up @@ -6050,6 +6071,30 @@ Remove "readonly" property type, add a "@readonly" tag instead

<br>

## DowngradePhp82

### DowngradeReadonlyClassRector

Remove "readonly" class type, decorate all properties to "readonly"

- class: [`Rector\DowngradePhp82\Rector\Class_\DowngradeReadonlyClassRector`](../rules/DowngradePhp82/Rector/Class_/DowngradeReadonlyClassRector.php)

```diff
-final readonly class SomeClass
+final class SomeClass
{
- public string $foo;
+ public readonly string $foo;

public function __construct()
{
$this->foo = 'foo';
}
}
```

<br>

## EarlyReturn

### ChangeAndIfToEarlyReturnRector
Expand Down Expand Up @@ -8178,6 +8223,26 @@ Change simple property init and assign to constructor promotion

<br>

### ConstantListClassToEnumRector

Upgrade constant list classes to full blown enum

- class: [`Rector\Php80\Rector\Class_\ConstantListClassToEnumRector`](../rules/Php80/Rector/Class_/ConstantListClassToEnumRector.php)

```diff
-class Direction
+enum Direction
{
- public const LEFT = 'left';
+ case LEFT;

- public const RIGHT = 'right';
+ case RIGHT;
}
```

<br>

### DoctrineAnnotationClassToAttributeRector

Refactor Doctrine `@annotation` annotated class to a PHP 8.0 attribute class
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Fixture;

use Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source\AnythingYouWant;

final class NoTypeParamMethod
{
public function with(AnythingYouWant $anythingYouWant)
{
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Fixture;

use Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source\AnythingYouWant;

final class NoTypeParamMethod
{
/**
* @param \Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source\AnythingYouWant::* $anythingYouWant
*/
public function with($anythingYouWant)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Fixture;

use Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source\GearValue;

final class ParamMethod
{
public function changeGear(GearValue $gearValue)
{
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Fixture;

use Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source\GearValue;

final class ParamMethod
{
/**
* @param \Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source\GearValue::* $gearValue
*/
public function changeGear(string $gearValue)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source;

enum AnythingYouWant
{
const LEFT = 'left';

const TWO = 5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace Rector\Tests\DowngradePhp80\Rector\Enum_\DowngradeEnumToConstantListClassRector\Source;

enum GearValue
{
case FIRST;

case SECOND;
}
97 changes: 97 additions & 0 deletions rules/DowngradePhp80/NodeAnalyzer/EnumAnalyzer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace Rector\DowngradePhp80\NodeAnalyzer;

use PhpParser\Node\Expr;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\Enum_;
use PhpParser\Node\Stmt\EnumCase;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\AstResolver;
use Rector\NodeTypeResolver\NodeTypeResolver;

final class EnumAnalyzer
{
public function __construct(
private readonly AstResolver $astResolver,
private readonly NodeTypeResolver $nodeTypeResolver
) {
}

public function resolveType(ClassReflection $classReflection): ?Identifier
{
$class = $this->astResolver->resolveClassFromClassReflection($classReflection, $classReflection->getName());
if (! $class instanceof Enum_) {
throw new ShouldNotHappenException();
}

$scalarType = $class->scalarType;
if ($scalarType instanceof Identifier) {
// can be only int or string
return $scalarType;
}

$enumExprTypes = $this->resolveEnumExprTypes($class);

$enumExprTypeClasses = [];

foreach ($enumExprTypes as $enumExprType) {
$enumExprTypeClasses[] = $enumExprType::class;
}

$uniqueEnumExprTypeClasses = array_unique($enumExprTypeClasses);
if (count($uniqueEnumExprTypeClasses) === 1) {
$uniqueEnumExprTypeClass = $uniqueEnumExprTypeClasses[0];
if (is_a($uniqueEnumExprTypeClass, StringType::class, true)) {
return new Identifier('string');
}

if (is_a($uniqueEnumExprTypeClass, IntegerType::class, true)) {
return new Identifier('int');
}

if (is_a($uniqueEnumExprTypeClass, FloatType::class, true)) {
return new Identifier('float');
}
}

// unknown or multiple types
return null;
}

/**
* @return Type[]
*/
private function resolveEnumExprTypes(Enum_ $enum): array
{
$enumExprTypes = [];

foreach ($enum->stmts as $classStmt) {
if (! $classStmt instanceof EnumCase) {
continue;
}

$enumExprTypes[] = $this->resolveEnumCaseType($classStmt);
}

return $enumExprTypes;
}

private function resolveEnumCaseType(EnumCase $enumCase): Type
{
$classExpr = $enumCase->expr;
if ($classExpr instanceof Expr) {
return $this->nodeTypeResolver->getType($classExpr);
}

// in case of no value, fallback to string type
return new StringType();
}
}

0 comments on commit e368dab

Please sign in to comment.