gopls/internal/lsp/source: move edit logic into the protocol package

Change-Id: I8a2dcafc109bf298b6edfe7a7029f8b9098880d6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/543920
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Findley <rfindley@google.com>
diff --git a/gopls/internal/cmd/cmd.go b/gopls/internal/cmd/cmd.go
index 83577f6..08aaa85 100644
--- a/gopls/internal/cmd/cmd.go
+++ b/gopls/internal/cmd/cmd.go
@@ -29,7 +29,6 @@
 	"golang.org/x/tools/gopls/internal/lsp/filecache"
 	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
 	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/internal/constraints"
 	"golang.org/x/tools/internal/diff"
@@ -585,7 +584,7 @@
 	if len(edits) == 0 {
 		return nil
 	}
-	newContent, renameEdits, err := source.ApplyProtocolEdits(mapper, edits)
+	newContent, renameEdits, err := protocol.ApplyEdits(mapper, edits)
 	if err != nil {
 		return err
 	}
diff --git a/gopls/internal/lsp/cache/mod_tidy.go b/gopls/internal/lsp/cache/mod_tidy.go
index 1964259..31a35a5 100644
--- a/gopls/internal/lsp/cache/mod_tidy.go
+++ b/gopls/internal/lsp/cache/mod_tidy.go
@@ -457,7 +457,7 @@
 	}
 	// Calculate the edits to be made due to the change.
 	edits := computeEdits(string(m.Content), string(newContent))
-	return ToProtocolEdits(m, edits)
+	return protocol.EditsFromDiffEdits(m, edits)
 }
 
 // missingModuleForImport creates an error for a given import path that comes
diff --git a/gopls/internal/lsp/cache/pkg.go b/gopls/internal/lsp/cache/pkg.go
index 2ab4694..44dcfa3 100644
--- a/gopls/internal/lsp/cache/pkg.go
+++ b/gopls/internal/lsp/cache/pkg.go
@@ -75,7 +75,6 @@
 	RemoveIntermediateTestVariants = source.RemoveIntermediateTestVariants
 	IsCommandLineArguments         = source.IsCommandLineArguments
 	BundleQuickFixes               = source.BundleQuickFixes
-	ToProtocolEdits                = source.ToProtocolEdits
 	NewFilterer                    = source.NewFilterer
 )
 
diff --git a/gopls/internal/lsp/command.go b/gopls/internal/lsp/command.go
index 3ff48b6..ce1b358 100644
--- a/gopls/internal/lsp/command.go
+++ b/gopls/internal/lsp/command.go
@@ -471,7 +471,7 @@
 	}
 	// Calculate the edits to be made due to the change.
 	diff := snapshot.Options().ComputeEdits(string(pm.Mapper.Content), string(newContent))
-	return source.ToProtocolEdits(pm.Mapper, diff)
+	return protocol.EditsFromDiffEdits(pm.Mapper, diff)
 }
 
 func (c *commandHandler) Test(ctx context.Context, uri protocol.DocumentURI, tests, benchmarks []string) error {
@@ -677,7 +677,7 @@
 
 	m := protocol.NewMapper(fh.URI(), oldContent)
 	diff := snapshot.Options().ComputeEdits(string(oldContent), string(newContent))
-	edits, err := source.ToProtocolEdits(m, diff)
+	edits, err := protocol.EditsFromDiffEdits(m, diff)
 	if err != nil {
 		return nil, err
 	}
diff --git a/gopls/internal/lsp/fake/edit.go b/gopls/internal/lsp/fake/edit.go
index 40762f2..2fac24b 100644
--- a/gopls/internal/lsp/fake/edit.go
+++ b/gopls/internal/lsp/fake/edit.go
@@ -6,7 +6,6 @@
 
 import (
 	"golang.org/x/tools/gopls/internal/lsp/protocol"
-	"golang.org/x/tools/gopls/internal/lsp/source"
 	"golang.org/x/tools/internal/diff"
 )
 
@@ -36,7 +35,7 @@
 // and returns a new slice containing the lines of the patched file.
 // It is a wrapper around diff.Apply; see that function for preconditions.
 func applyEdits(mapper *protocol.Mapper, edits []protocol.TextEdit, windowsLineEndings bool) ([]byte, error) {
-	diffEdits, err := source.FromProtocolEdits(mapper, edits)
+	diffEdits, err := protocol.EditsToDiffEdits(mapper, edits)
 	if err != nil {
 		return nil, err
 	}
diff --git a/gopls/internal/lsp/mod/format.go b/gopls/internal/lsp/mod/format.go
index b04baa2..7b0c6b1 100644
--- a/gopls/internal/lsp/mod/format.go
+++ b/gopls/internal/lsp/mod/format.go
@@ -27,5 +27,5 @@
 	}
 	// Calculate the edits to be made due to the change.
 	diffs := snapshot.Options().ComputeEdits(string(pm.Mapper.Content), string(formatted))
-	return source.ToProtocolEdits(pm.Mapper, diffs)
+	return protocol.EditsFromDiffEdits(pm.Mapper, diffs)
 }
