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

Issue:
Indentation issue when writing interface implemtations on separate lines
## Bug report

Hi there.

Since the upgrade to the 3.9 branch (coming from 3.8), the cs fixer applies a duplicate indentation in case a class implements multiple interfaces which are written on separate lines.

Maybe I'm overlooking a mistake in my configuration - in which case I'd appreciate a little suggestion.

Version:
```
PHP CS Fixer 3.9.4 Grand Awaiting by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 8.1.8
```

Command:
```
vendor/bin/php-cs-fixer --config=.php-cs-fixer.php fix --dry-run --diff -vvv
```

Config:
```
'@PSR2' => true,
'array_syntax' => [
	'syntax' => 'short'
],
'braces' => [
	'position_after_functions_and_oop_constructs' => 'same',
],
'ordered_imports' => [
	'sort_algorithm' => 'alpha'
],
'no_unused_imports' => true,
'indentation_type' => true,
```

<!--
  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.

  Please describe the problem and provide technical details such as:
   * PHP CS Fixer version and PHP runtime: php-cs-fixer -V
   * the command used to run PHP CS Fixer (run with `-vvv`)
   * the configuration (file) you used
-->

### Code snippet that reproduces the problem

```php
<?php

class Foobar implements
	Stringable,
	JsonSerializable {

	public function __toString(): string {
		return '';
	}

	public function jsonSerialize(): mixed {
		return '';
	}
}
```

### Result after run

```diff
@@ -3,12 +3,11 @@
 class Foobar implements
 	Stringable,
 	JsonSerializable {
+		public function __toString(): string {
+			return '';
+		}
 
-	public function __toString(): string {
-		return '';
+		public function jsonSerialize(): mixed {
+			return '';
+		}
 	}
-
-	public function jsonSerialize(): mixed {
-		return '';
-	}
-}

      ----------- end diff -----------

```

Pull request description:
bug: Fix indentation for multiline class definition
Fixes #6507.

Patch:
diff --git a/src/Fixer/FunctionNotation/RegularCallableCallFixer.php b/src/Fixer/FunctionNotation/RegularCallableCallFixer.php
index 90a9bd181..a06776b5e 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, ['{'])
diff --git a/src/Fixer/Whitespace/StatementIndentationFixer.php b/src/Fixer/Whitespace/StatementIndentationFixer.php
index 46615be58..3d7899ac6 100644
--- a/src/Fixer/Whitespace/StatementIndentationFixer.php
+++ b/src/Fixer/Whitespace/StatementIndentationFixer.php
@@ -102,12 +102,14 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
             T_CLASS,
             T_INTERFACE,
             T_TRAIT,
+            T_EXTENDS,
+            T_IMPLEMENTS,
         ];
         if (\defined('T_MATCH')) { // @TODO: drop condition when PHP 8.0+ is required
             $blockSignatureFirstTokens[] = T_MATCH;
         }
 
-        $blockFirstTokens = ['{', [CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN], [T_EXTENDS], [T_IMPLEMENTS], [CT::T_USE_TRAIT], [CT::T_GROUP_IMPORT_BRACE_OPEN]];
+        $blockFirstTokens = ['{', [CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN], [CT::T_USE_TRAIT], [CT::T_GROUP_IMPORT_BRACE_OPEN]];
         if (\defined('T_ATTRIBUTE')) { // @TODO: drop condition when PHP 8.0+ is required
             $blockFirstTokens[] = [T_ATTRIBUTE];
         }
@@ -212,7 +214,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
                         continue;
                     }
 
-                    if ($tokens[$endIndex]->equalsAny(['{', ';', [T_DOUBLE_ARROW]])) {
+                    if ($tokens[$endIndex]->equalsAny(['{', ';', [T_DOUBLE_ARROW], [T_IMPLEMENTS]])) {
                         break;
                     }
 
@@ -233,7 +235,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
                     'end_index' => $endIndex,
                     'end_index_inclusive' => true,
                     'initial_indent' => $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent),
-                    'is_indented_block' => false,
+                    'is_indented_block' => $token->isGivenKind([T_EXTENDS, T_IMPLEMENTS]),
                 ];
 
                 continue;


Test patch:
diff --git a/tests/Fixer/FunctionNotation/RegularCallableCallFixerTest.php b/tests/Fixer/FunctionNotation/RegularCallableCallFixerTest.php
index fad3e7698..ed3465b8f 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);
+  }
+}',
+        ];
     }
 
     /**
diff --git a/tests/Fixer/Whitespace/StatementIndentationFixerTest.php b/tests/Fixer/Whitespace/StatementIndentationFixerTest.php
index 9f20055e8..f82bd7eb3 100644
--- a/tests/Fixer/Whitespace/StatementIndentationFixerTest.php
+++ b/tests/Fixer/Whitespace/StatementIndentationFixerTest.php
@@ -719,6 +719,27 @@ class Foo {
       Baz {
        Baz::baz insteadof Bar;
        }
+}',
+        ];
+
+        yield 'multiline class definition' => [
+            '<?php
+class Foo
+extends
+    BaseFoo
+implements Bar,
+    Baz {
+    public function foo() {
+    }
+}',
+            '<?php
+class Foo
+  extends
+    BaseFoo
+   implements Bar,
+  Baz {
+    public function foo() {
+    }
 }',
         ];
     }