Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Starting static analysis with Go

164fd510e92a1912155b869b2c333c1e?s=47 Tsuji Daishiro
November 13, 2021

Starting static analysis with Go

Go Conference 2021 Autumn のセッションで使用した資料です。
- セッションの詳細: https://gocon.jp/2021autumn/sessions/go-static-analysis/
- 発表者: https://twitter.com/d_tutuz

資料に誤りがあればtwitterでご連絡ください。

164fd510e92a1912155b869b2c333c1e?s=128

Tsuji Daishiro

November 13, 2021
Tweet

More Decks by Tsuji Daishiro

Other Decks in Technology

Transcript

  1. The Go gopher was designed by Renée French. Goで静的解析をはじめてみよう! 2021/11/13(Sat)

    Go Conference 2021 Autumn Online Tsuji Daishiro
  2. Who are you? • 辻 大志郎(つじ だいしろう) ◦ @d_tutuz •

    所属 Future Architect(2014/10~)
  3. 本セッションのゴール • みなさんも go vet で使われているような静的解析モジュー ルを作れる!

  4. 静的解析はしきいが高い? • ソースコードの解析が必要? • 解析結果からロジックを実装する必要がある? • Goが提供している準標準ライブラリを使うことができる ◦ golang.org/x/tools/go/analysis ◦

    analysis パッケージは go vet でも使われている • analysisパッケージを使おう! • ロジックの実装に集中できる
  5. analysis パッケージの中心的な構造体 • analysis.Pass ◦ 静的解析に使う情報を扱う構造体 ◦ analysis.Pass を利用することでパッケージの情報や型、抽象構文木のトラ バース結果が簡単に手に入る!

    type Pass struct { // ... Pkg *types.Package // パッケージに関する情報 TypesInfo *types.Info // 抽象構文木の型に関する情報 // ... ResultOf map[*Analyzer]interface{} // 解析器をキーにした解析結果を保持 // ... }
  6. unmarshal モジュールで静的解析する流れ • Goのお手本の実装例を見るのがおすすめ ◦ unmarshal モジュール ◦ https://pkg.go.dev/golang.org/x/tools@v0.1.7/go/analysis/passes/unm arshal

    • 例:JSON のデコード ◦ json.Unmarshal や (*"encoding/json".Decoder).Decodeでは引数はポイ ンタ型である必要がある ◦ 引数がポインタ型でない場合は実行時エラー ◦ 静的解析(unmarshal モジュール)で引数の型をチェックできる
  7. unmarshal モジュールの実装 1. PreOrder(深さ優先探索)で抽象構文木の解析結果を取得 2. ノードがレシーバを保持しているかチェック 3. ノードの名前が Unmarshal か

    Decode であるかチェック 4. 関数呼び出しノードの引数の型情報を取得。ポインタ型やイン ターフェース型の場合はOK
  8. unmarshal モジュールの実装 (コア実装は70行程度) 1. PreOrder(深さ優先探索)で抽象構文木の解析結果を取得 → Pass.ResultOf の利用 2. ノードがレシーバを保持しているかチェック

    → Pass.ResultOf と Pass.TypesInfo の利用 3. ノードの名前が Unmarshal か Decode であるかチェック → Pass.ResultOf と Pass.TypesInfo の利用 4. 型情報から関数呼び出しノードの引数の型情報を取得。ポイ ンタ型やインターフェース型の場合はOK → Pass.ResultOf と Pass.TypesInfo の利用 Pass 構造体のフィールドを利用してロジックを実装できる
  9. まとめ • Goが提供している準標準ライブラリ (golang.org/x/tools/go/analysis) を使おう! ◦ 解析ロジックに集中できる • Goが提供している静的解析のモジュールのコードを参考に しよう!