2018-06-18 20:29:52 +00:00
|
|
|
// Package visitor contains walker.visitor implementations
|
|
|
|
package visitor
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
|
2018-06-29 21:51:11 +00:00
|
|
|
"github.com/z7zmey/php-parser/meta"
|
|
|
|
|
2018-06-18 20:29:52 +00:00
|
|
|
"github.com/z7zmey/php-parser/node"
|
|
|
|
|
|
|
|
"github.com/z7zmey/php-parser/walker"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GoDumper writes ast hierarchy to an io.Writer as native Golang struct
|
|
|
|
type GoDumper struct {
|
|
|
|
Writer io.Writer
|
|
|
|
depth int
|
|
|
|
isChildNode bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func printIndent(w io.Writer, d int) {
|
|
|
|
for i := 0; i < d; i++ {
|
|
|
|
io.WriteString(w, "\t")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnterNode is invoked at every node in hierarchy
|
|
|
|
func (d *GoDumper) EnterNode(w walker.Walkable) bool {
|
|
|
|
n := w.(node.Node)
|
|
|
|
|
|
|
|
nodeType := reflect.TypeOf(n).String()
|
|
|
|
nodeType = strings.Replace(nodeType, "*", "&", 1)
|
|
|
|
|
|
|
|
if d.isChildNode {
|
|
|
|
d.isChildNode = false
|
|
|
|
} else {
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
}
|
|
|
|
|
|
|
|
io.WriteString(d.Writer, nodeType+"{\n")
|
|
|
|
|
|
|
|
d.depth++
|
|
|
|
|
2018-06-24 07:19:44 +00:00
|
|
|
if p := n.GetPosition(); p != nil {
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprint(d.Writer, "Position: &position.Position{\n")
|
|
|
|
d.depth++
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "StartLine: %d,\n", p.StartLine)
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "EndLine: %d,\n", p.EndLine)
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "StartPos: %d,\n", p.StartPos)
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "EndPos: %d,\n", p.EndPos)
|
|
|
|
d.depth--
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprint(d.Writer, "},\n")
|
|
|
|
}
|
|
|
|
|
2018-07-29 08:44:38 +00:00
|
|
|
if mm := n.GetMeta(); len(*mm) > 0 {
|
2018-06-25 12:38:31 +00:00
|
|
|
printIndent(d.Writer, d.depth)
|
2018-06-29 21:51:11 +00:00
|
|
|
fmt.Fprint(d.Writer, "Meta: []meta.Meta{\n")
|
2018-06-25 12:38:31 +00:00
|
|
|
d.depth++
|
2018-07-29 08:44:38 +00:00
|
|
|
for _, m := range *mm {
|
2018-06-25 12:38:31 +00:00
|
|
|
printIndent(d.Writer, d.depth)
|
2018-07-29 08:44:38 +00:00
|
|
|
switch m.Type {
|
|
|
|
case meta.CommentType:
|
|
|
|
fmt.Fprint(d.Writer, "&meta.CommentType{\n")
|
|
|
|
case meta.WhiteSpaceType:
|
|
|
|
fmt.Fprint(d.Writer, "&meta.WhiteSpaceType{\n")
|
|
|
|
case meta.TokenType:
|
|
|
|
fmt.Fprint(d.Writer, "&meta.TokenType{\n")
|
2018-06-29 21:51:11 +00:00
|
|
|
}
|
2018-06-25 12:38:31 +00:00
|
|
|
d.depth++
|
|
|
|
|
|
|
|
printIndent(d.Writer, d.depth)
|
2018-10-24 14:04:13 +00:00
|
|
|
if m.Position != nil {
|
|
|
|
fmt.Fprint(d.Writer, "Position: &position.Position{\n")
|
|
|
|
d.depth++
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "StartLine: %d,\n", m.Position.StartLine)
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "EndLine: %d,\n", m.Position.EndLine)
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "StartPos: %d,\n", m.Position.StartPos)
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprintf(d.Writer, "EndPos: %d,\n", m.Position.EndPos)
|
|
|
|
d.depth--
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprint(d.Writer, "},\n")
|
|
|
|
} else {
|
|
|
|
fmt.Fprint(d.Writer, "Position: nil,\n")
|
|
|
|
}
|
2018-06-25 12:38:31 +00:00
|
|
|
|
|
|
|
printIndent(d.Writer, d.depth)
|
2018-06-29 21:51:11 +00:00
|
|
|
fmt.Fprintf(d.Writer, "Value: %q,\n", m.String())
|
2018-06-25 12:38:31 +00:00
|
|
|
printIndent(d.Writer, d.depth)
|
2018-07-29 08:44:38 +00:00
|
|
|
fmt.Fprintf(d.Writer, "TokenName: %d,\n", m.TokenName)
|
2018-06-25 12:38:31 +00:00
|
|
|
|
|
|
|
d.depth--
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprint(d.Writer, "},\n")
|
|
|
|
}
|
|
|
|
d.depth--
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
fmt.Fprint(d.Writer, "},\n")
|
|
|
|
}
|
|
|
|
|
2018-06-18 20:29:52 +00:00
|
|
|
if a := n.Attributes(); len(a) > 0 {
|
|
|
|
for key, attr := range a {
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
switch attr.(type) {
|
|
|
|
case string:
|
|
|
|
fmt.Fprintf(d.Writer, "%s: %q,\n", key, attr)
|
|
|
|
default:
|
|
|
|
fmt.Fprintf(d.Writer, "%s: %v,\n", key, attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// LeaveNode is invoked after node process
|
|
|
|
func (d *GoDumper) LeaveNode(n walker.Walkable) {
|
|
|
|
d.depth--
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
if d.depth != 0 {
|
|
|
|
io.WriteString(d.Writer, "},\n")
|
|
|
|
} else {
|
|
|
|
io.WriteString(d.Writer, "}\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *GoDumper) EnterChildNode(key string, w walker.Walkable) {
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
io.WriteString(d.Writer, key+": ")
|
|
|
|
d.isChildNode = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *GoDumper) LeaveChildNode(key string, w walker.Walkable) {
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *GoDumper) EnterChildList(key string, w walker.Walkable) {
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
io.WriteString(d.Writer, key+": []node.Node{\n")
|
|
|
|
d.depth++
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *GoDumper) LeaveChildList(key string, w walker.Walkable) {
|
|
|
|
d.depth--
|
|
|
|
printIndent(d.Writer, d.depth)
|
|
|
|
if d.depth != 0 {
|
|
|
|
io.WriteString(d.Writer, "},\n")
|
|
|
|
}
|
|
|
|
}
|