Go Analysis Framework: Goチームによるモジュール式静的解析
Go Analysis Framework: Goチームによるモジュール式静的解析
概要
Go analysis frameworkは、共通のAnalyzerインターフェースを定義します。これにより、開発者は、vet、テキストエディタ、ビルドシステム、カスタムリンターなどのドライバーで使用可能なモジュール式の静的解析を記述できます。
Analyzer型
Analyzerは、解析関数を静的に記述します。これには、name、documentation、flag set、Run関数、RunDespiteErrors、ResultType、Requires依存関係、およびFactTypesのフィールドが含まれます。Run関数は*Passを受け取り、interface{}の結果とエラーを返します。Validate関数は、Requiresグラフが非循環であること、factおよびresultの型が一意であること、およびRunがnilでないことを確認します。
Pass型
Passは、単一の作業単位、つまり1つのGoパッケージに対して1つのAnalyzerを適用することを表します。これは、ファイルセット、構文木、型情報、および診断を報告するためのヘルパーメソッドを提供します。ResultOfマップは、必要なAnalyzerからの結果を保持します。ReportfおよびReportRangefヘルパーは、位置、オプションのカテゴリ、およびメッセージを持つDiagnosticオブジェクトを作成します。また、Passは、パッケージ間でfactを共有するためのExportObjectFact、ImportObjectFact、ExportPackageFact、およびImportPackageFactを提供します。
Factsとモジュール式解析
Factは、解析がtypes.Objectまたはパッケージに付加できる、中間的でシリアル化可能な情報です。これにより、分離コンパイル形式の解析が可能になります。つまり、あるAnalyzerがexportしたfactを、後続のAnalyzerがドライバーを介してimportできます。Factの型はポインタである必要があり、gobでエンコードされます。コンテンツアドレス可能なキャッシュで動作させるために、これらはステートレスかつ決定論的である必要があります。printfチェッカーは、どの関数がfmt.Printfに委譲しているかを記録し、そのfactを再利用して他のパッケージからの呼び出しをチェックすることで、この例を示しています。
Analyzerのテスト
analysistestサブパッケージは、testdataファイル上でAnalyzerを実行し、ソース内の"// want"コメントを介して期待される診断とfactを検証することで、Analyzerのテストを支援します。これにより、完全なドライバーを構築することなく、正当性をアサートする軽量な方法が提供されます。
スタンドアロンコマンド
singlecheckerおよびmulticheckerサブパッケージは、1つまたは複数のAnalyzerを実行するコマンドラインツールの作成を簡素化します。典型的な単一Analyzerコマンドは以下の通りです:
package main
import (
"golang.org/x/tools/go/analysis/passes/findcall"
"golang.org/x/tools/go/analysis/singlechecker"
)
func main() { singlechecker.Main(findcall.Analyzer) }
multicheckerコマンドは、単に*Analyzerのスライスをmultichecker.Mainに渡すだけです。
エコシステムでの利用
コメントによると、このフレームワークはすでに多くのリンターで使用されています(golang.org/x/tools/go/analysisのインポートグラフを参照)。あるユーザーは、SpiceDBのためにカスタムAnalyzerを定義することに成功したと報告しており、フレームワークによって暗黙知の必要性が減り、コードレビューがスピードアップすることを強調しています。別のコメントでは、これらのプリミティブを使用してより広範なアーキテクチャリンターを構築できるかどうかが問われており、より高レベルなチェックへの関心が示唆されています。さらに別のコメントでは、ビルドタグやtestscriptを活用したパーソナルプロジェクトを例に挙げ、人間とエージェントの両方の開発のためのツールに焦点を当てているGoチームを称賛しています。
これらの観察は、analysisパッケージが、vetのような既存のツールとユーザー定義のチェッカーの両方にとって再利用可能な基盤として機能し、Goエコシステム全体でモジュール化されたfact駆動の静的解析をサポートしていることを裏付けています。