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)
}
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
}
}
}

View File

@ -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("}")

View File

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

View File

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

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