[gopls-release-branch.0.5] internal/lsp: fix handling of //-style comments in CRLF files
As part of the earlier changes, I didn't realize that multiple //-style
comments would be grouped as one *ast.Comment, even though they are
multiple comment tokens. Handle the possibility of multiple consecutive
comment tokens.
Fixes golang/go#42923
Change-Id: I6bc6cbdfb28a8e60c699288528566e406f27514c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/275012
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
(cherry picked from commit 73cf035baebf5c665180adbbb8f49d51e3d647e6)
Reviewed-on: https://go-review.googlesource.com/c/tools/+/275437
diff --git a/gopls/internal/regtest/formatting_test.go b/gopls/internal/regtest/formatting_test.go
index 80344c1..e6da9dc 100644
--- a/gopls/internal/regtest/formatting_test.go
+++ b/gopls/internal/regtest/formatting_test.go
@@ -162,31 +162,26 @@
})
}
-// Reproduce golang/go#41057.
-func TestCRLF(t *testing.T) {
- runner.Run(t, "-- main.go --", func(t *testing.T, env *Env) {
- want := `package main
+// Tests various possibilities for comments in files with CRLF line endings.
+// Import organization in these files has historically been a source of bugs.
+func TestCRLFLineEndings(t *testing.T) {
+ for _, tt := range []struct {
+ issue, want string
+ }{
+ {
+ issue: "41057",
+ want: `package main
/*
Hi description
*/
func Hi() {
}
-`
- crlf := strings.ReplaceAll(want, "\n", "\r\n")
- env.CreateBuffer("main.go", crlf)
- env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1))
- env.SaveBuffer("main.go")
- got := env.Editor.BufferText("main.go")
- if want != got {
- t.Errorf("unexpected content after save:\n%s", tests.Diff(want, got))
- }
- })
-}
-
-func TestCRLF_42646(t *testing.T) {
- runner.Run(t, "-- main.go --", func(t *testing.T, env *Env) {
- want := `package main
+`,
+ },
+ {
+ issue: "42646",
+ want: `package main
import (
"fmt"
@@ -211,15 +206,32 @@
const server_port = 8080
fmt.Printf("port: %d\n", server_port)
}
-`
- crlf := strings.ReplaceAll(want, "\n", "\r\n")
- env.CreateBuffer("main.go", crlf)
- env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1))
- env.OrganizeImports("main.go")
- got := env.Editor.BufferText("main.go")
- got = strings.ReplaceAll(got, "\r\n", "\n") // convert everything to LF for simplicity
- if want != got {
- t.Errorf("unexpected content after save:\n%s", tests.Diff(want, got))
- }
- })
+`,
+ },
+ {
+ issue: "42923",
+ want: `package main
+
+// Line 1.
+// aa
+type Tree struct {
+ arr []string
+}
+`,
+ },
+ } {
+ t.Run(tt.issue, func(t *testing.T) {
+ run(t, "-- main.go --", func(t *testing.T, env *Env) {
+ crlf := strings.ReplaceAll(tt.want, "\n", "\r\n")
+ env.CreateBuffer("main.go", crlf)
+ env.Await(CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1))
+ env.OrganizeImports("main.go")
+ got := env.Editor.BufferText("main.go")
+ got = strings.ReplaceAll(got, "\r\n", "\n") // convert everything to LF for simplicity
+ if tt.want != got {
+ t.Errorf("unexpected content after save:\n%s", tests.Diff(tt.want, got))
+ }
+ })
+ })
+ }
}
diff --git a/internal/lsp/source/format.go b/internal/lsp/source/format.go
index 522f522..77cb5c4 100644
--- a/internal/lsp/source/format.go
+++ b/internal/lsp/source/format.go
@@ -227,21 +227,23 @@
pkgEnd := f.Name.End()
importEnd = maybeAdjustToLineEnd(pkgEnd, false)
}
- for _, c := range f.Comments {
- if end := tok.Offset(c.End()); end > importEnd {
- startLine := tok.Position(c.Pos()).Line
- endLine := tok.Position(c.End()).Line
+ for _, cgroup := range f.Comments {
+ for _, c := range cgroup.List {
+ if end := tok.Offset(c.End()); end > importEnd {
+ startLine := tok.Position(c.Pos()).Line
+ endLine := tok.Position(c.End()).Line
- // Work around golang/go#41197 by checking if the comment might
- // contain "\r", and if so, find the actual end position of the
- // comment by scanning the content of the file.
- startOffset := tok.Offset(c.Pos())
- if startLine != endLine && bytes.Contains(src[startOffset:], []byte("\r")) {
- if commentEnd := scanForCommentEnd(tok, src[startOffset:]); commentEnd > 0 {
- end = startOffset + commentEnd
+ // Work around golang/go#41197 by checking if the comment might
+ // contain "\r", and if so, find the actual end position of the
+ // comment by scanning the content of the file.
+ startOffset := tok.Offset(c.Pos())
+ if startLine != endLine && bytes.Contains(src[startOffset:], []byte("\r")) {
+ if commentEnd := scanForCommentEnd(tok, src[startOffset:]); commentEnd > 0 {
+ end = startOffset + commentEnd
+ }
}
+ importEnd = maybeAdjustToLineEnd(tok.Pos(end), true)
}
- importEnd = maybeAdjustToLineEnd(tok.Pos(end), true)
}
}
if importEnd > len(src) {