diff --git a/gopls/internal/lsp/protocol/edits.go b/gopls/internal/lsp/protocol/edits.go
new file mode 100644
index 0000000..44694c5
--- /dev/null
+++ b/gopls/internal/lsp/protocol/edits.go
@@ -0,0 +1,62 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package protocol
+
+import "golang.org/x/tools/internal/diff"
+
+// EditsFromDiffEdits converts diff.Edits to a non-nil slice of LSP TextEdits.
+// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
+func EditsFromDiffEdits(m *Mapper, edits []diff.Edit) ([]TextEdit, error) {
+	// LSP doesn't require TextEditArray to be sorted:
+	// this is the receiver's concern. But govim, and perhaps
+	// other clients have historically relied on the order.
+	edits = append([]diff.Edit(nil), edits...)
+	diff.SortEdits(edits)
+
+	result := make([]TextEdit, len(edits))
+	for i, edit := range edits {
+		rng, err := m.OffsetRange(edit.Start, edit.End)
+		if err != nil {
+			return nil, err
+		}
+		result[i] = TextEdit{
+			Range:   rng,
+			NewText: edit.New,
+		}
+	}
+	return result, nil
+}
+
+// EditsToDiffEdits converts LSP TextEdits to diff.Edits.
+// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
+func EditsToDiffEdits(m *Mapper, edits []TextEdit) ([]diff.Edit, error) {
+	if edits == nil {
+		return nil, nil
+	}
+	result := make([]diff.Edit, len(edits))
+	for i, edit := range edits {
+		start, end, err := m.RangeOffsets(edit.Range)
+		if err != nil {
+			return nil, err
+		}
+		result[i] = diff.Edit{
+			Start: start,
+			End:   end,
+			New:   edit.NewText,
+		}
+	}
+	return result, nil
+}
+
+// ApplyEdits applies the patch (edits) to m.Content and returns the result.
+// It also returns the edits converted to diff-package form.
+func ApplyEdits(m *Mapper, edits []TextEdit) ([]byte, []diff.Edit, error) {
+	diffEdits, err := EditsToDiffEdits(m, edits)
+	if err != nil {
+		return nil, nil, err
+	}
+	out, err := diff.ApplyBytes(m.Content, diffEdits)
+	return out, diffEdits, err
+}
diff --git a/gopls/internal/lsp/regtest/marker.go b/gopls/internal/lsp/regtest/marker.go
index a96b409..e279396 100644
--- a/gopls/internal/lsp/regtest/marker.go
+++ b/gopls/internal/lsp/regtest/marker.go
@@ -33,7 +33,6 @@
 	"golang.org/x/tools/gopls/internal/lsp/lsprpc"
 	"golang.org/x/tools/gopls/internal/lsp/protocol"
 	"golang.org/x/tools/gopls/internal/lsp/safetoken"
-	"golang.org/x/tools/gopls/internal/lsp/source"
 	"golang.org/x/tools/gopls/internal/lsp/tests"
 	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
 	"golang.org/x/tools/internal/diff"
