php_codesniffer を使ってPSR12を継承しつつカスタマイズ自分用のコーディング規約を定義するめも

# 概要
メソッドコメントちゃんと書いてほしい
コードレビューめんどくさい、自動化できるとこは自動化したい
code_sniffer使って定義しておけば、どうにかなるはず
（PHPStormに整形させたり、規約に反していれば警告だしたりしてくれる）

などの気持ちを、調べながら実装していった。
ちょっとルールを追加したり、一部の検査を除外したかったりしただけなのに、ずいぶんつまずいたのでメモを残しておく。

# phpcs.xml(暫定/Laravel用)
~~~ xml
<?xml version="1.0"?>
<ruleset name="MyPSR12">
    <description>メソッドコメントなどをきちんとかきましょうの規約</description>

    <!-- app,config,routes,tests のみ検査対象 -->
    <exclude-pattern>*/bootstrap/*</exclude-pattern>
    <exclude-pattern>*/database/*</exclude-pattern>
    <exclude-pattern>*/node_modules/*</exclude-pattern>
    <exclude-pattern>*/public/*</exclude-pattern>
    <exclude-pattern>*/resources/*</exclude-pattern>
    <exclude-pattern>*/storage/*</exclude-pattern>
    <exclude-pattern>*/vendor/*</exclude-pattern>

    <!-- テストコードは暫定で除外 -->
    <exclude-pattern>*/tests/*</exclude-pattern>
    <!-- Laravelインストール時に作成されるコードの一部をチェック対象から除外 -->
    <exclude-pattern>*/app/Console/Kernel.php</exclude-pattern>
    <exclude-pattern>*/app/Http/Middleware/RedirectIfAuthenticated.php</exclude-pattern>
    <exclude-pattern>*/app/Http/Middleware/Authenticate.php</exclude-pattern>
    <exclude-pattern>*/app/Http/Middleware/TrustProxies.php</exclude-pattern>
    <exclude-pattern>*/app/Http/Middleware/VerifyCsrfToken.php</exclude-pattern>

    <!-- Include the whole PSR12 standard except FunctionComment, which we override -->
    <rule ref="PSR12"></rule>

    <!-- メソッドコメントを書きなさい -->
    <rule ref="Squiz.Commenting.FunctionComment">
        <!-- 細かすぎるとめんどいので除外 -->
        <exclude name="Squiz.Commenting.FunctionComment.SpacingAfterParamName"></exclude>
        <exclude name="Squiz.Commenting.FunctionComment.MissingParamComment"></exclude>
        <exclude name="Squiz.Commenting.FunctionComment.SpacingAfterParamType"></exclude>
        <exclude name="Squiz.Commenting.FunctionComment.TypeHintMissing"></exclude>
        <exclude name="Squiz.Commenting.FunctionComment.EmptyThrows"></exclude>
    </rule>

    <!-- メンバ変数にコメントを書きなさい -->
    <rule ref="Squiz.Commenting.VariableComment"></rule>

</ruleset>
~~~

# 概念/設計の理解
code_snifferでは、コーディング規約を大まかに以下の3階層に分けて定義できるようだ。

- Standard
- Sniffs 
- Error Code

## Standard
Standardは一番上の階層で、「規約」の概念そのものに対応している。例えば、PSR1、PSR2、PSR12などがこの階層で定義されている。  phpcs を -i 付きで叩くとstandardが一覧で表示される。

~~~ sh
phpcs -i
~~~

つまり、自分用にコーディング規約を定義したい場合はStandardを1つ（xmlファイルを1枚）作ればよい。

## Sniff
一連のルールを定義する。
また、Sniffsは自由に名前空間を設定できるっぽいので、階層が1つ以上になる。例えば
Squiz.Commenting.FunctionComment
が、メソッドコメントに関するルールに対応している。

## Error Code
これの説明がどこにも無いので非常に困った。
Sniffには、検査によって生じうるエラーが複数定義されていて、それらのエラーは必ずError Codeを持っている。

例えば、
Squiz.Commenting.FunctionComment.EmptyThrows
は、

Standard : Squiz 
Sniffs : Commenting.FunctionComment
Error Code: EmptyThrows
を示している。

Squiz.Commenting.FunctionComment と書いた場合は、Sniffを指し、
Squiz.Commenting.FunctionComment.EmptyThrows　と書いた場合はError Codeを指すため、非常にわかりにくい。

Sniffの名前空間が自由っぽいので、階層を見てもSniffなのかError Codeなのかの見分けがつかないのだ。

## まとめ
今の所、以下のように理解した。

- xml上では Standard がRuleset に対応している。
- Standard は、適用する複数の Sniffs を設定できる。
- Sniffには、複数のError Code が紐付いている。
- Error Codeだけを指定して検査することはできないっぽい
    - なぜなら、Error Code は Sniff ではないから（たぶん）
    - なので、Ruleset にSniffを入れて、Sniffの中に除外するError Codeを指定、という構造にすれば意図通り動く。

なお、Error Codeはドキュメントが揃ってないので、諦めて
vendor/squizlabs/php_codesniffer/src/Standards の中を見ましょう。


# ググり
## 検索ワード「FunctionComment sniffs」
全く同じ疑問を持った外人がおこってた
Subsniffs undocumented and undiscoverable
https://github.com/squizlabs/PHP_CodeSniffer/issues/2213
（ドキュメント整備しろとか言ってる暇があったらxml書いてプルリク出せば？的なこと言われてるっぽい）

- Sniffの下に、Error Codeの階層がある
- -e スイッチ付きで phpcs 叩くとスニフ一覧が見れるぞ

~~~ sh
phpcs -e
~~~

- オプションつければドキュメントっぽいテキストも出力できる  

~~~ sh
phpcs --standard=Squiz --generator=Text
~~~

 
> I've become aware that sniffs such as Squiz.Commenting.FunctionComment contain many sub-sniffs, including, but not limited to:

超適当訳：スニフに、サブスニフ的なの含まれてない？

> Where can I find a complete list of sniffs and subsniffs and documentation of their behaviour?

どこに一覧あんの？

> Those are not subsniffs, but error codes.

サブスニフじゃねえ、エラーコードだ


## 検索ワード「Squiz.Commenting.Function Error Code」
Finding PHP CodeSniffer rules 
https://stackoverflow.com/questions/44918498/finding-php-codesniffer-rules

- -s スイッチ付きで実行するとエラーコードが表示される

## 検索ワード「Sniffs php」
PHP Code SnifferのSniffを自作するにあたって知っておいてよかったこと
https://qiita.com/suin/items/34393032bb5f4cf49cbb

- Sniff周りのディレクトリ構成がわかる。ソースコードを見るときに助かりそう