前稿でphpcs-psr4-sniff:クラスがPSR-4に準拠しているかチェックするツールを作ったという話をしたが、PHP Code SnifferのSniff(プラグイン)を作るのは今回初めてだったので、そこで得た知見を共有したい。
ディレクトリ構成に決まりがある
- PSR-0のディレクトリ構成でないとならない。(PSR-4はだめ)
- そして、ベンダーネームスペース(下でいう「StandardName」)にruleset.xmlを置かないとならない。
- Sniffsというディレクトリが必要。
- Sniffsディレクトリのは以下はネームスペースで改装を作って良い。
- ファイル名は
Sniff.php
で終わる必要がある。
project-name
├── StandardName
│ ├── Sniffs
│ │ └── Classes
│ │ │ └── ClassNameSniff.php
│ │ ├── MyCustomSniff.php
│ ├── ruleset.xml
└── composer.json
テストにはslevomat氏作のTestCaseクラスを使うと楽
作ったSniffの単体テストをPHPUnitで行う場合、PHP Code Sniffer本家の書き方を真似したいところだが、それをしてしまうとテストコードが複雑になってしまう。
そこで、テストにはPHP Code Sniffer界の重鎮(?)である、slevomat氏作のTestCaseクラスを継承するのがおすすめ。テストコードを宣言的に書ける。
slevomat氏作のヘルパークラスが便利
カスタムSniffはPHP_CodeSniffer\Sniffs\Sniff
インターフェイスを実装するわけだが、実装に渡ってくるPHP_CodeSniffer\Files\File
オブジェクトはAPIが低レイヤーなので、解析に必要な情報を取り出すのが大変だ。
それを補うために、slevomat氏がヘルパークラスを数多く作ってくれているので、それを利用するとコードがすっきりする。
Packagistで配布するならtype
はphpcodesniffer-standard
にする
作ったSniffをPackagistで配布する場合は、type
をlibrary
にするのではなく、phpcodesniffer-standard
にすると良い。
{
"name": "owner/phpcs-standard-name",
"description": "A set of phpcs sniffs for modern php development.",
"type": "phpcodesniffer-standard",
}
そうしておくと、Dealerdirect/phpcodesniffer-composer-installerを使っているユーザが、あなたのSniffをインストールするとき、あなたのSniffが自動的にinstalled_paths
に入るようになる。
参考になるブログ記事
-
Creating Sniffs for a PHPCS Standard – Payton.Codes
- おすすめ
-
How to Write Custom Sniff for Code Sniffer 3 | Tomas Votruba
- ただし、EasyCodingStandard向けに書かれているので全部は参考にならない
参考になるカスタムSniffリポジトリ
-
suin/phpcs-psr4-sniff
- 手前味噌だがSniffがひとつしかないリポジトリなので参考になるかも
-
bmitch/Codor
- 比較的シンプルなので参考になった
- slevomat/coding-standard
- object-calisthenics/phpcs-calisthenics-rules
あまり参考にならないリポジトリ
-
Symplify/CodingStandard
- phpcsではなくEasyCondingStandardというツール向けに実装されているため参考にならない