@@ -1675,9 +1674,7 @@
 	}
 	filename := mark.path()
 	mapper := mark.mapper()
-	patched, _, err := source.ApplyProtocolEdits(mapper, append([]protocol.TextEdit{
-		*selected.TextEdit,
-	}, selected.AdditionalTextEdits...))
+	patched, _, err := protocol.ApplyEdits(mapper, append([]protocol.TextEdit{*selected.TextEdit}, selected.AdditionalTextEdits...))
 
 	if err != nil {
 		mark.errorf("ApplyProtocolEdits failed: %v", err)
@@ -1739,7 +1736,7 @@
 		mark.errorf("Editor.Mapper(%s) failed: %v", filename, err)
 		return
 	}
-	got, _, err := source.ApplyProtocolEdits(mapper, edits)
+	got, _, err := protocol.ApplyEdits(mapper, edits)
 	if err != nil {
 		mark.errorf("ApplyProtocolEdits failed: %v", err)
 		return
@@ -1766,7 +1763,7 @@
 			mark.errorf("Editor.Mapper(%s) failed: %v", filename, err)
 		}
 
-		got, _, err = source.ApplyProtocolEdits(mapper, edits)
+		got, _, err = protocol.ApplyEdits(mapper, edits)
 		if err != nil {
 			mark.errorf("ApplyProtocolEdits failed: %v", err)
 			return
@@ -2008,7 +2005,7 @@
 			if err != nil {
 				return err
 			}
-			patched, _, err := source.ApplyProtocolEdits(mapper, change.TextDocumentEdit.Edits)
+			patched, _, err := protocol.ApplyEdits(mapper, change.TextDocumentEdit.Edits)
 			if err != nil {
 				return err
 			}
@@ -2400,7 +2397,7 @@
 	}
 
 	m := mark.mapper()
-	got, _, err := source.ApplyProtocolEdits(m, edits)
+	got, _, err := protocol.ApplyEdits(m, edits)
 	if err != nil {
 		mark.errorf("ApplyProtocolEdits: %v", err)
 		return
diff --git a/gopls/internal/lsp/source/change_quote.go b/gopls/internal/lsp/source/change_quote.go
index 6bb7f37..4c2661d 100644
--- a/gopls/internal/lsp/source/change_quote.go
+++ b/gopls/internal/lsp/source/change_quote.go
@@ -69,7 +69,7 @@
 		End:   end,
 		New:   newText,
 	}}
-	pedits, err := ToProtocolEdits(pgf.Mapper, edits)
+	pedits, err := protocol.EditsFromDiffEdits(pgf.Mapper, edits)
 	if err != nil {
 		bug.Reportf("failed to convert diff.Edit to protocol.TextEdit:%v", err)
 		return protocol.CodeAction{}, false
diff --git a/gopls/internal/lsp/source/change_signature.go b/gopls/internal/lsp/source/change_signature.go
index dcd1185..5f30629 100644
--- a/gopls/internal/lsp/source/change_signature.go
+++ b/gopls/internal/lsp/source/change_signature.go
@@ -164,7 +164,7 @@
 		}
 		edits := diff.Bytes(before, after)
 		mapper := protocol.NewMapper(uri, before)
-		pedits, err := ToProtocolEdits(mapper, edits)
+		pedits, err := protocol.EditsFromDiffEdits(mapper, edits)
 		if err != nil {
 			return nil, fmt.Errorf("computing edits for %s: %v", uri, err)
 		}
diff --git a/gopls/internal/lsp/source/completion/util.go b/gopls/internal/lsp/source/completion/util.go
index 4b6ec09..e29e9f5 100644
--- a/gopls/internal/lsp/source/completion/util.go
+++ b/gopls/internal/lsp/source/completion/util.go
@@ -316,7 +316,7 @@
 	if err != nil {
 		return nil, err // can't happen: from/to came from c
 	}
