Skip to content

Commit 9cd7e18

Browse files
committed
internal/lsp: invert the diff dependencies so myers depends on diff
This makes it so the diff package is depended on by all implementations, rather than the diff package having to depend on the default myers implementation. Change-Id: I04b9caee6ff1017fa8e5476a7434e4b0e17753c3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/198379 Reviewed-by: Rebecca Stambler <[email protected]>
1 parent b2e299b commit 9cd7e18

File tree

7 files changed

+89
-89
lines changed

7 files changed

+89
-89
lines changed

internal/lsp/diff/hooks.go internal/lsp/diff/diff.go

+24
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,30 @@ var (
2424
ToUnified func(from, to string, before string, edits []TextEdit) string
2525
)
2626

27+
type OpKind int
28+
29+
const (
30+
Delete OpKind = iota
31+
Insert
32+
Equal
33+
)
34+
35+
func (k OpKind) String() string {
36+
switch k {
37+
case Delete:
38+
return "delete"
39+
case Insert:
40+
return "insert"
41+
case Equal:
42+
return "equal"
43+
default:
44+
panic("unknown operation kind")
45+
}
46+
}
47+
48+
// SortTextEdits attempts to order all edits by their starting points.
49+
// The sort is stable so that edits with the same starting point will not
50+
// be reordered.
2751
func SortTextEdits(d []TextEdit) {
2852
// Use a stable sort to maintain the order of edits inserted at the same position.
2953
sort.SliceStable(d, func(i int, j int) bool {

internal/lsp/diff/diff_test.go

-16
This file was deleted.

internal/lsp/diff/myers/diff.go

+10-27
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,23 @@
55
// Package myers implements the Myers diff algorithm.
66
package myers
77

8-
import "strings"
8+
import (
9+
"strings"
10+
11+
"golang.org/x/tools/internal/lsp/diff"
12+
)
913

1014
// Sources:
1115
// https://blog.jcoglan.com/2017/02/17/the-myers-diff-algorithm-part-3/
1216
// https://www.codeproject.com/Articles/42279/%2FArticles%2F42279%2FInvestigating-Myers-diff-algorithm-Part-1-of-2
1317

1418
type Op struct {
15-
Kind OpKind
19+
Kind diff.OpKind
1620
Content []string // content from b
1721
I1, I2 int // indices of the line in a
1822
J1 int // indices of the line in b, J2 implied by len(Content)
1923
}
2024

21-
type OpKind int
22-
23-
const (
24-
Delete OpKind = iota
25-
Insert
26-
Equal
27-
)
28-
29-
func (k OpKind) String() string {
30-
switch k {
31-
case Delete:
32-
return "delete"
33-
case Insert:
34-
return "insert"
35-
case Equal:
36-
return "equal"
37-
default:
38-
panic("unknown operation kind")
39-
}
40-
}
41-
4225
func ApplyEdits(a []string, operations []*Op) []string {
4326
var b []string
4427
var prevI2 int
@@ -50,7 +33,7 @@ func ApplyEdits(a []string, operations []*Op) []string {
5033
}
5134
}
5235
switch op.Kind {
53-
case Equal, Insert:
36+
case diff.Equal, diff.Insert:
5437
b = append(b, op.Content...)
5538
}
5639
prevI2 = op.I2
@@ -84,7 +67,7 @@ func Operations(a, b []string) []*Op {
8467
return
8568
}
8669
op.I2 = i2
87-
if op.Kind == Insert {
70+
if op.Kind == diff.Insert {
8871
op.Content = b[op.J1:j2]
8972
}
9073
solution[i] = op
@@ -100,7 +83,7 @@ func Operations(a, b []string) []*Op {
10083
for snake[0]-snake[1] > x-y {
10184
if op == nil {
10285
op = &Op{
103-
Kind: Delete,
86+
Kind: diff.Delete,
10487
I1: x,
10588
J1: y,
10689
}
@@ -116,7 +99,7 @@ func Operations(a, b []string) []*Op {
11699
for snake[0]-snake[1] < x-y {
117100
if op == nil {
118101
op = &Op{
119-
Kind: Insert,
102+
Kind: diff.Insert,
120103
I1: x,
121104
J1: y,
122105
}

internal/lsp/diff/myers/diff_test.go

+18-12
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"strings"
1515
"testing"
1616

17+
"golang.org/x/tools/internal/lsp/diff"
18+
"golang.org/x/tools/internal/lsp/diff/difftest"
1719
"golang.org/x/tools/internal/lsp/diff/myers"
1820
)
1921

@@ -26,6 +28,10 @@ const (
2628
var verifyDiff = flag.Bool("verify-diff", false, "Check that the unified diff output matches `diff -u`")
2729

2830
func TestDiff(t *testing.T) {
31+
difftest.DiffTest(t, myers.ComputeEdits)
32+
}
33+
34+
func TestMyersDiff(t *testing.T) {
2935
for _, test := range []struct {
3036
a, b string
3137
lines []*myers.Op
@@ -42,8 +48,8 @@ func TestDiff(t *testing.T) {
4248
a: "A\n",
4349
b: "B\n",
4450
operations: []*myers.Op{
45-
&myers.Op{Kind: myers.Delete, I1: 0, I2: 1, J1: 0},
46-
&myers.Op{Kind: myers.Insert, Content: []string{"B\n"}, I1: 1, I2: 1, J1: 0},
51+
&myers.Op{Kind: diff.Delete, I1: 0, I2: 1, J1: 0},
52+
&myers.Op{Kind: diff.Insert, Content: []string{"B\n"}, I1: 1, I2: 1, J1: 0},
4753
},
4854
unified: `
4955
@@ -1 +1 @@
@@ -53,8 +59,8 @@ func TestDiff(t *testing.T) {
5359
a: "A",
5460
b: "B",
5561
operations: []*myers.Op{
56-
&myers.Op{Kind: myers.Delete, I1: 0, I2: 1, J1: 0},
57-
&myers.Op{Kind: myers.Insert, Content: []string{"B"}, I1: 1, I2: 1, J1: 0},
62+
&myers.Op{Kind: diff.Delete, I1: 0, I2: 1, J1: 0},
63+
&myers.Op{Kind: diff.Insert, Content: []string{"B"}, I1: 1, I2: 1, J1: 0},
5864
},
5965
unified: `
6066
@@ -1 +1 @@
@@ -66,11 +72,11 @@ func TestDiff(t *testing.T) {
6672
a: "A\nB\nC\nA\nB\nB\nA\n",
6773
b: "C\nB\nA\nB\nA\nC\n",
6874
operations: []*myers.Op{
69-
&myers.Op{Kind: myers.Delete, I1: 0, I2: 1, J1: 0},
70-
&myers.Op{Kind: myers.Delete, I1: 1, I2: 2, J1: 0},
71-
&myers.Op{Kind: myers.Insert, Content: []string{"B\n"}, I1: 3, I2: 3, J1: 1},
72-
&myers.Op{Kind: myers.Delete, I1: 5, I2: 6, J1: 4},
73-
&myers.Op{Kind: myers.Insert, Content: []string{"C\n"}, I1: 7, I2: 7, J1: 5},
75+
&myers.Op{Kind: diff.Delete, I1: 0, I2: 1, J1: 0},
76+
&myers.Op{Kind: diff.Delete, I1: 1, I2: 2, J1: 0},
77+
&myers.Op{Kind: diff.Insert, Content: []string{"B\n"}, I1: 3, I2: 3, J1: 1},
78+
&myers.Op{Kind: diff.Delete, I1: 5, I2: 6, J1: 4},
79+
&myers.Op{Kind: diff.Insert, Content: []string{"C\n"}, I1: 7, I2: 7, J1: 5},
7480
},
7581
unified: `
7682
@@ -1,7 +1,6 @@
@@ -90,9 +96,9 @@ func TestDiff(t *testing.T) {
9096
a: "A\nB\n",
9197
b: "A\nC\n\n",
9298
operations: []*myers.Op{
93-
&myers.Op{Kind: myers.Delete, I1: 1, I2: 2, J1: 1},
94-
&myers.Op{Kind: myers.Insert, Content: []string{"C\n"}, I1: 2, I2: 2, J1: 1},
95-
&myers.Op{Kind: myers.Insert, Content: []string{"\n"}, I1: 2, I2: 2, J1: 2},
99+
&myers.Op{Kind: diff.Delete, I1: 1, I2: 2, J1: 1},
100+
&myers.Op{Kind: diff.Insert, Content: []string{"C\n"}, I1: 2, I2: 2, J1: 1},
101+
&myers.Op{Kind: diff.Insert, Content: []string{"\n"}, I1: 2, I2: 2, J1: 2},
96102
},
97103
unified: `
98104
@@ -1,2 +1,3 @@

internal/lsp/diff/myers.go internal/lsp/diff/myers/myers.go

+23-23
Original file line numberDiff line numberDiff line change
@@ -2,68 +2,68 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
package diff
5+
package myers
66

77
import (
88
"fmt"
99
"strings"
1010

11-
"golang.org/x/tools/internal/lsp/diff/myers"
11+
"golang.org/x/tools/internal/lsp/diff"
1212
"golang.org/x/tools/internal/span"
1313
)
1414

1515
func init() {
16-
ToUnified = myersToUnified
16+
diff.ToUnified = myersToUnified
1717
}
1818

19-
func MyersComputeEdits(uri span.URI, before, after string) []TextEdit {
20-
u := myers.SplitLines(before)
21-
f := myers.SplitLines(after)
22-
return myersDiffToEdits(uri, myers.Operations(u, f))
19+
func ComputeEdits(uri span.URI, before, after string) []diff.TextEdit {
20+
u := SplitLines(before)
21+
f := SplitLines(after)
22+
return myersDiffToEdits(uri, Operations(u, f))
2323
}
2424

25-
func myersToUnified(from, to string, before string, edits []TextEdit) string {
26-
u := myers.SplitLines(before)
25+
func myersToUnified(from, to string, before string, edits []diff.TextEdit) string {
26+
u := SplitLines(before)
2727
ops := myersEditsToDiff(edits)
28-
return fmt.Sprint(myers.ToUnified(from, to, u, ops))
28+
return fmt.Sprint(ToUnified(from, to, u, ops))
2929
}
3030

31-
func myersDiffToEdits(uri span.URI, ops []*myers.Op) []TextEdit {
32-
edits := make([]TextEdit, 0, len(ops))
31+
func myersDiffToEdits(uri span.URI, ops []*Op) []diff.TextEdit {
32+
edits := make([]diff.TextEdit, 0, len(ops))
3333
for _, op := range ops {
3434
s := span.New(uri, span.NewPoint(op.I1+1, 1, 0), span.NewPoint(op.I2+1, 1, 0))
3535
switch op.Kind {
36-
case myers.Delete:
36+
case diff.Delete:
3737
// Delete: unformatted[i1:i2] is deleted.
38-
edits = append(edits, TextEdit{Span: s})
39-
case myers.Insert:
38+
edits = append(edits, diff.TextEdit{Span: s})
39+
case diff.Insert:
4040
// Insert: formatted[j1:j2] is inserted at unformatted[i1:i1].
4141
if content := strings.Join(op.Content, ""); content != "" {
42-
edits = append(edits, TextEdit{Span: s, NewText: content})
42+
edits = append(edits, diff.TextEdit{Span: s, NewText: content})
4343
}
4444
}
4545
}
4646
return edits
4747
}
4848

49-
func myersEditsToDiff(edits []TextEdit) []*myers.Op {
49+
func myersEditsToDiff(edits []diff.TextEdit) []*Op {
5050
iToJ := 0
51-
ops := make([]*myers.Op, len(edits))
51+
ops := make([]*Op, len(edits))
5252
for i, edit := range edits {
5353
i1 := edit.Span.Start().Line() - 1
5454
i2 := edit.Span.End().Line() - 1
55-
kind := myers.Insert
55+
kind := diff.Insert
5656
if edit.NewText == "" {
57-
kind = myers.Delete
57+
kind = diff.Delete
5858
}
59-
ops[i] = &myers.Op{
59+
ops[i] = &Op{
6060
Kind: kind,
61-
Content: myers.SplitLines(edit.NewText),
61+
Content: SplitLines(edit.NewText),
6262
I1: i1,
6363
I2: i2,
6464
J1: i1 + iToJ,
6565
}
66-
if kind == myers.Insert {
66+
if kind == diff.Insert {
6767
iToJ += len(ops[i].Content)
6868
} else {
6969
iToJ -= i2 - i1

internal/lsp/diff/myers/unified.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package myers
77
import (
88
"fmt"
99
"strings"
10+
11+
"golang.org/x/tools/internal/lsp/diff"
1012
)
1113

1214
type Unified struct {
@@ -21,7 +23,7 @@ type Hunk struct {
2123
}
2224

2325
type Line struct {
24-
Kind OpKind
26+
Kind diff.OpKind
2527
Content string
2628
}
2729

@@ -67,14 +69,14 @@ func ToUnified(from, to string, lines []string, ops []*Op) Unified {
6769
}
6870
last = op.I1
6971
switch op.Kind {
70-
case Delete:
72+
case diff.Delete:
7173
for i := op.I1; i < op.I2; i++ {
72-
h.Lines = append(h.Lines, Line{Kind: Delete, Content: lines[i]})
74+
h.Lines = append(h.Lines, Line{Kind: diff.Delete, Content: lines[i]})
7375
last++
7476
}
75-
case Insert:
77+
case diff.Insert:
7678
for _, c := range op.Content {
77-
h.Lines = append(h.Lines, Line{Kind: Insert, Content: c})
79+
h.Lines = append(h.Lines, Line{Kind: diff.Insert, Content: c})
7880
}
7981
default:
8082
// all other op types ignored
@@ -97,7 +99,7 @@ func addEqualLines(h *Hunk, lines []string, start, end int) int {
9799
if i >= len(lines) {
98100
return delta
99101
}
100-
h.Lines = append(h.Lines, Line{Kind: Equal, Content: lines[i]})
102+
h.Lines = append(h.Lines, Line{Kind: diff.Equal, Content: lines[i]})
101103
delta++
102104
}
103105
return delta
@@ -113,9 +115,9 @@ func (u Unified) Format(f fmt.State, r rune) {
113115
fromCount, toCount := 0, 0
114116
for _, l := range hunk.Lines {
115117
switch l.Kind {
116-
case Delete:
118+
case diff.Delete:
117119
fromCount++
118-
case Insert:
120+
case diff.Insert:
119121
toCount++
120122
default:
121123
fromCount++
@@ -136,9 +138,9 @@ func (u Unified) Format(f fmt.State, r rune) {
136138
fmt.Fprint(f, " @@\n")
137139
for _, l := range hunk.Lines {
138140
switch l.Kind {
139-
case Delete:
141+
case diff.Delete:
140142
fmt.Fprintf(f, "-%s", l.Content)
141-
case Insert:
143+
case diff.Insert:
142144
fmt.Fprintf(f, "+%s", l.Content)
143145
default:
144146
fmt.Fprintf(f, " %s", l.Content)

internal/lsp/source/options.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"golang.org/x/tools/internal/lsp/diff"
13+
"golang.org/x/tools/internal/lsp/diff/myers"
1314
"golang.org/x/tools/internal/lsp/protocol"
1415
"golang.org/x/tools/internal/telemetry/tag"
1516
errors "golang.org/x/xerrors"
@@ -41,7 +42,7 @@ var (
4142
FuzzyMatching: true,
4243
Budget: 100 * time.Millisecond,
4344
},
44-
ComputeEdits: diff.MyersComputeEdits,
45+
ComputeEdits: myers.ComputeEdits,
4546
}
4647
)
4748

0 commit comments

Comments
 (0)