1 of 23

Creating a lint tool

with analysis

Go 1.12 Release Party in Tokyo

@knsh14

2 of 23

自己紹介

  • 鎌田健史
  • knsh14
    • GitHub
    • Twitter
  • backend engineer

3 of 23

話すこと

  • 作ったものの紹介
  • analysis で解析ツールを作って得た知見
    • 解析ツールを作る
    • パッケージ構成
    • テストの書き方
    • 勉強するときのここを見ろ!

4 of 23

何を作ったのか

  • Go の循環複雑度を調べるツール
  • gocyclo の再発明
  • 2015年頃に一度作ったものを書き直した

5 of 23

循環複雑度とは

  • 関数がどれくらい理解するのが難しいかの指標
  • if 分岐や for の数などを数えることで導き出す
  • 多ければ多いほど、条件を網羅するためのテストケースを大量に用意する必要がある
  • 多いものは潜在的なバグを含んでる可能性があるので警告する

6 of 23

DEMO

7 of 23

analysis を使って解析ツールを作る

8 of 23

analysis ツールの作り方

  • analysis.Analyzer をカスタマイズしたパッケージ変数を作る
  • main 関数でsingle/multi checker を呼び出す
  • おしまい!
  • github.com/tenntenn/gosa/skeleton使うと便利
    • 雛形を作成してくれる
    • Analyzerとそのテストを準備してくれる
    • CLIも作ってくれる

9 of 23

パッケージ構成

10 of 23

gocc のパッケージ構成

  • リポジトリのトップレベルにAnalyzerを置く
  • cmd/goccはコマンドラインツール
  • 肝になるロジックはcomplexity
  • skeletonも同じ構成にしてくれます!便利!

11 of 23

リポジトリのトップレベルに Analyzer を置く

  • 他のリポジトリから呼び出したときに gocc.Analyzer となるようにするべき
  • analyzer ディレクトリを作ってそちらで定義したが悪手だった
    • 他で呼び出すときにanalyzer.Analyzerになってダサい

12 of 23

ロジックをサブディレクトリに置く

  • 循環複雑度を計算する部分だけを取り出した
  • 結果この部分だけTDTで開発できて非常に楽だった
  • analysis/passesパッケージ以下の実装だとそうではない
    • あんまり標準じゃないのかな?

13 of 23

テスト

14 of 23

Analyzer のテストを作る

  • analyzerのテストはanalysistestパッケージを使う
  • testdata/src/ 以下にディレクトリを作ってテストデータを書く
    • 実際に検出するためのモデルコードを作ってアノテーションを付けていく
  • ディレクトリを大雑把なカテゴリで分けてフィルタすると結果が見やすくなる

15 of 23

テストデータのサンプル

package complexity

func SimpleFunction(n int) {

println(n)

}

func ComplexFunction(n int) { // want `func ComplexFunction complexity=10`

if n == 0 {

println("zero")

}

16 of 23

Analyzer のテストするコード

package gocc

import (

"testing"

"golang.org/x/tools/go/analysis/analysistest"

)

func TestAnalyzer(t *testing.T) {

testdata := analysistest.TestData()

analysistest.Run(t, testdata, Analyzer, "foo")

}

17 of 23

テストデータを作るときの特徴

  • テストデータはtestdataディレクトリ以下をGOPATHとしてコードを読み込む
    • 依存しているコードなどはそこに書く必要がある
  • diagnosticのためのアノテーションは正規表現で解釈される
    • 括弧などを使ってる場合注意したほうがいい
    • 無思考で書いてるとハマる

18 of 23

analysis を勉強する

19 of 23

いいドキュメント

20 of 23

実際にどの様に使われてるか知る

  • コードを読む一択
  • analysis/passes 以下に新しい vet で使うために用意されたものが大量にある
  • 実装の参考になるし、すでにある実装を使うこともできるので作る前に目を通しておくとよい
    • inspect などは非常に便利

21 of 23

宣伝 1

  • SoftwareDesign誌で記事を書きました!
    • goccの初期実装をするまでです
    • Goエンジニアではない人でもわかるように書いています

22 of 23

宣伝2

  • 静的解析Dayやります!
    • 前回
    • ハンズオンしたり自分でもくもく作ったり…
      • 高みに登りすぎた孤高の tenntenn が教えてくれるはず
    • 興味があればぜひ!
    • 詳細はその後日公開されるのでご期待ください!

23 of 23

まとめ

  • 静的解析ツールを作るのは簡単になった!
    • skeleton便利(3度目)
  • みんなも解析ツール作ろう!
    • よくやるレビューはツールに任せて楽になりましょう!