internal/lsp: fix unified diffs of edits at the end of a file
Change-Id: I3a7db9261f0bc16609af6d58b363ec52474cb07e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/200697
Run-TryBot: Ian Cottrell <iancottrell@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/diff/diff.go b/internal/lsp/diff/diff.go
index 2aad513..5536c3b 100644
--- a/internal/lsp/diff/diff.go
+++ b/internal/lsp/diff/diff.go
@@ -83,7 +83,9 @@
for i, edit := range edits {
edit.Span, _ = edit.Span.WithAll(c)
copied[i] = edit
- partial = partial || edit.Span.Start().Column() > 1 || edit.Span.End().Column() > 1
+ partial = partial ||
+ edit.Span.Start().Offset() >= len(before) ||
+ edit.Span.Start().Column() > 1 || edit.Span.End().Column() > 1
}
SortTextEdits(copied)
return c, copied, partial
@@ -127,6 +129,19 @@
edit.Span = span.New(edit.Span.URI(), start, end)
edit.NewText = before[start.Offset():start.Offset()+delta] + edit.NewText
}
+ if start.Offset() >= len(before) && start.Line() > 1 && before[len(before)-1] != '\n' {
+ // after end of file that does not end in eol, so join to last line of file
+ // to do this we need to know where the start of the last line was
+ eol := strings.LastIndex(before, "\n")
+ if eol < 0 {
+ // file is one non terminated line
+ eol = 0
+ }
+ delta := len(before) - eol
+ start = span.NewPoint(start.Line()-1, 1, start.Offset()-delta)
+ edit.Span = span.New(edit.Span.URI(), start, end)
+ edit.NewText = before[start.Offset():start.Offset()+delta] + edit.NewText
+ }
if end.Column() > 1 {
remains := before[end.Offset():]
eol := strings.IndexRune(remains, '\n')
diff --git a/internal/lsp/diff/difftest/difftest.go b/internal/lsp/diff/difftest/difftest.go
index 9a8f187..297515f 100644
--- a/internal/lsp/diff/difftest/difftest.go
+++ b/internal/lsp/diff/difftest/difftest.go
@@ -115,6 +115,31 @@
`[1:],
Edits: []diff.TextEdit{{Span: newSpan(0, 1), NewText: "B"}},
}, {
+ Name: "add_end",
+ In: "A",
+ Out: "AB",
+ Unified: UnifiedPrefix + `
+@@ -1 +1 @@
+-A
+\ No newline at end of file
++AB
+\ No newline at end of file
+`[1:],
+ Edits: []diff.TextEdit{{Span: newSpan(1, 1), NewText: "B"}},
+ LineEdits: []diff.TextEdit{{Span: newSpan(0, 1), NewText: "AB"}},
+}, {
+ Name: "add_newline",
+ In: "A",
+ Out: "A\n",
+ Unified: UnifiedPrefix + `
+@@ -1 +1 @@
+-A
+\ No newline at end of file
++A
+`[1:],
+ Edits: []diff.TextEdit{{Span: newSpan(1, 1), NewText: "\n"}},
+ LineEdits: []diff.TextEdit{{Span: newSpan(0, 1), NewText: "A\n"}},
+}, {
Name: "delete_front",
In: "A\nB\nC\nA\nB\nB\nA\n",
Out: "C\nB\nA\nB\nA\nC\n",