зеркало из https://github.com/golang/tools.git
internal/lsp: fix end positions for multi-line comments with CRLF lines
The previous work-around assumed that the end of the comment would be off by one line, when in reality, it is off by the offset of the number of \r in the comment, which may result in the comment end position being off by multiple lines. Work around this by scanning for the end of the comment position using text/scanner. Fixes golang/go#42646 Change-Id: Icc33e889546f324c6b65b55a98dea587f84c8f01 Reviewed-on: https://go-review.googlesource.com/c/tools/+/270879 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>
This commit is contained in:
Родитель
bd56c0adb3
Коммит
598b068a91
|
@ -181,3 +181,42 @@ func Hi() {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCRLF_42646(t *testing.T) {
|
||||
runner.Run(t, "-- main.go --", func(t *testing.T, env *Env) {
|
||||
want := `package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
func upload(c echo.Context) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
fmt.Fprintf(w, "ParseForm() err: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "POST request successful")
|
||||
path_ver := r.FormValue("path_ver")
|
||||
ukclin_ver := r.FormValue("ukclin_ver")
|
||||
|
||||
fmt.Fprintf(w, "Name = %s\n", path_ver)
|
||||
fmt.Fprintf(w, "Address = %s\n", ukclin_ver)
|
||||
}
|
||||
*/
|
||||
|
||||
func main() {
|
||||
const server_port = 8080
|
||||
fmt.Printf("port: %d\n", server_port)
|
||||
}
|
||||
`
|
||||
crlf := strings.ReplaceAll(want, "\n", "\r\n")
|
||||
env.CreateBuffer("main.go", crlf)
|
||||
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))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"go/parser"
|
||||
"go/token"
|
||||
"strings"
|
||||
"text/scanner"
|
||||
|
||||
"golang.org/x/tools/internal/event"
|
||||
"golang.org/x/tools/internal/imports"
|
||||
|
@ -228,12 +229,17 @@ func importPrefix(src []byte) string {
|
|||
}
|
||||
for _, c := range f.Comments {
|
||||
if end := tok.Offset(c.End()); end > importEnd {
|
||||
// Work-around golang/go#41197: For multi-line comments add +2 to
|
||||
// the offset. The end position does not account for the */ at the
|
||||
// end.
|
||||
startLine := tok.Position(c.Pos()).Line
|
||||
endLine := tok.Position(c.End()).Line
|
||||
if end+2 <= tok.Size() && tok.Position(tok.Pos(end+2)).Line == endLine {
|
||||
end += 2
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -244,6 +250,20 @@ func importPrefix(src []byte) string {
|
|||
return string(src[:importEnd])
|
||||
}
|
||||
|
||||
// scanForCommentEnd returns the offset of the end of the multi-line comment
|
||||
// at the start of the given byte slice.
|
||||
func scanForCommentEnd(tok *token.File, src []byte) int {
|
||||
var s scanner.Scanner
|
||||
s.Init(bytes.NewReader(src))
|
||||
s.Mode ^= scanner.SkipComments
|
||||
|
||||
t := s.Scan()
|
||||
if t == scanner.Comment {
|
||||
return s.Pos().Offset
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func computeTextEdits(ctx context.Context, snapshot Snapshot, pgf *ParsedGoFile, formatted string) ([]protocol.TextEdit, error) {
|
||||
_, done := event.Start(ctx, "source.computeTextEdits")
|
||||
defer done()
|
||||
|
|
Загрузка…
Ссылка в новой задаче