Go静的解析のSuggestedFixを完全に理解して静的解析ツールを書きたくなる
スニダンを開発しているSODA inc.の Advent Calendar 24日目の記事です!!!/
\昨日は imajo さんによる「開発途中の機能を公開してしまって落ち込んだ話」でした!
今日はGoの静的解析について書きます!
ゴール:静的解析ツールを書きたくなる
「Goの静的解析なんか難しそう」がこの記事を読んだあとに「思ったより簡単だな。なんか書いてみよう」に変わると嬉しいです。
Goは標準パッケージで静的解析が出来て便利
Goでは、 go/ast や go/types をはじめとして、標準パッケージで静的解析まわりのエコシステムが提供されています。
サードパーティなライブラリから静的解析まわりのエコシステムが提供される言語も多いですが、Goのように標準でサポートされていると色々と良いことがあります。
例えば、言語仕様に新しい機能が追加されたときに同時に対応されて嬉しかったり、静的解析の容易性も考慮された上で言語が実装されて安心だったり。
Goの静的解析はこれを見れば完全に理解できる
tenntennさん が公開されている資料を見ると、静的解析をコード生成も含めて完全に理解できます。ありがたや。
このブログでは静的解析の詳しい解説は避け、 analysis.SuggestedFix
まわりのみを中心に紹介します。
analysis.Diagnostic
と analysis.(*Pass).Reportf
で検出していく
Goの静的解析では、 analysis.Diagnostic
を作り、 analysis.Pass.Report
に渡すことで改善点などを検出することができます。
analysis.(*Pass).Reportf
はそれを簡易的に実現できる関数で、次の例のようにお手軽に検出することができます。
analysis.SuggestedFix
と -fix
オプションで修正提案していく
analysis.Diagnostic
の SuggestedFixes
フィールドに analysis.SuggestedFix
のスライスを入れて作って Report
に渡すことで、検出したコードに対して修正提案を作ることができます。
次の例のように、修正を入れる位置を Pos
で指定しつつ、修正内容を []byte
で指定していく形で実装します。
この例のように文字列を直接指定するのも良いですが、 format.Node
を使って go/ast
で作ったASTを文字列に変換したものを使うのもオススメです。
ちなみに、 unitchecker
ではなく singlechecker
や multichecker
で作ることで単一のCLIツールとして実行できるようになりますが、そのときに -fix
オプションを渡すと analysis.Diagnostic.SuggestedFixes
の通りにソースコードを修正してくれる機構も標準で提供されています。
analysistest.Run
と analysistest.RunWithSuggestedFixes
でテストも書ける
次の例のようにGoのファイルを作り、コメントで // want "検出されるときのメッセージ"
のように書いておき、そのファイルを対象に analysistest.Run
でテストする機構が標準で提供されています。
analysis.Diagnostic
が正しい Message
で正しい Pos
で Report
されているかテストできます。
また、次のように元ファイルと一緒にGoldenファイルを作っておき analysistest.Run
の代わりに analysistest.RunWithSuggestedFixes
を使うことで analysis.Diagnostic.SuggestedFixes
の内容をテストする機構も提供されています。
べんり!
Goは標準で静的解析が色々とサポートされてて便利!
株式会社SODAの開発組織がお届けするZenn Publicationです。 是非Entrance Bookもご覧ください! → recruit.soda-inc.jp/engineer
Discussion