printer: finalize comment printing, yay \o/

This commit is contained in:
Fatih Arslan 2015-11-01 01:24:50 +03:00
parent c9ef0afb41
commit 66daded6ac
6 changed files with 108 additions and 58 deletions

View File

@ -317,10 +317,15 @@ func (p *Parser) scan() token.Token {
comment, endline = p.consumeCommentGroup(1) comment, endline = p.consumeCommentGroup(1)
} }
if endline+1 == p.tok.Pos.Line { if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE {
// The next token is following on the line immediately after the switch p.tok.Type {
// comment group, thus the last comment group is a lead comment. case token.RBRACE, token.RBRACK:
p.leadComment = comment // 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
}
} }
} }

View File

@ -10,14 +10,15 @@ import (
) )
const ( const (
blank = byte(' ') blank = byte(' ')
newline = byte('\n') newline = byte('\n')
tab = byte('\t') tab = byte('\t')
infinity = 1 << 30 // offset or line
) )
type printer struct { type printer struct {
cfg Config cfg Config
prev ast.Node prev token.Pos
comments []*ast.CommentGroup // may be nil, contains all comments comments []*ast.CommentGroup // may be nil, contains all comments
standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) 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 { for _, c := range standaloneComments {
p.standaloneComments = append(p.standaloneComments, c) p.standaloneComments = append(p.standaloneComments, c)
} }
sort.Sort(ByPosition(p.standaloneComments)) 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 var count int
@ -100,31 +94,49 @@ func (p *printer) output(n interface{}) []byte {
case *ast.File: case *ast.File:
return p.output(t.Node) return p.output(t.Node)
case *ast.ObjectList: case *ast.ObjectList:
for i, item := range t.Items {
fmt.Printf("[%d] item: %s\n", i, item.Keys[0].Token.Text) var index int
buf.Write(p.output(item)) var nextItem token.Pos
if i != len(t.Items)-1 { 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}) buf.Write([]byte{newline, newline})
} }
index++
} }
case *ast.ObjectKey: case *ast.ObjectKey:
buf.WriteString(t.Token.Text) buf.WriteString(t.Token.Text)
case *ast.ObjectItem: case *ast.ObjectItem:
for _, c := range p.standaloneComments { p.prev = t.Pos()
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
buf.Write(p.objectItem(t)) buf.Write(p.objectItem(t))
case *ast.LiteralType: case *ast.LiteralType:
buf.WriteString(t.Token.Text) buf.WriteString(t.Token.Text)
@ -136,10 +148,6 @@ func (p *printer) output(n interface{}) []byte {
fmt.Printf(" unknown type: %T\n", n) fmt.Printf(" unknown type: %T\n", n)
} }
// if item, ok := n.(ast.Node); ok {
// p.prev = item
// }
return buf.Bytes() return buf.Bytes()
} }
@ -185,28 +193,36 @@ func (p *printer) objectType(o *ast.ObjectType) []byte {
var index int var index int
var nextItem token.Pos var nextItem token.Pos
var commented bool
for { for {
// Print stand alone comments
for _, c := range p.standaloneComments { for _, c := range p.standaloneComments {
for _, comment := range c.List { for _, comment := range c.List {
fmt.Printf("[%d] OBJECTTYPE p.prev = %+v\n", count, p.prev.Pos()) // if we hit the end, last item should be the brace
fmt.Printf("[%d] OBJECTTYPE comment.Pos() = %+v\n", count, comment.Pos())
if index != len(o.List.Items) { if index != len(o.List.Items) {
nextItem = o.List.Items[index].Pos() nextItem = o.List.Items[index].Pos()
} else { } else {
nextItem = o.Rbrace nextItem = o.Rbrace
} }
fmt.Printf("[%d] OBJECTTYPE nextItem = %+v\n", count, nextItem)
if comment.Pos().After(p.prev.Pos()) && comment.Pos().Before(nextItem) { if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
buf.Write(p.indent([]byte(comment.Text))) // TODO(arslan): indent // add newline if it's between other printed nodes
buf.WriteByte(newline) if index > 0 {
commented = true
buf.WriteByte(newline)
}
buf.Write(p.indent([]byte(comment.Text)))
buf.WriteByte(newline) buf.WriteByte(newline)
if index != len(o.List.Items) {
buf.WriteByte(newline) // do not print on the end
}
} }
} }
} }
if index == len(o.List.Items) { if index == len(o.List.Items) {
p.prev = o.Rbrace
break break
} }
@ -265,30 +281,26 @@ func (p *printer) objectType(o *ast.ObjectType) []byte {
break break
} }
fmt.Printf("==================> len(aligned) = %+v\n", len(aligned)) // put newlines if the items are between other non aligned items.
for _, b := range aligned { // newlines are also added if there is a standalone comment already, so
fmt.Printf("b = %+v\n", b) // check it too
} if !commented && index != len(aligned) {
// put newlines if the items are between other non aligned items
if index != len(aligned) {
buf.WriteByte(newline) buf.WriteByte(newline)
} }
if len(aligned) >= 1 { if len(aligned) >= 1 {
p.prev = aligned[len(aligned)-1] p.prev = aligned[len(aligned)-1].Pos()
items := p.alignedItems(aligned) items := p.alignedItems(aligned)
buf.Write(p.indent(items)) buf.Write(p.indent(items))
} else { } else {
p.prev = o.List.Items[index] p.prev = o.List.Items[index].Pos()
buf.Write(p.indent(p.objectItem(o.List.Items[index]))) buf.Write(p.indent(p.objectItem(o.List.Items[index])))
index++ index++
} }
buf.WriteByte(newline) buf.WriteByte(newline)
} }
buf.WriteString("}") buf.WriteString("}")

View File

@ -22,7 +22,6 @@ func (c *Config) Fprint(output io.Writer, node ast.Node) error {
cfg: *c, cfg: *c,
comments: make([]*ast.CommentGroup, 0), comments: make([]*ast.CommentGroup, 0),
standaloneComments: make([]*ast.CommentGroup, 0), standaloneComments: make([]*ast.CommentGroup, 0),
prev: ast.NewNode(),
// enableTrace: true, // enableTrace: true,
} }

View File

@ -28,6 +28,7 @@ var data = []entry{
{"list.input", "list.golden"}, {"list.input", "list.golden"},
{"comment.input", "comment.golden"}, {"comment.input", "comment.golden"},
{"comment_aligned.input", "comment_aligned.golden"}, {"comment_aligned.input", "comment_aligned.golden"},
{"comment_standalone.input", "comment_standalone.golden"},
} }
func TestFiles(t *testing.T) { func TestFiles(t *testing.T) {

View File

@ -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

View File

@ -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