From 66daded6ac0e9036b935ba404c6ddb3cbe04ce91 Mon Sep 17 00:00:00 2001 From: Fatih Arslan Date: Sun, 1 Nov 2015 01:24:50 +0300 Subject: [PATCH] printer: finalize comment printing, yay \o/ --- parser/parser.go | 13 ++- printer/nodes.go | 118 ++++++++++++--------- printer/printer.go | 1 - printer/printer_test.go | 1 + printer/testdata/comment_standalone.golden | 17 +++ printer/testdata/comment_standalone.input | 16 +++ 6 files changed, 108 insertions(+), 58 deletions(-) create mode 100644 printer/testdata/comment_standalone.golden create mode 100644 printer/testdata/comment_standalone.input diff --git a/parser/parser.go b/parser/parser.go index bd51411..648f871 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -317,10 +317,15 @@ func (p *Parser) scan() token.Token { comment, endline = p.consumeCommentGroup(1) } - if endline+1 == p.tok.Pos.Line { - // 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 + if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE { + switch p.tok.Type { + case token.RBRACE, token.RBRACK: + // Do not count for these cases + default: + // 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/printer/nodes.go b/printer/nodes.go index c4683e6..a2f72f1 100644 --- a/printer/nodes.go +++ b/printer/nodes.go @@ -10,14 +10,15 @@ import ( ) const ( - blank = byte(' ') - newline = byte('\n') - tab = byte('\t') + blank = byte(' ') + newline = byte('\n') + tab = byte('\t') + infinity = 1 << 30 // offset or line ) type printer struct { cfg Config - prev ast.Node + prev token.Pos comments []*ast.CommentGroup // may be nil, contains all comments standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) @@ -78,15 +79,8 @@ func (p *printer) collectComments(node ast.Node) { for _, c := range standaloneComments { p.standaloneComments = append(p.standaloneComments, c) } + sort.Sort(ByPosition(p.standaloneComments)) - - fmt.Printf("standaloneComments = %+v\n", len(p.standaloneComments)) - for _, c := range p.standaloneComments { - for _, comment := range c.List { - fmt.Printf("comment = %+v\n", comment) - } - } - } var count int @@ -100,31 +94,49 @@ func (p *printer) output(n interface{}) []byte { case *ast.File: return p.output(t.Node) case *ast.ObjectList: - for i, item := range t.Items { - fmt.Printf("[%d] item: %s\n", i, item.Keys[0].Token.Text) - buf.Write(p.output(item)) - if i != len(t.Items)-1 { + + var index int + var nextItem token.Pos + var commented bool + for { + // TODO(arslan): refactor below comment printing, we have the same in objectType + + // print stand alone upper level stand alone comments + for _, c := range p.standaloneComments { + for _, comment := range c.List { + if index != len(t.Items) { + nextItem = t.Items[index].Pos() + } else { + nextItem = token.Pos{Offset: infinity, Line: infinity} + } + + if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { + // if we hit the end add newlines so we can print the comment + if index == len(t.Items) { + buf.Write([]byte{newline, newline}) + } + + buf.WriteString(comment.Text) + // TODO(arslan): do not print new lines if the comments are one liner + buf.Write([]byte{newline, newline}) + } + } + } + + if index == len(t.Items) { + break + } + + buf.Write(p.output(t.Items[index])) + if !commented && index != len(t.Items)-1 { buf.Write([]byte{newline, newline}) } + index++ } case *ast.ObjectKey: buf.WriteString(t.Token.Text) case *ast.ObjectItem: - for _, c := range p.standaloneComments { - for _, comment := range c.List { - fmt.Printf("[%d] OBJECTITEM p.prev = %+v\n", count, p.prev.Pos()) - fmt.Printf("[%d] OBJECTITEM comment.Pos() = %+v\n", count, comment.Pos()) - fmt.Printf("[%d] OBJECTTYPE t.Pos() = %+v\n", count, t.Pos()) - if comment.Pos().After(p.prev.Pos()) && comment.Pos().Before(t.Pos()) { - buf.WriteString(comment.Text) - // TODO(arslan): do not print new lines if the comments are one lines - buf.WriteByte(newline) - buf.WriteByte(newline) - } - } - } - - p.prev = t + p.prev = t.Pos() buf.Write(p.objectItem(t)) case *ast.LiteralType: buf.WriteString(t.Token.Text) @@ -136,10 +148,6 @@ func (p *printer) output(n interface{}) []byte { fmt.Printf(" unknown type: %T\n", n) } - // if item, ok := n.(ast.Node); ok { - // p.prev = item - // } - return buf.Bytes() } @@ -185,28 +193,36 @@ func (p *printer) objectType(o *ast.ObjectType) []byte { var index int var nextItem token.Pos + var commented bool for { + // Print stand alone comments for _, c := range p.standaloneComments { for _, comment := range c.List { - fmt.Printf("[%d] OBJECTTYPE p.prev = %+v\n", count, p.prev.Pos()) - fmt.Printf("[%d] OBJECTTYPE comment.Pos() = %+v\n", count, comment.Pos()) - + // if we hit the end, last item should be the brace if index != len(o.List.Items) { nextItem = o.List.Items[index].Pos() } else { nextItem = o.Rbrace - } - fmt.Printf("[%d] OBJECTTYPE nextItem = %+v\n", count, nextItem) - if comment.Pos().After(p.prev.Pos()) && comment.Pos().Before(nextItem) { - buf.Write(p.indent([]byte(comment.Text))) // TODO(arslan): indent - buf.WriteByte(newline) + + if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { + // add newline if it's between other printed nodes + if index > 0 { + commented = true + buf.WriteByte(newline) + } + + buf.Write(p.indent([]byte(comment.Text))) buf.WriteByte(newline) + if index != len(o.List.Items) { + buf.WriteByte(newline) // do not print on the end + } } } } if index == len(o.List.Items) { + p.prev = o.Rbrace break } @@ -265,30 +281,26 @@ func (p *printer) objectType(o *ast.ObjectType) []byte { break } - fmt.Printf("==================> len(aligned) = %+v\n", len(aligned)) - for _, b := range aligned { - fmt.Printf("b = %+v\n", b) - } - - // put newlines if the items are between other non aligned items - if index != len(aligned) { + // put newlines if the items are between other non aligned items. + // newlines are also added if there is a standalone comment already, so + // check it too + if !commented && index != len(aligned) { buf.WriteByte(newline) } if len(aligned) >= 1 { - p.prev = aligned[len(aligned)-1] + p.prev = aligned[len(aligned)-1].Pos() items := p.alignedItems(aligned) buf.Write(p.indent(items)) } else { - p.prev = o.List.Items[index] + p.prev = o.List.Items[index].Pos() buf.Write(p.indent(p.objectItem(o.List.Items[index]))) index++ } buf.WriteByte(newline) - } buf.WriteString("}") diff --git a/printer/printer.go b/printer/printer.go index af7a939..613ad08 100644 --- a/printer/printer.go +++ b/printer/printer.go @@ -22,7 +22,6 @@ func (c *Config) Fprint(output io.Writer, node ast.Node) error { cfg: *c, comments: make([]*ast.CommentGroup, 0), standaloneComments: make([]*ast.CommentGroup, 0), - prev: ast.NewNode(), // enableTrace: true, } diff --git a/printer/printer_test.go b/printer/printer_test.go index 54c86dd..19f3739 100644 --- a/printer/printer_test.go +++ b/printer/printer_test.go @@ -28,6 +28,7 @@ var data = []entry{ {"list.input", "list.golden"}, {"comment.input", "comment.golden"}, {"comment_aligned.input", "comment_aligned.golden"}, + {"comment_standalone.input", "comment_standalone.golden"}, } func TestFiles(t *testing.T) { diff --git a/printer/testdata/comment_standalone.golden b/printer/testdata/comment_standalone.golden new file mode 100644 index 0000000..24bd43f --- /dev/null +++ b/printer/testdata/comment_standalone.golden @@ -0,0 +1,17 @@ +// A standalone comment + +aligned = { + # Standalone 1 + + a = "bar" # yoo1 + default = "bar" # yoo2 + + # Standalone 2 +} + +# Standalone 3 + +numbers = [1, 2] // another line here + +# Standalone 4 + diff --git a/printer/testdata/comment_standalone.input b/printer/testdata/comment_standalone.input new file mode 100644 index 0000000..4436cb1 --- /dev/null +++ b/printer/testdata/comment_standalone.input @@ -0,0 +1,16 @@ +// A standalone comment + +aligned { + # Standalone 1 + + a = "bar" # yoo1 + default = "bar" # yoo2 + + # Standalone 2 +} + + # Standalone 3 + +numbers = [1,2] // another line here + + # Standalone 4