CakePHP3 コーディング規約 PHP-CS-Fixer ”メソッド呼び出しの複数行規約”に対応する

CakePHP3 コーディング規約

CakePHP3のコーディング規約の中に、「メソッド呼び出しが複数行になるときは、初めの引数の前を改行して、引数毎にインデントつけて」というのがあるようです。

cakephp-codesnifferの結果でいうと、以下のあたりが該当するのだと思います。

  61 | ERROR | [x] Opening parenthesis of a multi-line function call
     |       |     must be the last content on the line
  63 | ERROR | [x] Closing parenthesis of a multi-line function call
     |       |     must be on a line by itself
  64 | ERROR | [x] Multi-line function call not indented correctly;
     |       |     expected 16 spaces but found 20
 

PHP-CS-Fixerでオプション設定する

これはPSR-2の範囲でないのか、PHP-CS-Fixerではオプション指定する必要があります。

https://github.com/FriendsOfPHP/PHP-CS-Fixer

method_argument_space [@PSR2, @Symfony]

In method arguments and method call, there MUST NOT be a space before each comma and there MUST be one space after each comma. Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.

Configuration options:

ensure_fully_multiline (bool): ensure every argument of a multiline argument list is on its own line; defaults to false
keep_multiple_spaces_after_comma (bool): whether keep multiple spaces after comma; defaults to false

※2017/06/29時点 version 2.3.2

“method_argument_space”ルールの”ensure_fully_multiline”オプションが該当すると見ております。デフォルトではfalseです。
以下のように指定します。

<?php

$rules = [
    '@PSR2'             => true,
    'no_whitespace_before_comma_in_array' => true,
    'whitespace_after_comma_in_array' => true,
    'blank_line_before_return' => true,
    'concat_space' => ['spacing' => 'one'],
    'ordered_imports' => true,
    'method_argument_space' => ['ensure_fully_multiline' => true],
];
$excludes = ['vendor', 'webroot', 'bin', 'plugin'];

return PhpCsFixer\Config::create()
    ->setRules($rules)
    ->setFinder(
        PhpCsFixer\Finder::create()
            ->in(__DIR__)
            ->exclude($excludes)
            ->notName('README.md')
            ->notName('*.xml')
            ->notName('*.yml')
            ->notName('*.json')
            ->notName('*.ctp')
    );

しかし、効かない

これが読まれている時点でこのオプションが効果を発揮しているなら、まったく読む必要がないのですが、2017/06/29時点では動作しませんでした。
単純に思っていたルールでなかったのかとも考えましたが、ソースを直接見てみるとそれらしい処理です。
https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php

ドキュメントとソースには機能追加されたものの、どうやらまだリリースされていないようです。

https://github.com/FriendsOfPHP/PHP-CS-Fixer/commits/master/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php

2017/06/14に機能追加してくださっているようです。

我慢してリリースしてくださるのを待つのもいいですが、どうせ自分の端末にしか影響がないので、Composerで開発バージョンを取り込む手もあります。端末のcomposer.jsonのバージョンを以下のように変えてしまい、”composer global update”します。

{
"require": {
"fabpot/php-cs-fixer": "dev-master"
}

やたら時間が掛かりましたがこれで機能するようになりました。

php-cs-fixer -V
PHP CS Fixer 2.4.0-DEV by Fabien Potencier and Dariusz Ruminski

ちなみに”PHP-CS-Fixer”は”describe”で調整例も出して下さるようです。

php-cs-fixer describe method_argument_space

Description of method_argument_space rule.
In method arguments and method call, there MUST NOT be a space before each comma and there MUST be one space after each comma. Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.

Fixer is configurable using following options:
* keep_multiple_spaces_after_comma (bool): whether keep multiple spaces after comma; defaults to false
* ensure_fully_multiline (bool): ensure every argument of a multiline argument list is on its own line; defaults to false

Fixing examples:
* Example #1.
---------- begin diff ----------
--- Original
+++ New
@@ @@
&lt;?php
-function sample($a=10,$b=20,$c=30) {}
-sample(1, 2);
+function sample($a=10, $b=20, $c=30) {}
+sample(1, 2);
----------- end diff -----------

* Example #2. Fixing with configuration: ['keep_multiple_spaces_after_comma' =&gt; false].
---------- begin diff ----------
--- Original
+++ New
@@ @@
&lt;?php
-function sample($a=10,$b=20,$c=30) {}
-sample(1, 2);
+function sample($a=10, $b=20, $c=30) {}
+sample(1, 2);
----------- end diff -----------

* Example #3. Fixing with configuration: ['keep_multiple_spaces_after_comma' =&gt; true].
---------- begin diff ----------
--- Original
+++ New
@@ @@
&lt;?php
-function sample($a=10,$b=20,$c=30) {}
+function sample($a=10, $b=20, $c=30) {}
sample(1, 2);
----------- end diff -----------

* Example #4. Fixing with configuration: ['ensure_fully_multiline' =&gt; true].
---------- begin diff ----------
--- Original
+++ New
@@ @@
&lt;?php
-function sample($a=10,
- $b=20,$c=30) {}
-sample(1,
- 2);
+function sample(
+ $a=10,
+ $b=20,
+ $c=30
+) {}
+sample(
+ 1,
+ 2
+);
----------- end diff -----------

* Example #5. Fixing with configuration: ['ensure_fully_multiline' =&gt; true, 'keep_multiple_spaces_after_comma' =&gt; true].
---------- begin diff ----------
--- Original
+++ New
@@ @@
&lt;?php
-function sample($a=10,
- $b=20,$c=30) {}
-sample(1,
- 2);
+function sample(
+ $a=10,
+ $b=20,
+ $c=30
+) {}
+sample(
+ 1,
+ 2
+);
sample('foo', 'foobarbaz', 'baz');
sample('foobar', 'bar', 'baz');
----------- end diff -----------

* Example #6. Fixing with configuration: ['ensure_fully_multiline' =&gt; true, 'keep_multiple_spaces_after_comma' =&gt; false].
---------- begin diff ----------
--- Original
+++ New
@@ @@
&lt;?php
-function sample($a=10,
- $b=20,$c=30) {}
-sample(1,
- 2);
-sample('foo', 'foobarbaz', 'baz');
-sample('foobar', 'bar', 'baz');
+function sample(
+ $a=10,
+ $b=20,
+ $c=30
+) {}
+sample(
+ 1,
+ 2
+);
+sample('foo', 'foobarbaz', 'baz');
+sample('foobar', 'bar', 'baz');
----------- end diff -----------

もちろんstable versionではないので覚悟が必要ですが、今のところは上手く動作してくれているようです。もしお困りでしたら一考しても宜しいかと思います。

以上。