Slide 1

Slide 1 text

gopls を改造したら 開発⽣産性が⾼まった tenntenn.go #17 - 静的解析ナイト 2024年10⽉24⽇

Slide 2

Slide 2 text

About Me Satoru Kitaguchi ● 株式会社エウレカ ○ Product Back-end Team ■ Go ■ Pairs の機能開発‧保守‧運⽤ ○ 平⽇も休⽇も Vim をいじってます ■ Vim Conf 2024 参加します!

Slide 3

Slide 3 text

本⽇のゴール 独⾃の静的解析ツールを組み込んだ gopls いいかもと思ってもらう

Slide 4

Slide 4 text

★ LSP とは ★ 静的解析の役割 ★ 改造版 gopls 導⼊の背景と導⼊してみて ★ 改造版 gopls の作り⽅ ★ 改造版 gopls の運⽤⽅法 ★ まとめ Agenda

Slide 5

Slide 5 text

LSP とは

Slide 6

Slide 6 text

LSP とは オートコンプリート、定義への移動、ホバー上のドキュメントなどの機能を IDE や Editor が共通して使⽤するための共通規格 (JSON-RPCベースのプロトコル) 画像出典: Language Server Extension Guide https://microsoft.github.io/language-server-protocol/overviews/lsp/overview/

Slide 7

Slide 7 text

静的解析の役割

Slide 8

Slide 8 text

静的解析の役割 ★ バグ、エラー、潜在的なリスクの早期発⾒ 修正コストの削減、品質の担保 ★ コーディング規約とベストプラクティスの遵守 レビュー負担の軽減 可読性、メンテナンス性、パフォーマンスの向上 ★ 開発⽣産性の向上 ⼊⼒⽀援 画像出典: GopherCon 2021: Akhil Indurti - Writing a Static Analyzer for Go Code

Slide 9

Slide 9 text

改造版 gopls 導⼊の背景と導⼊してみて

Slide 10

Slide 10 text

改造版 gopls 導⼊の背景 静的解析ツールの⼿動実⾏が⼿間 リアルタイムに静的解析ツールで検出したい

Slide 11

Slide 11 text

改造版 gopls の使⽤例 ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例 ハイライトされた34~36⾏⽬から実⾏できる

Slide 12

Slide 12 text

改造版 gopls の使⽤例 ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例 cursor を合わせて Quick Fix を表⽰すると 実⾏可能な textDocument/codeAction を選べる

Slide 13

Slide 13 text

改造版 gopls の使⽤例 ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例 実⾏すると全カラムが⾃動⼊⼒された! omit tag がついているカラムは⾃動⼊⼒の対象外になっている

Slide 14

Slide 14 text

改造版 gopls を導⼊してみて 実装中にWarning, Errorに気づけるようになった →リアルタイムで(⾃動)修正できるので実装速度の向上、⼿戻りの削減 Back-endメンバー全員が 静的解析ツールを追加/メンテする⽂化の醸成 →ポストモーテムの恒久対応として選ばれるように 静的解析ツールの作成がより⾝近になった

Slide 15

Slide 15 text

改造版 gopls の作り⽅ 1. 組み込み戦略

Slide 16

Slide 16 text

1. 組み込み戦略 textDocument/diagnostic & textDocument/codeAction ● 静的解析のナレッジを使える ● 独⾃ Analyzer を Plugin ライクに 追加できる ● コマンドラインから使いやすい ○ GoLand に優しい ● ほとんどメンテフリー textDocument/completion & snippet support ● 本家とConflict が発⽣しやすい ● Analyzer を組み込む形にはできない ● コマンドラインから使いにくい ● GoLand で使うのが厳しそう ● メンテ必須 ○ gopls を拡張する必要があるため

Slide 17

Slide 17 text

1. 組み込み戦略 git subtreeを使⽤して本家(golang/tools)に変更を加える

Slide 18

Slide 18 text

1. 組み込み戦略 独⾃ Analyzer を取り込んで本家を build するイメージ

Slide 19

Slide 19 text

改造版 gopls の作り⽅ 2. Analyzer の作成

