mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
internal/lsp: clean up ApplyEdits
This should be a faster but equivalent implementation. Change-Id: I7bc756644c601b953ba7715e093bfa10ca5ea97b Reviewed-on: https://go-review.googlesource.com/c/tools/+/198878 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
5bee6a6eb8
commit
c9f9432ec4
@ -6,8 +6,8 @@
|
|||||||
package diff
|
package diff
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/span"
|
"golang.org/x/tools/internal/span"
|
||||||
)
|
)
|
||||||
@ -41,44 +41,33 @@ func ApplyEdits(before string, edits []TextEdit) string {
|
|||||||
// Preconditions:
|
// Preconditions:
|
||||||
// - all of the edits apply to before
|
// - all of the edits apply to before
|
||||||
// - and all the spans for each TextEdit have the same URI
|
// - and all the spans for each TextEdit have the same URI
|
||||||
|
if len(edits) == 0 {
|
||||||
// copy edits so we don't make a mess of the caller's slice
|
return before
|
||||||
s := make([]TextEdit, len(edits))
|
|
||||||
copy(s, edits)
|
|
||||||
edits = s
|
|
||||||
|
|
||||||
// TODO(matloob): Initialize the Converter Once?
|
|
||||||
var conv span.Converter = span.NewContentConverter("", []byte(before))
|
|
||||||
offset := func(point span.Point) int {
|
|
||||||
if point.HasOffset() {
|
|
||||||
return point.Offset()
|
|
||||||
}
|
|
||||||
offset, err := conv.ToOffset(point.Line(), point.Column())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return offset
|
|
||||||
}
|
}
|
||||||
|
edits = prepareEdits(edits)
|
||||||
// sort the copy
|
c := span.NewContentConverter("", []byte(before))
|
||||||
sort.Slice(edits, func(i, j int) bool { return offset(edits[i].Span.Start()) < offset(edits[j].Span.Start()) })
|
after := strings.Builder{}
|
||||||
|
last := 0
|
||||||
var after bytes.Buffer
|
|
||||||
beforeOffset := 0
|
|
||||||
for _, edit := range edits {
|
for _, edit := range edits {
|
||||||
if offset(edit.Span.Start()) < beforeOffset {
|
spn, _ := edit.Span.WithAll(c)
|
||||||
panic("overlapping edits") // TODO(matloob): ApplyEdits doesn't return an error. What do we do?
|
start := spn.Start().Offset()
|
||||||
} else if offset(edit.Span.Start()) > beforeOffset {
|
if start > last {
|
||||||
after.WriteString(before[beforeOffset:offset(edit.Span.Start())])
|
after.WriteString(before[last:start])
|
||||||
beforeOffset = offset(edit.Span.Start())
|
last = start
|
||||||
}
|
}
|
||||||
// offset(edit.Span.Start) is now equal to beforeOffset
|
|
||||||
after.WriteString(edit.NewText)
|
after.WriteString(edit.NewText)
|
||||||
beforeOffset += offset(edit.Span.End()) - offset(edit.Span.Start())
|
last = spn.End().Offset()
|
||||||
}
|
}
|
||||||
if beforeOffset < len(before) {
|
if last < len(before) {
|
||||||
after.WriteString(before[beforeOffset:])
|
after.WriteString(before[last:])
|
||||||
beforeOffset = len(before[beforeOffset:]) // just to preserve invariants
|
|
||||||
}
|
}
|
||||||
return after.String()
|
return after.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepareEdits returns a sorted copy of the edits
|
||||||
|
func prepareEdits(edits []TextEdit) []TextEdit {
|
||||||
|
copied := make([]TextEdit, len(edits))
|
||||||
|
copy(copied, edits)
|
||||||
|
SortTextEdits(copied)
|
||||||
|
return copied
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user