My External Storage

Jul 18, 2020 - 4 minute read - Comments - vim go

[Go] gopls 0.4.3で構造体を初期化("fillstruct")しようとしても、"No code actions found"とだけ表示される

gopls 0.4.3を使って構造体を初期化(fillstruct)しようとする(正確に言うとvim-lspで:LspCodeActionをする)と、No code actions foundと表示されるだけで初期化ができなかった。
0.4.3でも構造体の初期化を行うためのメモ。

Fillstruct performance improvements. It is now enabled by default again. (@joshbaum)

TL;DR

  • Vimでgoplsを使ったGoの開発環境構築をしている
  • 構造体を初期化するfillstruct機能がローカルでは動作しなかった
  • gopls 0.4.3からfillstruct機能は無効になっているので、明示的に有効にする必要がある。
  • vim-lspで有効にするには次のような設定になる。
  let g:lsp_settings = {}
  let g:lsp_settings['gopls'] = {
    \  'workspace_config': {
    \    'usePlaceholders': v:true,
    \    'analyses': {
    \      'fillstruct': v:true,
    \    },
    \  },
    \  'initialization_options': {
    \    'usePlaceholders': v:true,
    \    'analyses': {
    \      'fillstruct': v:true,
    \    },
    \  },
    \}

今回の現象が発生する各ツールのバージョンは次の通り。

$ vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled May 19 2020 22:07:34)
macOS version
Included patches: 1-800
Compiled by Homebrew
...
$ gopls version
golang.org/x/tools/gopls 0.4.3
    golang.org/x/tools/gopls@v0.4.3 h1:irz7Q+XdHNECamFKbNWKvMV2Ak6zBbwdwbZndG4545I=

goplsを使って構造体を初期化したい

Vim、vim-lsp、goplsを使ってGoの開発環境を構築している。
vim-go利用時に便利だった構造体を中身をゼロ値で初期化するfillstruct機能が便利だったので、goplsでも使いたいと思った。

ただ、実際に自分のVimでtweetの通りに(:LspCodeActionを)実行してもNo code actions foundと出るだけで構造体の初期化ができなかった。

goplsはgo get golang.org/x/tools/gopls@latestして2020/07/17時点で最新のバージョン(0.4.3)を利用していた。

gopls0.4.3以降ではfillstruct機能はデフォルト無効になっている

vim-jp Slackで質問していろいろ調べてもらった結果、goplsのfillstrcut機能は2020/07/09にリリースされたv0.4.3からはデフォルトオフになっていた。

Disable the fillstruct analysis by default. We recently uncovered some performance issues with the analysis, leading us to disable it by default. Once those issues are resolved, we will enable it by default again.

パフォーマンス問題が解決するまではデフォルト無効になったようだ。 リリースノートにはVS Codeで有効化する方法が書いてあるが、vim-lspでこれと同じfillstrcut機能を有効化する設定方法は次のとおり。

  let g:lsp_settings = {}
  let g:lsp_settings['gopls'] = {
    \  'workspace_config': {
    \    'usePlaceholders': v:true,
    \    'analyses': {
    \      'fillstruct': v:true,
    \    },
    \  },
    \  'initialization_options': {
    \    'usePlaceholders': v:true,
    \    'analyses': {
    \      'fillstruct': v:true,
    \    },
    \  },
    \}

Tips

調査の中で教えてもらった便利なことをメモしておく

特定のバージョンのgoplsを利用する

再現などの用途で特定のバージョンのライブラリを利用したいときはgo getするときにgo get golang.org/x/tools/gopls@v0.4.2とする。 goplsをgo getするときは-uを使ってはいけない。

LspInstallServerコマンドについて

vim-lsp-settingspの:LspInstallServerを行うと、独自にgoplsのバイナリがインストールされてしまうらしい。 ターミナル上で手動go getを使って取得したgoplsを使いたいときは、:LspUninstallServer goplsしておくこと。
また、vim-lsp-settingsでインストールしたバイナリを更新したいときは、再度:LspInstallServer goplsをすればVimが見ているgoplsが更新される。

LspCodeLensで使える機能はまだVimには早いかも

このあたりの設定を見ると、LSPからgo testが実行できそうに見える。 https://github.com/golang/tools/blob/0dca43fff13b95e02f929f8c7fd7e5952943e224/internal/lsp/source/options.go#L103-L109

SupportedCommands: []string{
  CommandTest,
  CommandTidy,
  CommandUpgradeDependency,
  CommandGenerate,
  CommandRegenerateCgo,
},

これは次のような設定を使うと、有効化される。

\ "codelens": {
\   "test": v:true
\ },

ただ、vim-lspにはLSPが実行したテストの結果をパースする機能がないため、UI上でその結果を得られないためまだちゃんと使える機能ではないらしい。

終わりに

リリースノートを読んでから使おうね案件だった。
ただ、自分でリリースノートを見ても、vim上で"gopls": {"analyses": {"fillstruct": true}}の設定をどう書けばいいのかわからなかったので、質問してよかった。
ローカルで再現してくれたり、g:lsp_settingsの書き方を教えてくださったり、vim-jp Slackのみなさんに感謝!!

fillstructはまだ載っていないが、)goplsでできることは次のMarkdownにまとまっているので、他にも有効化すべき機能はないか探してみる。 https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md

vim-goからLSPに移行をしてみて、だいぶ設定ができたと思うので、もうちょっとこなれたら改めてLSPの設定をまとめようと思う。

参考

関連記事