changing ClosureUse node purpose

Now ClosureUse is a container node for variable and reference nodes
This commit is contained in:
z7zmey 2018-05-25 09:38:44 +03:00
parent ec0ef26bd6
commit 6ccca996a8
13 changed files with 1225 additions and 1252 deletions

View File

@ -11,19 +11,19 @@ type Closure struct {
Static bool Static bool
PhpDocComment string PhpDocComment string
Params []node.Node Params []node.Node
Uses []node.Node ClosureUse *ClosureUse
ReturnType node.Node ReturnType node.Node
Stmts []node.Node Stmts []node.Node
} }
// NewClosure node constructor // NewClosure node constructor
func NewClosure(Params []node.Node, Uses []node.Node, ReturnType node.Node, Stmts []node.Node, Static bool, ReturnsRef bool, PhpDocComment string) *Closure { func NewClosure(Params []node.Node, ClosureUse *ClosureUse, ReturnType node.Node, Stmts []node.Node, Static bool, ReturnsRef bool, PhpDocComment string) *Closure {
return &Closure{ return &Closure{
ReturnsRef, ReturnsRef,
Static, Static,
PhpDocComment, PhpDocComment,
Params, Params,
Uses, ClosureUse,
ReturnType, ReturnType,
Stmts, Stmts,
} }
@ -54,13 +54,9 @@ func (n *Closure) Walk(v walker.Visitor) {
} }
} }
if n.Uses != nil { if n.ClosureUse != nil {
vv := v.GetChildrenVisitor("Uses") vv := v.GetChildrenVisitor("ClosureUse")
for _, nn := range n.Uses { n.ClosureUse.Walk(vv)
if nn != nil {
nn.Walk(vv)
}
}
} }
if n.ReturnType != nil { if n.ReturnType != nil {

View File

@ -7,13 +7,13 @@ import (
// ClosureUse node // ClosureUse node
type ClosureUse struct { type ClosureUse struct {
Variable node.Node Uses []node.Node
} }
// NewClosureUse node constructor // NewClosureUse node constructor
func NewClosureUse(Variable node.Node) *ClosureUse { func NewClosureUse(Uses []node.Node) *ClosureUse {
return &ClosureUse{ return &ClosureUse{
Variable, Uses,
} }
} }
@ -29,9 +29,13 @@ func (n *ClosureUse) Walk(v walker.Visitor) {
return return
} }
if n.Variable != nil { if n.Uses != nil {
vv := v.GetChildrenVisitor("Variable") vv := v.GetChildrenVisitor("Uses")
n.Variable.Walk(vv) for _, nn := range n.Uses {
if nn != nil {
nn.Walk(vv)
}
}
} }
v.LeaveNode(n) v.LeaveNode(n)

View File

@ -24,7 +24,6 @@ func TestClosure(t *testing.T) {
ReturnsRef: false, ReturnsRef: false,
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -64,12 +63,10 @@ func TestClosureUse(t *testing.T) {
Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}}, Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
}, },
}, },
ClosureUse: &expr.ClosureUse{
Uses: []node.Node{ Uses: []node.Node{
&expr.ClosureUse{ &expr.Variable{VarName: &node.Identifier{Value: "c"}},
Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}, &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
},
&expr.ClosureUse{
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
}, },
}, },
Stmts: []node.Node{}, Stmts: []node.Node{},
@ -111,12 +108,10 @@ func TestClosureUse2(t *testing.T) {
Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}}, Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
}, },
}, },
ClosureUse: &expr.ClosureUse{
Uses: []node.Node{ Uses: []node.Node{
&expr.ClosureUse{ &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}},
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}}, &expr.Variable{VarName: &node.Identifier{Value: "d"}},
},
&expr.ClosureUse{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}},
}, },
}, },
Stmts: []node.Node{}, Stmts: []node.Node{},
@ -146,7 +141,6 @@ func TestClosureReturnType(t *testing.T) {
ReturnsRef: false, ReturnsRef: false,
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Uses: []node.Node{},
ReturnType: &name.Name{ ReturnType: &name.Name{
Parts: []node.Node{&name.NamePart{Value: "void"}}, Parts: []node.Node{&name.NamePart{Value: "void"}},
}, },

View File

@ -81,9 +81,11 @@ var nodesToTest = []struct {
}, },
{ {
&expr.ClosureUse{ &expr.ClosureUse{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "a"}}, Uses: []node.Node{
&expr.Variable{VarName: &node.Identifier{Value: "a"}},
}, },
[]string{"Variable"}, },
[]string{"Uses"},
map[string]interface{}{}, map[string]interface{}{},
}, },
{ {
@ -92,11 +94,11 @@ var nodesToTest = []struct {
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Params: []node.Node{&node.Parameter{}}, Params: []node.Node{&node.Parameter{}},
Uses: []node.Node{&expr.ClosureUse{}}, ClosureUse: &expr.ClosureUse{},
ReturnType: &name.Name{}, ReturnType: &name.Name{},
Stmts: []node.Node{&stmt.Nop{}}, Stmts: []node.Node{&stmt.Nop{}},
}, },
[]string{"Params", "Uses", "ReturnType", "Stmts"}, []string{"Params", "ClosureUse", "ReturnType", "Stmts"},
map[string]interface{}{"ReturnsRef": true, "Static": false, "PhpDocComment": ""}, map[string]interface{}{"ReturnsRef": true, "Static": false, "PhpDocComment": ""},
}, },
{ {

View File

@ -298,7 +298,6 @@ func TestPhp7ParameterNode(t *testing.T) {
&stmt.Expression{ &stmt.Expression{
Expr: &expr.Closure{ Expr: &expr.Closure{
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -306,7 +305,6 @@ func TestPhp7ParameterNode(t *testing.T) {
Expr: &expr.Closure{ Expr: &expr.Closure{
Static: true, Static: true,
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -368,7 +366,6 @@ func TestPhp5ParameterNode(t *testing.T) {
&stmt.Expression{ &stmt.Expression{
Expr: &expr.Closure{ Expr: &expr.Closure{
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -376,7 +373,6 @@ func TestPhp5ParameterNode(t *testing.T) {
Expr: &expr.Closure{ Expr: &expr.Closure{
Static: true, Static: true,
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ import (
ClassExtends *stmt.ClassExtends ClassExtends *stmt.ClassExtends
ClassImplements *stmt.ClassImplements ClassImplements *stmt.ClassImplements
InterfaceExtends *stmt.InterfaceExtends InterfaceExtends *stmt.InterfaceExtends
ClosureUse *expr.ClosureUse
} }
%type <token> $unk %type <token> $unk
@ -252,10 +253,11 @@ import (
%type <ClassExtends> extends_from %type <ClassExtends> extends_from
%type <ClassImplements> implements_list %type <ClassImplements> implements_list
%type <InterfaceExtends> interface_extends_list %type <InterfaceExtends> interface_extends_list
%type <ClosureUse> lexical_vars
%type <list> top_statement_list namespace_name use_declarations use_function_declarations use_const_declarations %type <list> top_statement_list namespace_name use_declarations use_function_declarations use_const_declarations
%type <list> inner_statement_list global_var_list static_var_list encaps_list isset_variables non_empty_array_pair_list %type <list> inner_statement_list global_var_list static_var_list encaps_list isset_variables non_empty_array_pair_list
%type <list> array_pair_list assignment_list lexical_var_list lexical_vars elseif_list new_elseif_list non_empty_for_expr %type <list> array_pair_list assignment_list lexical_var_list elseif_list new_elseif_list non_empty_for_expr
%type <list> for_expr case_list echo_expr_list unset_variables declare_list catch_statement additional_catches %type <list> for_expr case_list echo_expr_list unset_variables declare_list catch_statement additional_catches
%type <list> non_empty_additional_catches parameter_list non_empty_parameter_list class_statement_list %type <list> non_empty_additional_catches parameter_list non_empty_parameter_list class_statement_list
%type <list> class_statement_list variable_modifiers method_modifiers class_variable_declaration %type <list> class_statement_list variable_modifiers method_modifiers class_variable_declaration
@ -2589,9 +2591,13 @@ function:
lexical_vars: lexical_vars:
/* empty */ /* empty */
{ $$ = []node.Node{} } { $$ = nil }
| T_USE '(' lexical_var_list ')' | T_USE '(' lexical_var_list ')'
{ $$ = $3; } {
$$ = expr.NewClosureUse($3)
yylex.(*Parser).positions.AddPosition($$, yylex.(*Parser).positionBuilder.NewTokensPosition($1, $4))
}
; ;
lexical_var_list: lexical_var_list:
@ -2605,11 +2611,7 @@ lexical_var_list:
yylex.(*Parser).positions.AddPosition(variable, yylex.(*Parser).positionBuilder.NewTokenPosition($3)) yylex.(*Parser).positions.AddPosition(variable, yylex.(*Parser).positionBuilder.NewTokenPosition($3))
yylex.(*Parser).comments.AddComments(variable, $3.Comments()) yylex.(*Parser).comments.AddComments(variable, $3.Comments())
use := expr.NewClosureUse(variable) $$ = append($1, variable)
yylex.(*Parser).positions.AddPosition(use, yylex.(*Parser).positionBuilder.NewTokenPosition($3))
yylex.(*Parser).comments.AddComments(use, $3.Comments())
$$ = append($1, use)
} }
| lexical_var_list ',' '&' T_VARIABLE | lexical_var_list ',' '&' T_VARIABLE
{ {
@ -2623,11 +2625,7 @@ lexical_var_list:
reference := expr.NewReference(variable) reference := expr.NewReference(variable)
use := expr.NewClosureUse(reference) $$ = append($1, reference)
yylex.(*Parser).positions.AddPosition(use, yylex.(*Parser).positionBuilder.NewTokensPosition($3, $4))
yylex.(*Parser).comments.AddComments(use, $3.Comments())
$$ = append($1, use)
} }
| T_VARIABLE | T_VARIABLE
{ {
@ -2639,11 +2637,7 @@ lexical_var_list:
yylex.(*Parser).positions.AddPosition(variable, yylex.(*Parser).positionBuilder.NewTokenPosition($1)) yylex.(*Parser).positions.AddPosition(variable, yylex.(*Parser).positionBuilder.NewTokenPosition($1))
yylex.(*Parser).comments.AddComments(variable, $1.Comments()) yylex.(*Parser).comments.AddComments(variable, $1.Comments())
use := expr.NewClosureUse(variable) $$ = []node.Node{variable}
yylex.(*Parser).positions.AddPosition(use, yylex.(*Parser).positionBuilder.NewTokenPosition($1))
yylex.(*Parser).comments.AddComments(use, $1.Comments())
$$ = []node.Node{use}
} }
| '&' T_VARIABLE | '&' T_VARIABLE
{ {
@ -2657,11 +2651,7 @@ lexical_var_list:
reference := expr.NewReference(variable) reference := expr.NewReference(variable)
use := expr.NewClosureUse(reference) $$ = []node.Node{reference}
yylex.(*Parser).positions.AddPosition(use, yylex.(*Parser).positionBuilder.NewTokensPosition($1, $2))
yylex.(*Parser).comments.AddComments(use, $1.Comments())
$$ = []node.Node{use}
} }
; ;

View File

@ -523,7 +523,6 @@ func TestPhp5(t *testing.T) {
&stmt.Expression{ &stmt.Expression{
Expr: &expr.Closure{ Expr: &expr.Closure{
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -531,7 +530,6 @@ func TestPhp5(t *testing.T) {
Expr: &expr.Closure{ Expr: &expr.Closure{
Static: true, Static: true,
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -1987,7 +1985,6 @@ func TestPhp5(t *testing.T) {
ReturnsRef: false, ReturnsRef: false,
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -2008,12 +2005,10 @@ func TestPhp5(t *testing.T) {
Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}}, Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
}, },
}, },
ClosureUse: &expr.ClosureUse{
Uses: []node.Node{ Uses: []node.Node{
&expr.ClosureUse{ &expr.Variable{VarName: &node.Identifier{Value: "c"}},
Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}, &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
},
&expr.ClosureUse{
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
}, },
}, },
Stmts: []node.Node{}, Stmts: []node.Node{},
@ -2036,12 +2031,10 @@ func TestPhp5(t *testing.T) {
Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}}, Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
}, },
}, },
ClosureUse: &expr.ClosureUse{
Uses: []node.Node{ Uses: []node.Node{
&expr.ClosureUse{ &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}},
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}}, &expr.Variable{VarName: &node.Identifier{Value: "d"}},
},
&expr.ClosureUse{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}},
}, },
}, },
Stmts: []node.Node{}, Stmts: []node.Node{},
@ -2052,7 +2045,6 @@ func TestPhp5(t *testing.T) {
ReturnsRef: false, ReturnsRef: false,
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ import (
ClassExtends *stmt.ClassExtends ClassExtends *stmt.ClassExtends
ClassImplements *stmt.ClassImplements ClassImplements *stmt.ClassImplements
InterfaceExtends *stmt.InterfaceExtends InterfaceExtends *stmt.InterfaceExtends
ClosureUse *expr.ClosureUse
} }
%type <token> $unk %type <token> $unk
@ -271,6 +272,7 @@ import (
%type <ClassExtends> extends_from %type <ClassExtends> extends_from
%type <ClassImplements> implements_list %type <ClassImplements> implements_list
%type <InterfaceExtends> interface_extends_list %type <InterfaceExtends> interface_extends_list
%type <ClosureUse> lexical_vars
%type <node> member_modifier %type <node> member_modifier
%type <node> use_type %type <node> use_type
@ -281,7 +283,7 @@ import (
%type <list> const_list echo_expr_list for_exprs non_empty_for_exprs global_var_list %type <list> const_list echo_expr_list for_exprs non_empty_for_exprs global_var_list
%type <list> unprefixed_use_declarations inline_use_declarations property_list static_var_list %type <list> unprefixed_use_declarations inline_use_declarations property_list static_var_list
%type <list> case_list trait_adaptation_list unset_variables %type <list> case_list trait_adaptation_list unset_variables
%type <list> use_declarations lexical_var_list lexical_vars isset_variables non_empty_array_pair_list %type <list> use_declarations lexical_var_list isset_variables non_empty_array_pair_list
%type <list> array_pair_list non_empty_argument_list top_statement_list %type <list> array_pair_list non_empty_argument_list top_statement_list
%type <list> inner_statement_list parameter_list non_empty_parameter_list class_statement_list %type <list> inner_statement_list parameter_list non_empty_parameter_list class_statement_list
%type <list> method_modifiers variable_modifiers %type <list> method_modifiers variable_modifiers
@ -3246,9 +3248,19 @@ returns_ref:
lexical_vars: lexical_vars:
/* empty */ /* empty */
{ $$ = []node.Node{} } { $$ = nil }
| T_USE '(' lexical_var_list ')' | T_USE '(' lexical_var_list ')'
{ $$ = $3; } {
$$ = expr.NewClosureUse($3)
// save position
yylex.(*Parser).positions.AddPosition($$, yylex.(*Parser).positionBuilder.NewTokensPosition($1, $4))
// save comments
yylex.(*Parser).comments.AddFromToken($$, $1, comment.UseToken)
yylex.(*Parser).comments.AddFromToken($$, $2, comment.OpenParenthesisToken)
yylex.(*Parser).comments.AddFromToken($$, $4, comment.CloseParenthesisToken)
}
; ;
lexical_var_list: lexical_var_list:
@ -3267,23 +3279,20 @@ lexical_var:
T_VARIABLE T_VARIABLE
{ {
identifier := node.NewIdentifier(strings.TrimLeft($1.Value, "$")) identifier := node.NewIdentifier(strings.TrimLeft($1.Value, "$"))
variable := expr.NewVariable(identifier) $$ = expr.NewVariable(identifier)
$$ = expr.NewClosureUse(variable)
// save position // save position
yylex.(*Parser).positions.AddPosition(identifier, yylex.(*Parser).positionBuilder.NewTokenPosition($1)) yylex.(*Parser).positions.AddPosition(identifier, yylex.(*Parser).positionBuilder.NewTokenPosition($1))
yylex.(*Parser).positions.AddPosition(variable, yylex.(*Parser).positionBuilder.NewTokenPosition($1))
yylex.(*Parser).positions.AddPosition($$, yylex.(*Parser).positionBuilder.NewTokenPosition($1)) yylex.(*Parser).positions.AddPosition($$, yylex.(*Parser).positionBuilder.NewTokenPosition($1))
// save comments // save comments
yylex.(*Parser).comments.AddFromToken(variable, $1, comment.VariableToken) yylex.(*Parser).comments.AddFromToken($$, $1, comment.VariableToken)
} }
| '&' T_VARIABLE | '&' T_VARIABLE
{ {
identifier := node.NewIdentifier(strings.TrimLeft($2.Value, "$")) identifier := node.NewIdentifier(strings.TrimLeft($2.Value, "$"))
variable := expr.NewVariable(identifier) variable := expr.NewVariable(identifier)
reference := expr.NewReference(variable) $$ = expr.NewReference(variable)
$$ = expr.NewClosureUse(reference)
// save position // save position
yylex.(*Parser).positions.AddPosition(identifier, yylex.(*Parser).positionBuilder.NewTokenPosition($2)) yylex.(*Parser).positions.AddPosition(identifier, yylex.(*Parser).positionBuilder.NewTokenPosition($2))
@ -3292,7 +3301,7 @@ lexical_var:
// save comments // save comments
yylex.(*Parser).comments.AddFromToken($$, $1, comment.AmpersandToken) yylex.(*Parser).comments.AddFromToken($$, $1, comment.AmpersandToken)
yylex.(*Parser).comments.AddFromToken(reference, $2, comment.VariableToken) yylex.(*Parser).comments.AddFromToken(variable, $2, comment.VariableToken)
} }
; ;

View File

@ -558,7 +558,6 @@ func TestPhp7(t *testing.T) {
&stmt.Expression{ &stmt.Expression{
Expr: &expr.Closure{ Expr: &expr.Closure{
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -566,7 +565,6 @@ func TestPhp7(t *testing.T) {
Expr: &expr.Closure{ Expr: &expr.Closure{
Static: true, Static: true,
Params: expectedParams, Params: expectedParams,
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -2118,7 +2116,6 @@ func TestPhp7(t *testing.T) {
ReturnsRef: false, ReturnsRef: false,
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Uses: []node.Node{},
Stmts: []node.Node{}, Stmts: []node.Node{},
}, },
}, },
@ -2139,12 +2136,10 @@ func TestPhp7(t *testing.T) {
Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}}, Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
}, },
}, },
ClosureUse: &expr.ClosureUse{
Uses: []node.Node{ Uses: []node.Node{
&expr.ClosureUse{ &expr.Variable{VarName: &node.Identifier{Value: "c"}},
Variable: &expr.Variable{VarName: &node.Identifier{Value: "c"}}, &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
},
&expr.ClosureUse{
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
}, },
}, },
Stmts: []node.Node{}, Stmts: []node.Node{},
@ -2155,7 +2150,6 @@ func TestPhp7(t *testing.T) {
ReturnsRef: false, ReturnsRef: false,
Static: false, Static: false,
PhpDocComment: "", PhpDocComment: "",
Uses: []node.Node{},
ReturnType: &name.Name{ ReturnType: &name.Name{
Parts: []node.Node{&name.NamePart{Value: "void"}}, Parts: []node.Node{&name.NamePart{Value: "void"}},
}, },

View File

@ -1006,7 +1006,10 @@ func (p *Printer) printExprClone(n node.Node) {
func (p *Printer) printExprClosureUse(n node.Node) { func (p *Printer) printExprClosureUse(n node.Node) {
nn := n.(*expr.ClosureUse) nn := n.(*expr.ClosureUse)
p.Print(nn.Variable)
io.WriteString(p.w, "use (")
p.joinPrint(", ", nn.Uses)
io.WriteString(p.w, ")")
} }
func (p *Printer) printExprClosure(n node.Node) { func (p *Printer) printExprClosure(n node.Node) {
@ -1026,10 +1029,9 @@ func (p *Printer) printExprClosure(n node.Node) {
p.joinPrint(", ", nn.Params) p.joinPrint(", ", nn.Params)
io.WriteString(p.w, ")") io.WriteString(p.w, ")")
if nn.Uses != nil { if nn.ClosureUse != nil {
io.WriteString(p.w, " use (") io.WriteString(p.w, " ")
p.joinPrint(", ", nn.Uses) p.Print(nn.ClosureUse)
io.WriteString(p.w, ")")
} }
if nn.ReturnType != nil { if nn.ReturnType != nil {

View File

@ -1371,10 +1371,13 @@ func TestPrintExprClosureUse(t *testing.T) {
p := printer.NewPrinter(o, " ") p := printer.NewPrinter(o, " ")
p.Print(&expr.ClosureUse{ p.Print(&expr.ClosureUse{
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}}}, Uses: []node.Node{
&expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "foo"}}},
&expr.Variable{VarName: &node.Identifier{Value: "bar"}},
},
}) })
expected := `&$var` expected := `use (&$foo, $bar)`
actual := o.String() actual := o.String()
if expected != actual { if expected != actual {
@ -1398,12 +1401,10 @@ func TestPrintExprClosure(t *testing.T) {
Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}}, Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
}, },
}, },
ClosureUse: &expr.ClosureUse{
Uses: []node.Node{ Uses: []node.Node{
&expr.ClosureUse{ &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "a"}}}, &expr.Variable{VarName: &node.Identifier{Value: "b"}},
},
&expr.ClosureUse{
Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
}, },
}, },
ReturnType: &name.FullyQualified{Parts: []node.Node{&name.NamePart{Value: "Foo"}}}, ReturnType: &name.FullyQualified{Parts: []node.Node{&name.NamePart{Value: "Foo"}}},