Skip to content

Commit 261fa1a

Browse files
committed
gopls/internal: remove myers diff implementation from gopls
CL 548175 removed the sergey/diffmatchpatch diff implementation, which had been disabled by default for some time. This change removes the dependency from gopls to the myers implementation, and the associated configuration plumbing for alternative implementations. The myers implementation was not actually used because the GoDiff=true default in Hooks (see default.go) was always overridden. Unfortunately we cannot yet delete the myers implementation completely because the marker tests depend on the details of its behavior. A follow-up change should apply the diff and compare the result, instead of comparing diffs. Fixes golang/go#52967 Change-Id: I67796e260ac00f7edc31ce18fda7b1042e8374f8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/548856 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
1 parent 4d2b6e1 commit 261fa1a

File tree

13 files changed

+39
-41
lines changed

13 files changed

+39
-41
lines changed

gopls/internal/hooks/hooks.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,11 @@ package hooks // import "golang.org/x/tools/gopls/internal/hooks"
99

1010
import (
1111
"golang.org/x/tools/gopls/internal/settings"
12-
"golang.org/x/tools/internal/diff"
1312
"mvdan.cc/xurls/v2"
1413
)
1514

1615
func Options(options *settings.Options) {
1716
options.LicensesText = licensesText
18-
if options.GoDiff {
19-
options.ComputeEdits = diff.Strings
20-
}
2117
options.URLRegexp = xurls.Relaxed()
2218
updateAnalyzers(options)
2319
updateGofumpt(options)

gopls/internal/lsp/cache/mod_tidy.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
"golang.org/x/tools/gopls/internal/file"
2020
"golang.org/x/tools/gopls/internal/lsp/command"
2121
"golang.org/x/tools/gopls/internal/lsp/protocol"
22-
"golang.org/x/tools/gopls/internal/settings"
22+
"golang.org/x/tools/internal/diff"
2323
"golang.org/x/tools/internal/event"
2424
"golang.org/x/tools/internal/event/tag"
2525
"golang.org/x/tools/internal/gocommand"
@@ -180,7 +180,7 @@ func modTidyDiagnostics(ctx context.Context, snapshot *Snapshot, pm *ParsedModul
180180
for _, req := range wrongDirectness {
181181
// Handle dependencies that are incorrectly labeled indirect and
182182
// vice versa.
183-
srcDiag, err := directnessDiagnostic(pm.Mapper, req, snapshot.Options().ComputeEdits)
183+
srcDiag, err := directnessDiagnostic(pm.Mapper, req)
184184
if err != nil {
185185
// We're probably in a bad state if we can't compute a
186186
// directnessDiagnostic, but try to keep going so as to not suppress
@@ -357,7 +357,7 @@ func unusedDiagnostic(m *protocol.Mapper, req *modfile.Require, onlyDiagnostic b
357357

358358
// directnessDiagnostic extracts errors when a dependency is labeled indirect when
359359
// it should be direct and vice versa.
360-
func directnessDiagnostic(m *protocol.Mapper, req *modfile.Require, computeEdits settings.DiffFunction) (*Diagnostic, error) {
360+
func directnessDiagnostic(m *protocol.Mapper, req *modfile.Require) (*Diagnostic, error) {
361361
rng, err := m.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)
362362
if err != nil {
363363
return nil, err
@@ -378,7 +378,7 @@ func directnessDiagnostic(m *protocol.Mapper, req *modfile.Require, computeEdits
378378
}
379379
}
380380
// If the dependency should be indirect, add the // indirect.
381-
edits, err := switchDirectness(req, m, computeEdits)
381+
edits, err := switchDirectness(req, m)
382382
if err != nil {
383383
return nil, err
384384
}
@@ -430,7 +430,7 @@ func missingModuleDiagnostic(pm *ParsedModule, req *modfile.Require) (*Diagnosti
430430

431431
// switchDirectness gets the edits needed to change an indirect dependency to
432432
// direct and vice versa.
433-
func switchDirectness(req *modfile.Require, m *protocol.Mapper, computeEdits settings.DiffFunction) ([]protocol.TextEdit, error) {
433+
func switchDirectness(req *modfile.Require, m *protocol.Mapper) ([]protocol.TextEdit, error) {
434434
// We need a private copy of the parsed go.mod file, since we're going to
435435
// modify it.
436436
copied, err := modfile.Parse("", m.Content, nil)
@@ -464,7 +464,7 @@ func switchDirectness(req *modfile.Require, m *protocol.Mapper, computeEdits set
464464
return nil, err
465465
}
466466
// Calculate the edits to be made due to the change.
467-
edits := computeEdits(string(m.Content), string(newContent))
467+
edits := diff.Bytes(m.Content, newContent)
468468
return protocol.EditsFromDiffEdits(m, edits)
469469
}
470470

gopls/internal/lsp/source/format.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func computeFixEdits(snapshot *cache.Snapshot, pgf *ParsedGoFile, options *impor
196196
if fixedData == nil || fixedData[len(fixedData)-1] != '\n' {
197197
fixedData = append(fixedData, '\n') // ApplyFixes may miss the newline, go figure.
198198
}
199-
edits := snapshot.Options().ComputeEdits(left, string(fixedData))
199+
edits := diff.Strings(left, string(fixedData))
200200
return protocolEditsFromSource([]byte(left), edits)
201201
}
202202

@@ -306,7 +306,7 @@ func computeTextEdits(ctx context.Context, snapshot *cache.Snapshot, pgf *Parsed
306306
_, done := event.Start(ctx, "source.computeTextEdits")
307307
defer done()
308308

309-
edits := snapshot.Options().ComputeEdits(string(pgf.Src), formatted)
309+
edits := diff.Strings(string(pgf.Src), formatted)
310310
return protocol.EditsFromDiffEdits(pgf.Mapper, edits)
311311
}
312312

gopls/internal/lsp/source/rename.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ func renamePackageName(ctx context.Context, s *cache.Snapshot, f file.Handle, ne
704704
}
705705

706706
// Calculate the edits to be made due to the change.
707-
edits := s.Options().ComputeEdits(string(pm.Mapper.Content), string(newContent))
707+
edits := diff.Bytes(pm.Mapper.Content, newContent)
708708
renamingEdits[pm.URI] = append(renamingEdits[pm.URI], edits...)
709709
}
710710

gopls/internal/lsp/source/stub.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,13 @@ func (%s%s%s) %s%s {
231231
}
232232

233233
// Pretty-print.
234-
var output strings.Builder
234+
var output bytes.Buffer
235235
if err := format.Node(&output, fset, newF); err != nil {
236236
return nil, nil, fmt.Errorf("format.Node: %w", err)
237237
}
238238

239239
// Report the diff.
240-
diffs := snapshot.Options().ComputeEdits(string(input), output.String())
240+
diffs := diff.Bytes(input, output.Bytes())
241241
return tokeninternal.FileSetFor(declPGF.Tok), // edits use declPGF.Tok
242242
&analysis.SuggestedFix{TextEdits: diffToTextEdits(declPGF.Tok, diffs)},
243243
nil

gopls/internal/mod/format.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"golang.org/x/tools/gopls/internal/file"
1111
"golang.org/x/tools/gopls/internal/lsp/cache"
1212
"golang.org/x/tools/gopls/internal/lsp/protocol"
13+
"golang.org/x/tools/internal/diff"
1314
"golang.org/x/tools/internal/event"
1415
)
1516

@@ -26,6 +27,6 @@ func Format(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]pr
2627
return nil, err
2728
}
2829
// Calculate the edits to be made due to the change.
29-
diffs := snapshot.Options().ComputeEdits(string(pm.Mapper.Content), string(formatted))
30+
diffs := diff.Bytes(pm.Mapper.Content, formatted)
3031
return protocol.EditsFromDiffEdits(pm.Mapper, diffs)
3132
}

gopls/internal/server/command.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"golang.org/x/tools/gopls/internal/util/maps"
3838
"golang.org/x/tools/gopls/internal/vulncheck"
3939
"golang.org/x/tools/gopls/internal/vulncheck/scan"
40+
"golang.org/x/tools/internal/diff"
4041
"golang.org/x/tools/internal/event"
4142
"golang.org/x/tools/internal/gocommand"
4243
"golang.org/x/tools/internal/tokeninternal"
@@ -490,7 +491,7 @@ func dropDependency(snapshot *cache.Snapshot, pm *cache.ParsedModule, modulePath
490491
return nil, err
491492
}
492493
// Calculate the edits to be made due to the change.
493-
diff := snapshot.Options().ComputeEdits(string(pm.Mapper.Content), string(newContent))
494+
diff := diff.Bytes(pm.Mapper.Content, newContent)
494495
return protocol.EditsFromDiffEdits(pm.Mapper, diff)
495496
}
496497

@@ -693,7 +694,7 @@ func collectFileEdits(ctx context.Context, snapshot *cache.Snapshot, uri protoco
693694
}
694695

695696
m := protocol.NewMapper(fh.URI(), oldContent)
696-
diff := snapshot.Options().ComputeEdits(string(oldContent), string(newContent))
697+
diff := diff.Bytes(oldContent, newContent)
697698
edits, err := protocol.EditsFromDiffEdits(m, diff)
698699
if err != nil {
699700
return nil, err

gopls/internal/settings/default.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"golang.org/x/tools/gopls/internal/file"
1212
"golang.org/x/tools/gopls/internal/lsp/command"
1313
"golang.org/x/tools/gopls/internal/lsp/protocol"
14-
"golang.org/x/tools/internal/diff/myers"
1514
)
1615

1716
var (
@@ -118,14 +117,11 @@ func DefaultOptions(overrides ...func(*Options)) *Options {
118117
LinkifyShowMessage: false,
119118
},
120119
Hooks: Hooks{
121-
// TODO(adonovan): switch to new diff.Strings implementation.
122-
ComputeEdits: myers.ComputeEdits,
123120
URLRegexp: urlRegexp(),
124121
DefaultAnalyzers: defaultAnalyzers(),
125122
TypeErrorAnalyzers: typeErrorAnalyzers(),
126123
ConvenienceAnalyzers: convenienceAnalyzers(),
127124
StaticcheckAnalyzers: map[string]*Analyzer{},
128-
GoDiff: true,
129125
},
130126
}
131127
})

gopls/internal/settings/settings.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ import (
6969
"golang.org/x/tools/gopls/internal/file"
7070
"golang.org/x/tools/gopls/internal/lsp/command"
7171
"golang.org/x/tools/gopls/internal/lsp/protocol"
72-
"golang.org/x/tools/internal/diff"
7372
)
7473

7574
type Annotation string
@@ -434,25 +433,15 @@ func (u *UserOptions) SetEnvSlice(env []string) {
434433
}
435434
}
436435

