#31 dump to native golang struct

This commit is contained in:
z7zmey
2018-06-18 23:29:52 +03:00
parent 063726aac4
commit dd572a8fed
173 changed files with 1279 additions and 735 deletions

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"reflect"
"strings"
"github.com/z7zmey/php-parser/comment"
"github.com/z7zmey/php-parser/node"
@@ -24,7 +25,7 @@ type Dumper struct {
}
// EnterNode is invoked at every node in hierarchy
func (d Dumper) EnterNode(w walker.Walkable) bool {
func (d *Dumper) EnterNode(w walker.Walkable) bool {
n := w.(node.Node)
fmt.Fprintf(d.Writer, "%v[%v]\n", d.Indent, reflect.TypeOf(n))
@@ -59,13 +60,26 @@ func (d Dumper) EnterNode(w walker.Walkable) bool {
return true
}
// GetChildrenVisitor is invoked at every node parameter that contains children nodes
func (d Dumper) GetChildrenVisitor(key string) walker.Visitor {
fmt.Fprintf(d.Writer, "%v%q:\n", d.Indent+" ", key)
return Dumper{d.Writer, d.Indent + " ", d.Comments, d.Positions, d.NsResolver}
}
// LeaveNode is invoked after node process
func (d Dumper) LeaveNode(n walker.Walkable) {
func (d *Dumper) LeaveNode(n walker.Walkable) {
// do nothing
}
// GetChildrenVisitor is invoked at every node parameter that contains children nodes
func (d *Dumper) EnterChildNode(key string, w walker.Walkable) {
fmt.Fprintf(d.Writer, "%v%q:\n", d.Indent+" ", key)
d.Indent = d.Indent + " "
}
func (d *Dumper) LeaveChildNode(key string, w walker.Walkable) {
d.Indent = strings.TrimSuffix(d.Indent, " ")
}
func (d *Dumper) EnterChildList(key string, w walker.Walkable) {
fmt.Fprintf(d.Writer, "%v%q:\n", d.Indent+" ", key)
d.Indent = d.Indent + " "
}
func (d *Dumper) LeaveChildList(key string, w walker.Walkable) {
d.Indent = strings.TrimSuffix(d.Indent, " ")
}

View File

@@ -29,7 +29,7 @@ func ExampleDumper() {
nsResolver := visitor.NewNamespaceResolver()
nodes.Walk(nsResolver)
dumper := visitor.Dumper{
dumper := &visitor.Dumper{
Writer: os.Stdout,
Indent: "| ",
Comments: php7parser.GetComments(),

93
visitor/go_dumper.go Normal file
View File

@@ -0,0 +1,93 @@
// Package visitor contains walker.visitor implementations
package visitor
import (
"fmt"
"io"
"reflect"
"strings"
"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++
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")
}
}

111
visitor/go_dumper_test.go Normal file
View File

@@ -0,0 +1,111 @@
//Package visitor contains walker.visitor implementations
package visitor_test
import (
"bytes"
"os"
"github.com/z7zmey/php-parser/php7"
"github.com/z7zmey/php-parser/visitor"
)
func ExampleGoDumper() {
src := `<?php
namespace Foo {
class Bar {
public function FunctionName(Type $var = null)
{
//some comment
$var;
}
}
}`
php7parser := php7.NewParser(bytes.NewBufferString(src), "test.php")
php7parser.Parse()
nodes := php7parser.GetRootNode()
nsResolver := visitor.NewNamespaceResolver()
nodes.Walk(nsResolver)
dumper := &visitor.GoDumper{
Writer: os.Stdout,
}
nodes.Walk(dumper)
// Unordered output:
//&node.Root{
// Stmts: []node.Node{
// &stmt.Namespace{
// NamespaceName: &name.Name{
// Parts: []node.Node{
// &name.NamePart{
// Value: "Foo",
// },
// },
// },
// Stmts: []node.Node{
// &stmt.Class{
// PhpDocComment: "",
// ClassName: &node.Identifier{
// Value: "Bar",
// },
// Stmts: []node.Node{
// &stmt.ClassMethod{
// ReturnsRef: false,
// PhpDocComment: "",
// MethodName: &node.Identifier{
// Value: "FunctionName",
// },
// Modifiers: []node.Node{
// &node.Identifier{
// Value: "public",
// },
// },
// Params: []node.Node{
// &node.Parameter{
// ByRef: false,
// Variadic: false,
// VariableType: &name.Name{
// Parts: []node.Node{
// &name.NamePart{
// Value: "Type",
// },
// },
// },
// Variable: &expr.Variable{
// VarName: &node.Identifier{
// Value: "var",
// },
// },
// DefaultValue: &expr.ConstFetch{
// Constant: &name.Name{
// Parts: []node.Node{
// &name.NamePart{
// Value: "null",
// },
// },
// },
// },
// },
// },
// Stmt: &stmt.StmtList{
// Stmts: []node.Node{
// &stmt.Expression{
// Expr: &expr.Variable{
// VarName: &node.Identifier{
// Value: "var",
// },
// },
// },
// },
// },
// },
// },
// },
// },
// },
// },
//}
}

View File

@@ -181,11 +181,6 @@ func (nsr *NamespaceResolver) EnterNode(w walker.Walkable) bool {
return true
}
// GetChildrenVisitor is invoked at every node parameter that contains children nodes
func (nsr *NamespaceResolver) GetChildrenVisitor(key string) walker.Visitor {
return nsr
}
// LeaveNode is invoked after node process
func (nsr *NamespaceResolver) LeaveNode(w walker.Walkable) {
switch n := w.(type) {
@@ -196,6 +191,22 @@ func (nsr *NamespaceResolver) LeaveNode(w walker.Walkable) {
}
}
func (nsr *NamespaceResolver) EnterChildNode(key string, w walker.Walkable) {
// do nothing
}
func (nsr *NamespaceResolver) LeaveChildNode(key string, w walker.Walkable) {
// do nothing
}
func (nsr *NamespaceResolver) EnterChildList(key string, w walker.Walkable) {
// do nothing
}
func (nsr *NamespaceResolver) LeaveChildList(key string, w walker.Walkable) {
// do nothing
}
// AddAlias adds a new alias
func (nsr *NamespaceResolver) AddAlias(useType string, nn node.Node, prefix []node.Node) {
switch use := nn.(type) {