Slide 20

Slide 20 text

2. Analyzerの作成 analysis package LSP Methods Pass.Reportf textDocument/diagnostic Pass.Report + Diagnostic + SuggestedFix textDocument/codeAction

Slide 21

Slide 21 text

2. Analyzer の作成 - textDocument/diagnostic textDocument/diagnostic を表⽰する analysis#Analyzer を作成するには analysis#Pass.Reportf を使⽤して Diagnostic を報告する 第1引数にコードの位置、第2引数に書式、第3引数以降にはその引数を取ってエラーを報告する analysis#Pass.Report の helper 関数になっている

Slide 22

Slide 22 text

2. Analyzer の作成 - textDocument/diagnostic の例 package 名のチェックをする例 (弊社ではほとんどの静的解析が textDocument/codeAction で実装されている)

Slide 23

Slide 23 text

2. Analyzer の作成 - textDocument/codeAction textDocument/codeAction を使⽤する analysis#Analyzer を作成するには analysis#Pass.Report に analysis#Diagnostic を指定して analysis#SuggestedFix で修正候補を表⽰する リファクタリングやエラー修正など修正内容が明確なユースケースで使⽤する

Slide 24

Slide 24 text

ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例 2. Analyzer の作成 - textDocument/codeAction の例 - VSCode ハイライトされた34~36⾏⽬から実⾏できる

Slide 25

Slide 25 text

ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例 2. Analyzer の作成 - textDocument/codeAction の例 - VSCode cursor を合わせて Quick Fix を表⽰すると 実⾏可能な textDocument/codeAction を選べる

Slide 26

Slide 26 text

ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例 2. Analyzer の作成 - textDocument/codeAction の例 - VSCode 実⾏すると全カラムが⾃動⼊⼒された! omit tag がついているカラムは⾃動⼊⼒の対象外になっている

Slide 27

Slide 27 text

2. Analyzer の作成 - textDocument/codeAction の例 - Vim 34~36⾏⽬がハイライトされている :LspDocumentDiagnostics を実⾏して 診断結果を表⽰する (直接遷移することもできるが、 わかりやすさのためファイル全体の診断を⾏う) ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例

Slide 28

Slide 28 text

2. Analyzer の作成 - textDocument/codeAction の例 - Vim 診断結果を Location List で確認して 診断結果までジャンプする cursor を合わせるとコマンドラインに メッセージが表⽰される ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例

Slide 29

Slide 29 text

2. Analyzer の作成 - textDocument/codeAction の例 - Vim :LspCodeAction quickfix を実⾏すると 全カラムが⾃動⼊⼒された! omit tag がついているカラムは ⾃動⼊⼒の対象外になっている :LspDocumentDiagnostics の実⾏は必須ではなく :LspNextDiagnostics など任意の動作で移動した後 そのまま textDocument/codeAction を実⾏できる また複数の textDocument/codeAction が有効な場合は lsp-quickpick を利⽤して選択することができる (Vim) ORM XORM から MasterMinds/squirrel に安全に移⾏するために ワイルドカードを禁⽌し全カラムを⾃動⼊⼒する静的解析ツールの実⾏例

Slide 30

Slide 30 text

2. Analyzer の作成 - textDocument/codeAction の例 - Vim golden 形式で⽐較する Controller 単位の endpoint テストを⾃動作成する例 7~9⾏⽬がハイライトされている :LspDocumentDiagnostics を実⾏して 診断結果を表⽰する (直接遷移することもできるが、 わかりやすさのためファイル全体の診断を⾏う)

Slide 31

Slide 31 text

2. Analyzer の作成 - textDocument/codeAction の例 - Vim golden 形式で⽐較する Controller 単位の endpoint テストを⾃動作成する例 診断結果を Location List で確認して 診断結果までジャンプする cursor を合わせるとコマンドラインに メッセージが表⽰される

Slide 32

Slide 32 text