-	return source.ToProtocolEdits(c.mapper, []diff.Edit{{
+	return protocol.EditsFromDiffEdits(c.mapper, []diff.Edit{{
 		Start: start,
 		End:   end,
 		New:   newText,
diff --git a/gopls/internal/lsp/source/format.go b/gopls/internal/lsp/source/format.go
index 9f3597c..d36d50b 100644
--- a/gopls/internal/lsp/source/format.go
+++ b/gopls/internal/lsp/source/format.go
@@ -306,7 +306,7 @@
 	defer done()
 
 	edits := snapshot.Options().ComputeEdits(string(pgf.Src), formatted)
-	return ToProtocolEdits(pgf.Mapper, edits)
+	return protocol.EditsFromDiffEdits(pgf.Mapper, edits)
 }
 
 // protocolEditsFromSource converts text edits to LSP edits using the original
@@ -333,57 +333,6 @@
 	return result, nil
 }
 
-// ToProtocolEdits converts diff.Edits to a non-nil slice of LSP TextEdits.
-// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
 func ToProtocolEdits(m *protocol.Mapper, edits []diff.Edit) ([]protocol.TextEdit, error) {
-	// LSP doesn't require TextEditArray to be sorted:
-	// this is the receiver's concern. But govim, and perhaps
-	// other clients have historically relied on the order.
-	edits = append([]diff.Edit(nil), edits...)
-	diff.SortEdits(edits)
-
-	result := make([]protocol.TextEdit, len(edits))
-	for i, edit := range edits {
-		rng, err := m.OffsetRange(edit.Start, edit.End)
-		if err != nil {
-			return nil, err
-		}
-		result[i] = protocol.TextEdit{
-			Range:   rng,
-			NewText: edit.New,
-		}
-	}
-	return result, nil
-}
-
-// FromProtocolEdits converts LSP TextEdits to diff.Edits.
-// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
-func FromProtocolEdits(m *protocol.Mapper, edits []protocol.TextEdit) ([]diff.Edit, error) {
-	if edits == nil {
-		return nil, nil
-	}
-	result := make([]diff.Edit, len(edits))
-	for i, edit := range edits {
-		start, end, err := m.RangeOffsets(edit.Range)
-		if err != nil {
-			return nil, err
-		}
-		result[i] = diff.Edit{
-			Start: start,
-			End:   end,
-			New:   edit.NewText,
-		}
-	}
-	return result, nil
-}
-
-// ApplyProtocolEdits applies the patch (edits) to m.Content and returns the result.
-// It also returns the edits converted to diff-package form.
-func ApplyProtocolEdits(m *protocol.Mapper, edits []protocol.TextEdit) ([]byte, []diff.Edit, error) {
-	diffEdits, err := FromProtocolEdits(m, edits)
-	if err != nil {
-		return nil, nil, err
-	}
-	out, err := diff.ApplyBytes(m.Content, diffEdits)
-	return out, diffEdits, err
+	return protocol.EditsFromDiffEdits(m, edits)
 }
diff --git a/gopls/internal/lsp/source/rename.go b/gopls/internal/lsp/source/rename.go
index 936ef6a..42a22d2 100644
--- a/gopls/internal/lsp/source/rename.go
+++ b/gopls/internal/lsp/source/rename.go
@@ -276,7 +276,7 @@
 			return nil, false, err
 		}
 		m := protocol.NewMapper(uri, data)
-		protocolEdits, err := ToProtocolEdits(m, edits)
+		protocolEdits, err := protocol.EditsFromDiffEdits(m, edits)
 		if err != nil {
 			return nil, false, err
 		}
diff --git a/gopls/internal/lsp/work/format.go b/gopls/internal/lsp/work/format.go
index 4fc6dd7..ef86952 100644
--- a/gopls/internal/lsp/work/format.go
+++ b/gopls/internal/lsp/work/format.go
@@ -25,5 +25,5 @@
 	formatted := modfile.Format(pw.File.Syntax)
 	// Calculate the edits to be made due to the change.
 	diffs := snapshot.Options().ComputeEdits(string(pw.Mapper.Content), string(formatted))
-	return source.ToProtocolEdits(pw.Mapper, diffs)
+	return protocol.EditsFromDiffEdits(pw.Mapper, diffs)
 }