#30 created json dumper
This commit is contained in:
parent
dd572a8fed
commit
09c984ebdb
10
README.md
10
README.md
@ -47,9 +47,17 @@ CLI
|
|||||||
---
|
---
|
||||||
|
|
||||||
```
|
```
|
||||||
php-parser [-php5 -noDump] <path> ...
|
php-parser [flags] <path> ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
| flag | type | description |
|
||||||
|
|-------|------|----------------------------------------------|
|
||||||
|
| -d |string| dump format: [custom, go, json, pretty-json] |
|
||||||
|
| -p | bool | show positions |
|
||||||
|
| -c | bool | show comments |
|
||||||
|
| -r | bool | resolve names |
|
||||||
|
| -php5 | bool | parse as PHP5 |
|
||||||
|
|
||||||
Dump AST to stdout.
|
Dump AST to stdout.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
|
57
main.go
57
main.go
@ -17,11 +17,18 @@ import (
|
|||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var usePhp5 *bool
|
var usePhp5 *bool
|
||||||
var noDump *bool
|
var dumpType string
|
||||||
|
var showPositions *bool
|
||||||
|
var showComments *bool
|
||||||
|
var showResolvedNs *bool
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
usePhp5 = flag.Bool("php5", false, "use PHP5 parserWorker")
|
usePhp5 = flag.Bool("php5", false, "parse as PHP5")
|
||||||
noDump = flag.Bool("noDump", false, "disable dumping to stdout")
|
showPositions = flag.Bool("p", false, "show positions")
|
||||||
|
showComments = flag.Bool("c", false, "show comments")
|
||||||
|
showResolvedNs = flag.Bool("r", false, "resolve names")
|
||||||
|
flag.StringVar(&dumpType, "d", "", "dump format: [custom, go, json, pretty_json]")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
pathCh := make(chan string)
|
pathCh := make(chan string)
|
||||||
@ -95,19 +102,53 @@ func printer(result <-chan parser.Parser) {
|
|||||||
fmt.Println(e)
|
fmt.Println(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !*noDump {
|
var nsResolver *visitor.NamespaceResolver
|
||||||
nsResolver := visitor.NewNamespaceResolver()
|
if *showResolvedNs {
|
||||||
|
nsResolver = visitor.NewNamespaceResolver()
|
||||||
parserWorker.GetRootNode().Walk(nsResolver)
|
parserWorker.GetRootNode().Walk(nsResolver)
|
||||||
|
}
|
||||||
|
|
||||||
|
var comments parser.Comments
|
||||||
|
if *showComments {
|
||||||
|
comments = parserWorker.GetComments()
|
||||||
|
}
|
||||||
|
|
||||||
|
var positions parser.Positions
|
||||||
|
if *showPositions {
|
||||||
|
positions = parserWorker.GetPositions()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch dumpType {
|
||||||
|
case "custom":
|
||||||
dumper := &visitor.Dumper{
|
dumper := &visitor.Dumper{
|
||||||
Writer: os.Stdout,
|
Writer: os.Stdout,
|
||||||
Indent: " | ",
|
Indent: "| ",
|
||||||
Comments: parserWorker.GetComments(),
|
Comments: comments,
|
||||||
Positions: parserWorker.GetPositions(),
|
Positions: positions,
|
||||||
NsResolver: nsResolver,
|
NsResolver: nsResolver,
|
||||||
}
|
}
|
||||||
parserWorker.GetRootNode().Walk(dumper)
|
parserWorker.GetRootNode().Walk(dumper)
|
||||||
|
case "json":
|
||||||
|
dumper := &visitor.JsonDumper{
|
||||||
|
Writer: os.Stdout,
|
||||||
|
Comments: comments,
|
||||||
|
Positions: positions,
|
||||||
|
NsResolver: nsResolver,
|
||||||
}
|
}
|
||||||
|
parserWorker.GetRootNode().Walk(dumper)
|
||||||
|
case "pretty_json":
|
||||||
|
dumper := &visitor.PrettyJsonDumper{
|
||||||
|
Writer: os.Stdout,
|
||||||
|
Comments: comments,
|
||||||
|
Positions: positions,
|
||||||
|
NsResolver: nsResolver,
|
||||||
|
}
|
||||||
|
parserWorker.GetRootNode().Walk(dumper)
|
||||||
|
case "go":
|
||||||
|
dumper := &visitor.GoDumper{Writer: os.Stdout}
|
||||||
|
parserWorker.GetRootNode().Walk(dumper)
|
||||||
|
}
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,13 @@ func (d *Dumper) EnterNode(w walker.Walkable) bool {
|
|||||||
|
|
||||||
if d.Positions != nil {
|
if d.Positions != nil {
|
||||||
if p := d.Positions[n]; p != nil {
|
if p := d.Positions[n]; p != nil {
|
||||||
fmt.Fprintf(d.Writer, "%v\"Position\": %s;\n", d.Indent+" ", *p)
|
fmt.Fprintf(d.Writer, "%v\"Position\": %s\n", d.Indent+" ", *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.NsResolver != nil {
|
if d.NsResolver != nil {
|
||||||
if namespacedName, ok := d.NsResolver.ResolvedNames[n]; ok {
|
if namespacedName, ok := d.NsResolver.ResolvedNames[n]; ok {
|
||||||
fmt.Fprintf(d.Writer, "%v\"NamespacedName\": %s;\n", d.Indent+" ", namespacedName)
|
fmt.Fprintf(d.Writer, "%v\"NamespacedName\": %q\n", d.Indent+" ", namespacedName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,12 @@ func (d *Dumper) EnterNode(w walker.Walkable) bool {
|
|||||||
|
|
||||||
if a := n.Attributes(); len(a) > 0 {
|
if a := n.Attributes(); len(a) > 0 {
|
||||||
for key, attr := range a {
|
for key, attr := range a {
|
||||||
fmt.Fprintf(d.Writer, "%v\"%v\": %v;\n", d.Indent+" ", key, attr)
|
switch attr.(type) {
|
||||||
|
case string:
|
||||||
|
fmt.Fprintf(d.Writer, "%v\"%v\": %q\n", d.Indent+" ", key, attr)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(d.Writer, "%v\"%v\": %v\n", d.Indent+" ", key, attr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,84 +39,84 @@ func ExampleDumper() {
|
|||||||
nodes.Walk(dumper)
|
nodes.Walk(dumper)
|
||||||
|
|
||||||
// Unordered output:
|
// Unordered output:
|
||||||
//| [*node.Root]
|
// | [*node.Root]
|
||||||
//| "Position": Pos{Line: 3-11 Pos: 10-143};
|
// | "Position": Pos{Line: 3-11 Pos: 10-143}
|
||||||
//| "Stmts":
|
// | "Stmts":
|
||||||
//| [*stmt.Namespace]
|
// | [*stmt.Namespace]
|
||||||
//| "Position": Pos{Line: 3-11 Pos: 10-143};
|
// | "Position": Pos{Line: 3-11 Pos: 10-143}
|
||||||
//| "NamespaceName":
|
// | "NamespaceName":
|
||||||
//| [*name.Name]
|
// | [*name.Name]
|
||||||
//| "Position": Pos{Line: 3-3 Pos: 20-22};
|
// | "Position": Pos{Line: 3-3 Pos: 20-22}
|
||||||
//| "Parts":
|
// | "Parts":
|
||||||
//| [*name.NamePart]
|
// | [*name.NamePart]
|
||||||
//| "Position": Pos{Line: 3-3 Pos: 20-22};
|
// | "Position": Pos{Line: 3-3 Pos: 20-22}
|
||||||
//| "Value": Foo;
|
// | "Value": "Foo"
|
||||||
//| "Stmts":
|
// | "Stmts":
|
||||||
//| [*stmt.Class]
|
// | [*stmt.Class]
|
||||||
//| "Position": Pos{Line: 4-10 Pos: 29-139};
|
// | "Position": Pos{Line: 4-10 Pos: 29-139}
|
||||||
//| "NamespacedName": Foo\Bar;
|
// | "NamespacedName": "Foo\\Bar"
|
||||||
//| "PhpDocComment": ;
|
// | "PhpDocComment": ""
|
||||||
//| "ClassName":
|
// | "ClassName":
|
||||||
//| [*node.Identifier]
|
// | [*node.Identifier]
|
||||||
//| "Position": Pos{Line: 4-4 Pos: 35-37};
|
// | "Position": Pos{Line: 4-4 Pos: 35-37}
|
||||||
//| "Value": Bar;
|
// | "Value": "Bar"
|
||||||
//| "Stmts":
|
// | "Stmts":
|
||||||
//| [*stmt.ClassMethod]
|
// | [*stmt.ClassMethod]
|
||||||
//| "Position": Pos{Line: 5-9 Pos: 45-134};
|
// | "Position": Pos{Line: 5-9 Pos: 45-134}
|
||||||
//| "ReturnsRef": false;
|
// | "ReturnsRef": false
|
||||||
//| "PhpDocComment": ;
|
// | "PhpDocComment": ""
|
||||||
//| "MethodName":
|
// | "MethodName":
|
||||||
//| [*node.Identifier]
|
// | [*node.Identifier]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 61-72};
|
// | "Position": Pos{Line: 5-5 Pos: 61-72}
|
||||||
//| "Value": FunctionName;
|
// | "Value": "FunctionName"
|
||||||
//| "Modifiers":
|
// | "Modifiers":
|
||||||
//| [*node.Identifier]
|
// | [*node.Identifier]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 45-50};
|
// | "Position": Pos{Line: 5-5 Pos: 45-50}
|
||||||
//| "Value": public;
|
// | "Value": "public"
|
||||||
//| "Params":
|
// | "Params":
|
||||||
//| [*node.Parameter]
|
// | [*node.Parameter]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 74-89};
|
// | "Position": Pos{Line: 5-5 Pos: 74-89}
|
||||||
//| "ByRef": false;
|
// | "Variadic": false
|
||||||
//| "Variadic": false;
|
// | "ByRef": false
|
||||||
//| "VariableType":
|
// | "VariableType":
|
||||||
//| [*name.Name]
|
// | [*name.Name]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 74-77};
|
// | "Position": Pos{Line: 5-5 Pos: 74-77}
|
||||||
//| "NamespacedName": Foo\Type;
|
// | "NamespacedName": "Foo\\Type"
|
||||||
//| "Parts":
|
// | "Parts":
|
||||||
//| [*name.NamePart]
|
// | [*name.NamePart]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 74-77};
|
// | "Position": Pos{Line: 5-5 Pos: 74-77}
|
||||||
//| "Value": Type;
|
// | "Value": "Type"
|
||||||
//| "Variable":
|
// | "Variable":
|
||||||
//| [*expr.Variable]
|
// | [*expr.Variable]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 79-82};
|
// | "Position": Pos{Line: 5-5 Pos: 79-82}
|
||||||
//| "VarName":
|
// | "VarName":
|
||||||
//| [*node.Identifier]
|
// | [*node.Identifier]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 79-82};
|
// | "Position": Pos{Line: 5-5 Pos: 79-82}
|
||||||
//| "Value": var;
|
// | "Value": "var"
|
||||||
//| "DefaultValue":
|
// | "DefaultValue":
|
||||||
//| [*expr.ConstFetch]
|
// | [*expr.ConstFetch]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 86-89};
|
// | "Position": Pos{Line: 5-5 Pos: 86-89}
|
||||||
//| "Constant":
|
// | "Constant":
|
||||||
//| [*name.Name]
|
// | [*name.Name]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 86-89};
|
// | "Position": Pos{Line: 5-5 Pos: 86-89}
|
||||||
//| "NamespacedName": null;
|
// | "NamespacedName": "null"
|
||||||
//| "Parts":
|
// | "Parts":
|
||||||
//| [*name.NamePart]
|
// | [*name.NamePart]
|
||||||
//| "Position": Pos{Line: 5-5 Pos: 86-89};
|
// | "Position": Pos{Line: 5-5 Pos: 86-89}
|
||||||
//| "Value": null;
|
// | "Value": "null"
|
||||||
//| "Stmt":
|
// | "Stmt":
|
||||||
//| [*stmt.StmtList]
|
// | [*stmt.StmtList]
|
||||||
//| "Position": Pos{Line: 6-9 Pos: 96-134};
|
// | "Position": Pos{Line: 6-9 Pos: 96-134}
|
||||||
//| "Stmts":
|
// | "Stmts":
|
||||||
//| [*stmt.Expression]
|
// | [*stmt.Expression]
|
||||||
//| "Position": Pos{Line: 8-8 Pos: 124-128};
|
// | "Position": Pos{Line: 8-8 Pos: 124-128}
|
||||||
//| "Expr":
|
// | "Expr":
|
||||||
//| [*expr.Variable]
|
// | [*expr.Variable]
|
||||||
//| "Position": Pos{Line: 8-8 Pos: 124-127};
|
// | "Position": Pos{Line: 8-8 Pos: 124-127}
|
||||||
//| "Comments":
|
// | "Comments":
|
||||||
//| "// some comment\n" before "VariableToken"
|
// | "// some comment\n" before "VariableToken"
|
||||||
//| "VarName":
|
// | "VarName":
|
||||||
//| [*node.Identifier]
|
// | [*node.Identifier]
|
||||||
//| "Position": Pos{Line: 8-8 Pos: 124-127};
|
// | "Position": Pos{Line: 8-8 Pos: 124-127}
|
||||||
//| "Value": var;
|
// | "Value": "var"
|
||||||
}
|
}
|
||||||
|
97
visitor/json_dumper.go
Normal file
97
visitor/json_dumper.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Package visitor contains walker.visitor implementations
|
||||||
|
package visitor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/node"
|
||||||
|
"github.com/z7zmey/php-parser/parser"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/walker"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JsonDumper struct {
|
||||||
|
Writer io.Writer
|
||||||
|
Comments parser.Comments
|
||||||
|
Positions parser.Positions
|
||||||
|
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)
|
||||||
|
|
||||||
|
if d.Positions != nil {
|
||||||
|
if p := d.Positions[n]; p != nil {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.NsResolver != nil {
|
||||||
|
if namespacedName, ok := d.NsResolver.ResolvedNames[n]; ok {
|
||||||
|
fmt.Fprintf(d.Writer, ",%q:%q", "namespacedName", namespacedName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Comments != nil {
|
||||||
|
if c := d.Comments[n]; len(c) > 0 {
|
||||||
|
fmt.Fprintf(d.Writer, ",%q:[", "comments")
|
||||||
|
|
||||||
|
for k, cc := range c {
|
||||||
|
if k == 0 {
|
||||||
|
fmt.Fprintf(d.Writer, "%q", cc)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(d.Writer, ",%q", cc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(d.Writer, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if a := n.Attributes(); len(a) > 0 {
|
||||||
|
for key, attr := range a {
|
||||||
|
switch attr.(type) {
|
||||||
|
case string:
|
||||||
|
fmt.Fprintf(d.Writer, ",\"%s\":%q", key, attr)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(d.Writer, ",\"%s\":%v", key, attr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, "]")
|
||||||
|
}
|
43
visitor/json_dumper_test.go
Normal file
43
visitor/json_dumper_test.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//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 ExampleJsonDumper() {
|
||||||
|
src := `<?php
|
||||||
|
|
||||||
|
namespace Foo {
|
||||||
|
class Bar {
|
||||||
|
public function FunctionName(Type $var = null)
|
||||||
|
{
|
||||||
|
// some comment
|
||||||
|
// second comment
|
||||||
|
$var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
php7parser := php7.NewParser(bytes.NewBufferString(src), "test.php")
|
||||||
|
php7parser.Parse()
|
||||||
|
nodes := php7parser.GetRootNode()
|
||||||
|
|
||||||
|
nsResolver := visitor.NewNamespaceResolver()
|
||||||
|
nodes.Walk(nsResolver)
|
||||||
|
|
||||||
|
dumper := &visitor.JsonDumper{
|
||||||
|
Writer: os.Stdout,
|
||||||
|
Comments: php7parser.GetComments(),
|
||||||
|
Positions: php7parser.GetPositions(),
|
||||||
|
NsResolver: nsResolver,
|
||||||
|
}
|
||||||
|
nodes.Walk(dumper)
|
||||||
|
|
||||||
|
// Unordered output:
|
||||||
|
// {"type":"*node.Root","position":{"startPos":10,"endPos":166,"startLine":3,"endLine":12},"Stmts":[{"type":"*stmt.Namespace","position":{"startPos":10,"endPos":166,"startLine":3,"endLine":12},"NamespaceName":{"type":"*name.Name","position":{"startPos":20,"endPos":22,"startLine":3,"endLine":3},"Parts":[{"type":"*name.NamePart","position":{"startPos":20,"endPos":22,"startLine":3,"endLine":3},"Value":"Foo"}]},"Stmts":[{"type":"*stmt.Class","position":{"startPos":29,"endPos":162,"startLine":4,"endLine":11},"namespacedName":"Foo\\Bar","PhpDocComment":"","ClassName":{"type":"*node.Identifier","position":{"startPos":35,"endPos":37,"startLine":4,"endLine":4},"Value":"Bar"},"Stmts":[{"type":"*stmt.ClassMethod","position":{"startPos":45,"endPos":157,"startLine":5,"endLine":10},"ReturnsRef":false,"PhpDocComment":"","MethodName":{"type":"*node.Identifier","position":{"startPos":61,"endPos":72,"startLine":5,"endLine":5},"Value":"FunctionName"},"Modifiers":[{"type":"*node.Identifier","position":{"startPos":45,"endPos":50,"startLine":5,"endLine":5},"Value":"public"}],"Params":[{"type":"*node.Parameter","position":{"startPos":74,"endPos":89,"startLine":5,"endLine":5},"ByRef":false,"Variadic":false,"VariableType":{"type":"*name.Name","position":{"startPos":74,"endPos":77,"startLine":5,"endLine":5},"namespacedName":"Foo\\Type","Parts":[{"type":"*name.NamePart","position":{"startPos":74,"endPos":77,"startLine":5,"endLine":5},"Value":"Type"}]},"Variable":{"type":"*expr.Variable","position":{"startPos":79,"endPos":82,"startLine":5,"endLine":5},"VarName":{"type":"*node.Identifier","position":{"startPos":79,"endPos":82,"startLine":5,"endLine":5},"Value":"var"}},"DefaultValue":{"type":"*expr.ConstFetch","position":{"startPos":86,"endPos":89,"startLine":5,"endLine":5},"Constant":{"type":"*name.Name","position":{"startPos":86,"endPos":89,"startLine":5,"endLine":5},"namespacedName":"null","Parts":[{"type":"*name.NamePart","position":{"startPos":86,"endPos":89,"startLine":5,"endLine":5},"Value":"null"}]}}}],"Stmt":{"type":"*stmt.StmtList","position":{"startPos":96,"endPos":157,"startLine":6,"endLine":10},"Stmts":[{"type":"*stmt.Expression","position":{"startPos":147,"endPos":151,"startLine":9,"endLine":9},"Expr":{"type":"*expr.Variable","position":{"startPos":147,"endPos":150,"startLine":9,"endLine":9},"comments":["// some comment\n","// second comment\n"],"VarName":{"type":"*node.Identifier","position":{"startPos":147,"endPos":150,"startLine":9,"endLine":9},"Value":"var"}}}]}}]}]}]}
|
||||||
|
}
|
145
visitor/pretty_json_dumper.go
Normal file
145
visitor/pretty_json_dumper.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
// Package visitor contains walker.visitor implementations
|
||||||
|
package visitor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/node"
|
||||||
|
"github.com/z7zmey/php-parser/parser"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/walker"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PrettyJsonDumper struct {
|
||||||
|
Writer io.Writer
|
||||||
|
Comments parser.Comments
|
||||||
|
Positions parser.Positions
|
||||||
|
NsResolver *NamespaceResolver
|
||||||
|
depth int
|
||||||
|
isChildNode bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PrettyJsonDumper) printIndent(w io.Writer) {
|
||||||
|
for i := 0; i < d.depth; i++ {
|
||||||
|
fmt.Fprint(d.Writer, " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnterNode is invoked at every node in hierarchy
|
||||||
|
func (d *PrettyJsonDumper) EnterNode(w walker.Walkable) bool {
|
||||||
|
n := w.(node.Node)
|
||||||
|
|
||||||
|
nodeType := reflect.TypeOf(n).String()
|
||||||
|
|
||||||
|
if d.isChildNode {
|
||||||
|
d.isChildNode = false
|
||||||
|
} else {
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(d.Writer, "{\n")
|
||||||
|
d.depth++
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: %q", "type", nodeType)
|
||||||
|
|
||||||
|
if d.Positions != nil {
|
||||||
|
if p := d.Positions[n]; p != nil {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: {\n", "position")
|
||||||
|
d.depth++
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: %d,\n", "startPos", p.StartPos)
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: %d,\n", "endPos", p.EndPos)
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: %d,\n", "startLine", p.StartLine)
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: %d\n", "endLine", p.EndLine)
|
||||||
|
d.depth--
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprint(d.Writer, "}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.NsResolver != nil {
|
||||||
|
if namespacedName, ok := d.NsResolver.ResolvedNames[n]; ok {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "\"namespacedName\": %q", namespacedName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Comments != nil {
|
||||||
|
if c := d.Comments[n]; len(c) > 0 {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprint(d.Writer, "\"comments\": [\n")
|
||||||
|
d.depth++
|
||||||
|
for k, cc := range c {
|
||||||
|
if k == 0 {
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q", cc)
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q", cc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.depth--
|
||||||
|
fmt.Fprint(d.Writer, "\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprint(d.Writer, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if a := n.Attributes(); len(a) > 0 {
|
||||||
|
for key, attr := range a {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
switch attr.(type) {
|
||||||
|
case string:
|
||||||
|
fmt.Fprintf(d.Writer, "\"%s\": %q", key, attr)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(d.Writer, "\"%s\": %v", key, attr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeaveNode is invoked after node process
|
||||||
|
func (d *PrettyJsonDumper) LeaveNode(n walker.Walkable) {
|
||||||
|
d.depth--
|
||||||
|
fmt.Fprint(d.Writer, "\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprint(d.Writer, "}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PrettyJsonDumper) EnterChildNode(key string, w walker.Walkable) {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: ", key)
|
||||||
|
d.isChildNode = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PrettyJsonDumper) LeaveChildNode(key string, w walker.Walkable) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PrettyJsonDumper) EnterChildList(key string, w walker.Walkable) {
|
||||||
|
fmt.Fprint(d.Writer, ",\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprintf(d.Writer, "%q: [\n", key)
|
||||||
|
d.depth++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PrettyJsonDumper) LeaveChildList(key string, w walker.Walkable) {
|
||||||
|
d.depth--
|
||||||
|
fmt.Fprint(d.Writer, "\n")
|
||||||
|
d.printIndent(d.Writer)
|
||||||
|
fmt.Fprint(d.Writer, "]")
|
||||||
|
}
|
269
visitor/pretty_json_dumper_test.go
Normal file
269
visitor/pretty_json_dumper_test.go
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
//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 ExamplePrettyJsonDumper() {
|
||||||
|
src := `<?php
|
||||||
|
|
||||||
|
namespace Foo {
|
||||||
|
class Bar {
|
||||||
|
public function FunctionName(Type $var = null)
|
||||||
|
{
|
||||||
|
// some comment
|
||||||
|
// second comment
|
||||||
|
$var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
php7parser := php7.NewParser(bytes.NewBufferString(src), "test.php")
|
||||||
|
php7parser.Parse()
|
||||||
|
nodes := php7parser.GetRootNode()
|
||||||
|
|
||||||
|
nsResolver := visitor.NewNamespaceResolver()
|
||||||
|
nodes.Walk(nsResolver)
|
||||||
|
|
||||||
|
dumper := &visitor.PrettyJsonDumper{
|
||||||
|
Writer: os.Stdout,
|
||||||
|
Comments: php7parser.GetComments(),
|
||||||
|
Positions: php7parser.GetPositions(),
|
||||||
|
NsResolver: nsResolver,
|
||||||
|
}
|
||||||
|
nodes.Walk(dumper)
|
||||||
|
|
||||||
|
// Unordered output:
|
||||||
|
// {
|
||||||
|
// "type": "*node.Root",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 10,
|
||||||
|
// "endPos": 166,
|
||||||
|
// "startLine": 3,
|
||||||
|
// "endLine": 12
|
||||||
|
// },
|
||||||
|
// "Stmts": [
|
||||||
|
// {
|
||||||
|
// "type": "*stmt.Namespace",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 10,
|
||||||
|
// "endPos": 166,
|
||||||
|
// "startLine": 3,
|
||||||
|
// "endLine": 12
|
||||||
|
// },
|
||||||
|
// "NamespaceName": {
|
||||||
|
// "type": "*name.Name",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 20,
|
||||||
|
// "endPos": 22,
|
||||||
|
// "startLine": 3,
|
||||||
|
// "endLine": 3
|
||||||
|
// },
|
||||||
|
// "Parts": [
|
||||||
|
// {
|
||||||
|
// "type": "*name.NamePart",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 20,
|
||||||
|
// "endPos": 22,
|
||||||
|
// "startLine": 3,
|
||||||
|
// "endLine": 3
|
||||||
|
// },
|
||||||
|
// "Value": "Foo"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// "Stmts": [
|
||||||
|
// {
|
||||||
|
// "type": "*stmt.Class",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 29,
|
||||||
|
// "endPos": 162,
|
||||||
|
// "startLine": 4,
|
||||||
|
// "endLine": 11
|
||||||
|
// },
|
||||||
|
// "namespacedName": "Foo\\Bar",
|
||||||
|
// "PhpDocComment": "",
|
||||||
|
// "ClassName": {
|
||||||
|
// "type": "*node.Identifier",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 35,
|
||||||
|
// "endPos": 37,
|
||||||
|
// "startLine": 4,
|
||||||
|
// "endLine": 4
|
||||||
|
// },
|
||||||
|
// "Value": "Bar"
|
||||||
|
// },
|
||||||
|
// "Stmts": [
|
||||||
|
// {
|
||||||
|
// "type": "*stmt.ClassMethod",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 45,
|
||||||
|
// "endPos": 157,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 10
|
||||||
|
// },
|
||||||
|
// "ReturnsRef": false,
|
||||||
|
// "PhpDocComment": "",
|
||||||
|
// "MethodName": {
|
||||||
|
// "type": "*node.Identifier",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 61,
|
||||||
|
// "endPos": 72,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "Value": "FunctionName"
|
||||||
|
// },
|
||||||
|
// "Modifiers": [
|
||||||
|
// {
|
||||||
|
// "type": "*node.Identifier",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 45,
|
||||||
|
// "endPos": 50,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "Value": "public"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "Params": [
|
||||||
|
// {
|
||||||
|
// "type": "*node.Parameter",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 74,
|
||||||
|
// "endPos": 89,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "ByRef": false,
|
||||||
|
// "Variadic": false,
|
||||||
|
// "VariableType": {
|
||||||
|
// "type": "*name.Name",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 74,
|
||||||
|
// "endPos": 77,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "namespacedName": "Foo\\Type",
|
||||||
|
// "Parts": [
|
||||||
|
// {
|
||||||
|
// "type": "*name.NamePart",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 74,
|
||||||
|
// "endPos": 77,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "Value": "Type"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// "Variable": {
|
||||||
|
// "type": "*expr.Variable",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 79,
|
||||||
|
// "endPos": 82,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "VarName": {
|
||||||
|
// "type": "*node.Identifier",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 79,
|
||||||
|
// "endPos": 82,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "Value": "var"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "DefaultValue": {
|
||||||
|
// "type": "*expr.ConstFetch",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 86,
|
||||||
|
// "endPos": 89,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "Constant": {
|
||||||
|
// "type": "*name.Name",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 86,
|
||||||
|
// "endPos": 89,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "namespacedName": "null",
|
||||||
|
// "Parts": [
|
||||||
|
// {
|
||||||
|
// "type": "*name.NamePart",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 86,
|
||||||
|
// "endPos": 89,
|
||||||
|
// "startLine": 5,
|
||||||
|
// "endLine": 5
|
||||||
|
// },
|
||||||
|
// "Value": "null"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "Stmt": {
|
||||||
|
// "type": "*stmt.StmtList",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 96,
|
||||||
|
// "endPos": 157,
|
||||||
|
// "startLine": 6,
|
||||||
|
// "endLine": 10
|
||||||
|
// },
|
||||||
|
// "Stmts": [
|
||||||
|
// {
|
||||||
|
// "type": "*stmt.Expression",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 147,
|
||||||
|
// "endPos": 151,
|
||||||
|
// "startLine": 9,
|
||||||
|
// "endLine": 9
|
||||||
|
// },
|
||||||
|
// "Expr": {
|
||||||
|
// "type": "*expr.Variable",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 147,
|
||||||
|
// "endPos": 150,
|
||||||
|
// "startLine": 9,
|
||||||
|
// "endLine": 9
|
||||||
|
// },
|
||||||
|
// "comments": [
|
||||||
|
// "// some comment\n",
|
||||||
|
// "// second comment\n"
|
||||||
|
// ],
|
||||||
|
// "VarName": {
|
||||||
|
// "type": "*node.Identifier",
|
||||||
|
// "position": {
|
||||||
|
// "startPos": 147,
|
||||||
|
// "endPos": 150,
|
||||||
|
// "startLine": 9,
|
||||||
|
// "endLine": 9
|
||||||
|
// },
|
||||||
|
// "Value": "var"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user