diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index c31b65bb53..38ee0de3bb 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -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 diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go index 714a6e0237..2516cedc88 100644 --- a/src/go/parser/parser_test.go +++ b/src/go/parser/parser_test.go @@ -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()) + } +}