package node_test import ( "testing" "gotest.tools/assert" "github.com/z7zmey/php-parser/node/name" "github.com/z7zmey/php-parser/position" "github.com/z7zmey/php-parser/node/expr" "github.com/z7zmey/php-parser/node" "github.com/z7zmey/php-parser/node/stmt" "github.com/z7zmey/php-parser/php5" "github.com/z7zmey/php-parser/php7" ) func TestIdentifier(t *testing.T) { src := `bar($a, ...$b); foo::bar($a, ...$b); $foo::bar($a, ...$b); new foo($a, ...$b); /** anonymous class */ new class ($a, ...$b) {}; ` expected := &node.Root{ Position: &position.Position{ StartLine: 2, EndLine: 9, StartPos: 6, EndPos: 186, }, Stmts: []node.Node{ &stmt.Expression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 21, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 20, }, Function: &name.Name{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 9, EndPos: 20, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 14, EndPos: 19, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 40, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 39, }, Function: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, Value: "foo", }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 28, EndPos: 39, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 33, EndPos: 38, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 64, }, Expr: &expr.MethodCall{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 63, }, Variable: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, Value: "foo", }, }, Method: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 49, EndPos: 52, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 63, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, IsReference: false, Variadic: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 57, EndPos: 62, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 87, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 86, }, Class: &name.Name{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, Value: "foo", }, }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 72, EndPos: 75, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 86, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 80, EndPos: 85, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 111, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 110, }, Class: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, Value: "foo", }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 96, EndPos: 99, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 110, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 104, EndPos: 109, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 133, }, Expr: &expr.New{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 132, }, Class: &name.Name{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 132, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 126, EndPos: 131, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 161, EndPos: 186, }, Expr: &expr.New{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 161, EndPos: 185, }, Class: &stmt.Class{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 165, EndPos: 185, }, PhpDocComment: "/** anonymous class */", ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 171, EndPos: 182, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 174, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 174, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 174, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 176, EndPos: 181, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 179, EndPos: 181, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 179, EndPos: 181, }, Value: "b", }, }, }, }, }, Stmts: []node.Node{}, }, }, }, }, } php7parser := php7.NewParser([]byte(src), "7.4") php7parser.Parse() actual := php7parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestPhp5ArgumentNode(t *testing.T) { src := `bar($a, ...$b); foo::bar($a, ...$b); $foo::bar($a, ...$b); new foo($a, ...$b); ` expected := &node.Root{ Position: &position.Position{ StartLine: 2, EndLine: 7, StartPos: 6, EndPos: 133, }, Stmts: []node.Node{ &stmt.Expression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 21, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 20, }, Function: &name.Name{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 9, EndPos: 20, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 14, EndPos: 19, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 40, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 39, }, Function: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, Value: "foo", }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 28, EndPos: 39, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 33, EndPos: 38, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 64, }, Expr: &expr.MethodCall{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 63, }, Variable: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, Value: "foo", }, }, Method: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 49, EndPos: 52, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 63, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 57, EndPos: 62, }, IsReference: false, Variadic: true, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 87, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 86, }, Class: &name.Name{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, Value: "foo", }, }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 72, EndPos: 75, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 86, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 80, EndPos: 85, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 111, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 110, }, Class: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, Value: "foo", }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 96, EndPos: 99, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 110, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 104, EndPos: 109, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 133, }, Expr: &expr.New{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 132, }, Class: &name.Name{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 132, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 126, EndPos: 131, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, Value: "b", }, }, }, }, }, }, }, }, } php5parser := php5.NewParser([]byte(src), "5.6") php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestPhp7ParameterNode(t *testing.T) { src := `