package php7_test import ( "testing" "gotest.tools/assert" "github.com/z7zmey/php-parser/internal/php7" "github.com/z7zmey/php-parser/internal/scanner" "github.com/z7zmey/php-parser/pkg/ast" "github.com/z7zmey/php-parser/pkg/ast/traverser" "github.com/z7zmey/php-parser/pkg/ast/visitor" "github.com/z7zmey/php-parser/pkg/position" ) 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 := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 9, StartPos: 6, EndPos: 186, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 21, }, }, Expr: &ast.ExprFunctionCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 20, }, }, Function: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, }, Value: []byte("foo"), }, }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 9, EndPos: 20, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 14, EndPos: 19, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 40, }, }, Expr: &ast.ExprFunctionCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 39, }, }, Function: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, }, Value: []byte("$foo"), }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 28, EndPos: 39, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 33, EndPos: 38, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 64, }, }, Expr: &ast.ExprMethodCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 63, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, }, Value: []byte("$foo"), }, }, Method: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 49, EndPos: 52, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 63, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, }, IsReference: false, Variadic: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 57, EndPos: 62, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 87, }, }, Expr: &ast.ExprStaticCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 86, }, }, Class: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, }, Value: []byte("foo"), }, }, }, Call: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 72, EndPos: 75, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 86, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 80, EndPos: 85, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 111, }, }, Expr: &ast.ExprStaticCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 110, }, }, Class: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, }, Value: []byte("$foo"), }, }, Call: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 96, EndPos: 99, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 110, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 104, EndPos: 109, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 133, }, }, Expr: &ast.ExprNew{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 132, }, }, Class: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, }, Value: []byte("foo"), }, }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 132, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 126, EndPos: 131, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 161, EndPos: 186, }, }, Expr: &ast.ExprNew{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 161, EndPos: 185, }, }, Class: &ast.StmtClass{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 165, EndPos: 185, }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 171, EndPos: 182, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 174, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 174, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 172, EndPos: 174, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 176, EndPos: 181, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 179, EndPos: 181, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 9, EndLine: 9, StartPos: 179, EndPos: 181, }, }, Value: []byte("$b"), }, }, }, }, }, Stmts: []ast.Vertex{}, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestPhp7ParameterNode(t *testing.T) { src := `bar()";` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, }, Expr: &ast.ScalarEncapsed{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, }, Parts: []ast.Vertex{ &ast.ScalarEncapsedStringPart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 9, }, }, Value: []byte("test "), }, &ast.ExprPropertyFetch{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 18, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 13, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 13, }, }, Value: []byte("$foo"), }, }, Property: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Value: []byte("bar"), }, }, &ast.ScalarEncapsedStringPart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("()"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestScalarEncapsed_DollarOpenCurlyBraces(t *testing.T) { src := `bar()}";` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 24, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 24, }, }, Expr: &ast.ScalarEncapsed{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 23, }, }, Parts: []ast.Vertex{ &ast.ScalarEncapsedStringPart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 9, }, }, Value: []byte("test "), }, &ast.ExprMethodCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 21, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 14, }, }, Value: []byte("$foo"), }, }, Method: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 19, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 19, EndPos: 21, }, }, }, }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestScalarHeredoc_HeredocSimpleLabel(t *testing.T) { src := ` $v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, Value: []byte("$v"), }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 30, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestStmtForeach_ExprWithKey(t *testing.T) { src := ` $v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Expr: &ast.ExprShortArray{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Items: []ast.Vertex{}, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, Value: []byte("$v"), }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 30, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestStmtForeach_WithRef(t *testing.T) { src := ` &$v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 27, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, Value: []byte("$v"), }, }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestStmtForeach_WithList(t *testing.T) { src := ` list($v)) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 36, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 36, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 32, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Val: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Value: []byte("$v"), }, }, }, }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 34, EndPos: 36, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestStmtFunction(t *testing.T) { src := `
` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Stmts: []ast.Vertex{ &ast.StmtNop{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, }, &ast.StmtInlineHtml{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 5, EndPos: 17, }, }, Value: []byte("
"), }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestStmtInterface(t *testing.T) { src := `1, &$b,);` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, }, Expr: &ast.ExprArray{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 20, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 13, }, }, Key: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 10, }, }, Value: []byte("1"), }, Val: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 13, }, }, Value: []byte("1"), }, }, &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Val: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, }, Value: []byte("$b"), }, }, }, }, &ast.ExprArrayItem{}, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprArray_ItemUnpack(t *testing.T) { src := ` $a;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 14, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 14, }, }, Expr: &ast.ExprArrowFunction{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, ReturnsRef: false, Static: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, Value: []byte("$a"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprArrowFunction_ReturnType(t *testing.T) { src := ` $a;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 23, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 23, }, }, Expr: &ast.ExprArrowFunction{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, }, Static: false, ReturnsRef: true, ReturnType: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 13, EndPos: 16, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 13, EndPos: 16, }, }, Value: []byte("foo"), }, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 22, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 22, }, }, Value: []byte("$a"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprBitwiseNot(t *testing.T) { src := `foo();` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Expr: &ast.ExprMethodCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Method: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, }, Value: []byte("foo"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprNew(t *testing.T) { src := `foo;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Expr: &ast.ExprPropertyFetch{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Property: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, }, Value: []byte("foo"), }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprReference_ForeachWithRef(t *testing.T) { t.Helper() src := ` &$v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 27, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, Value: []byte("$v"), }, }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprShellExec(t *testing.T) { src := "1, &$b,];` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, }, Expr: &ast.ExprShortArray{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 15, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 8, }, }, Key: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 5, }, }, Value: []byte("1"), }, Val: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 8, }, }, Value: []byte("1"), }, }, &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 13, }, }, Val: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 13, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, Value: []byte("$b"), }, }, }, }, &ast.ExprArrayItem{}, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprShortList(t *testing.T) { src := ` $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 18, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 18, }, }, Expr: &ast.ExprYield{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$a"), }, }, Value: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprYield_Expr(t *testing.T) { src := ` 1;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Expr: &ast.ExprYield{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$a"), }, }, Value: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 16, }, }, Value: []byte("1"), }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprYieldFrom(t *testing.T) { src := `>= $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Expr: &ast.ExprAssignShiftRight{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprAssign_Coalesce(t *testing.T) { src := `= $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Expr: &ast.ExprBinaryGreaterOrEqual{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprBinary_Greater(t *testing.T) { src := ` $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Expr: &ast.ExprBinaryGreater{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 8, EndPos: 10, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 8, EndPos: 10, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprBinary_Identical(t *testing.T) { src := `> $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Expr: &ast.ExprBinaryShiftRight{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } func TestExprBinary_SmallerOrEqual(t *testing.T) { src := ` $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Expr: &ast.ExprBinarySpaceship{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "7.4", false, nil) php7parser := php7.NewParser(lexer, nil) php7parser.Parse() actual := php7parser.GetRootNode() traverser.NewDFS(new(visitor.FilterParserNodes)).Traverse(actual) assert.DeepEqual(t, expected, actual) } // expr cast func TestExprCast_Array(t *testing.T) { src := `