diff --git a/src/ast.js b/src/ast.js index a78c6cb79..ba287c8c0 100644 --- a/src/ast.js +++ b/src/ast.js @@ -46,6 +46,7 @@ const Position = require("./ast/position"); * - [Exit](#exit) * - [Clone](#clone) * - [Assign](#assign) + * - [AssignRef](#assignref) * - [Array](#array) * - [List](#list) * - [Variable](#variable) @@ -458,6 +459,7 @@ AST.prototype.checkNodes = function() { [ require("./ast/array"), require("./ast/assign"), + require("./ast/assignref"), require("./ast/bin"), require("./ast/block"), require("./ast/boolean"), diff --git a/src/ast/assign.js b/src/ast/assign.js index 1a77582e0..0d8050398 100644 --- a/src/ast/assign.js +++ b/src/ast/assign.js @@ -24,7 +24,7 @@ module.exports = Expression.extends(KIND, function Assign( location ) { Expression.apply(this, [KIND, docs, location]); - this.operator = operator; this.left = left; this.right = right; + this.operator = operator; }); diff --git a/src/ast/assignref.js b/src/ast/assignref.js new file mode 100644 index 000000000..cde820f20 --- /dev/null +++ b/src/ast/assignref.js @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "assignref"; + +/** + * Assigns a value to the specified target + * @constructor Assign + * @extends {Expression} + * @property {Expression} left + * @property {Expression} right + * @property {String} operator + */ +module.exports = Expression.extends(KIND, function AssignRef( + left, + right, + docs, + location +) { + Expression.apply(this, [KIND, docs, location]); + this.left = left; + this.right = right; +}); diff --git a/src/parser/expr.js b/src/parser/expr.js index 250a2fa7d..721a95fb1 100644 --- a/src/parser/expr.js +++ b/src/parser/expr.js @@ -354,21 +354,19 @@ module.exports = { if (isConst) this.error("VARIABLE"); let right; if (this.next().token == "&") { - right = this.read_byref( - function() { - if (this.token === this.tok.T_NEW) { - if (this.php7) { - this.error(); - } - return this.read_new_expr(); - } else { - return this.read_variable(false, false); - } - }.bind(this) - ); - } else { - right = this.read_expr(); + this.next(); + if (this.token === this.tok.T_NEW) { + if (this.php7) { + this.error(); + } + right = this.read_new_expr(); + } else { + right = this.read_variable(false, false); + } + + return result("assignref", expr, right); } + right = this.read_expr(); return result("assign", expr, right, "="); } diff --git a/test/snapshot/__snapshots__/assign.test.js.snap b/test/snapshot/__snapshots__/assign.test.js.snap index 28c9e3f46..2bb47f92c 100644 --- a/test/snapshot/__snapshots__/assign.test.js.snap +++ b/test/snapshot/__snapshots__/assign.test.js.snap @@ -402,16 +402,14 @@ exports[`assign with ref 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "bar", }, - "operator": "=", "right": Variable { - "byref": true, "curly": false, "kind": "variable", "name": "foo", diff --git a/test/snapshot/__snapshots__/byref.test.js.snap b/test/snapshot/__snapshots__/byref.test.js.snap index b0a79c975..b839867a1 100644 --- a/test/snapshot/__snapshots__/byref.test.js.snap +++ b/test/snapshot/__snapshots__/byref.test.js.snap @@ -4,14 +4,13 @@ exports[`byref call result 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "a", }, - "operator": "=", "right": Call { "arguments": Array [ Variable { @@ -21,7 +20,6 @@ Program { "name": "b", }, ], - "byref": true, "kind": "call", "what": ClassReference { "kind": "classreference", @@ -42,16 +40,14 @@ exports[`byref callable variable #2 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": Variable { - "byref": true, "curly": true, "kind": "variable", "name": Variable { @@ -73,16 +69,14 @@ exports[`byref callable variable #3 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": Variable { - "byref": true, "curly": false, "kind": "variable", "name": Variable { @@ -108,16 +102,14 @@ exports[`byref callable variable #4 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": OffsetLookup { - "byref": true, "kind": "offsetlookup", "offset": Variable { "curly": false, @@ -143,16 +135,14 @@ exports[`byref callable variable #5 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": OffsetLookup { - "byref": true, "kind": "offsetlookup", "offset": Variable { "curly": false, @@ -178,16 +168,14 @@ exports[`byref callable variable #6 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": OffsetLookup { - "byref": true, "kind": "offsetlookup", "offset": Variable { "curly": false, @@ -221,17 +209,15 @@ exports[`byref callable variable #7 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": Call { "arguments": Array [], - "byref": true, "kind": "call", "what": PropertyLookup { "kind": "propertylookup", @@ -259,17 +245,15 @@ exports[`byref callable variable #8 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": Call { "arguments": Array [], - "byref": true, "kind": "call", "what": ClassReference { "kind": "classreference", @@ -290,16 +274,14 @@ exports[`byref callable variable 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": Variable { - "byref": true, "curly": false, "kind": "variable", "name": "var", @@ -498,17 +480,15 @@ exports[`byref new class 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "a", }, - "operator": "=", "right": New { "arguments": Array [], - "byref": true, "kind": "new", "what": ClassReference { "kind": "classreference", @@ -555,16 +535,14 @@ exports[`byref propertylookup 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": PropertyLookup { - "byref": true, "kind": "propertylookup", "offset": Identifier { "kind": "identifier", @@ -607,16 +585,14 @@ exports[`byref static lookup 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": false, @@ -642,16 +618,14 @@ exports[`byref staticlookup #2 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": true, @@ -681,16 +655,14 @@ exports[`byref staticlookup #3 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": false, @@ -724,16 +696,14 @@ exports[`byref staticlookup #4 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": false, @@ -759,16 +729,14 @@ exports[`byref staticlookup #5 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": true, @@ -798,16 +766,14 @@ exports[`byref staticlookup #6 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": false, @@ -841,16 +807,14 @@ exports[`byref staticlookup 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": StaticLookup { - "byref": true, "kind": "staticlookup", "offset": Variable { "curly": false, @@ -876,16 +840,14 @@ exports[`byref variable 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "var", }, - "operator": "=", "right": Variable { - "byref": true, "curly": false, "kind": "variable", "name": "foo", @@ -903,16 +865,14 @@ exports[`byref variable 2`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "a", }, - "operator": "=", "right": Variable { - "byref": true, "curly": false, "kind": "variable", "name": "var", @@ -962,3 +922,70 @@ Program { "kind": "program", } `; + +exports[`byref with bin #2 1`] = ` +Program { + "children": Array [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "right": Number { + "kind": "number", + "value": "1", + }, + "type": "+", + }, + "kind": "expressionstatement", + }, + ], + "errors": Array [], + "kind": "program", +} +`; + +exports[`byref with bin 1`] = ` +Program { + "children": Array [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "||", + }, + "kind": "expressionstatement", + }, + ], + "errors": Array [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/location.test.js.snap b/test/snapshot/__snapshots__/location.test.js.snap index 0464c287b..bad31dd8c 100644 --- a/test/snapshot/__snapshots__/location.test.js.snap +++ b/test/snapshot/__snapshots__/location.test.js.snap @@ -1684,6 +1684,96 @@ Program { } `; +exports[`Test locations assign by ref 1`] = ` +Program { + "children": Array [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var = &$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var = &$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": Array [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var = &$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + exports[`Test locations assign mutliple 1`] = ` Program { "children": Array [ diff --git a/test/snapshot/__snapshots__/new.test.js.snap b/test/snapshot/__snapshots__/new.test.js.snap index 618baa8b7..74990b872 100644 --- a/test/snapshot/__snapshots__/new.test.js.snap +++ b/test/snapshot/__snapshots__/new.test.js.snap @@ -4,17 +4,15 @@ exports[`new #348 - byref usage deprecated 1`] = ` Program { "children": Array [ ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "a", }, - "operator": "=", "right": New { "arguments": Array [], - "byref": true, "kind": "new", "what": ClassReference { "kind": "classreference", diff --git a/test/snapshot/__snapshots__/variable.test.js.snap b/test/snapshot/__snapshots__/variable.test.js.snap index 2d73e0e8f..a643a0fcf 100644 --- a/test/snapshot/__snapshots__/variable.test.js.snap +++ b/test/snapshot/__snapshots__/variable.test.js.snap @@ -788,16 +788,14 @@ Program { "kind": "expressionstatement", }, ExpressionStatement { - "expression": Assign { - "kind": "assign", + "expression": AssignRef { + "kind": "assignref", "left": Variable { "curly": false, "kind": "variable", "name": "b", }, - "operator": "=", "right": Variable { - "byref": true, "curly": false, "kind": "variable", "name": "c", diff --git a/test/snapshot/byref.test.js b/test/snapshot/byref.test.js index d6ac4674b..9f8bdf4d9 100644 --- a/test/snapshot/byref.test.js +++ b/test/snapshot/byref.test.js @@ -101,4 +101,10 @@ describe('byref', () => { it('closure', () => { expect(parser.parseEval('$var = function () use (&$message) { };')).toMatchSnapshot(); }); + it('with bin', () => { + expect(parser.parseEval('$foo = &$bar || $bar;')).toMatchSnapshot(); + }); + it('with bin #2', () => { + expect(parser.parseEval('$foo = &$bar + 1;')).toMatchSnapshot(); + }); }); diff --git a/test/snapshot/location.test.js b/test/snapshot/location.test.js index 8fc0bda19..106ba94b7 100644 --- a/test/snapshot/location.test.js +++ b/test/snapshot/location.test.js @@ -542,6 +542,16 @@ describe("Test locations", function() { }) ).toMatchSnapshot(); }); + it("assign by ref", function() { + expect( + parser.parseEval("$var = &$var;", { + ast: { + withPositions: true, + withSource: true + } + }) + ).toMatchSnapshot(); + }); it("assign mutliple", function() { expect( parser.parseEval("$var = $other = true;", {