From cec2a53fb2396f4bd1af25116e77abcd87fdde10 Mon Sep 17 00:00:00 2001 From: Pontus Leitzler Date: Tue, 9 Feb 2021 07:51:01 +0100 Subject: [PATCH] cmd/govim: remove internal buffer on BufWipeout (#1037) There are cases where we might get a BufWipeout autocmd without the BufDelete (most notably when running :vimgrep). When that happen we kept the internal buffer in govim even if we had no use of it anymore. When using :bwipe we do get both BufDelete and BufWipeout, but as far as we know BufDelete will always appear before BufWipeout. Trying to remove an internal buffer due to BufWipeout will not cause an error. Fixes #1033 --- cmd/govim/buffer_events.go | 25 +++++++++++++++++++------ cmd/govim/main.go | 3 ++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cmd/govim/buffer_events.go b/cmd/govim/buffer_events.go index d7f77e0c6..a1977da6a 100644 --- a/cmd/govim/buffer_events.go +++ b/cmd/govim/buffer_events.go @@ -214,35 +214,48 @@ func (v *vimstate) handleBufferEvent(b *types.Buffer) error { return err } -func (v *vimstate) deleteCurrentBuffer(args ...json.RawMessage) error { +func (v *vimstate) bufDelete(args ...json.RawMessage) error { currBufNr := v.ParseInt(args[0]) cb, ok := v.buffers[currBufNr] if !ok { return fmt.Errorf("tried to remove buffer %v; but we have no record of it", currBufNr) } + return v.deleteBuffer(cb) +} + +func (v *vimstate) bufWipeout(args ...json.RawMessage) error { + currBufNr := v.ParseInt(args[0]) + if v.vimgrepPendingBufs != nil { delete(v.vimgrepPendingBufs, currBufNr) } + if cb, ok := v.buffers[currBufNr]; ok { + return v.deleteBuffer(cb) + } + return nil +} + +func (v *vimstate) deleteBuffer(b *types.Buffer) error { // The diagnosticsCache is updated with -1 (unknown buffer) as bufnr. // We don't want to remove the entries completely here since we want to show them in // the quickfix window. And we don't need to remove existing signs or text properties // either here since they are removed by vim automatically when a buffer is deleted. diags := *v.diagnosticsCache for i, d := range diags { - if d.Buf == currBufNr { + if d.Buf == b.Num { diags[i].Buf = -1 } } - v.ChannelCall("listener_remove", cb.Listener) - delete(v.buffers, cb.Num) + v.ChannelCall("listener_remove", b.Listener) + delete(v.buffers, b.Num) params := &protocol.DidCloseTextDocumentParams{ - TextDocument: cb.ToTextDocumentIdentifier(), + TextDocument: b.ToTextDocumentIdentifier(), } if err := v.server.DidClose(context.Background(), params); err != nil { - return fmt.Errorf("failed to call gopls.DidClose on %v: %v", cb.Name, err) + return fmt.Errorf("failed to call gopls.DidClose on %v: %v", b.Name, err) } return nil } diff --git a/cmd/govim/main.go b/cmd/govim/main.go index 7144570b1..17103435b 100644 --- a/cmd/govim/main.go +++ b/cmd/govim/main.go @@ -294,7 +294,8 @@ func (g *govimplugin) Init(gg govim.Govim, errCh chan error) error { g.DefineCommand(string(config.CommandSuggestedFixes), g.vimstate.suggestFixes, govim.NArgsZeroOrOne) g.DefineCommand(string(config.CommandGoToPrevDef), g.vimstate.gotoPrevDef, govim.NArgsZeroOrOne, govim.CountN(1)) g.DefineFunction(string(config.FunctionHover), []string{}, g.vimstate.hover) - g.DefineAutoCommand("", govim.Events{govim.EventBufDelete}, govim.Patterns{"*.go", "go.mod", "go.sum"}, false, g.vimstate.deleteCurrentBuffer, "eval(expand(''))") + g.DefineAutoCommand("", govim.Events{govim.EventBufDelete}, govim.Patterns{"*.go", "go.mod", "go.sum"}, false, g.vimstate.bufDelete, "eval(expand(''))") + g.DefineAutoCommand("", govim.Events{govim.EventBufWipeout}, govim.Patterns{"*.go", "go.mod", "go.sum"}, false, g.vimstate.bufWipeout, "eval(expand(''))") g.DefineCommand(string(config.CommandGoFmt), g.vimstate.gofmtCurrentBufferRange) g.DefineCommand(string(config.CommandGoImports), g.vimstate.goimportsCurrentBufferRange) g.DefineCommand(string(config.CommandQuickfixDiagnostics), g.vimstate.quickfixDiagnostics)