goパッケージで型情報を用いた
ソースコード検索を実現する
2017/04/13(木)
@Shinjuku.go#1
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license.
自己紹介
メルカリ/ソウゾウ
上田拓也
twitter: @tenntenn
■ コミュニティ活動
Google Cloud Platform User Group (GCPUG) Tokyo
Goビギナーズ
golang.tokyo
Go Conference
■ 業務
GAE/Goでメルカリアッテを作ってます
GoやGCPコミュニティを盛り上げる仕事
Gopherを描く仕事(LINEスタンプ)
2
静的解析をして型情報から
ソースコードを検索しよう
3
ソースコードの静的解析とは?
4
■ ソースコードを実行せずに解析すること
● ソースコードから抽象構文木(AST)などを取
得して解析する
● 静的型付け言語だと、静的解析で型情報が
取得できる
● 逆は実行して解析する動的解析
Goで静的解析をすると何が嬉しいのか?
● リファクタリングツール
○ 変数の宣言位置や使用箇所の抽出
○ パッケージの解析
● コードジェネレーター
○ コメントによるアノテーションの抽出
○ コードフォーマッタ
● 処理系
○ 抽象構文木(AST)の解析
○ 定数の扱い
5
静的型付け言語なので
静的解析でも多くの事が知れる
6
コントリビュータになれる!
7
https://www.slideshare.net/takuyaueda967/go-72158330
開発ツールとソースコードの静的解析
8
■ 開発ツールの多くは静的解析を行っている
● gofmt/goimports
○ コードフォーマッター
● go vet/golint
○ コードチェッカー、リンター
● guru
○ 静的解析
● gocode
○ コード補完
● errcheck
○ エラー処理のチェック
● gorename/gomvpkg
○ リファクタリングツール
■ 標準パッケージで静的解析の機能を提供
goパッケージ
9
go/ast 抽象構文木(AST)を提供
go/build パッケージに関する情報を集める
go/constant 定数に関する型を提供
go/doc ドキュメントをASTから取り出す
go/format コードフォーマッタの機能を提供
go/importer コンパイラに適したImporterを提供
go/parser 構文解析の機能を提供
go/printer ASTの表示機能を提供
go/scanner 字句解析の機能を提供
go/token トークンに関する型を提供
go/types 型チェックに関する機能を提供
静的解析の流れ
10
ソースコード
トークン
抽象構文木(AST)
型情報
構文解析
字句解析
型チェック
go/scanner
go/token
go/parser
go/ast
go/types
go/constant
字句解析 - go/scanner,go/token
■ 文字列をトークンにしていく
● 空白などを取り除き、意味のある単位=トー
クンにしていく作業
11
v + 1
IDENT ADD INT
トークン
ソースコード
構文解析 - go/parser,go/ast
■ トークンを抽象構文木(AST)にしていく
● プログラムの構造を持たせる
12
v + 1
IDENT ADD INT
ソースコード
+
v 1
BinaryExpr
Ident BasicLit
トークン
抽象構文木(AST)
型チェック - go/types,go/constant
■ 型チェックを行う
● 識別子の解決
● 型の推論
● 定数の評価
13
n := 100 + 200
fmt.Println(n)
定数の評価
=300
型の推論
-> int
識別子の解決
識別子の解決
-> fmtパッケージ
型情報を用いて検索してみる
14
具象型のエラーを返してる部分を検索
15
■ やりたいこと
● errorインタフェースを実装している型を返
す関数を探す
● そのうち、error型として返さず別の型とし
て返しているものを探す
■ やりかた
● ASTを取得する
● 型情報を取得する
● 型情報とASTから該当の関数を探す
ほら、簡単!
今回対象とするサンプル
type Err string
func (err Err) Error() string {
return string(err)
}
func f() Err { return Err("error") }
func main() {
fmt.Println(f())
fmt.Println(func() Err {
return Err("error2")
})
fmt.Println(func() error {
return nil
})
}
16
これ
これ
ここから
ライブコーディング!
17
https://gist.github.com/tenntenn/607e27
638a3ec850c9a7c2dec334b5b7
まとめ
18
■ 静的解析はかんたん
● goパッケージを使う
● ASTや型情報の取得も簡単
● 静的解析で多くの情報が知れる
■ 開発ツールを作って開発効率を上げよう
● 標準でも多くの開発ツールがある
● 自分でも簡単に開発ツールが作れる
● 21世紀なのでソースコードの質はツールで
保証しよう
Thank you!
twitter: @tenntenn
Qiita: tenntenn
connpass: tenntenn
19

goパッケージで型情報を用いたソースコード検索を実現する