stringer を読み解く

# 概要
* 自動生成を試してみたかったので単純な(ことをしているように見える)stringer のソースを見る。
* [ソース](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go)

# 読み解く
#### [1-85](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L1-L85)
* 使い方やライセンスのコメント
* import


#### [86-103](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L86-L103)
* flagの設定
* [Usage](https://golang.org/pkg/flag/#pkg-variables) という便利なものがある

#### [105-170](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L105-L170)
* main

##### [106-141](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L106-L141)
* 変数の初期化等
* [Generator](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L129) が処理を担う

##### [142-169](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L142-L169)
* [143: パース処理](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L143)
* [152-155: 自動生成部分](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L152-L155)
* [158: フォーマット処理](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L158)
* Generator インスタンス内に解析した情報を保持して typeName 毎に出力出来るようにしている

#### [181-最後](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L181-L648)
* Genratorのメソッドとそれに附随するtypeやメソッド
* [Genrator](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L183)
* [File](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L196)
* [Package](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L207)
* [Value](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L344)

##### [parsePackage: 213-249](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L213-L249)
* main で出てきた1つ目のGenrator の処理
* [packagesライブラリ](https://godoc.org/golang.org/x/tools/go/packages)を使って、Package, File インスタンスを作成する
* Fileインスタンスは、packages.Package.Syntax 毎に作成 ([*ast.Filesの配列](https://godoc.org/golang.org/x/tools/go/packages#Package))

##### [generate:251-297](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L254-L297)
* [254-262](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L254-L262)でtypeName型の変数名と値を取得しvaluesに保持します。(処理の詳細は[File.genDecl](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L376-L469))
* [splitIntoRuns~build: (276-295)](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L276-L295) で連番ごとのsliceに分割し、sliceの数が1,~10,11以上で生成するコードを変える。[理由コメントが詳しく書いてある](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L277-L288)

###### [slice が一つのとき](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L554-L569)
* [558](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L558): 定数名を結合した文字列と、各定数の文字列内の開始Index一覧のconst,varを生成
* [564-568](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L564-L558): 生成したconst,varを使って文字列を決定するString()を生成

###### slice が~10, 11以上のとき
* [603](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L603): ~10のときは、複数のconst, varを生成する
* [629](https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L629) : 11以上のときは map を生成し、それを使用するString()を生成する

#### [format: [332-342] (https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L332-L342)]
* go/format パッケージ使うだけ

# 所感
* 解析にはgo/parserが必要でない
* genDecl部分と、ast.Fileの理解が出来れば簡単に自動生成が使えそう
* コメントがかなり丁寧に書いてある


# 参考
* [ast.File について](https://qiita.com/tenntenn/items/0cbc6f1f00dc579fcd8c)