437-
// DiffFunction is the type for a function that produces a set of edits that
438-
// convert from the before content to the after content.
439-
type DiffFunction func(before, after string) []diff.Edit
440-
441436
// Hooks contains configuration that is provided to the Gopls command by the
442437
// main package.
443438
type Hooks struct {
444439
// LicensesText holds third party licenses for software used by gopls.
445440
LicensesText string
446441

447-
// GoDiff is used in gopls/hooks to get Myers' diff
448-
GoDiff bool
449-
450442
// Whether staticcheck is supported.
451443
StaticcheckSupported bool
452444

453-
// ComputeEdits is used to compute edits between file versions.
454-
ComputeEdits DiffFunction
455-
456445
// URLRegexp is used to find potential URLs in comments/strings.
457446
//
458447
// Not all matches are shown to the user: if the matched URL is not detected
@@ -766,9 +755,7 @@ func (o *Options) Clone() *Options {
766755
ClientOptions: o.ClientOptions,
767756
InternalOptions: o.InternalOptions,
768757
Hooks: Hooks{
769-
GoDiff: o.GoDiff,
770758
StaticcheckSupported: o.StaticcheckSupported,
771-
ComputeEdits: o.ComputeEdits,
772759
GofumptFormat: o.GofumptFormat,
773760
URLRegexp: o.URLRegexp,
774761
},
@@ -1137,6 +1124,9 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
11371124
// This setting should be handled before all of the other options are
11381125
// processed, so do nothing here.
11391126

1127+
case "newDiff":
1128+
result.deprecated("")
1129+
11401130
case "subdirWatchPatterns":
11411131
if s, ok := result.asOneOf(
11421132
string(SubdirWatchPatternsOn),

gopls/internal/test/marker/marker_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,15 @@ func checkDiffs(mark marker, changed map[string][]byte, golden *Golden) {
11491149
for name, after := range changed {
11501150
before := mark.run.env.FileContent(name)
11511151
// TODO(golang/go#64023): switch back to diff.Strings.
1152+
// The attached issue is only one obstacle to switching.
1153+
// Another is that different diff algorithms produce
1154+
// different results, so if we commit diffs in test
1155+
// expectations, then we need to either (1) state
1156+
// which diff implementation they use and never change
1157+
// it, or (2) don't compare diffs, but instead apply
1158+
// the "want" diff and check that it produces the
1159+
// "got" output. Option 2 is more robust, as it allows
1160+
// the test expectation to use any valid diff.
11521161
edits := myers.ComputeEdits(before, string(after))
11531162
d, err := diff.ToUnified("before", "after", before, edits, 0)
11541163
if err != nil {

gopls/internal/test/marker/testdata/suggestedfix/missingfunction.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
This test checks the quick fix for undefined functions.
22

3-
-- settings.json --
4-
{
5-
"newDiff": "ol"
6-
}
7-
83
-- channels.go --
94
package missingfunction
105

gopls/internal/work/format.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"golang.org/x/tools/gopls/internal/file"
1212
"golang.org/x/tools/gopls/internal/lsp/cache"
1313
"golang.org/x/tools/gopls/internal/lsp/protocol"
14+
"golang.org/x/tools/internal/diff"
1415
"golang.org/x/tools/internal/event"
1516
)
1617

@@ -24,6 +25,6 @@ func Format(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle) ([]pr
2425
}
2526
formatted := modfile.Format(pw.File.Syntax)
2627
// Calculate the edits to be made due to the change.
27-
diffs := snapshot.Options().ComputeEdits(string(pw.Mapper.Content), string(formatted))
28+
diffs := diff.Bytes(pw.Mapper.Content, formatted)
2829
return protocol.EditsFromDiffEdits(pw.Mapper, diffs)
2930
}

internal/diff/myers/diff.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ import (
1515
// https://blog.jcoglan.com/2017/02/17/the-myers-diff-algorithm-part-3/
1616
// https://www.codeproject.com/Articles/42279/%2FArticles%2F42279%2FInvestigating-Myers-diff-algorithm-Part-1-of-2
1717

18+
// ComputeEdits returns the diffs of two strings using a simple
19+
// line-based implementation, like [diff.Strings].
20+
//
21+
// Deprecated: this implementation is moribund. However, when diffs
22+
// appear in marker test expectations, they are the particular diffs
23+
// produced by this implementation. The marker test framework
24+
// asserts diff(orig, got)==wantDiff, but ideally it would compute
25+
// got==apply(orig, wantDiff) so that the notation of the diff
26+
// is immaterial.
1827
func ComputeEdits(before, after string) []diff.Edit {
1928
beforeLines := splitLines(before)
2029
ops := operations(beforeLines, splitLines(after))

0 commit comments

Comments
 (0)