From b6bf2958931606642f3451852c25103758bd2fd9 Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Mon, 19 Nov 2018 19:19:47 -0500 Subject: [PATCH] internal/lsp: fix formatting bug that keeps adding extra newlines If a file ends with an empty newline, go/token treats the newline as the final character of the previous line. VSCode, however, treats this as a final line with no characters. We handle this by determining if the file we are formatting ends with a newline character and updating the protocol ranges accordingly. Change-Id: Id8be0fd776ae65c8f0f937f3e718825e407cb217 Reviewed-on: https://go-review.googlesource.com/c/150338 Reviewed-by: Ian Cottrell Run-TryBot: Rebecca Stambler TryBot-Result: Gobot Gobot --- internal/lsp/server.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/internal/lsp/server.go b/internal/lsp/server.go index ad51fa4d..5c9b4f2b 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -277,21 +277,36 @@ func formatRange(ctx context.Context, v *source.View, uri protocol.DocumentURI, } else { r = fromProtocolRange(tok, *rng) } + content, err := f.Read() + if err != nil { + return nil, err + } edits, err := source.Format(ctx, f, r) if err != nil { return nil, err } - return toProtocolEdits(tok, edits), nil + return toProtocolEdits(tok, content, edits), nil } -func toProtocolEdits(f *token.File, edits []source.TextEdit) []protocol.TextEdit { +func toProtocolEdits(tok *token.File, content []byte, edits []source.TextEdit) []protocol.TextEdit { if edits == nil { return nil } + // When a file ends with an empty line, the newline character is counted + // as part of the previous line. This causes the formatter to insert + // another unnecessary newline on each formatting. We handle this case by + // checking if the file already ends with a newline character. + hasExtraNewline := content[len(content)-1] == '\n' result := make([]protocol.TextEdit, len(edits)) for i, edit := range edits { + rng := toProtocolRange(tok, edit.Range) + // If the edit ends at the end of the file, add the extra line. + if hasExtraNewline && tok.Offset(edit.Range.End) == len(content) { + rng.End.Line++ + rng.End.Character = 0 + } result[i] = protocol.TextEdit{ - Range: toProtocolRange(f, edit.Range), + Range: rng, NewText: edit.NewText, } }