Repository: FriendsOfPHP/PHP-CS-Fixer (php)

Issue:
switch_case_semicolon_to_colon fixer breaks match expressions
## Bug report

PHP CS Fixer 2.18.0 on PHP 8.0.1

If I run PHP CS Fixer on a file containing a match expression, that file is listed under

```
Files that were not fixed due to errors reported during linting after fixing
```

In verbose mode, I get the following error message:

```
[PhpCsFixer\Linter\LintingException]                                              
Parse error: syntax error, unexpected token ":", expecting "," or ";" on line 7.

Applied fixers: switch_case_semicolon_to_colon
```

If I disable the mentioned `switch_case_semicolon_to_colon` fixer, the error is gone.

### Code snippet that reproduces the problem

```php
echo match (\PHP_MAJOR_VERSION) {
    8 => 'eight',
    9 => 'nine',
    default => 'unknown',
};
```

Pull request:
switch_case_semicolon_to_colon should skip match/default statements
Fixes #5446.

Patch:
diff --git a/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php b/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php
index a7e9682fe..e27f97f5d 100644
--- a/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php
+++ b/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php
@@ -71,9 +71,12 @@ public function isCandidate(Tokens $tokens)
     protected function applyFix(\SplFileInfo $file, Tokens $tokens)
     {
         foreach ($tokens as $index => $token) {
-            if ($token->isGivenKind([T_CASE, T_DEFAULT])) {
+            if ($token->isGivenKind(T_CASE)) {
                 $this->fixSwitchCase($tokens, $index);
             }
+            if ($token->isGivenKind(T_DEFAULT)) {
+                $this->fixSwitchDefault($tokens, $index);
+            }
         }
     }
 
@@ -110,4 +113,20 @@ protected function fixSwitchCase(Tokens $tokens, $index)
             $tokens[$index] = new Token(':');
         }
     }
+
+    /**
+     * @param int $index
+     */
+    protected function fixSwitchDefault(Tokens $tokens, $index)
+    {
+        do {
+            if ($tokens[$index]->equalsAny([':', ';', [T_DOUBLE_ARROW]])) {
+                break;
+            }
+        } while (++$index);
+
+        if ($tokens[$index]->equals(';')) {
+            $tokens[$index] = new Token(':');
+        }
+    }
 }


Test patch:
diff --git a/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php b/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php
index 93763ed7b..9fe44e626 100644
--- a/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php
+++ b/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php
@@ -65,6 +65,20 @@ public function provideFixCases()
                 }
                 ',
             ],
+            [
+                '<?php
+                switch ($a) {
+                    case ["foo" => "bar"]:
+                        break;
+                }
+                ',
+                '<?php
+                switch ($a) {
+                    case ["foo" => "bar"];
+                        break;
+                }
+                ',
+            ],
             [
                 '<?php
                     switch ($a) {
@@ -260,4 +274,56 @@ public function provideFix70Cases()
             ],
         ];
     }
+
+    /**
+     * @param string      $expected
+     * @param null|string $input
+     *
+     * @dataProvider provideFix80Cases
+     * @requires PHP 8
+     */
+    public function testFix80($expected, $input = null)
+    {
+        $this->doTest($expected, $input);
+    }
+
+    public function provideFix80Cases()
+    {
+        return [
+            'Simple match' => [
+                '<?php
+                    echo match ($a) {
+                        default => "foo",
+                    };
+                ',
+            ],
+            'Match in switch' => [
+                '<?php
+                    switch ($foo) {
+                        case "bar":
+                            echo match ($a) {
+                                default => "foo",
+                            };
+                            break;
+                    }
+                ',
+            ],
+            'Match in case value' => [
+                '<?php
+                    switch ($foo) {
+                        case match ($bar) {
+                            default => "foo",
+                        }: echo "It works!";
+                    }
+                ',
+                '<?php
+                    switch ($foo) {
+                        case match ($bar) {
+                            default => "foo",
+                        }; echo "It works!";
+                    }
+                ',
+            ],
+        ];
+    }
 }