公私でGoを書くときはVimを使っている。
ファイル保存時にgolangci-lint
を実行するように設定しているのだが、表題のエラーが出て静的解析が実行されなかったので原因調査・解決した。
TL;DR
- VimでGoを書いているとき、
vim-go: [golangci-lint] FAIL
エラーがでてgolangci-lint
が失敗するようになった :messages
を見てもわからなかった:GoMetaLinter
コマンドを実行したところ、本当のエラーメッセージがわかったlevel=error msg="Running error: --enable-all and --disable-all options must not be combined"
.golangci.yml
の設定を修正して解決した
エラーが出てvim-goでgolangci-lintが動かない
公私でGoを書くときはVimを使っている。
私のVimでは(golangci-lint
を使う設定をして、)GoMetaLinterAutoSaveToggle
オプションを有効にしているので、ファイル保存時にgolangci-lint
が実行される。
- GoMetaLinterAutoSaveToggle | fatih/vim-go
ここで、あるGoのプロジェクトで作業しているときだけ、ファイル保存時にvim-go: [golangci-lint] FAIL
とエラーメッセージが表示されるだけで静的解析が実行されなくなった。
原因調査: :GoMetaLinter
コマンドを直接実行してみる
コマンドラインから直接golangci-lint
コマンドを実行しても正常に実行できていた。
:messages
コマンドでVimが出力しているログを見ても、何が問題でgolangci-lint
コマンドが失敗しているのかよくわからなかった。
- message - Vim日本語ドキュメント
起動直後にファイルを保存してエラーが出た状態で:messages
コマンドでログをみても以下の通り。
Messages maintainer: Bram Moolenaar <Bram@vim.org>
"main.go" 100L, 2767C
vim-go: initializing gopls
"main.go" 100L, 2767C written
vim-go: [golangci-lint] dispatched
vim-go: [golangci-lint] FAIL
ここで、vim-go
を利用しているVimでは、:GoMetaLinter
コマンドを使うことで、明示的にgolangci-lint
を実行できる。
:GoMetaLinter
| fatih/vim-go
:GoMetaLinter
コマンドを実行してみたところ、以下のようなエラーメッセージを確認することができた。
level=error msg="Running error: --enable-all and --disable-all options must not be combined"
どうやら、プロジェクトに配置してある.golangci.yml
に記載されている設定と、vim-go
でgolangci-lint
コマンドを呼び出すときのオプションが競合しているのが原因だった。
vim-go
はgolangci-lint
コマンドを呼び出すとき以下のように実行コマンドを組み立てる。この中で、--disable-all
オプションを指定している。
function! s:golangcilintcmd(bin_path)
let cmd = [a:bin_path]
let cmd += ["run"]
let cmd += ["--print-issued-lines=false"]
let cmd += ['--build-tags', go#config#BuildTags()]
let cmd += ["--disable-all"]
" do not use the default exclude patterns, because doing so causes golint
" problems about missing doc strings to be ignored and other things that
" golint identifies.
let cmd += ["--exclude-use-default=false"]
return cmd
endfunction
今回、プロジェクトで設置してある.golangci.yml
ファイルではenable-all
をベースに静的解析の設定を組み立てていため、enable-all
とdisable-all
設定が競合していた。
linters:
enable-all: true
disable:
- funlen
- dogsled
解決方法:.golangci.yml
の設定を修正する
今回は以下の理由により、.golangci.yml
側の設定方法を修正することで対応した。
- Vim側の
golangci-lint
コマンドの呼び出し時の設定を変更する方法がよくわからなかった enable-all
ベースで設定していると、golangci-lint
コマンドが新しいツールをサポートしたとき、意図せず有効化されるdisable-all
したあと、明示的に利用する静的解析ツールを指定したほうがヒューマンリーダブルな設定になる
golangci-lint
コマンドはgolangci-lint linters
コマンドでそのプロジェクト上(ディレクトリ上)の静的解析の設定を確認することができる。
なので、一度enable-all
ベースの設定でgolangci-lint linters
コマンドを実行し、ファイルに出力を保存しておいた。
$ golangci-lint linters
Enabled by your configuration linters:
bodyclose: checks whether HTTP response body is closed successfully [fast: true, auto-fix: false]
deadcode: Finds unused code [fast: true, auto-fix: false]
...
Disabled by your configuration linters:
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
dogsled: Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
...
その後、disable-all
ベースの設定に書き直し、golangci-lint linters
コマンドの結果が以前と同じであることを確認した。
終わりに
私のVimの設定は一応golangci-lint
やgopls
を利用するように設定しているのだが、一度整理したほうがよいかなと思いつつズルズル使っている。
LSP系のプラグイン経由でgopls
を実行するほうがいろいろ設定できるらしいので、一度整理しようかなあ。