)
+// Obtain a (single) token position before the next comment.
+// Use this function to correct a token position such that the
+// token is placed before the next comment (which may be a line
+// comment introducing a newline and possibly introducing a
+// semicolon). Use moveCommentsAfter() to move a comment past
+// more than a single token. beforeComment() is preferable if
+// if can be used as it produces better results.
+//
+// Remove this after transitioning to new semicolon syntax and
+// some reasonable grace period (12/11/09).
+func (p *printer) beforeComment(pos token.Position) token.Position {
+ if p.comment != nil {
+ p := p.comment.List[0].Position;
+ if !pos.IsValid() || pos.Offset > p.Offset {
+ return p
+ }
+ }
+ return pos;
+}
+
+
// Print a list of expressions. If the list spans multiple
// source lines, the original line breaks are respected between
// expressions. Sets multiLine to true if the list spans multiple
line = x.Pos().Line;
if i > 0 {
if mode&plusSep != 0 {
- p.print(blank, token.ADD)
+ p.print(blank, p.beforeComment(noPos), token.ADD)
}
if mode&commaSep != 0 {
p.print(token.COMMA)
}
xline := p.pos.Line; // before the operator (it may be on the next line!)
yline := x.Y.Pos().Line;
- p.print(x.OpPos, x.Op);
+ p.print(p.beforeComment(x.OpPos), x.Op);
if xline != yline && xline > 0 && yline > 0 {
// at least one line break, but respect an extra empty line
// in the source
// block prints an *ast.BlockStmt; it always spans at least two lines.
func (p *printer) block(s *ast.BlockStmt, indent int, moveComments bool) {
if moveComments {
- p.moveCommentsAfter(s.Pos())
+ p.print(p.beforeComment(s.Pos()))
+ } else {
+ p.print(s.Pos())
}
- p.print(s.Pos(), token.LBRACE);
+ p.print(token.LBRACE);
p.stmtList(s.List, indent);
p.linebreak(s.Rbrace.Line, 1, maxStmtNewlines, ignore, true);
p.print(s.Rbrace, token.RBRACE);
if s.Name != nil {
p.expr(s.Name, multiLine);
p.print(blank);
+ p.moveCommentsAfter(s.Path[0].Pos());
}
- p.moveCommentsAfter(s.Path[0].Pos());
p.expr(&ast.StringList{s.Path}, multiLine);
comment = s.Comment;
// make sure a comment doesn't cause semicolons to be inserted
import _ "foo" // a comment
+import // a comment
+"bar"
+import "foo" // a comment
import "bar" // a comment
+import (
+ _ "foo" + // a comment
+ // a comment
+ "bar" +
+ "foo" + // a comment
+ "bar"; // a comment
+)
+
+// a case that caused problems in the past (comment placement)
+import (
+ . "fmt";
+ "io";
+ "malloc"; // for the malloc count test only
+ "math";
+ "strings";
+ "testing";
+)
+
// at least one empty line between declarations of different kind
import _ "io"
// making function declarations safe for new semicolon rules
func _() { /* one-line func */ }
-func _() { // opening "{" must move up /* one-line func */ }
+func _() { // opening "{" must move up
+ /* one-line func */ }
-func _() { // opening "{" must move up// multi-line func
+func _() { // opening "{" must move up
+ // multi-line func
// in the following declarations, a comment must not
// introduce a newline and thus cause a semicolon to