2018-06-19 20:55:12 +00:00
|
|
|
// Package visitor contains walker.visitor implementations
|
|
|
|
package visitor
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"reflect"
|
2018-06-29 21:51:11 +00:00
|
|
|
"sort"
|
|
|
|
|
|
|
|
"github.com/z7zmey/php-parser/meta"
|
2018-06-19 20:55:12 +00:00
|
|
|
|
|
|
|
"github.com/z7zmey/php-parser/node"
|
|
|
|
|
|
|
|
"github.com/z7zmey/php-parser/walker"
|
|
|
|
)
|
|
|
|
|
|
|
|
type JsonDumper struct {
|
|
|
|
Writer io.Writer
|
|
|
|
NsResolver *NamespaceResolver
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnterNode is invoked at every node in hierarchy
|
|
|
|
func (d *JsonDumper) EnterNode(w walker.Walkable) bool {
|
|
|
|
n := w.(node.Node)
|
|
|
|
|
|
|
|
nodeType := reflect.TypeOf(n).String()
|
|
|
|
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q", "type", nodeType)
|
|
|
|
|
2018-06-24 07:19:44 +00:00
|
|
|
if p := n.GetPosition(); p != nil {
|
|
|
|
p := n.GetPosition()
|
|
|
|
fmt.Fprintf(d.Writer, ",%q:{%q:%d,%q:%d,%q:%d,%q:%d}",
|
|
|
|
"position",
|
|
|
|
"startPos", p.StartPos,
|
|
|
|
"endPos", p.EndPos,
|
|
|
|
"startLine", p.StartLine,
|
|
|
|
"endLine", p.EndLine)
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if d.NsResolver != nil {
|
|
|
|
if namespacedName, ok := d.NsResolver.ResolvedNames[n]; ok {
|
|
|
|
fmt.Fprintf(d.Writer, ",%q:%q", "namespacedName", namespacedName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-29 08:44:38 +00:00
|
|
|
if mm := n.GetMeta(); len(*mm) > 0 {
|
2018-06-29 21:51:11 +00:00
|
|
|
fmt.Fprintf(d.Writer, ",%q:[", "meta")
|
|
|
|
|
2018-07-29 08:44:38 +00:00
|
|
|
for k, m := range *mm {
|
2018-06-29 21:51:11 +00:00
|
|
|
if k != 0 {
|
|
|
|
fmt.Fprint(d.Writer, ",")
|
|
|
|
}
|
2018-06-25 12:38:31 +00:00
|
|
|
|
2018-07-29 08:44:38 +00:00
|
|
|
switch m.Type {
|
|
|
|
case meta.CommentType:
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q,%q:%q,%q:%q}", "type", "*meta.CommentType", "value", m.String(), "tokenName", m.TokenName.String())
|
|
|
|
case meta.WhiteSpaceType:
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q,%q:%q,%q:%q}", "type", "*meta.WhiteSpaceType", "value", m.String(), "tokenName", m.TokenName.String())
|
|
|
|
case meta.TokenType:
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q,%q:%q,%q:%q}", "type", "*meta.TokenType", "value", m.String(), "tokenName", m.TokenName.String())
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-25 12:38:31 +00:00
|
|
|
|
|
|
|
fmt.Fprint(d.Writer, "]")
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if a := n.Attributes(); len(a) > 0 {
|
2018-06-29 21:51:11 +00:00
|
|
|
var attributes []string
|
|
|
|
for key := range n.Attributes() {
|
|
|
|
attributes = append(attributes, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(attributes)
|
|
|
|
|
|
|
|
for _, attributeName := range attributes {
|
|
|
|
attr := a[attributeName]
|
2018-06-19 20:55:12 +00:00
|
|
|
switch attr.(type) {
|
|
|
|
case string:
|
2018-06-29 21:51:11 +00:00
|
|
|
fmt.Fprintf(d.Writer, ",\"%s\":%q", attributeName, attr)
|
2018-06-19 20:55:12 +00:00
|
|
|
default:
|
2018-06-29 21:51:11 +00:00
|
|
|
fmt.Fprintf(d.Writer, ",\"%s\":%v", attributeName, attr)
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// LeaveNode is invoked after node process
|
|
|
|
func (d *JsonDumper) LeaveNode(n walker.Walkable) {
|
|
|
|
fmt.Fprint(d.Writer, "}")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *JsonDumper) EnterChildNode(key string, w walker.Walkable) {
|
|
|
|
fmt.Fprintf(d.Writer, ",%q:", key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *JsonDumper) LeaveChildNode(key string, w walker.Walkable) {
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *JsonDumper) EnterChildList(key string, w walker.Walkable) {
|
|
|
|
fmt.Fprintf(d.Writer, ",%q:[", key)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *JsonDumper) LeaveChildList(key string, w walker.Walkable) {
|
|
|
|
fmt.Fprint(d.Writer, "]")
|
|
|
|
}
|