From 3c50ac166654870465a03fedd72c5466835c36e3 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Wed, 12 Aug 2020 16:21:05 -0400 Subject: [PATCH] Fix edit application in formatting --- internal/action/actions.go | 4 +--- internal/buffer/buffer.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/internal/action/actions.go b/internal/action/actions.go index 04db5b44..cac954a1 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -1844,9 +1844,7 @@ func (h *BufPane) AutoFormat() bool { return false } - for _, e := range edits { - h.Buf.ApplyEdit(e) - } + h.Buf.ApplyEdits(edits) return true } diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index e4d27859..68092f8d 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -12,6 +12,7 @@ import ( "path" gopath "path" "path/filepath" + "sort" "strconv" "strings" "sync" @@ -517,6 +518,25 @@ func (b *Buffer) ApplyEdit(e lspt.TextEdit) { } } +func (b *Buffer) ApplyEdits(edits []lspt.TextEdit) { + deltas := make([]Delta, len(edits)) + for i, e := range edits { + deltas[i] = Delta{ + Text: []byte(e.NewText), + Start: toLoc(e.Range.Start), + End: toLoc(e.Range.End), + } + } + // Since edit ranges are guaranteed by LSP to never overlap we can sort + // by last edit first and apply each edit in order + // Perhaps in the future we should make this more robust to a non-conforming + // server that sends overlapping ranges + sort.Slice(deltas, func(i, j int) bool { + return deltas[i].Start.GreaterThan(deltas[j].Start) + }) + b.MultipleReplace(deltas) +} + // FileType returns the buffer's filetype func (b *Buffer) FileType() string { return b.Settings["filetype"].(string)