Hamee Advent Calendar 2021 15日目の記事です。
https://qiita.com/advent-calendar/2021/hamee
はじめに
Q. 綺麗にコード書きたくね?
A. はい。
静的解析とは
静的コード解析(static code analysis)または静的プログラム解析(static program analysis)とは、コンピュータのソフトウェアの解析手法の一種であり、実行ファイルを実行することなく解析を行うこと。逆にソフトウェアを実行して行う解析を動的プログラム解析と呼ぶ[1]。静的コード解析はソースコードに対して行われることが多く、少数ながらオブジェクトコードに対して行う場合もある。
Wikipediaより引用
つまるところ、機械的にコードを分析して悪いところ見つけてくれるってことですね。
例えば、IntelliJ にある PHP の静的解析は以下の画像ような指摘をしてくれます。
$unused
が使われてなさそうだね。
みたいな感じです。
表示される変数も灰色になって使われてないよアピールをしてくれます。
PHPにおける静的解析
IntelliJ を始め、世に出回っているIDEやエディタは静的解析できるものが多いですが、どうせなら PHP 専用の静的解析ツール使いたくないですか...?
PHP CodeSniffer
1つ目は、PHP CodeSniffer と言ってコーディング規約のチェックをしてくれるツールです。
Laravel とか CakePHP などフレームワークに合わせた規約も用意してくれているすごいやつ。
以下の例は CakePHP の環境で実行しています。
> phpcs --colors -p src/
......E..................................................... 60 / 85 (71%)
......................... 85 / 85 (100%)
FILE: /src/hoge.php
----------------------------------------------------------------------
FOUND 2 ERRORS AND 1 WARNING AFFECTING 3 LINES
----------------------------------------------------------------------
216 | WARNING | [ ] Missing @return tag in function comment
224 | ERROR | [x] Expected 1 space(s) after IF keyword; 0 found
226 | ERROR | [x] Missing blank line before return statement
----------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------
Time: 31.67 secs; Memory: 22MB
PHPStan
AutoLoader を解釈したり、PHP を一部実行したりして解析を行うツールです。
存在しないプロパティへのアクセスや、null に対するメソッドの呼び出しの可能性などをチェックしてくれます。
> phpstan analyse
Note: Using configuration file /phpstan.neon.
84/84 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Line src/hoge.php
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
222 Cannot access property $interface_1 on array|Cake\Datasource\EntityInterface.
223 Cannot access property $interface_2 on array|Cake\Datasource\EntityInterface.
230 Cannot call method set() on array|Cake\Datasource\EntityInterface.
238 Method src\Hoge::method_1() should return App\Model\Entity|false but returns array|Cake\Datasource\EntityInterface.
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[ERROR] Found 4 errors
PHPStan には 0 ~ 9 のレベルが存在し、0 が一番緩く 9 が一番厳格なルールになっています。
ちなみに各ルールの差異は以下の通りです(原文ママ)
Here’s a brief overview of what’s checked on each level. Levels are cumulative - for example running level 5 also gives you all the checks from levels 0-4.
0 . basic checks, unknown classes, unknown functions, unknown methods called on $this, wrong number of arguments passed to those methods and functions, always undefined variables
- possibly undefined variables, unknown magic methods and properties on classes with __call and __get
- unknown methods checked on all expressions (not just $this), validating PHPDocs
- return types, types assigned to properties
- basic dead code checking - always false instanceof and other type checks, dead else branches, unreachable code after return; etc.
- checking types of arguments passed to methods and functions
- report missing typehints
- report partially wrong union types - if you call a method that only exists on some types in a union type, level 7 starts to report that; other possibly incorrect situations
- report calling methods and accessing properties on nullable types
- be strict about the mixed type - the only allowed operation you can do with it is to pass it to another mixed
レベル 9 が通る頃には可読性・メンテナンス性が高いコードになっているはず。
ここまで静的解析について述べてきたが、新しく開発環境を作るたびに静的解析ツールの整備をしたり、コードの追記・修正をする度に解析ツールを手動で回すのも割と面倒...
そこで、Github Actions の出番である。
Github Actions
いわゆる CI/CD 的なことをやってくれるやつです。
わざわざ CircleCI のような CI/CD サービスに登録しなくても Github 内ですべて完結するので嬉しい。
設定
リポジトリのルートに .github/workflows
ディレクトリ を作成し、その中に *.yml
の形式で記述します。
workflows 内にいくつも .yml
を置けるので好きなだけ actions を設定できます。
CircleCI だと .circleci/config.yml
に全ての CI/CD を記述しなければならずゴチャるので、設定が分けられるのもポイント高いですね。
試しに PHPStan の action を設定して push してみます。
name: PHPStan
on: [commit, pull_request]
jobs:
phpstan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
tools: composer, cs2pr, phpstan
coverage: none
- name: Composer install
run: composer install
- name: Run PHPStan
run: vendor/bin/phpstan analyze --memory-limit=-1
まとめ
複数人でプロジェクトを運営する時にはコーディング規約を設けると思いますが、こういったサービスを駆使して「Github Actionsが全て通ること」なんてルールにしてしまえば楽そうですよね。
Let's enjoy PHP !