internal/lsp: avoid panic caused by assuming file ends with newline

importPrefix in format.go computes the end of the package statement
including a trailing newline. This causes a panic if the user has
not typed the newline. The code now checks for that case.

Fixes golang/go#40208

Change-Id: I4c5118a5de78027e6c5e6ed91dfddca81e38f7e9
Reviewed-on: https://go-review.googlesource.com/c/tools/+/242638
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/source/format.go b/internal/lsp/source/format.go
index d7629ea..2f3dab7 100644
--- a/internal/lsp/source/format.go
+++ b/internal/lsp/source/format.go
@@ -214,6 +214,9 @@
 	}
 	if importEnd == 0 {
 		importEnd = pkgEnd
+		if importEnd > len(src) {
+			importEnd-- // pkgEnd is off by 1 because Pos is 1-based
+		}
 	}
 	for _, c := range f.Comments {
 		if int(c.End()) > importEnd {
diff --git a/internal/lsp/source/format_test.go b/internal/lsp/source/format_test.go
index 845c87c..f929812 100644
--- a/internal/lsp/source/format_test.go
+++ b/internal/lsp/source/format_test.go
@@ -10,6 +10,7 @@
 
 func TestImportPrefix(t *testing.T) {
 	var tdata = []data{
+		{"package foo", "package foo"},
 		{"package foo\n", "package foo\n"},
 		{"package foo\n\nfunc f(){}\n", "package foo\n"},
 		{"package foo\n\nimport \"fmt\"\n", "package foo\n\nimport \"fmt\""},
@@ -24,7 +25,7 @@
 	for i, x := range tdata {
 		got := importPrefix([]byte(x.input))
 		if got != x.want {
-			t.Errorf("%d: got\n%q, wanted\n%q", i, got, x.want)
+			t.Errorf("%d: got\n%q, wanted\n%q for %q", i, got, x.want, x.input)
 		}
 	}
 }