mirror of
https://github.com/golang/go
synced 2024-11-18 16:54:43 -07:00
internal/lsp/diff: rewrite ApplyEdits to work with sub-line diffs
This replaces the definition of ApplyEdits to be more like that in go vet -fix, so that we can apply the results of suggested fixes. Change-Id: Ib5724139464954e3790bc51ed1edc3ce4b2115ff Reviewed-on: https://go-review.googlesource.com/c/tools/+/193959 Run-TryBot: Michael Matloob <matloob@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
81ca6dc79c
commit
27d1b4e4f3
58
internal/lsp/diff/apply_edits.go
Normal file
58
internal/lsp/diff/apply_edits.go
Normal file
@ -0,0 +1,58 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ApplyEdits = applyEdits
|
||||
}
|
||||
|
||||
func applyEdits(before string, edits []TextEdit) string {
|
||||
// Preconditions:
|
||||
// - all of the edits apply to before
|
||||
// - and all the spans for each TextEdit have the same URI
|
||||
|
||||
// copy edits so we don't make a mess of the caller's slice
|
||||
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
|
||||
}
|
||||
|
||||
// sort the copy
|
||||
sort.Slice(edits, func(i, j int) bool { return offset(edits[i].Span.Start()) < offset(edits[j].Span.Start()) })
|
||||
|
||||
var after bytes.Buffer
|
||||
beforeOffset := 0
|
||||
for _, edit := range edits {
|
||||
if offset(edit.Span.Start()) < beforeOffset {
|
||||
panic("overlapping edits") // TODO(matloob): ApplyEdits doesn't return an error. What do we do?
|
||||
} else if offset(edit.Span.Start()) > beforeOffset {
|
||||
after.WriteString(before[beforeOffset:offset(edit.Span.Start())])
|
||||
beforeOffset = offset(edit.Span.Start())
|
||||
}
|
||||
// offset(edit.Span.Start) is now equal to beforeOffset
|
||||
after.WriteString(edit.NewText)
|
||||
beforeOffset += offset(edit.Span.End()) - offset(edit.Span.Start())
|
||||
}
|
||||
if beforeOffset < len(before) {
|
||||
after.WriteString(before[beforeOffset:])
|
||||
beforeOffset = len(before[beforeOffset:]) // just to preserve invariants
|
||||
}
|
||||
return after.String()
|
||||
}
|
29
internal/lsp/diff/apply_edits_test.go
Normal file
29
internal/lsp/diff/apply_edits_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
func TestApplyEdits(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
before string
|
||||
edits []TextEdit
|
||||
want string
|
||||
}{
|
||||
{"", nil, ""},
|
||||
{"X", []TextEdit{{newSpan(0, 1), "Y"}}, "Y"},
|
||||
{" X ", []TextEdit{{newSpan(1, 2), "Y"}}, " Y "},
|
||||
{" X X ", []TextEdit{{newSpan(1, 2), "Y"}, {newSpan(3, 4), "Z"}}, " Y Z "},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
if got := applyEdits(tc.before, tc.edits); got != tc.want {
|
||||
t.Errorf("applyEdits(%v, %v): got %v, want %v", tc.before, tc.edits, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newSpan(start, end int) span.Span {
|
||||
return span.New("", span.NewPoint(0, 0, start), span.NewPoint(0, 0, end))
|
||||
}
|
@ -14,7 +14,6 @@ import (
|
||||
|
||||
func init() {
|
||||
ComputeEdits = myersComputeEdits
|
||||
ApplyEdits = myersApplyEdits
|
||||
ToUnified = myersToUnified
|
||||
}
|
||||
|
||||
@ -24,11 +23,6 @@ func myersComputeEdits(uri span.URI, before, after string) []TextEdit {
|
||||
return myersDiffToEdits(uri, myers.Operations(u, f))
|
||||
}
|
||||
|
||||
func myersApplyEdits(before string, edits []TextEdit) string {
|
||||
ops := myersEditsToDiff(edits)
|
||||
return strings.Join(myers.ApplyEdits(myers.SplitLines(before), ops), "")
|
||||
}
|
||||
|
||||
func myersToUnified(from, to string, before string, edits []TextEdit) string {
|
||||
u := myers.SplitLines(before)
|
||||
ops := myersEditsToDiff(edits)
|
||||
|
Loading…
Reference in New Issue
Block a user