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

Issue:
`Braces` fixer working incorrectly in case of `callable` return type
## Bug report

<!--
  Before reporting a bug, make sure PHP CS Fixer is up-to-date.

  Check that the issue is NOT regarded to an applied rule by using the `-vvv` option (will list applied rules) on a minimal code snippet.
-->

### Description

<!--
  Please describe the problem.
-->
Running PHP-CS-Fixer on a large codebase revealed that the `braces` fixer is not working correctly in the case of a `callable` return type. It puts the function opening bracket on a new line, which does not happen for other return types.

### Runtime version
3.15.1
<!--
   Provide PHP CS Fixer version and PHP runtime by sharing result of this command:
   $ php-cs-fixer -V
-->

### Used command

<!--
   Provide the command used to run PHP CS Fixer (run with `-vvv`).
-->
`php-cs-fixer fix --rules=braces --diff TestCSFixer.php -vvv`
### Configuration file
N/A
<!--
   Provide content of configuration file you used (.php-cs-fixer[.dist].php).
-->

### Code snippet that reproduces the problem
```php
<?php

declare(strict_types=1);

class TestCSFixer
{
    private function testFunction(
        string $argument,
    ): callable {
        return function (): void {
        };
    }

    private function testFunction2(
        string $argument,
    ): string {
        return $argument;
    }
}
```

which becomes

```php
<?php

declare(strict_types=1);

class TestCSFixer
{
    private function testFunction(
        string $argument,
    ): callable
    {
        return function (): void {
        };
    }

    private function testFunction2(
        string $argument,
    ): string {
        return $argument;
    }
}

```

Diff:
```
   1) TestCSFixer.php (braces)
      ---------- begin diff ----------
--- TestCSFixer.php
+++ TestCSFixer.php
@@ -7,7 +7,8 @@
     private function testFunction(
         string $argument,
         bool $secondArgument,
-    ): callable {
+    ): callable
+    {
         return function (): void {
         };
     }

      ----------- end diff -----------
```


Discussion:
Thanks @TomBrouws for reporting this. We'll try to fix that as soon as possible (but PR is more than welcome 😉).

Another reason for finishing #4885 @julienfalque 🙂.



Patch:
diff --git a/src/Fixer/Basic/CurlyBracesPositionFixer.php b/src/Fixer/Basic/CurlyBracesPositionFixer.php
index 42b343dbbd7..705d9b99061 100644
--- a/src/Fixer/Basic/CurlyBracesPositionFixer.php
+++ b/src/Fixer/Basic/CurlyBracesPositionFixer.php
@@ -255,7 +255,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
                 $previousTokenIndex = $openBraceIndex;
                 do {
                     $previousTokenIndex = $tokens->getPrevMeaningfulToken($previousTokenIndex);
-                } while ($tokens[$previousTokenIndex]->isGivenKind([CT::T_TYPE_COLON, CT::T_NULLABLE_TYPE, T_STRING, T_NS_SEPARATOR, CT::T_ARRAY_TYPEHINT, T_STATIC, CT::T_TYPE_ALTERNATION, CT::T_TYPE_INTERSECTION]));
+                } while ($tokens[$previousTokenIndex]->isGivenKind([CT::T_TYPE_COLON, CT::T_NULLABLE_TYPE, T_STRING, T_NS_SEPARATOR, CT::T_ARRAY_TYPEHINT, T_STATIC, CT::T_TYPE_ALTERNATION, CT::T_TYPE_INTERSECTION, T_CALLABLE]));
 
                 if ($tokens[$previousTokenIndex]->equals(')')) {
                     if ($tokens[--$previousTokenIndex]->isComment()) {


Test patch:
diff --git a/tests/Fixer/Basic/CurlyBracesPositionFixerTest.php b/tests/Fixer/Basic/CurlyBracesPositionFixerTest.php
index 0873fd7d272..c528fd6b0e5 100644
--- a/tests/Fixer/Basic/CurlyBracesPositionFixerTest.php
+++ b/tests/Fixer/Basic/CurlyBracesPositionFixerTest.php
@@ -607,6 +607,21 @@ function foo($foo
             ['control_structures_opening_brace' => 'next_line_unless_newline_at_signature_end'],
         ];
 
+        yield 'next line with newline before closing parenthesis and callable type' => [
+            '<?php
+                function foo($foo
+                ): callable {
+                    return function (): void {};
+                }',
+            '<?php
+                function foo($foo
+                ): callable
+                {
+                    return function (): void {};
+                }',
+            ['control_structures_opening_brace' => 'next_line_unless_newline_at_signature_end'],
+        ];
+
         yield 'next line with newline in signature but not before closing parenthesis and return type' => [
             '<?php
                 function foo(