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

Issue:
Rule `regular_callable_call` throws exception (code 64)
## Bug report

When applying rule `regular_callable_call`, php-cs-fixer throws an exception.

### Version:
```bash
php-cs-fixer -V
PHP CS Fixer 3.9.5 Grand Awaiting by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.30
```

### Command:

```bash
php-cs-fixer --rules=regular_callable_call --allow-risky=yes fix --dry-run -vvv --using-cache=no Test.php
```

### Output

```lua
PHP CS Fixer 3.9.5 Grand Awaiting by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.30
Loaded config default.
E                                                                                                                                                                                                                                                                                         1 / 1 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error

Checked all files in 0.002 seconds, 12.000 MB memory used

Files that were not fixed due to errors reported during fixing:
   1) /home/wsldev/www/Test.php

                                                                                                                                                                                                                                                            
        [TypeError]                                                                                                                                                                                                                                         
        Argument 2 passed to PhpCsFixer\Tokenizer\Tokens::findBlockEnd() must be of the type int, null given, called in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php on line 146  
                                                                                                                                                                                                                                                            

      PhpCsFixer\Tokenizer\Tokens->findBlockEnd()
        in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php at line 146
      PhpCsFixer\Fixer\FunctionNotation\RegularCallableCallFixer->processCall()
        in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php at line 110
      PhpCsFixer\Fixer\FunctionNotation\RegularCallableCallFixer->applyFix()
        in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/AbstractFixer.php at line 75
      PhpCsFixer\AbstractFixer->fix()
        in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/Runner/Runner.php at line 173
      PhpCsFixer\Runner\Runner->fixFile()
        in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/Runner/Runner.php at line 114
      PhpCsFixer\Runner\Runner->fix()
        in /home/wsldev/www/php-cs-fixer/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommand.php at line 307
      PhpCsFixer\Console\Command\FixCommand->execute()
        in /home/wsldev/www/php-cs-fixer/vendor/symfony/console/Command/Command.php at line 298
      [ ... ]
```

### Code snippet that reproduces the problem

I expected the fixer would turn the `call_user_func_array` line into something similar like the one above it, that is commented out.

```php
<?php

class Test {

  public static $factory;

  public static function createFromFactory(...$args) {
    if (isset(static::$factory) && \is_callable(static::$factory)) {
      // return (static::$factory)(...$args);
      return call_user_func_array(static::$factory, $args);
    }
    return new static(...$args);
  }
}

```



Discussion:

Patch:
diff --git a/src/Fixer/FunctionNotation/RegularCallableCallFixer.php b/src/Fixer/FunctionNotation/RegularCallableCallFixer.php
index 90a9bd181c1..a06776b5e0f 100644
--- a/src/Fixer/FunctionNotation/RegularCallableCallFixer.php
+++ b/src/Fixer/FunctionNotation/RegularCallableCallFixer.php
@@ -140,7 +140,13 @@ private function processCall(Tokens $tokens, int $index, array $arguments): void
             $newCallTokens->clearEmptyTokens();
 
             $this->replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgIndex);
-        } elseif ($firstArgToken->isGivenKind([T_FUNCTION, T_STATIC])) {
+        } elseif (
+            $firstArgToken->isGivenKind(T_FUNCTION)
+            || (
+                $firstArgToken->isGivenKind(T_STATIC)
+                && $tokens[$tokens->getNextMeaningfulToken($firstArgIndex)]->isGivenKind(T_FUNCTION)
+            )
+        ) {
             $firstArgEndIndex = $tokens->findBlockEnd(
                 Tokens::BLOCK_TYPE_CURLY_BRACE,
                 $tokens->getNextTokenOfKind($firstArgIndex, ['{'])


Test patch:
diff --git a/tests/Fixer/FunctionNotation/RegularCallableCallFixerTest.php b/tests/Fixer/FunctionNotation/RegularCallableCallFixerTest.php
index fad3e7698f2..ed3465b8fb7 100644
--- a/tests/Fixer/FunctionNotation/RegularCallableCallFixerTest.php
+++ b/tests/Fixer/FunctionNotation/RegularCallableCallFixerTest.php
@@ -229,6 +229,16 @@ function call_user_func($foo){}
         yield 'binary string upper single quote' => [
             '<?php call_user_func(B"foo", 1,);',
         ];
+
+        yield 'static property as first argument' => [
+            '<?php
+class Foo {
+  public static $factory;
+  public static function createFromFactory(...$args) {
+    return call_user_func_array(static::$factory, $args);
+  }
+}',
+        ];
     }
 
     /**