expr visitor tests

This commit is contained in:
z7zmey 2018-02-10 02:02:54 +02:00
parent d301afb65c
commit d79f18f315
7 changed files with 430 additions and 24 deletions

View File

@ -31,15 +31,15 @@ func (n *ClassConstFetch) Walk(v walker.Visitor) {
return
}
if n.ConstantName != nil {
vv := v.GetChildrenVisitor("ConstantName")
n.ConstantName.Walk(vv)
}
if n.Class != nil {
vv := v.GetChildrenVisitor("Class")
n.Class.Walk(vv)
}
if n.ConstantName != nil {
vv := v.GetChildrenVisitor("ConstantName")
n.ConstantName.Walk(vv)
}
v.LeaveNode(n)
}

View File

@ -5,22 +5,22 @@ import (
"github.com/z7zmey/php-parser/walker"
)
// ClusureUse node
type ClusureUse struct {
// ClosureUse node
type ClosureUse struct {
ByRef bool
Variable node.Node
}
// NewClusureUse node constuctor
func NewClusureUse(Variable node.Node, ByRef bool) *ClusureUse {
return &ClusureUse{
// NewClosureUse node constuctor
func NewClosureUse(Variable node.Node, ByRef bool) *ClosureUse {
return &ClosureUse{
ByRef,
Variable,
}
}
// Attributes returns node attributes as map
func (n *ClusureUse) Attributes() map[string]interface{} {
func (n *ClosureUse) Attributes() map[string]interface{} {
return map[string]interface{}{
"ByRef": n.ByRef,
}
@ -28,7 +28,7 @@ func (n *ClusureUse) Attributes() map[string]interface{} {
// Walk traverses nodes
// Walk is invoked recursively until v.EnterNode returns true
func (n *ClusureUse) Walk(v walker.Visitor) {
func (n *ClosureUse) Walk(v walker.Visitor) {
if v.EnterNode(n) == false {
return
}

406
node/expr/t_visitor_test.go Normal file
View File

@ -0,0 +1,406 @@
package expr_test
import (
"reflect"
"testing"
"github.com/z7zmey/php-parser/node/stmt"
"github.com/z7zmey/php-parser/node/name"
"github.com/z7zmey/php-parser/node/scalar"
"github.com/kylelemons/godebug/pretty"
"github.com/z7zmey/php-parser/node"
"github.com/z7zmey/php-parser/node/expr"
"github.com/z7zmey/php-parser/walker"
)
var nodesToTest = []struct {
node node.Node // node
expectedVisitedKeys []string // visited keys
expectedAttributes map[string]interface{}
}{
{
&expr.ArrayDimFetch{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
Dim: &scalar.Lnumber{Value: "1"},
},
[]string{"Variable", "Dim"},
map[string]interface{}{},
},
{
&expr.ArrayItem{
ByRef: false,
Key: &scalar.String{Value: "key"},
Val: &scalar.Lnumber{Value: "1"},
},
[]string{"Key", "Val"},
map[string]interface{}{"ByRef": false},
},
{
&expr.Array{
Items: []node.Node{
&expr.ArrayItem{
ByRef: false,
Key: &scalar.String{Value: "key"},
Val: &scalar.Lnumber{Value: "1"},
},
},
},
[]string{"Items"},
map[string]interface{}{},
},
{
&expr.BitwiseNot{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.BooleanNot{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.ClassConstFetch{
Class: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
ConstantName: &node.Identifier{Value: "foo"},
},
[]string{"Class", "ConstantName"},
map[string]interface{}{},
},
{
&expr.Clone{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.ClosureUse{
ByRef: false,
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Variable"},
map[string]interface{}{"ByRef": false},
},
{
&expr.Closure{
ReturnsRef: true,
Static: false,
PhpDocComment: "",
Params: []node.Node{&node.Parameter{}},
Uses: []node.Node{&expr.ClosureUse{}},
ReturnType: &name.Name{},
Stmts: []node.Node{&stmt.Nop{}},
},
[]string{"Params", "Uses", "ReturnType", "Stmts"},
map[string]interface{}{"ReturnsRef": true, "Static": false, "PhpDocComment": ""},
},
{
&expr.ConstFetch{
Constant: &node.Identifier{Value: "foo"},
},
[]string{"Constant"},
map[string]interface{}{},
},
{
&expr.Empty{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.ErrorSuppress{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.Eval{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.Exit{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
IsDie: false,
},
[]string{"Expr"},
map[string]interface{}{"IsDie": false},
},
{
&expr.FunctionCall{
Function: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
Arguments: []node.Node{&node.Argument{}},
},
[]string{"Function", "Arguments"},
map[string]interface{}{},
},
{
&expr.IncludeOnce{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.Include{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.InstanceOf{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
Class: &name.Name{},
},
[]string{"Expr", "Class"},
map[string]interface{}{},
},
{
&expr.Isset{
Variables: []node.Node{
&expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
},
[]string{"Variables"},
map[string]interface{}{},
},
{
&expr.List{
Items: []node.Node{
&expr.ArrayItem{},
},
},
[]string{"Items"},
map[string]interface{}{},
},
{
&expr.MethodCall{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
Method: &node.Identifier{Value: "foo"},
Arguments: []node.Node{&node.Argument{}},
},
[]string{"Variable", "Method", "Arguments"},
map[string]interface{}{},
},
{
&expr.New{
Class: &name.Name{},
Arguments: []node.Node{&node.Argument{}},
},
[]string{"Class", "Arguments"},
map[string]interface{}{},
},
{
&expr.PostDec{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Variable"},
map[string]interface{}{},
},
{
&expr.PostInc{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Variable"},
map[string]interface{}{},
},
{
&expr.PreDec{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Variable"},
map[string]interface{}{},
},
{
&expr.PreInc{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Variable"},
map[string]interface{}{},
},
{
&expr.Print{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.PropertyFetch{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
Property: &node.Identifier{Value: "foo"},
},
[]string{"Variable", "Property"},
map[string]interface{}{},
},
{
&expr.RequireOnce{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.Require{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.ShellExec{
Parts: []node.Node{
&scalar.EncapsedStringPart{},
},
},
[]string{"Parts"},
map[string]interface{}{},
},
{
&expr.ShortArray{
Items: []node.Node{
&expr.ArrayItem{},
},
},
[]string{"Items"},
map[string]interface{}{},
},
{
&expr.ShortList{
Items: []node.Node{
&expr.ArrayItem{},
},
},
[]string{"Items"},
map[string]interface{}{},
},
{
&expr.StaticCall{
Class: &name.Name{},
Call: &node.Identifier{Value: "foo"},
Arguments: []node.Node{&node.Argument{}},
},
[]string{"Class", "Call", "Arguments"},
map[string]interface{}{},
},
{
&expr.StaticPropertyFetch{
Class: &name.Name{},
Property: &node.Identifier{Value: "foo"},
},
[]string{"Class", "Property"},
map[string]interface{}{},
},
{
&expr.Ternary{
Condition: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
IfTrue: &expr.Variable{VarName: &node.Identifier{Value: "$b"}},
IfFalse: &expr.Variable{VarName: &node.Identifier{Value: "$c"}},
},
[]string{"Condition", "IfTrue", "IfFalse"},
map[string]interface{}{},
},
{
&expr.UnaryMinus{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.UnaryPlus{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.Variable{VarName: &node.Identifier{Value: "$a"}},
[]string{"VarName"},
map[string]interface{}{},
},
{
&expr.YieldFrom{
Expr: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
},
[]string{"Expr"},
map[string]interface{}{},
},
{
&expr.Yield{
Key: &expr.Variable{VarName: &node.Identifier{Value: "$a"}},
Value: &expr.Variable{VarName: &node.Identifier{Value: "$b"}},
},
[]string{"Key", "Value"},
map[string]interface{}{},
},
}
type visitorMock struct {
visitChildren bool
visitedKeys []string
}
func (v *visitorMock) EnterNode(n walker.Walker) bool { return v.visitChildren }
func (v *visitorMock) GetChildrenVisitor(key string) walker.Visitor {
v.visitedKeys = append(v.visitedKeys, key)
return &visitorMock{v.visitChildren, nil}
}
func (v *visitorMock) LeaveNode(n walker.Walker) {}
func TestVisitorDisableChildren(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 TestVisitor(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)
}
}
}

View File

@ -4935,7 +4935,7 @@ yydefault:
positions.AddPosition(variable, positionBuilder.NewTokenPosition(yyDollar[3].token))
comments.AddComments(variable, yyDollar[3].token.Comments())
use := expr.NewClusureUse(variable, false)
use := expr.NewClosureUse(variable, false)
positions.AddPosition(use, positionBuilder.NewTokenPosition(yyDollar[3].token))
comments.AddComments(use, yyDollar[3].token.Comments())
@ -4953,7 +4953,7 @@ yydefault:
positions.AddPosition(variable, positionBuilder.NewTokenPosition(yyDollar[4].token))
comments.AddComments(variable, yyDollar[3].token.Comments())
use := expr.NewClusureUse(variable, true)
use := expr.NewClosureUse(variable, true)
positions.AddPosition(use, positionBuilder.NewTokensPosition(yyDollar[3].token, yyDollar[4].token))
comments.AddComments(use, yyDollar[3].token.Comments())
@ -4971,7 +4971,7 @@ yydefault:
positions.AddPosition(variable, positionBuilder.NewTokenPosition(yyDollar[1].token))
comments.AddComments(variable, yyDollar[1].token.Comments())
use := expr.NewClusureUse(variable, false)
use := expr.NewClosureUse(variable, false)
positions.AddPosition(use, positionBuilder.NewTokenPosition(yyDollar[1].token))
comments.AddComments(use, yyDollar[1].token.Comments())
@ -4989,7 +4989,7 @@ yydefault:
positions.AddPosition(variable, positionBuilder.NewTokenPosition(yyDollar[2].token))
comments.AddComments(variable, yyDollar[1].token.Comments())
use := expr.NewClusureUse(variable, true)
use := expr.NewClosureUse(variable, true)
positions.AddPosition(use, positionBuilder.NewTokensPosition(yyDollar[1].token, yyDollar[2].token))
comments.AddComments(use, yyDollar[1].token.Comments())

View File

@ -2369,7 +2369,7 @@ lexical_var_list:
positions.AddPosition(variable, positionBuilder.NewTokenPosition($3))
comments.AddComments(variable, $3.Comments())
use := expr.NewClusureUse(variable, false)
use := expr.NewClosureUse(variable, false)
positions.AddPosition(use, positionBuilder.NewTokenPosition($3))
comments.AddComments(use, $3.Comments())
@ -2385,7 +2385,7 @@ lexical_var_list:
positions.AddPosition(variable, positionBuilder.NewTokenPosition($4))
comments.AddComments(variable, $3.Comments())
use := expr.NewClusureUse(variable, true)
use := expr.NewClosureUse(variable, true)
positions.AddPosition(use, positionBuilder.NewTokensPosition($3, $4))
comments.AddComments(use, $3.Comments())
@ -2401,7 +2401,7 @@ lexical_var_list:
positions.AddPosition(variable, positionBuilder.NewTokenPosition($1))
comments.AddComments(variable, $1.Comments())
use := expr.NewClusureUse(variable, false)
use := expr.NewClosureUse(variable, false)
positions.AddPosition(use, positionBuilder.NewTokenPosition($1))
comments.AddComments(use, $1.Comments())
@ -2417,7 +2417,7 @@ lexical_var_list:
positions.AddPosition(variable, positionBuilder.NewTokenPosition($2))
comments.AddComments(variable, $1.Comments())
use := expr.NewClusureUse(variable, true)
use := expr.NewClosureUse(variable, true)
positions.AddPosition(use, positionBuilder.NewTokensPosition($1, $2))
comments.AddComments(use, $1.Comments())

View File

@ -4830,7 +4830,7 @@ yydefault:
positions.AddPosition(identifier, positionBuilder.NewTokenPosition(yyDollar[1].token))
variable := expr.NewVariable(identifier)
positions.AddPosition(variable, positionBuilder.NewTokenPosition(yyDollar[1].token))
yyVAL.node = expr.NewClusureUse(variable, false)
yyVAL.node = expr.NewClosureUse(variable, false)
positions.AddPosition(yyVAL.node, positionBuilder.NewTokenPosition(yyDollar[1].token))
comments.AddComments(identifier, yyDollar[1].token.Comments())
@ -4845,7 +4845,7 @@ yydefault:
positions.AddPosition(identifier, positionBuilder.NewTokenPosition(yyDollar[2].token))
variable := expr.NewVariable(identifier)
positions.AddPosition(variable, positionBuilder.NewTokenPosition(yyDollar[2].token))
yyVAL.node = expr.NewClusureUse(variable, true)
yyVAL.node = expr.NewClosureUse(variable, true)
positions.AddPosition(yyVAL.node, positionBuilder.NewTokensPosition(yyDollar[1].token, yyDollar[2].token))
comments.AddComments(identifier, yyDollar[2].token.Comments())

View File

@ -1933,7 +1933,7 @@ lexical_var:
positions.AddPosition(identifier, positionBuilder.NewTokenPosition($1))
variable := expr.NewVariable(identifier)
positions.AddPosition(variable, positionBuilder.NewTokenPosition($1))
$$ = expr.NewClusureUse(variable, false)
$$ = expr.NewClosureUse(variable, false)
positions.AddPosition($$, positionBuilder.NewTokenPosition($1))
comments.AddComments(identifier, $1.Comments())
@ -1946,7 +1946,7 @@ lexical_var:
positions.AddPosition(identifier, positionBuilder.NewTokenPosition($2))
variable := expr.NewVariable(identifier)
positions.AddPosition(variable, positionBuilder.NewTokenPosition($2))
$$ = expr.NewClusureUse(variable, true)
$$ = expr.NewClosureUse(variable, true)
positions.AddPosition($$, positionBuilder.NewTokensPosition($1, $2))
comments.AddComments(identifier, $2.Comments())