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"
|
|
|
|
|
2019-02-13 20:18:07 +00:00
|
|
|
"github.com/z7zmey/php-parser/freefloating"
|
2018-06-19 20:55:12 +00:00
|
|
|
"github.com/z7zmey/php-parser/node"
|
|
|
|
"github.com/z7zmey/php-parser/walker"
|
|
|
|
)
|
|
|
|
|
|
|
|
type JsonDumper struct {
|
2019-03-28 17:49:57 +00:00
|
|
|
Writer io.Writer
|
|
|
|
NsResolver *NamespaceResolver
|
|
|
|
isChildNode bool
|
|
|
|
isNotFirstNode bool
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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()
|
|
|
|
|
2019-03-28 17:49:57 +00:00
|
|
|
if d.isChildNode {
|
|
|
|
d.isChildNode = false
|
|
|
|
} else if d.isNotFirstNode {
|
|
|
|
fmt.Fprint(d.Writer, ",")
|
|
|
|
} else {
|
|
|
|
d.isNotFirstNode = true
|
|
|
|
}
|
|
|
|
|
2018-06-19 20:55:12 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-13 20:18:07 +00:00
|
|
|
if !n.GetFreeFloating().IsEmpty() {
|
|
|
|
fmt.Fprintf(d.Writer, ",%q:{", "freefloating")
|
|
|
|
|
|
|
|
var freefloatingStringsKeys []int
|
|
|
|
for key := range *n.GetFreeFloating() {
|
|
|
|
freefloatingStringsKeys = append(freefloatingStringsKeys, int(key))
|
|
|
|
}
|
2018-06-29 21:51:11 +00:00
|
|
|
|
2019-02-13 20:18:07 +00:00
|
|
|
sort.Ints(freefloatingStringsKeys)
|
|
|
|
|
|
|
|
i := 0
|
|
|
|
for _, k := range freefloatingStringsKeys {
|
|
|
|
key := freefloating.Position(k)
|
|
|
|
freeFloatingStrings := (*n.GetFreeFloating())[key]
|
|
|
|
if i != 0 {
|
2018-06-29 21:51:11 +00:00
|
|
|
fmt.Fprint(d.Writer, ",")
|
|
|
|
}
|
2019-02-13 20:18:07 +00:00
|
|
|
i++
|
|
|
|
|
|
|
|
fmt.Fprintf(d.Writer, "%q: [", key.String())
|
|
|
|
|
|
|
|
j := 0
|
|
|
|
for _, freeFloatingString := range freeFloatingStrings {
|
|
|
|
if j != 0 {
|
|
|
|
fmt.Fprint(d.Writer, ",")
|
|
|
|
}
|
|
|
|
j++
|
|
|
|
|
|
|
|
switch freeFloatingString.StringType {
|
|
|
|
case freefloating.CommentType:
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q,%q:%q}", "type", "freefloating.CommentType", "value", freeFloatingString.Value)
|
|
|
|
case freefloating.WhiteSpaceType:
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q,%q:%q}", "type", "freefloating.WhiteSpaceType", "value", freeFloatingString.Value)
|
|
|
|
case freefloating.TokenType:
|
|
|
|
fmt.Fprintf(d.Writer, "{%q:%q,%q:%q}", "type", "freefloating.TokenType", "value", freeFloatingString.Value)
|
|
|
|
}
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
2019-02-13 20:18:07 +00:00
|
|
|
|
|
|
|
fmt.Fprint(d.Writer, "]")
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
2018-06-25 12:38:31 +00:00
|
|
|
|
2019-02-13 20:18:07 +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)
|
2019-03-28 17:49:57 +00:00
|
|
|
d.isChildNode = true
|
2018-06-19 20:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2019-03-28 17:49:57 +00:00
|
|
|
d.isNotFirstNode = false
|
2018-06-19 20:55:12 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *JsonDumper) LeaveChildList(key string, w walker.Walkable) {
|
|
|
|
fmt.Fprint(d.Writer, "]")
|
|
|
|
}
|