[#82] Arrow function and assign coalesce
This commit is contained in:
66
node/expr/assign/n_coalesce.go
Normal file
66
node/expr/assign/n_coalesce.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package assign
|
||||
|
||||
import (
|
||||
"github.com/z7zmey/php-parser/freefloating"
|
||||
"github.com/z7zmey/php-parser/node"
|
||||
"github.com/z7zmey/php-parser/position"
|
||||
"github.com/z7zmey/php-parser/walker"
|
||||
)
|
||||
|
||||
// Coalesce node
|
||||
type Coalesce struct {
|
||||
FreeFloating freefloating.Collection
|
||||
Position *position.Position
|
||||
Variable node.Node
|
||||
Expression node.Node
|
||||
}
|
||||
|
||||
// NewCoalesce node constructor
|
||||
func NewCoalesce(Variable node.Node, Expression node.Node) *Coalesce {
|
||||
return &Coalesce{
|
||||
FreeFloating: nil,
|
||||
Variable: Variable,
|
||||
Expression: Expression,
|
||||
}
|
||||
}
|
||||
|
||||
// SetPosition sets node position
|
||||
func (n *Coalesce) SetPosition(p *position.Position) {
|
||||
n.Position = p
|
||||
}
|
||||
|
||||
// GetPosition returns node positions
|
||||
func (n *Coalesce) GetPosition() *position.Position {
|
||||
return n.Position
|
||||
}
|
||||
|
||||
func (n *Coalesce) GetFreeFloating() *freefloating.Collection {
|
||||
return &n.FreeFloating
|
||||
}
|
||||
|
||||
// Attributes returns node attributes as map
|
||||
func (n *Coalesce) Attributes() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Walk traverses nodes
|
||||
// Walk is invoked recursively until v.EnterNode returns true
|
||||
func (n *Coalesce) Walk(v walker.Visitor) {
|
||||
if v.EnterNode(n) == false {
|
||||
return
|
||||
}
|
||||
|
||||
if n.Variable != nil {
|
||||
v.EnterChildNode("Variable", n)
|
||||
n.Variable.Walk(v)
|
||||
v.LeaveChildNode("Variable", n)
|
||||
}
|
||||
|
||||
if n.Expression != nil {
|
||||
v.EnterChildNode("Expression", n)
|
||||
n.Expression.Walk(v)
|
||||
v.LeaveChildNode("Expression", n)
|
||||
}
|
||||
|
||||
v.LeaveNode(n)
|
||||
}
|
||||
@@ -1272,3 +1272,73 @@ func TestShiftRight(t *testing.T) {
|
||||
actual = php5parser.GetRootNode()
|
||||
assert.DeepEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestCoalesce(t *testing.T) {
|
||||
src := `<? $a ??= $b;`
|
||||
|
||||
expected := &node.Root{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 13,
|
||||
},
|
||||
Stmts: []node.Node{
|
||||
&stmt.Expression{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 13,
|
||||
},
|
||||
Expr: &assign.Coalesce{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 12,
|
||||
},
|
||||
Variable: &expr.Variable{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 5,
|
||||
},
|
||||
VarName: &node.Identifier{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 5,
|
||||
},
|
||||
Value: "a",
|
||||
},
|
||||
},
|
||||
Expression: &expr.Variable{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 10,
|
||||
EndPos: 12,
|
||||
},
|
||||
VarName: &node.Identifier{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 10,
|
||||
EndPos: 12,
|
||||
},
|
||||
Value: "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
php7parser := php7.NewParser([]byte(src), "7.4")
|
||||
php7parser.Parse()
|
||||
actual := php7parser.GetRootNode()
|
||||
assert.DeepEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ var nodes = []node.Node{
|
||||
&assign.BitwiseXor{
|
||||
FreeFloating: expected,
|
||||
},
|
||||
&assign.Coalesce{
|
||||
FreeFloating: expected,
|
||||
},
|
||||
&assign.Concat{
|
||||
FreeFloating: expected,
|
||||
},
|
||||
|
||||
@@ -56,6 +56,14 @@ var nodesToTest = []struct {
|
||||
[]string{"Variable", "Expression"},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
&assign.Coalesce{
|
||||
Variable: &expr.Variable{},
|
||||
Expression: &expr.Variable{},
|
||||
},
|
||||
[]string{"Variable", "Expression"},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
&assign.Concat{
|
||||
Variable: &expr.Variable{},
|
||||
|
||||
88
node/expr/n_arrow_function.go
Normal file
88
node/expr/n_arrow_function.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"github.com/z7zmey/php-parser/freefloating"
|
||||
"github.com/z7zmey/php-parser/node"
|
||||
"github.com/z7zmey/php-parser/position"
|
||||
"github.com/z7zmey/php-parser/walker"
|
||||
)
|
||||
|
||||
// ArrowFunction node
|
||||
type ArrowFunction struct {
|
||||
FreeFloating freefloating.Collection
|
||||
Position *position.Position
|
||||
ReturnsRef bool
|
||||
Static bool
|
||||
PhpDocComment string
|
||||
Params []node.Node
|
||||
ReturnType node.Node
|
||||
Expr node.Node
|
||||
}
|
||||
|
||||
// NewArrowFunction node constructor
|
||||
func NewArrowFunction(Params []node.Node, ReturnType node.Node, Stmt node.Node, Static bool, ReturnsRef bool, PhpDocComment string) *ArrowFunction {
|
||||
return &ArrowFunction{
|
||||
FreeFloating: nil,
|
||||
ReturnsRef: ReturnsRef,
|
||||
Static: Static,
|
||||
PhpDocComment: PhpDocComment,
|
||||
Params: Params,
|
||||
ReturnType: ReturnType,
|
||||
Expr: Stmt,
|
||||
}
|
||||
}
|
||||
|
||||
// SetPosition sets node position
|
||||
func (n *ArrowFunction) SetPosition(p *position.Position) {
|
||||
n.Position = p
|
||||
}
|
||||
|
||||
// GetPosition returns node positions
|
||||
func (n *ArrowFunction) GetPosition() *position.Position {
|
||||
return n.Position
|
||||
}
|
||||
|
||||
func (n *ArrowFunction) GetFreeFloating() *freefloating.Collection {
|
||||
return &n.FreeFloating
|
||||
}
|
||||
|
||||
// Attributes returns node attributes as map
|
||||
func (n *ArrowFunction) Attributes() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"ReturnsRef": n.ReturnsRef,
|
||||
"Static": n.Static,
|
||||
"PhpDocComment": n.PhpDocComment,
|
||||
}
|
||||
}
|
||||
|
||||
// Walk traverses nodes
|
||||
// Walk is invoked recursively until v.EnterNode returns true
|
||||
func (n *ArrowFunction) Walk(v walker.Visitor) {
|
||||
if v.EnterNode(n) == false {
|
||||
return
|
||||
}
|
||||
|
||||
if n.Params != nil {
|
||||
v.EnterChildList("Params", n)
|
||||
for _, nn := range n.Params {
|
||||
if nn != nil {
|
||||
nn.Walk(v)
|
||||
}
|
||||
}
|
||||
v.LeaveChildList("Params", n)
|
||||
}
|
||||
|
||||
if n.ReturnType != nil {
|
||||
v.EnterChildNode("ReturnType", n)
|
||||
n.ReturnType.Walk(v)
|
||||
v.LeaveChildNode("ReturnType", n)
|
||||
}
|
||||
|
||||
if n.Expr != nil {
|
||||
v.EnterChildNode("Expr", n)
|
||||
n.Expr.Walk(v)
|
||||
v.LeaveChildNode("Expr", n)
|
||||
}
|
||||
|
||||
v.LeaveNode(n)
|
||||
}
|
||||
144
node/expr/t_arrow_function_test.go
Normal file
144
node/expr/t_arrow_function_test.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package expr_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/z7zmey/php-parser/node"
|
||||
"github.com/z7zmey/php-parser/node/expr"
|
||||
"github.com/z7zmey/php-parser/node/name"
|
||||
"github.com/z7zmey/php-parser/node/stmt"
|
||||
"github.com/z7zmey/php-parser/php7"
|
||||
"github.com/z7zmey/php-parser/position"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestArrowFunction(t *testing.T) {
|
||||
src := `<? fn() => $a;`
|
||||
|
||||
expected := &node.Root{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 14,
|
||||
},
|
||||
Stmts: []node.Node{
|
||||
&stmt.Expression{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 14,
|
||||
},
|
||||
Expr: &expr.ArrowFunction{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 13,
|
||||
},
|
||||
ReturnsRef: false,
|
||||
Static: false,
|
||||
PhpDocComment: "",
|
||||
Expr: &expr.Variable{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 11,
|
||||
EndPos: 13,
|
||||
},
|
||||
VarName: &node.Identifier{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 11,
|
||||
EndPos: 13,
|
||||
},
|
||||
Value: "a",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
php7parser := php7.NewParser([]byte(src), "7.4")
|
||||
php7parser.Parse()
|
||||
actual := php7parser.GetRootNode()
|
||||
assert.DeepEqual(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestArrowFunctionReturnType(t *testing.T) {
|
||||
src := `<? fn & () : foo => $a;`
|
||||
|
||||
expected := &node.Root{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 23,
|
||||
},
|
||||
Stmts: []node.Node{
|
||||
&stmt.Expression{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 23,
|
||||
},
|
||||
Expr: &expr.ArrowFunction{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 3,
|
||||
EndPos: 22,
|
||||
},
|
||||
Static: false,
|
||||
PhpDocComment: "",
|
||||
ReturnsRef: true,
|
||||
ReturnType: &name.Name{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 13,
|
||||
EndPos: 16,
|
||||
},
|
||||
Parts: []node.Node{
|
||||
&name.NamePart{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 13,
|
||||
EndPos: 16,
|
||||
},
|
||||
Value: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
Expr: &expr.Variable{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 20,
|
||||
EndPos: 22,
|
||||
},
|
||||
VarName: &node.Identifier{
|
||||
Position: &position.Position{
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
StartPos: 20,
|
||||
EndPos: 22,
|
||||
},
|
||||
Value: "a",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
php7parser := php7.NewParser([]byte(src), "7.4")
|
||||
php7parser.Parse()
|
||||
actual := php7parser.GetRootNode()
|
||||
assert.DeepEqual(t, expected, actual)
|
||||
}
|
||||
@@ -35,6 +35,9 @@ var nodes = []node.Node{
|
||||
&expr.Array{
|
||||
FreeFloating: expected,
|
||||
},
|
||||
&expr.ArrowFunction{
|
||||
FreeFloating: expected,
|
||||
},
|
||||
&expr.BitwiseNot{
|
||||
FreeFloating: expected,
|
||||
},
|
||||
|
||||
@@ -97,6 +97,18 @@ var nodesToTest = []struct {
|
||||
[]string{"Params", "ClosureUse", "ReturnType", "Stmts"},
|
||||
map[string]interface{}{"ReturnsRef": true, "Static": false, "PhpDocComment": ""},
|
||||
},
|
||||
{
|
||||
&expr.ArrowFunction{
|
||||
ReturnsRef: true,
|
||||
Static: false,
|
||||
PhpDocComment: "",
|
||||
Params: []node.Node{&node.Parameter{}},
|
||||
ReturnType: &name.Name{},
|
||||
Expr: &expr.Variable{},
|
||||
},
|
||||
[]string{"Params", "ReturnType", "Expr"},
|
||||
map[string]interface{}{"ReturnsRef": true, "Static": false, "PhpDocComment": ""},
|
||||
},
|
||||
{
|
||||
&expr.ConstFetch{
|
||||
Constant: &node.Identifier{Value: "foo"},
|
||||
|
||||
Reference in New Issue
Block a user