2. Analyzer の作成 - textDocument/codeAction の例 - Vim golden 形式で⽐較する Controller 単位の endpoint テストを⾃動作成する例 :LspCodeAction quickfix を実⾏すると テストが⾃動⽣成された! :LspDocumentDiagnostics の実⾏は必須ではなく :LspNextDiagnostics など任意の動作で移動した後 そのまま textDocument/codeAction を実⾏できる また複数の textDocument/codeAction が利⽤できる場合 lsp-quickpick を利⽤して選択できる (Vim)

Slide 33

Slide 33 text

golden 形式で⽐較する Controller 単位の endpoint テストを⾃動作成する例 2. Analyzer の作成 - textDocument/codeAction の例 - VSCode ハイライトされた7~9⾏⽬から実⾏できる

Slide 34

Slide 34 text

golden 形式で⽐較する Controller 単位の endpoint テストを⾃動作成する例 2. Analyzer の作成 - textDocument/codeAction の例 - VSCode cursor を合わせて Quick Fix を表⽰すると 実⾏可能な textDocument/codeAction を選べる

Slide 35

Slide 35 text

golden 形式で⽐較する Controller 単位の endpoint テストを⾃動作成する例 2. Analyzer の作成 - textDocument/codeAction の例 - VSCode 実⾏するとテストの雛形が作成された!

Slide 36

Slide 36 text

改造版 gopls の作り⽅ 3. Analyzer の組み込み

Slide 37

Slide 37 text

3. Analyzer の組み込み golang.org/x/tools/gopls/internal/settings/analysis.go の DefaultAnalyzer に builtin の Analyzer が登録される

Slide 38

Slide 38 text

3. Analyzer の組み込み 登録された Analyzer が goroutine で実⾏される

Slide 39

Slide 39 text

3. Analyzer の組み込み DefaultAnalyzer に独⾃ Analyzer を組み込めるように改変する 稀に型や変数名が変わることがありコンフリクトすることがある コンフリクトを解消しやすいように初期化時に DefaultAnalyzer に代⼊しないようにする

Slide 40

Slide 40 text

3. Analyzer の組み込み analysis#Analyzer の追加⼿順 1. golang.org/x/tools/eure/analyzer に Analyzer を実装する 2. golang.org/x/tools/gopls/internal/settings/eure.go に1を追加する 3. cmd に1を追加する

Slide 41

Slide 41 text

3. Analyzer の組み込み analysis#Analyzer の追加⼿順 1. golang.org/x/tools/eure/analyzer に Analyzer を実装する 2. golang.org/x/tools/gopls/internal/settings/eure.go に1を追加する 3. cmd に1を追加する

Slide 42

Slide 42 text

改造版 gopls の作り⽅ 4. Editor / IDE の連携

Slide 43

Slide 43 text

4. Editor / IDE の連携 Vim / VS Code 改造版 gopls が使われていることを確認するだけ! GoLand gopls を使⽤しないため integration が必要 コマンドライン経由で発⽕させたり、Kotlin で Plugin を書いたり

Slide 44

Slide 44 text

改造版 gopls の運⽤⽅法 1. 本体との同期とメンテナンス

Slide 45

Slide 45 text

1. 本体との同期とメンテナンス GitHub Actionsで本家との同期を⾏う package名の変更などでconflictした場合は ⼿直しする必要がある

Slide 46

Slide 46 text

改造版 gopls の運⽤⽅法 2. linter と reviewdog の連携

Slide 47

Slide 47 text

linter と reviewdog の連携 CI でも gopls 同様の Analyzer のチェックをしたい! →まとめて1つの linter として定義し PR で reviewdog に指摘してもらう gopls check でも良いけれど下記の点でmulticheckerを使うことに ★ package 単位で実⾏したい ★ 静的解析ツール追加時に go-tools のみの変更に留めたい

Slide 48

Slide 48 text

まとめ

Slide 49

Slide 49 text

まとめ 独⾃ Analyzer を組み込めるように gopls を改造して 運⽤を始めてから2年以上経った ★ リアルタイムで修正できることで開発⽣産性が向上 ★ チーム全員で静的解析ツールを追加/メンテできるように gopls 改造は簡単に始められます。 公式に拡張がサポートされる未来にも期待しましょう。

Slide 50

Slide 50 text

No content