Skip to content

Commit 74ba6f4

Browse files
jorgsowaczosel
authored andcommitted
fix: nullsafe operator parenthesized
1 parent 78d0127 commit 74ba6f4

3 files changed

Lines changed: 203 additions & 4 deletions

File tree

src/parser/expr.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ module.exports = {
114114
}
115115
}
116116

117+
if (this.token === this.tok.T_NULLSAFE_OBJECT_OPERATOR) {
118+
expr = result("nullsafepropertylookup", expr, this.read_what());
119+
expr = this.recursive_variable_chain_scan(expr, false, true);
120+
}
121+
117122
// extra operations :
118123
// $username = $_GET['user'] ?? 'nobody';
119124
if (this.token === this.tok.T_COALESCE) {
@@ -842,7 +847,8 @@ module.exports = {
842847
while (this.token !== this.EOF) {
843848
if (
844849
this.token === this.tok.T_OBJECT_OPERATOR ||
845-
this.token === this.tok.T_DOUBLE_COLON
850+
this.token === this.tok.T_DOUBLE_COLON ||
851+
this.token === this.tok.T_NULLSAFE_OBJECT_OPERATOR
846852
) {
847853
expr = this.recursive_variable_chain_scan(expr, false, false, true);
848854
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {

test/snapshot/__snapshots__/call.test.js.snap

Lines changed: 165 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,84 @@ Program {
10841084
}
10851085
`;
10861086

1087+
exports[`Test call nullsafepropertylookup (1) 1`] = `
1088+
Program {
1089+
"children": [
1090+
ExpressionStatement {
1091+
"expression": Call {
1092+
"arguments": [],
1093+
"kind": "call",
1094+
"what": NullSafePropertyLookup {
1095+
"kind": "nullsafepropertylookup",
1096+
"offset": Identifier {
1097+
"kind": "identifier",
1098+
"name": "call",
1099+
},
1100+
"what": Variable {
1101+
"curly": false,
1102+
"kind": "variable",
1103+
"name": "obj",
1104+
},
1105+
},
1106+
},
1107+
"kind": "expressionstatement",
1108+
},
1109+
],
1110+
"errors": [],
1111+
"kind": "program",
1112+
}
1113+
`;
1114+
10871115
exports[`Test call nullsafepropertylookup (2) 1`] = `
1116+
Program {
1117+
"children": [
1118+
ExpressionStatement {
1119+
"expression": NullSafePropertyLookup {
1120+
"kind": "nullsafepropertylookup",
1121+
"offset": Identifier {
1122+
"kind": "identifier",
1123+
"name": "prop",
1124+
},
1125+
"what": Variable {
1126+
"curly": false,
1127+
"kind": "variable",
1128+
"name": "obj",
1129+
},
1130+
},
1131+
"kind": "expressionstatement",
1132+
},
1133+
],
1134+
"errors": [],
1135+
"kind": "program",
1136+
}
1137+
`;
1138+
1139+
exports[`Test call nullsafepropertylookup (3) 1`] = `
1140+
Program {
1141+
"children": [
1142+
ExpressionStatement {
1143+
"expression": NullSafePropertyLookup {
1144+
"kind": "nullsafepropertylookup",
1145+
"offset": Identifier {
1146+
"kind": "identifier",
1147+
"name": "property",
1148+
},
1149+
"what": Variable {
1150+
"curly": false,
1151+
"kind": "variable",
1152+
"name": "obj",
1153+
"parenthesizedExpression": true,
1154+
},
1155+
},
1156+
"kind": "expressionstatement",
1157+
},
1158+
],
1159+
"errors": [],
1160+
"kind": "program",
1161+
}
1162+
`;
1163+
1164+
exports[`Test call nullsafepropertylookup (4) 1`] = `
10881165
Program {
10891166
"children": [
10901167
ExpressionStatement {
@@ -1119,7 +1196,42 @@ Program {
11191196
}
11201197
`;
11211198

1122-
exports[`Test call nullsafepropertylookup 1`] = `
1199+
exports[`Test call nullsafepropertylookup (5) 1`] = `
1200+
Program {
1201+
"children": [
1202+
ExpressionStatement {
1203+
"expression": Call {
1204+
"arguments": [
1205+
Variable {
1206+
"curly": false,
1207+
"kind": "variable",
1208+
"name": "parameter",
1209+
},
1210+
],
1211+
"kind": "call",
1212+
"what": NullSafePropertyLookup {
1213+
"kind": "nullsafepropertylookup",
1214+
"offset": Identifier {
1215+
"kind": "identifier",
1216+
"name": "cal",
1217+
},
1218+
"what": Variable {
1219+
"curly": false,
1220+
"kind": "variable",
1221+
"name": "obj",
1222+
"parenthesizedExpression": true,
1223+
},
1224+
},
1225+
},
1226+
"kind": "expressionstatement",
1227+
},
1228+
],
1229+
"errors": [],
1230+
"kind": "program",
1231+
}
1232+
`;
1233+
1234+
exports[`Test call nullsafepropertylookup (6) 1`] = `
11231235
Program {
11241236
"children": [
11251237
ExpressionStatement {
@@ -1130,14 +1242,65 @@ Program {
11301242
"kind": "nullsafepropertylookup",
11311243
"offset": Identifier {
11321244
"kind": "identifier",
1133-
"name": "call",
1245+
"name": "parameter",
1246+
},
1247+
"what": Call {
1248+
"arguments": [
1249+
Variable {
1250+
"curly": false,
1251+
"kind": "variable",
1252+
"name": "parameter",
1253+
},
1254+
],
1255+
"kind": "call",
1256+
"what": NullSafePropertyLookup {
1257+
"kind": "nullsafepropertylookup",
1258+
"offset": Identifier {
1259+
"kind": "identifier",
1260+
"name": "cal",
1261+
},
1262+
"what": Variable {
1263+
"curly": false,
1264+
"kind": "variable",
1265+
"name": "obj",
1266+
"parenthesizedExpression": true,
1267+
},
1268+
},
1269+
},
1270+
},
1271+
},
1272+
"kind": "expressionstatement",
1273+
},
1274+
],
1275+
"errors": [],
1276+
"kind": "program",
1277+
}
1278+
`;
1279+
1280+
exports[`Test call nullsafepropertylookup (7) 1`] = `
1281+
Program {
1282+
"children": [
1283+
ExpressionStatement {
1284+
"expression": Bin {
1285+
"kind": "bin",
1286+
"left": NullSafePropertyLookup {
1287+
"kind": "nullsafepropertylookup",
1288+
"offset": Identifier {
1289+
"kind": "identifier",
1290+
"name": "cal",
11341291
},
11351292
"what": Variable {
11361293
"curly": false,
11371294
"kind": "variable",
11381295
"name": "obj",
1296+
"parenthesizedExpression": true,
11391297
},
11401298
},
1299+
"right": NullKeyword {
1300+
"kind": "nullkeyword",
1301+
"raw": "null",
1302+
},
1303+
"type": "!==",
11411304
},
11421305
"kind": "expressionstatement",
11431306
},

test/snapshot/call.test.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,48 @@ describe("Test call", function () {
4949
});
5050
expect(ast).toMatchSnapshot();
5151
});
52-
it("nullsafepropertylookup", function () {
52+
it("nullsafepropertylookup (1)", function () {
5353
const ast = parser.parseEval("$obj?->call();", {
5454
parser: { debug: false },
5555
});
5656
expect(ast).toMatchSnapshot();
5757
});
5858
it("nullsafepropertylookup (2)", function () {
59+
const ast = parser.parseEval("$obj?->prop;", {
60+
parser: { debug: false },
61+
});
62+
expect(ast).toMatchSnapshot();
63+
});
64+
it("nullsafepropertylookup (3)", function () {
65+
const ast = parser.parseEval("($obj)?->property;", {
66+
parser: { debug: false },
67+
});
68+
expect(ast).toMatchSnapshot();
69+
});
70+
it("nullsafepropertylookup (4)", function () {
5971
const ast = parser.parseEval("$obj?->property?->call();", {
6072
parser: { debug: false },
6173
});
6274
expect(ast).toMatchSnapshot();
6375
});
76+
it("nullsafepropertylookup (5)", function () {
77+
const ast = parser.parseEval("($obj)?->cal($parameter);", {
78+
parser: { debug: false },
79+
});
80+
expect(ast).toMatchSnapshot();
81+
});
82+
it("nullsafepropertylookup (6)", function () {
83+
const ast = parser.parseEval("($obj)?->cal($parameter)?->parameter();", {
84+
parser: { debug: false },
85+
});
86+
expect(ast).toMatchSnapshot();
87+
});
88+
it("nullsafepropertylookup (7)", function () {
89+
const ast = parser.parseEval("($obj)?->cal !== null;", {
90+
parser: { debug: false },
91+
});
92+
expect(ast).toMatchSnapshot();
93+
});
6494
it("staticlookup", function () {
6595
const ast = parser.parseEval("$obj::call();", {
6696
parser: { debug: false },

0 commit comments

Comments
 (0)