This bug is fixed by #2887
Have following .vimrc:
call plug#begin()
let g:go_imports_autosave = 1
Plug 'fatih/vim-go', { 'for': 'go', 'do': ':GoUpdateBinaries' }
Plug 'neoclide/coc.nvim', {'branch': 'release'}
call plug#end()
Following :CocConfig (in my case in ~/.vim/coc-settings.json):
{
"coc.preferences.useQuickfixForLocations": true,
"coc.preferences.snippets.enable": true,
"coc.preferences.extensionUpdateCheck": "never",
"suggest.disableMenu": true,
"suggest.snippetIndicator": "",
"diagnostic.level": "warning",
"languageserver": {
"golang": {
"command": "gopls",
"rootPatterns": ["go.mod", ".vim/", ".git/", ".hg/"],
"filetypes": ["go"]
}
}
}
And following file:
package main
import (
"os"
)
func main() {
fmt.Println(os.Args)
}
Then I save this file, and it's "fmt" is correctly added, but I get an error on line func main() that says [compiler] [E] undeclared name: fmt
I expect that coc.vim processes file that is transformed with goimports
It seems coc.vim processed file without imports added and marked errors on it, and only after this the contents of buffer were replaced leaving wrong errors in wrong places.
As above
master
:version):
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Apr 13 2020 07:47:09)
macOS version
Included patches: 1-550
go version):
go version go1.14.2 darwin/amd64
go env Output:
GO111MODULE=""
GOARCH="amd64"
GOBIN="/Users/sheerun/go/bin"
GOCACHE="/Users/sheerun/Library/Caches/go-build"
GOENV="/Users/sheerun/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/sheerun/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.14.2_1/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.14.2_1/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/sheerun/Source/Projects/gossandra/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/qc/03n3xp8n0v3866tj26mg953r0000gn/T/go-build495168971=/tmp/go-build -gno-record-gcc-switches -fno-common"
gopls version Output:
golang.org/x/tools/gopls 0.4.1
golang.org/x/tools/[email protected] h1:0e3BPxGV4B3cd0zdMuccwW72SgmHp92lAjOyxX/ScAw=
vim-go configuration
g:go_jump_to_error = 1
g:go_imports_autosave = 1
g:go_loaded_gosnippets = 1
g:go_loaded_install = 1
filetype detection
filetype detection:ON plugin:ON indent:ON
I don't believe this is issue with coc.vim, because vim-go currently saves file two times instead of one (one with unformatted contents and one with formatted contents), #2887 fixes this by formatting file in memory and then saving one time.
I don't understand why you're filing this as an issue with vim-go given that you've determined the error isn't coming from vim-go. Have you reached out to coc.nvim to file an issue there?
coc parses file as soon as it changes. the "fix" on their part would mean that file would be parsed and linted two times for each time vim-go changes it, which would not be sufficient and would cause performance issues as well as glitches in UI. I think true fix is to write file one time instead of two times
Do you experience this error if you use let g:go_fmt_command='goimports'?
yes, it's the same (which makes sense because let g:go_imports_autosave = 1 causes vim-go to follow practically the same code path)
Forgive me, but I don't see how it's writing the file without the adjusted imports in a way that's causing coc to see that file as changed. When g:go_fmt_command='goimports' is used where are the two writes that you're referring to?
To see this please create main.go:
锘匡豢package main
import (
"fmt"
"os"
)
func main() {
fmt.Println(os.Args)
}
Then please install fswatch and run fswatch main.go
Then open this file in vim, remove "fmt" line, and save file.
With current version of vim-go, the output is:
/Users/sheerun/Source/Projects/project/main.go
/Users/sheerun/Source/Projects/project/main.go
which means system marks this file as changed two times. If you use my branch as follows:
Plug 'sheerun/vim-go', { 'branch': 'improve-formatting-2', 'for': 'go', 'do': ':GoUpdateBinaries' }
Then the output after saving is:
/Users/sheerun/Source/Projects/project/main.go
which means file is saved one time
This would cause issues not only with Coc but also any software that depends on filesystem changes notificatons, like live-reloading or servers
Yes, it will save twice, but it should not be being saved with the insufficient imports if you use let g:go_fmt_command='goimports'; I don't see a way for coc.nvim to see the file with the insufficient imports in that case.
I installed coc.nvim to test this and was able to see the error a few times, but it's not consistent. I noticed, too, that the error I only saw the error when coc.nvim comes before vim-go in the runtime path (and even then it's not consistent). I suspect the problem is happening because of the event that coc.nvim is using to decide when to check the file. And since coc.nvim is primarily async, it's entirely possible that any errors that could seemingly be resolved with #2887 would only be made less likely and not actually eliminated.
The issue is not that file is written multiple times, but that file is written multiple times with different contents (one before formatting and one after formatting), #2887 makes sure that file is not written to disk before being formatted so it's not possible it doesn't solve this problem :)
I don't see a place in vim-go's code where it writes the file to disk (other than the temp file) before the imports are adjusted when you have g:go_fmt_command='goimports'. Where do you see that?
@sheerun the order of operations for formatting when g:go_fmt_command is goimports are:
BufWritePre autocmdg:go_fmt_commandBufWritePre autocmd completesThe two file writes you see are from when the temporary file is moved to the buffer's file location and Vim saving the file to disk; I don't see a time there where it would be written to disk before the imports are adjusted. Do you?
I just know this happens (fswatch shows this), and my PR fixed this. I don't have time to debug exactly why it happens :(
If someone has similar issue in the future: I've started using coc.vim without vim-go. It turns out coc.vim supports autocomplete, formatting, go to definition, and listing references, plus it works not only for go but also for other languages. Here's .vimrc (I use vim-plug):
call plug#begin()
Plug 'sheerun/vim-polyglot'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~ '\s'
endfunction
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
nmap <silent> <Enter> <Plug>(coc-definition)
nmap <silent> <Leader>r <Plug>(coc-references)
nmap <silent> <Leader>f <Plug>(coc-fix-current)
call plug#end()
And here's :CocConfig:
{
"coc.preferences.useQuickfixForLocations": true,
"coc.preferences.extensionUpdateCheck": "never",
"coc.preferences.messageLevel": "error",
"coc.preferences.snippets.enable": true,
"coc.preferences.formatOnType": true,
"suggest.disableMenu": true,
"suggest.snippetIndicator": "",
"diagnostic.level": "warning",
"diagnostic.messageDelay": 0,
"diagnostic.checkCurrentLine": true,
"diagnostic.format": "%message",
"languageserver": {
"golang": {
"command": "gopls",
"rootPatterns": ["go.mod", ".git/"],
"disableWorkspaceFolders": true,
"filetypes": ["go"],
"initializationOptions": {
"completeUnimported": true
}
}
}
}
I add missing / remove unused imports by pressing <Leader>f and applying quickfix.
Most helpful comment
If someone has similar issue in the future: I've started using coc.vim without vim-go. It turns out coc.vim supports autocomplete, formatting, go to definition, and listing references, plus it works not only for go but also for other languages. Here's .vimrc (I use vim-plug):
And here's
:CocConfig:I add missing / remove unused imports by pressing
<Leader>fand applying quickfix.