skeletonにgo.modを作らないモードを作った
skeletonとは?
skeletonはGoで静的解析ツールをサクッと作るためのスケルトンコードジェネレータです。詳しくはskeletonで始めるGoの静的解析を御覧ください。
次のようにインストールできます。
$ go install github.com/gostaticanalysis/skeleton/v2@latest
実行すると次のようなディレクトリを作ってくれます。
$ skeleton github.com/tenntenn/findId
$ tree findId
findId
├── cmd
│ └── findId
│ └── main.go
├── findId.go
├── findId_test.go
├── go.mod
└── testdata
└── src
└── a
├── a.go
└── go.mod
5 directories, 6 files
ほとんどの雛形を作ってくれるので後は作りたい静的解析ツールにアルゴリズムに集中できます。生成されるコードや静的解析自体について知りたい場合はプログラミング言語Go完全入門の14章 静的解析とコード生成をご覧ください。
go.modが不要な場合
skeletonは作者も便利に使っているのですが、たまに不便だなと思う点がありました。その1つがすでにモジュールで管理されているコードベース以下でskeletonを使う場合です。
これまでのskeleton(v2)では、自動でgo.modファイルを生成していました。それ自体は非常に便利ですが、不要な場合もあります。例えば、zganeのような静的解析器をまとめたようなツールです。zaganeについてはこちらのブログをご参照ください。
そこでv2.2.0ではgomod
フラグを導入し、true
の場合のみgo.mod
ファイルを生成できるようにしました。たとえば、次のように実行するとカレントディレクトリの所属しているモジュールの情報を使ってスケルトンコードを生成してくれます。
$ cat go.mod
module example.com/example
go 1.18
$ skeleton -gomod=false mylinter
$ tree .
.
├── go.mod
└── mylinter
├── cmd
│ └── mylinter
│ └── main.go
├── mylinter.go
├── mylinter_test.go
└── testdata
└── src
└── a
├── a.go
└── go.mod
6 directories, 6 files
パッケージのインポートパスもモジュールパスからexample.com/example/mylinter
のように自動で補足してくれます。そのため、テストコードは次のようになります。ちゃんとモジュールパスが付加されてインポートしていることがわかります。
package mylinter_test
import (
"testing"
"example.com/example/mylinter"
"github.com/gostaticanalysis/testutil"
"golang.org/x/tools/go/analysis/analysistest"
)
// TestAnalyzer is a test for Analyzer.
func TestAnalyzer(t *testing.T) {
testdata := testutil.WithModules(t, analysistest.TestData(), nil)
analysistest.Run(t, testdata, mylinter.Analyzer, "a")
}
ちなみに、Go Moduleで管理されていないディレクトリ以下ではgomod
フラグはfalse
にできません。
$ skeleton -gomod=false mylinter
Error: cannot find go.mod, . may not managed with Go Modules
少し便利になったskeletonをぜひ使ってみてください!GitHubスターもポチッとお願いします。
Discussion