From 0ac5412aa05c9bac128abf2c1dab6d453e1f9ce1 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 25 Apr 2021 14:07:36 +0700 Subject: [PATCH] [Php80] Add default case when variable initialized on ChangeSwitchToMatchRector (#6230) * Add failing test fixture for ChangeSwitchToMatchRector # Failing Test for ChangeSwitchToMatchRector Based on https://getrector.org/demo/f7f2ba48-3c19-4fdb-bc0a-e956e037eefd It's important to add the default case to prevent this error when passing another code: ``` Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type int ``` https://3v4l.org/E64Um * Closes #6216 * phpstan * phpstan Co-authored-by: Ruud Kamphuis --- ..._case_when_variable_is_initialized.php.inc | 40 +++++++++++++++++++ .../Switch_/ChangeSwitchToMatchRector.php | 27 ++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 rules-tests/Php80/Rector/Switch_/ChangeSwitchToMatchRector/Fixture/add_default_case_when_variable_is_initialized.php.inc diff --git a/rules-tests/Php80/Rector/Switch_/ChangeSwitchToMatchRector/Fixture/add_default_case_when_variable_is_initialized.php.inc b/rules-tests/Php80/Rector/Switch_/ChangeSwitchToMatchRector/Fixture/add_default_case_when_variable_is_initialized.php.inc new file mode 100644 index 00000000000..76c93df0346 --- /dev/null +++ b/rules-tests/Php80/Rector/Switch_/ChangeSwitchToMatchRector/Fixture/add_default_case_when_variable_is_initialized.php.inc @@ -0,0 +1,40 @@ + +----- + 'code_10', + 11 => 'code_11', + default => null, + }; + return $error; + } +} +?> diff --git a/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php b/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php index 4ca19472b8f..1603ba0caf5 100644 --- a/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php +++ b/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php @@ -9,10 +9,12 @@ use PhpParser\Node\Expr; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\Match_; use PhpParser\Node\MatchArm; +use PhpParser\Node\Name; use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Return_; use PhpParser\Node\Stmt\Switch_; use Rector\Core\Rector\AbstractRector; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Php80\NodeAnalyzer\SwitchAnalyzer; use Rector\Php80\NodeResolver\SwitchExprsResolver; use Rector\Php80\ValueObject\CondAndExpr; @@ -135,12 +137,35 @@ CODE_SAMPLE } if ($this->assignExpr) { - return new Assign($this->assignExpr, $match); + /** @var Expr $assignExpr */ + $assignExpr = $this->assignExpr; + return $this->changeToAssign($node, $match, $assignExpr); } return $match; } + private function changeToAssign(Switch_ $switch, Match_ $match, Expr $assignExpr): Assign + { + $prevInitializedAssign = $this->betterNodeFinder->findFirstPreviousOfNode($switch, function (Node $node) use ($assignExpr): bool { + return $node instanceof Assign && $this->nodeComparator->areNodesEqual($node->var, $assignExpr); + }); + + $assign = new Assign($assignExpr, $match); + if ($prevInitializedAssign instanceof Assign) { + /** @var Match_ $expr */ + $expr = $assign->expr; + $expr->arms[] = new MatchArm(null, $prevInitializedAssign->expr); + + $parentAssign = $prevInitializedAssign->getAttribute(AttributeKey::PARENT_NODE); + if ($parentAssign instanceof Expression) { + $this->removeNode($parentAssign); + } + } + + return $assign; + } + private function shouldSkipSwitch(Switch_ $switch): bool { if (! $this->switchAnalyzer->hasEachCaseBreak($switch)) {