package node_test import ( "bytes" "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: 7, EndPos: 186, }, Stmts: []node.Node{ &stmt.Expression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 21, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 20, }, Function: &name.Name{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 9, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 9, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 20, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 11, EndPos: 12, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 11, EndPos: 12, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 11, EndPos: 12, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 15, EndPos: 19, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 18, EndPos: 19, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 18, EndPos: 19, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 40, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 39, }, Function: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 28, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 28, }, Value: "foo", }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 39, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 30, EndPos: 31, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 30, EndPos: 31, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 30, EndPos: 31, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 34, EndPos: 38, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 37, EndPos: 38, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 37, EndPos: 38, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 64, }, Expr: &expr.MethodCall{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 63, }, Variable: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 47, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 47, }, Value: "foo", }, }, Method: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 50, EndPos: 52, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 63, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, IsReference: false, Variadic: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 58, EndPos: 62, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 61, EndPos: 62, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 61, EndPos: 62, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 87, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 86, }, Class: &name.Name{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 70, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 70, }, Value: "foo", }, }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 73, EndPos: 75, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 86, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 81, EndPos: 85, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 84, EndPos: 85, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 84, EndPos: 85, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 111, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 110, }, Class: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 94, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 94, }, Value: "foo", }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 97, EndPos: 99, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 110, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 105, EndPos: 109, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 108, EndPos: 109, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 108, EndPos: 109, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 115, EndPos: 133, }, Expr: &expr.New{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 115, EndPos: 132, }, Class: &name.Name{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 119, EndPos: 121, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 119, EndPos: 121, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 132, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 127, EndPos: 131, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 130, EndPos: 131, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 130, EndPos: 131, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 162, EndPos: 186, }, Expr: &expr.New{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 162, EndPos: 185, }, Class: &stmt.Class{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 166, EndPos: 185, }, PhpDocComment: "/** anonymous class */", ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 182, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 173, EndPos: 174, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 173, EndPos: 174, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 173, EndPos: 174, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 177, EndPos: 181, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 180, EndPos: 181, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 180, EndPos: 181, }, Value: "b", }, }, }, }, }, Stmts: []node.Node{}, }, }, }, }, } php7parser := php7.NewParser(bytes.NewBufferString(src), "test.php") 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: 7, EndPos: 133, }, Stmts: []node.Node{ &stmt.Expression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 21, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 20, }, Function: &name.Name{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 9, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 7, EndPos: 9, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 20, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 11, EndPos: 12, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 11, EndPos: 12, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 11, EndPos: 12, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 15, EndPos: 19, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 18, EndPos: 19, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 18, EndPos: 19, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 40, }, Expr: &expr.FunctionCall{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 39, }, Function: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 28, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 25, EndPos: 28, }, Value: "foo", }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 39, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 30, EndPos: 31, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 30, EndPos: 31, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 30, EndPos: 31, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 34, EndPos: 38, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 37, EndPos: 38, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 37, EndPos: 38, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 64, }, Expr: &expr.MethodCall{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 63, }, Variable: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 47, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 44, EndPos: 47, }, Value: "foo", }, }, Method: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 50, EndPos: 52, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 63, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 58, EndPos: 62, }, IsReference: false, Variadic: true, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 61, EndPos: 62, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 61, EndPos: 62, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 87, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 86, }, Class: &name.Name{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 70, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 68, EndPos: 70, }, Value: "foo", }, }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 73, EndPos: 75, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 86, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 81, EndPos: 85, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 84, EndPos: 85, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 84, EndPos: 85, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 111, }, Expr: &expr.StaticCall{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 110, }, Class: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 94, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 91, EndPos: 94, }, Value: "foo", }, }, Call: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 97, EndPos: 99, }, Value: "bar", }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 110, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 105, EndPos: 109, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 108, EndPos: 109, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 108, EndPos: 109, }, Value: "b", }, }, }, }, }, }, }, &stmt.Expression{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 115, EndPos: 133, }, Expr: &expr.New{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 115, EndPos: 132, }, Class: &name.Name{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 119, EndPos: 121, }, Parts: []node.Node{ &name.NamePart{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 119, EndPos: 121, }, Value: "foo", }, }, }, ArgumentList: &node.ArgumentList{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 132, }, Arguments: []node.Node{ &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, Variadic: false, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, Value: "a", }, }, }, &node.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 127, EndPos: 131, }, Variadic: true, IsReference: false, Expr: &expr.Variable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 130, EndPos: 131, }, VarName: &node.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 130, EndPos: 131, }, Value: "b", }, }, }, }, }, }, }, }, } php5parser := php5.NewParser(bytes.NewBufferString(src), "test.php") php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestPhp7ParameterNode(t *testing.T) { src := `