概要
- Goの 静的解析フレームワーク の概要と設計思想
- Analyzer型 による解析器の定義と利用方法
- Pass型 による解析単位と診断結果の報告方法
- Fact を用いたモジュラー解析の仕組み
- 実装・運用上の注意点 とテスト方法の紹介
Go静的解析フレームワークの設計と利用
- 静的解析 とは、Goコードのパッケージを検査し、 診断情報やリファクタ提案 などを報告する仕組み
- Checker は、コードのミスを報告する解析器の非公式な呼称
- 代表例として、 printf checker はfmt.Printfのフォーマット文字列の誤りを検出
- モジュラー解析 では、パッケージ単位で解析し、下位パッケージの情報を上位パッケージ解析時に活用
- 例:log.Fatalfがfmt.Printfを委譲する事実を記録し、他パッケージからの呼び出しも検査
- 共通インターフェース により、様々な解析器をコマンドラインツール・IDE・ビルドシステムなど多様なドライバーで再利用可能
Analyzer型による解析器の定義
- Analyzer型 は、解析器の名前・説明文・フラグ・依存関係・解析ロジックなどを記述する型
- 解析器は、 Analyzer型の変数 として宣言
- 例:
- Name: "unusedresult"
- Doc: "特定関数の戻り値未使用の検査"
- Run: 解析本体関数
- 例:
- ドライバープログラム(例: vet)は、利用したい Analyzerのリスト をimportし、実行
- Flags フィールドで解析器固有のフラグを宣言し、ドライバーが設定方法を決定
- RunDespiteErrors で型エラーの際の挙動を制御
- ResultType/Requires で他解析器との依存関係や結果型を明示
- FactTypes でモジュラー解析用のFact型を宣言
Pass型と診断結果の報告
- Pass型 は、特定パッケージに対する特定解析器の適用単位を表現
- Fset, Files, Pkg, TypesInfo などで構文木・型情報・ソース位置を保持
- OtherFiles/IgnoredFiles で非Goファイルやビルド設定により除外されたファイル名を管理
- ResultOf で依存解析器の結果を参照
- Report/Reportf で診断情報をソース位置付きで報告
- Diagnostic型:Pos, Category, Messageを保持
- 診断の重要度(severity)はAnalyzerではなくドライバー側で制御
非Goファイルや生テキストへの診断
- Pass.ReadFile で任意ファイル内容を取得可能
- token.FileSet を用いて生テキストファイルの行番号診断を実現
モジュラー解析とFactの利用
- Fact は「fはprintfラッパーである」など、診断以外の中間的事実を表現
- 解析器は FactTypes で利用するFact型を宣言
- ExportObjectFact/ImportObjectFact でオブジェクト単位のFactを入出力
- ExportPackageFact/ImportPackageFact でパッケージ単位のFactを入出力
- Factはgobエンコーディングでシリアライズ され、ドライバー間で安全に伝播
- Factはstatelessかつ決定的なシリアライズが必須
- 標準パッケージへのFact伝播に制限 があるため、解析器実装時は注意
テスト方法
- analysistestサブパッケージ で、少ないコードで解析器のテストが可能
- テストデータ用のパッケージへの適用をサポート
この内容により、Goの静的解析フレームワークの設計・利用方法・拡張性・運用上の注意点が体系的に把握可能。