go/parser: use non-adjusted position while parsing CommentGroups

Line directives should not affect the way Comments get grouped
into CommentGroups.

Change-Id: I9aa4b558cb1333b32be692e8720291d0e6961cae
GitHub-Last-Rev: de867b27bff28983716ba9126329d75f456a2b5a
GitHub-Pull-Request: golang/go#69133
Reviewed-on: https://go-review.googlesource.com/c/go/+/609515
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Mateusz Poliwczak 2025-05-01 12:20:45 +00:00 committed by Gopher Robot
parent 6953ef86cd
commit 93e3d5dc5f
2 changed files with 48 additions and 6 deletions

View File

@ -161,11 +161,16 @@ func (p *parser) next0() {
}
}
// lineFor returns the line of pos, ignoring line directive adjustments.
func (p *parser) lineFor(pos token.Pos) int {
return p.file.PositionFor(pos, false).Line
}
// Consume a comment and return it and the line on which it ends.
func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
// /*-style comments may end on a different line than where they start.
// Scan the comment for '\n' chars and adjust endline accordingly.
endline = p.file.Line(p.pos)
endline = p.lineFor(p.pos)
if p.lit[1] == '*' {
// don't use range here - no need to decode Unicode code points
for i := 0; i < len(p.lit); i++ {
@ -187,8 +192,8 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
// empty lines terminate a comment group.
func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
var list []*ast.Comment
endline = p.file.Line(p.pos)
for p.tok == token.COMMENT && p.file.Line(p.pos) <= endline+n {
endline = p.lineFor(p.pos)
for p.tok == token.COMMENT && p.lineFor(p.pos) <= endline+n {
var comment *ast.Comment
comment, endline = p.consumeComment()
list = append(list, comment)
@ -225,11 +230,11 @@ func (p *parser) next() {
var comment *ast.CommentGroup
var endline int
if p.file.Line(p.pos) == p.file.Line(prev) {
if p.lineFor(p.pos) == p.lineFor(prev) {
// The comment is on same line as the previous token; it
// cannot be a lead comment but may be a line comment.
comment, endline = p.consumeCommentGroup(0)
if p.file.Line(p.pos) != endline || p.tok == token.SEMICOLON || p.tok == token.EOF {
if p.lineFor(p.pos) != endline || p.tok == token.SEMICOLON || p.tok == token.EOF {
// The next token is on a different line, thus
// the last comment group is a line comment.
p.lineComment = comment
@ -242,7 +247,7 @@ func (p *parser) next() {
comment, endline = p.consumeCommentGroup(1)
}
if endline+1 == p.file.Line(p.pos) {
if endline+1 == p.lineFor(p.pos) {
// The next token is following on the line immediately after the
// comment group, thus the last comment group is a lead comment.
p.leadComment = comment

View File

@ -9,6 +9,7 @@ import (
"go/ast"
"go/token"
"io/fs"
"reflect"
"strings"
"testing"
)
@ -859,3 +860,39 @@ func TestEmptyFileHasValidStartEnd(t *testing.T) {
}
}
}
func TestCommentGroupWithLineDirective(t *testing.T) {
const src = `package main
func test() {
//line a:15:1
//
}
`
fset := token.NewFileSet()
f, err := ParseFile(fset, "test.go", src, ParseComments|SkipObjectResolution)
if err != nil {
t.Fatal(err)
}
wantCommentGroups := []*ast.CommentGroup{
{
List: []*ast.Comment{
{
Slash: token.Pos(28),
Text: "//line a:15:1",
},
{
Slash: token.Pos(43),
Text: "//",
},
},
},
}
if !reflect.DeepEqual(f.Comments, wantCommentGroups) {
var got, want strings.Builder
ast.Fprint(&got, fset, f.Comments, nil)
ast.Fprint(&want, fset, wantCommentGroups, nil)
t.Fatalf("unexpected f.Comments got:\n%v\nwant:\n%v", got.String(), want.String())
}
}