add node_tests
This commit is contained in:
parent
621c18ba27
commit
6d90e1258f
204
node/node_test.go
Normal file
204
node/node_test.go
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
package node_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/node/name"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/node/expr"
|
||||||
|
|
||||||
|
"github.com/kylelemons/godebug/pretty"
|
||||||
|
"github.com/z7zmey/php-parser/node"
|
||||||
|
"github.com/z7zmey/php-parser/node/stmt"
|
||||||
|
"github.com/z7zmey/php-parser/parser"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertEqual(t *testing.T, expected interface{}, actual interface{}) {
|
||||||
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
|
diff := pretty.Compare(expected, actual)
|
||||||
|
|
||||||
|
if diff != "" {
|
||||||
|
t.Errorf("diff: (-expected +actual)\n%s", diff)
|
||||||
|
} else {
|
||||||
|
t.Errorf("expected and actual are not equal\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIdentifier(t *testing.T) {
|
||||||
|
src := `<? $foo;`
|
||||||
|
|
||||||
|
expected := &stmt.StmtList{
|
||||||
|
Stmts: []node.Node{
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.Variable{
|
||||||
|
VarName: &node.Identifier{Value: "$foo"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, _, _ := parser.Parse(bytes.NewBufferString(src), "test.php")
|
||||||
|
|
||||||
|
assertEqual(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArgumentNode(t *testing.T) {
|
||||||
|
src := `<?
|
||||||
|
foo($a, ...$b);
|
||||||
|
$foo($a, ...$b);
|
||||||
|
$foo->bar($a, ...$b);
|
||||||
|
foo::bar($a, ...$b);
|
||||||
|
$foo::bar($a, ...$b);
|
||||||
|
new foo($a, ...$b);
|
||||||
|
/** anonymous class */
|
||||||
|
new class ($a, ...$b) {};
|
||||||
|
`
|
||||||
|
|
||||||
|
expected := &stmt.StmtList{
|
||||||
|
Stmts: []node.Node{
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.FunctionCall{
|
||||||
|
Function: &name.Name{Parts: []node.Node{&name.NamePart{Value: "foo"}}},
|
||||||
|
Arguments: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.FunctionCall{
|
||||||
|
Function: &expr.Variable{VarName: &node.Identifier{Value: "$foo"}},
|
||||||
|
Arguments: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.MethodCall{
|
||||||
|
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$foo"}},
|
||||||
|
Method: &node.Identifier{Value: "bar"},
|
||||||
|
Arguments: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.StaticCall{
|
||||||
|
Class: &name.Name{Parts: []node.Node{&name.NamePart{Value: "foo"}}},
|
||||||
|
Call: &node.Identifier{Value: "bar"},
|
||||||
|
Arguments: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.StaticCall{
|
||||||
|
Class: &expr.Variable{VarName: &node.Identifier{Value: "$foo"}},
|
||||||
|
Call: &node.Identifier{Value: "bar"},
|
||||||
|
Arguments: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.New{
|
||||||
|
Class: &name.Name{Parts: []node.Node{&name.NamePart{Value: "foo"}}},
|
||||||
|
Arguments: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.New{
|
||||||
|
Class: &stmt.Class{
|
||||||
|
PhpDocComment: "/** anonymous class */",
|
||||||
|
Args: []node.Node{
|
||||||
|
&node.Argument{Variadic: false, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}},
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}},
|
||||||
|
},
|
||||||
|
Stmts: []node.Node{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, _, _ := parser.Parse(bytes.NewBufferString(src), "test.php")
|
||||||
|
|
||||||
|
assertEqual(t, expected, actual)
|
||||||
|
}
|
||||||
|
func TestParameterNode(t *testing.T) {
|
||||||
|
src := `<?
|
||||||
|
function foo(?bar $bar=null, baz &...$baz) {}
|
||||||
|
class foo {public function foo(?bar $bar=null, baz &...$baz) {}}
|
||||||
|
function(?bar $bar=null, baz &...$baz) {};
|
||||||
|
static function(?bar $bar=null, baz &...$baz) {};
|
||||||
|
`
|
||||||
|
|
||||||
|
expectedParams := []node.Node{
|
||||||
|
&node.Parameter{
|
||||||
|
ByRef: false,
|
||||||
|
Variadic: false,
|
||||||
|
VariableType: &node.Nullable{Expr: &name.Name{Parts: []node.Node{&name.NamePart{Value: "bar"}}}},
|
||||||
|
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$bar"}},
|
||||||
|
DefaultValue: &expr.ConstFetch{Constant: &name.Name{Parts: []node.Node{&name.NamePart{Value: "null"}}}},
|
||||||
|
},
|
||||||
|
&node.Parameter{
|
||||||
|
ByRef: true,
|
||||||
|
Variadic: true,
|
||||||
|
VariableType: &name.Name{Parts: []node.Node{&name.NamePart{Value: "baz"}}},
|
||||||
|
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$baz"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := &stmt.StmtList{
|
||||||
|
Stmts: []node.Node{
|
||||||
|
&stmt.Function{
|
||||||
|
ReturnsRef: false,
|
||||||
|
PhpDocComment: "",
|
||||||
|
FunctionName: &node.Identifier{Value: "foo"},
|
||||||
|
Params: expectedParams,
|
||||||
|
Stmts: []node.Node{},
|
||||||
|
},
|
||||||
|
&stmt.Class{
|
||||||
|
ClassName: &node.Identifier{Value: "foo"},
|
||||||
|
Stmts: []node.Node{
|
||||||
|
&stmt.ClassMethod{
|
||||||
|
MethodName: &node.Identifier{Value: "foo"},
|
||||||
|
Modifiers: []node.Node{&node.Identifier{Value: "public"}},
|
||||||
|
Params: expectedParams,
|
||||||
|
Stmts: []node.Node{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.Closure{
|
||||||
|
Params: expectedParams,
|
||||||
|
Uses: []node.Node{},
|
||||||
|
Stmts: []node.Node{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stmt.Expression{
|
||||||
|
Expr: &expr.Closure{
|
||||||
|
Static: true,
|
||||||
|
Params: expectedParams,
|
||||||
|
Uses: []node.Node{},
|
||||||
|
Stmts: []node.Node{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, _, _ := parser.Parse(bytes.NewBufferString(src), "test.php")
|
||||||
|
|
||||||
|
assertEqual(t, expected, actual)
|
||||||
|
}
|
@ -9,19 +9,19 @@ type Class struct {
|
|||||||
PhpDocComment string
|
PhpDocComment string
|
||||||
ClassName node.Node
|
ClassName node.Node
|
||||||
Modifiers []node.Node
|
Modifiers []node.Node
|
||||||
args []node.Node
|
Args []node.Node
|
||||||
Extends node.Node
|
Extends node.Node
|
||||||
Implements []node.Node
|
Implements []node.Node
|
||||||
Stmts []node.Node
|
Stmts []node.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClass node constuctor
|
// NewClass node constuctor
|
||||||
func NewClass(ClassName node.Node, Modifiers []node.Node, args []node.Node, Extends node.Node, Implements []node.Node, Stmts []node.Node, PhpDocComment string) *Class {
|
func NewClass(ClassName node.Node, Modifiers []node.Node, Args []node.Node, Extends node.Node, Implements []node.Node, Stmts []node.Node, PhpDocComment string) *Class {
|
||||||
return &Class{
|
return &Class{
|
||||||
PhpDocComment,
|
PhpDocComment,
|
||||||
ClassName,
|
ClassName,
|
||||||
Modifiers,
|
Modifiers,
|
||||||
args,
|
Args,
|
||||||
Extends,
|
Extends,
|
||||||
Implements,
|
Implements,
|
||||||
Stmts,
|
Stmts,
|
||||||
@ -56,9 +56,9 @@ func (n *Class) Walk(v node.Visitor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.args != nil {
|
if n.Args != nil {
|
||||||
vv := v.GetChildrenVisitor("args")
|
vv := v.GetChildrenVisitor("Args")
|
||||||
for _, nn := range n.args {
|
for _, nn := range n.Args {
|
||||||
if nn != nil {
|
if nn != nil {
|
||||||
nn.Walk(vv)
|
nn.Walk(vv)
|
||||||
}
|
}
|
||||||
|
102
node/visitor_test.go
Normal file
102
node/visitor_test.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package node_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/node/scalar"
|
||||||
|
|
||||||
|
"github.com/z7zmey/php-parser/node/expr"
|
||||||
|
|
||||||
|
"github.com/kylelemons/godebug/pretty"
|
||||||
|
"github.com/z7zmey/php-parser/node"
|
||||||
|
)
|
||||||
|
|
||||||
|
var nodesToTest = []struct {
|
||||||
|
node node.Node // node
|
||||||
|
expectedVisitedKeys []string // visited keys
|
||||||
|
expectedAttributes map[string]interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
&node.Identifier{Value: "foo"},
|
||||||
|
[]string{},
|
||||||
|
map[string]interface{}{"Value": "foo"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&node.Nullable{Expr: &expr.Variable{VarName: &node.Identifier{Value: "foo"}}},
|
||||||
|
[]string{"Expr"},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&node.Argument{Variadic: true, Expr: &expr.Variable{VarName: &node.Identifier{Value: "foo"}}},
|
||||||
|
[]string{"Expr"},
|
||||||
|
map[string]interface{}{"Variadic": true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&node.Parameter{
|
||||||
|
ByRef: false,
|
||||||
|
Variadic: true,
|
||||||
|
VariableType: &node.Identifier{Value: "foo"},
|
||||||
|
Variable: &expr.Variable{VarName: &node.Identifier{Value: "bar"}},
|
||||||
|
DefaultValue: &scalar.Lnumber{Value: "0"},
|
||||||
|
},
|
||||||
|
[]string{"VariableType", "Variable", "DefaultValue"},
|
||||||
|
map[string]interface{}{"ByRef": false, "Variadic": true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type visitorMock struct {
|
||||||
|
visitChildren bool
|
||||||
|
visitedKeys []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *visitorMock) EnterNode(n node.Node) bool { return v.visitChildren }
|
||||||
|
func (v *visitorMock) GetChildrenVisitor(key string) node.Visitor {
|
||||||
|
v.visitedKeys = append(v.visitedKeys, key)
|
||||||
|
return &visitorMock{v.visitChildren, nil}
|
||||||
|
}
|
||||||
|
func (v *visitorMock) LeaveNode(n node.Node) {}
|
||||||
|
|
||||||
|
func TestNameVisitorDisableChildren(t *testing.T) {
|
||||||
|
for _, tt := range nodesToTest {
|
||||||
|
v := &visitorMock{false, nil}
|
||||||
|
tt.node.Walk(v)
|
||||||
|
|
||||||
|
expected := []string{}
|
||||||
|
actual := v.visitedKeys
|
||||||
|
|
||||||
|
diff := pretty.Compare(expected, actual)
|
||||||
|
if diff != "" {
|
||||||
|
t.Errorf("%s diff: (-expected +actual)\n%s", reflect.TypeOf(tt.node), diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNameVisitor(t *testing.T) {
|
||||||
|
for _, tt := range nodesToTest {
|
||||||
|
v := &visitorMock{true, nil}
|
||||||
|
tt.node.Walk(v)
|
||||||
|
|
||||||
|
expected := tt.expectedVisitedKeys
|
||||||
|
actual := v.visitedKeys
|
||||||
|
|
||||||
|
diff := pretty.Compare(expected, actual)
|
||||||
|
if diff != "" {
|
||||||
|
t.Errorf("%s diff: (-expected +actual)\n%s", reflect.TypeOf(tt.node), diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test Attributes()
|
||||||
|
|
||||||
|
func TestNameAttributes(t *testing.T) {
|
||||||
|
for _, tt := range nodesToTest {
|
||||||
|
expected := tt.expectedAttributes
|
||||||
|
actual := tt.node.Attributes()
|
||||||
|
|
||||||
|
diff := pretty.Compare(expected, actual)
|
||||||
|
if diff != "" {
|
||||||
|
t.Errorf("%s diff: (-expected +actual)\n%s", reflect.TypeOf(tt.node), diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user