go/printer, gofmt: improved comment placement
Applied gofmt -w src misc (no changes).
Fixes #3147.
R=r, rsc
CC=golang-dev
https://golang.org/cl/5710046
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go
index 1ab4456..a027d32 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/pkg/go/printer/printer.go
@@ -277,10 +277,9 @@
// it as is likely to help position the comment nicely.
// pos is the comment position, next the position of the item
// after all pending comments, prev is the previous comment in
-// a group of comments (or nil), and isKeyword indicates if the
-// next item is a keyword.
+// a group of comments (or nil), and tok is the next token.
//
-func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *ast.Comment, isKeyword bool) {
+func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *ast.Comment, tok token.Token) {
if len(p.output) == 0 {
// the comment is the first item to be printed - don't write any whitespace
return
@@ -335,38 +334,41 @@
// comment on a different line:
// separate with at least one line break
droppedLinebreak := false
- if prev == nil {
- // first comment of a comment group
- j := 0
- for i, ch := range p.wsbuf {
- switch ch {
- case blank, vtab:
- // ignore any horizontal whitespace before line breaks
- p.wsbuf[i] = ignore
+ j := 0
+ for i, ch := range p.wsbuf {
+ switch ch {
+ case blank, vtab:
+ // ignore any horizontal whitespace before line breaks
+ p.wsbuf[i] = ignore
+ continue
+ case indent:
+ // apply pending indentation
+ continue
+ case unindent:
+ // if this is not the last unindent, apply it
+ // as it is (likely) belonging to the last
+ // construct (e.g., a multi-line expression list)
+ // and is not part of closing a block
+ if i+1 < len(p.wsbuf) && p.wsbuf[i+1] == unindent {
continue
- case indent:
- // apply pending indentation
- continue
- case unindent:
- // if the next token is a keyword, apply the outdent
- // if it appears that the comment is aligned with the
- // keyword; otherwise assume the outdent is part of a
- // closing block and stop (this scenario appears with
- // comments before a case label where the comments
- // apply to the next case instead of the current one)
- if isKeyword && pos.Column == next.Column {
- continue
- }
- case newline, formfeed:
- // TODO(gri): may want to keep formfeed info in some cases
- p.wsbuf[i] = ignore
- droppedLinebreak = true
}
- j = i
- break
+ // if the next token is not a closing }, apply the unindent
+ // if it appears that the comment is aligned with the
+ // token; otherwise assume the unindent is part of a
+ // closing block and stop (this scenario appears with
+ // comments before a case label where the comments
+ // apply to the next case instead of the current one)
+ if tok != token.RBRACE && pos.Column == next.Column {
+ continue
+ }
+ case newline, formfeed:
+ p.wsbuf[i] = ignore
+ droppedLinebreak = prev == nil // record only if first comment of a group
}
- p.writeWhitespace(j)
+ j = i
+ break
}
+ p.writeWhitespace(j)
// determine number of linebreaks before the comment
n := 0
@@ -675,7 +677,7 @@
var last *ast.Comment
for p.commentBefore(next) {
for _, c := range p.comment.List {
- p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok.IsKeyword())
+ p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok)
p.writeComment(c)
last = c
}
diff --git a/src/pkg/go/printer/testdata/comments.golden b/src/pkg/go/printer/testdata/comments.golden
index 4c6f1ab..d9aa2d8 100644
--- a/src/pkg/go/printer/testdata/comments.golden
+++ b/src/pkg/go/printer/testdata/comments.golden
@@ -168,6 +168,91 @@
// this comment should not be indented
}
+//
+// Indentation of comments after possibly indented multi-line constructs
+// (test cases for issue 3147).
+//
+
+func _() {
+ s := 1 +
+ 2
+ // should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+ // should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+ // should be indented like s
+ _ = 0
+}
+
+func _() {
+ s := 1 +
+ 2
+ // should be indented like s
+ _ = 0
+}
+
+func _() {
+ s := 1 +
+ 2
+
+ // should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+
+ // should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+
+ // should be indented like s
+ _ = 0
+}
+
+func _() {
+ s := 1 +
+ 2
+
+ // should be indented like s
+ _ = 0
+}
+
+// Test case from issue 3147.
+func f() {
+ templateText := "a" + // A
+ "b" + // B
+ "c" // C
+
+ // should be aligned with f()
+ f()
+}
+
+// Modified test case from issue 3147.
+func f() {
+ templateText := "a" + // A
+ "b" + // B
+ "c" // C
+
+ // may not be aligned with f() (source is not aligned)
+ f()
+}
+
+//
+// Test cases for alignment of lines in general comments.
+//
+
func _() {
/* freestanding comment
aligned line
diff --git a/src/pkg/go/printer/testdata/comments.input b/src/pkg/go/printer/testdata/comments.input
index c0f8cca..6084b3f 100644
--- a/src/pkg/go/printer/testdata/comments.input
+++ b/src/pkg/go/printer/testdata/comments.input
@@ -171,6 +171,91 @@
// this comment should not be indented
}
+//
+// Indentation of comments after possibly indented multi-line constructs
+// (test cases for issue 3147).
+//
+
+func _() {
+ s := 1 +
+ 2
+// should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+ // should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+ // should be indented like s
+ _ = 0
+}
+
+func _() {
+ s := 1 +
+ 2
+ // should be indented like s
+ _ = 0
+}
+
+func _() {
+ s := 1 +
+ 2
+
+// should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+
+ // should be indented like s
+}
+
+func _() {
+ s := 1 +
+ 2 // comment
+
+ // should be indented like s
+ _ = 0
+}
+
+func _() {
+ s := 1 +
+ 2
+
+ // should be indented like s
+ _ = 0
+}
+
+// Test case from issue 3147.
+func f() {
+ templateText := "a" + // A
+ "b" + // B
+ "c" // C
+
+ // should be aligned with f()
+ f()
+}
+
+// Modified test case from issue 3147.
+func f() {
+ templateText := "a" + // A
+ "b" + // B
+ "c" // C
+
+ // may not be aligned with f() (source is not aligned)
+ f()
+}
+
+//
+// Test cases for alignment of lines in general comments.
+//
+
func _() {
/* freestanding comment
aligned line