LoginSignup
4
0

More than 3 years have passed since last update.

【Goland】 自作静的解析ツールをファイル保存時にフックさせる

Last updated at Posted at 2020-12-02

この記事はWanoグループ Advent Calendar 2020 の3日目の記事になります。🎅🎁

何をするのか

Golandでは、 gofmtgoimport のような静的解析のコマンドは少しの設定でファイル保存時に実行することができます。
今回は自作の静的解析ツールを上と同じように保存時にフックさせてみようと思います。

プロジェクト特有のコマンドをCIで実行しているような場合、それをローカルでも通してからpushしたい! みたいなケースで使えそうです

使うライブラリ

今回は、 TODO コメントが一つでもあったら怒られるというスパルタコマンドを checom という名前で作成 -> Golandに設定 してみます。
ちなみにTODOコメントに他意はありません

静的解析

コメントを抜き出すだけなら標準のライブラリで十分です。
* https://golang.org/pkg/go/parser/
* https://golang.org/pkg/go/token/

CLIツール

cobra というCLIツール作成用のライブラリを使っていますが、必須ではないです。
* github.com/spf13/cobra

静的解析ツールの作成

静的解析は標準の go パッケージを使えば非常に簡単

checom/main.go

package main

import (
    "fmt"
    "go/parser"
    "go/token"
    "os"
    "strings"

    "github.com/spf13/cobra"
)

func main() {
    if err := rootCmd.Execute(); err != nil {
        fmt.Fprintf(os.Stderr, "%s: %v\n", os.Args[0], err)
        os.Exit(-1)
    }
}

func init() {
    cobra.OnInitialize()
}

var rootCmd = &cobra.Command{
    Use: "checom",
    Run: CommentChecker,
}

const ngWord = "TODO"

func CommentChecker(cmd *cobra.Command, args []string) {
    fset := token.NewFileSet()

    f, err := parser.ParseFile(fset, args[0], nil, parser.ParseComments)
    if err != nil {
        fmt.Println(err)
        return
    }

    var cnt int
    for _, cg := range f.Comments {
        t := cg.Text()
        if strings.Contains(strings.ToUpper(t), ngWord) {
            cnt++
            fmt.Printf("😡 \n%s\n", t)
        }
    }

    if cnt != 0 {
        fmt.Println("😡 DO NOW 😡")
        return
    }
    fmt.Println("You're hard worker 😆")
}


f, err := parser.ParseFile(fset, args[0], nil, parser.ParseComments)

arg[0]にファイルのパスが入ってくる想定で、ファイルをパースしてコメントを引っこ抜いてます。

CLIツールはこれだけで、非常にシンプル

go install コマンドで $GOPATH/bin/ にバイナリを設置します。

$ cd project/checom
$ go install
$ ll $GOPATH/bin/ | grep checom
-rwxr-xr-x  1 user  staff   4922168 11  4 17:03 checom

これで $GOPATH/bin にパスが通っていれば checom /path/to/file で実行できるようになりました。

Golandの設定

Golandでは File watcher というファイル監視機構が用意されているのでそれを使います。
Preference > Tools > File watcher > + > custom から以下の設定します。
https://pleiades.io/help/go/new-watcher-dialog.html

スクリーンショット 2019-11-04 18.08.41.png

スクリーンショット 2019-11-04 17.09.27.png

File type

  • どのファイル形式の保存・変更時にフックさせるかの設定です。今回は Go ですね。

Program

  • ↑のバイナリの置き場所の指定です。
  • $GOPATH$ はGoland側に設定してあるマクロというかエイリアスなので、もし設定していなければ普通にバイナリまでのパスを書いても動きます。

Argument

  • コマンドの引数を指定できます。
  • 同様に $FilePath$ はGoland側の設定で、保存・変更したファイルのパスになります。

Show console

  • コマンドの実行結果をコンソールに出力する際の設定です。
  • デフォルトでは On error ですが、今回は全て標準出力に出力するようにしてしまっていたので、 Always にしないと何も表示されません。

ということで、上記を設定することで、Goland上で /path/to/project/hoge.go を保存・変更した場合に

$GOPATH/bin/checom /path/to/project/hoge.go

が走るようになりました。

動作

スクリーンショット 2019-11-04 18.04.21.png

小文字でも見逃してくれません。

スクリーンショット 2019-11-04 17.57.45.png

無事動きました

まとめ

静的解析ツールを作るハードルがかなり低いので、プロジェクト内でもCIなどで必要なニーズが出てきたら簡単に導入できそう。
Golandは全体の2%くらいしか機能を使えてない気がするので、もっと活用していこうという気になりました。


Wanoでは積極的にエンジニア採用を行なっています!
まずはオンラインでVPoEとのカジュアル面談から。お好きな入り口からお気軽にお声がけください!
Wano Recruitページ https://group.wano.co.jp/recruit/
QiitaJobs https://jobs.qiita.com/employers/wano-inc/postings/1297
Wantedly https://www.wantedly.com/companies/wano/projects
Findy https://findy-code.io/companies/522

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0