From a0d2e9699f1cc83a854c52843ff15d07f83bce47 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 9 Nov 2016 14:15:59 -0800 Subject: go/printer: don't drop required semi/linebreak after /*-comment For details, see the issues. Fixes #11274. Fixes #15137. Change-Id: Ia11e71a054b3195e3007f490418a9c53a7e9cdf1 Reviewed-on: https://go-review.googlesource.com/33016 Reviewed-by: Alan Donovan --- src/go/printer/printer.go | 36 ++++++++++++++++++++++++--------- src/go/printer/testdata/comments.golden | 26 ++++++++++++++++++++++++ src/go/printer/testdata/comments.input | 18 +++++++++++++++++ 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/go/printer/printer.go b/src/go/printer/printer.go index 2390544b6f..eabf23e8b2 100644 --- a/src/go/printer/printer.go +++ b/src/go/printer/printer.go @@ -712,6 +712,16 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (wroteNewline, dropped return } +// containsLinebreak reports whether the whitespace buffer contains any line breaks. +func (p *printer) containsLinebreak() bool { + for _, ch := range p.wsbuf { + if ch == newline || ch == formfeed { + return true + } + } + return false +} + // intersperseComments consumes all comments that appear before the next token // tok and prints it together with the buffered whitespace (i.e., the whitespace // that needs to be written before the next token). A heuristic is used to mix @@ -730,23 +740,31 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro } if last != nil { - // if the last comment is a /*-style comment and the next item + // If the last comment is a /*-style comment and the next item // follows on the same line but is not a comma, and not a "closing" // token immediately following its corresponding "opening" token, - // add an extra blank for separation unless explicitly disabled + // add an extra separator unless explicitly disabled. Use a blank + // as separator unless we have pending linebreaks and they are not + // disabled, in which case we want a linebreak (issue 15137). + needsLinebreak := false if p.mode&noExtraBlank == 0 && last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line && tok != token.COMMA && (tok != token.RPAREN || p.prevOpen == token.LPAREN) && (tok != token.RBRACK || p.prevOpen == token.LBRACK) { - p.writeByte(' ', 1) + if p.containsLinebreak() && p.mode&noExtraLinebreak == 0 { + needsLinebreak = true + } else { + p.writeByte(' ', 1) + } + } + // Ensure that there is a line break after a //-style comment, + // before EOF, and before a closing '}' unless explicitly disabled. + if last.Text[1] == '/' || + tok == token.EOF || + tok == token.RBRACE && p.mode&noExtraLinebreak == 0 { + needsLinebreak = true } - // ensure that there is a line break after a //-style comment, - // before a closing '}' unless explicitly disabled, or at eof - needsLinebreak := - last.Text[1] == '/' || - tok == token.RBRACE && p.mode&noExtraLinebreak == 0 || - tok == token.EOF return p.writeCommentSuffix(needsLinebreak) } diff --git a/src/go/printer/testdata/comments.golden b/src/go/printer/testdata/comments.golden index 849fa62448..4d92e65327 100644 --- a/src/go/printer/testdata/comments.golden +++ b/src/go/printer/testdata/comments.golden @@ -601,6 +601,32 @@ func _() { _ = a } +// Test cases from issues 11274, 15137: +// Semicolon must not be lost when multiple statements are on the same line with a comment. +func _() { + x := 0 /**/ + y := 1 +} + +func _() { + f() + f() + f() /* comment */ + f() + f() /* comment */ + f() + f() /* a */ /* b */ + f() + f() /* a */ /* b */ + f() + f() /* a */ /* b */ + f() +} + +func _() { + f() /* a */ /* b */ +} + // Comments immediately adjacent to punctuation followed by a newline // remain after the punctuation (looks better and permits alignment of // comments). diff --git a/src/go/printer/testdata/comments.input b/src/go/printer/testdata/comments.input index 30cd23c6dd..40351eeef6 100644 --- a/src/go/printer/testdata/comments.input +++ b/src/go/printer/testdata/comments.input @@ -607,6 +607,24 @@ func _() { _ = a } +// Test cases from issues 11274, 15137: +// Semicolon must not be lost when multiple statements are on the same line with a comment. +func _() { + x := 0 /**/; y := 1 +} + +func _() { + f(); f() + f(); /* comment */ f() + f() /* comment */; f() + f(); /* a */ /* b */ f() + f() /* a */ /* b */; f() + f() /* a */; /* b */ f() +} + +func _() { + f() /* a */ /* b */ } + // Comments immediately adjacent to punctuation followed by a newline // remain after the punctuation (looks better and permits alignment of // comments). -- cgit v1.2.3-54-g00ecf