diff --git a/phpstan.neon b/phpstan.neon index 1def084a..375f1f41 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -107,6 +107,7 @@ parameters: - rules/DowngradePhp74/Rector/MethodCall/DowngradeReflectionGetTypeRector.php - rules/DowngradePhp80/Rector/MethodCall/DowngradeReflectionGetAttributesRector.php - rules/DowngradePhp73/Rector/String_/DowngradeFlexibleHeredocSyntaxRector.php + - rules/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector.php # local attribute key - '#Parameter \#2 \$attributeKey of static method Rector\\PhpParser\\NodeTraverser\\SimpleNodeTraverser\:\:decorateWithAttributeValue\(\) expects#' diff --git a/rules-tests/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector/Fixture/in_array_dim_fetch.php.inc b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector/Fixture/in_array_dim_fetch.php.inc new file mode 100644 index 00000000..80222490 --- /dev/null +++ b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector/Fixture/in_array_dim_fetch.php.inc @@ -0,0 +1,42 @@ + 'TypeError', + 'Exception' => 'ErrorException', + default => $c, + }][$n] = $v; + } +} + +?> +----- + diff --git a/rules/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector.php b/rules/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector.php index 5f7ba9bb..b9171bf1 100644 --- a/rules/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector.php +++ b/rules/DowngradePhp80/Rector/Expression/DowngradeMatchToSwitchRector.php @@ -8,6 +8,7 @@ use PhpParser\Node\Arg; use PhpParser\Node\ArrayItem; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\ArrowFunction; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\BinaryOp; @@ -19,6 +20,7 @@ use PhpParser\Node\Expr\NullsafeMethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Throw_; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\MatchArm; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Break_; @@ -29,6 +31,7 @@ use PhpParser\Node\Stmt\Switch_; use PhpParser\NodeVisitor; use PHPStan\Analyser\Scope; +use Rector\Naming\Naming\VariableNaming; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Php72\NodeFactory\AnonymousFunctionFactory; use Rector\PHPStan\ScopeFetcher; @@ -44,7 +47,8 @@ final class DowngradeMatchToSwitchRector extends AbstractRector { public function __construct( - private readonly AnonymousFunctionFactory $anonymousFunctionFactory + private readonly AnonymousFunctionFactory $anonymousFunctionFactory, + private readonly VariableNaming $variableNaming ) { } @@ -102,7 +106,7 @@ public function getNodeTypes(): array /** * @param Echo_|Expression|Return_ $node */ - public function refactor(Node $node): ?Node + public function refactor(Node $node): null|Node|array { /** @var Match_|null $match */ $match = null; @@ -110,6 +114,29 @@ public function refactor(Node $node): ?Node $scope = ScopeFetcher::fetch($node); + if ($node instanceof Expression + && $node->expr instanceof Assign + && $node->expr->var instanceof ArrayDimFetch + && $node->expr->var->var instanceof ArrayDimFetch + && $node->expr->var->var->dim instanceof Match_) { + $matchVariable = new Variable($this->variableNaming->createCountedValueName('match', $scope)); + $expression = new Expression(new Assign($matchVariable, $node->expr->var->var->dim)); + $expression->setAttribute(AttributeKey::SCOPE, $scope); + $refactored = $this->refactor($expression); + + if ($refactored === null) { + return null; + } + + $node->expr->var->var->dim = $matchVariable; + + $stmts = is_array($refactored) + ? $refactored : + [$refactored]; + + return [...$stmts, $node]; + } + $this->traverseNodesWithCallable( $node, function (Node $subNode) use ($node, &$match, &$hasChanged, $scope) {