Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ AST.prototype.isRightAssociative = function (operator) {
*/
AST.prototype.swapLocations = function (target, first, last, parser) {
if (this.withPositions) {
if (!target || !target.loc || !first || !first.loc || !last || !last.loc) {
return;
}
target.loc.start = first.loc.start;
target.loc.end = last.loc.end;
if (this.withSource) {
Expand All @@ -198,6 +201,9 @@ AST.prototype.swapLocations = function (target, first, last, parser) {
*/
AST.prototype.resolveLocations = function (target, first, last, parser) {
if (this.withPositions) {
if (!target || !target.loc || !first || !first.loc || !last || !last.loc) {
return;
}
if (target.loc.start.offset > first.loc.start.offset) {
target.loc.start = first.loc.start;
}
Expand Down
9 changes: 9 additions & 0 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,21 @@ Parser.prototype.raiseError = function (message, msgExpect, expect, token) {
throw err;
}
// Error node :
// Temporarily set prev to the current token's end so the error node
// spans from the current token's start to its end (not the previous token's end).
const savedPrev = this.prev;
this.prev = [
this.lexer.yylloc.last_line,
this.lexer.yylloc.last_column,
this.lexer.offset,
];
const node = this.ast.prepare("error", null, this)(
message,
token,
this.lexer.yylloc.first_line,
expect,
);
this.prev = savedPrev;
this._errors.push(node);
return node;
};
Expand Down
276 changes: 276 additions & 0 deletions test/snapshot/__snapshots__/graceful.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,281 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`Test graceful mode suppressErrors with withPositions should not throw on call-like expression followed by block (issue #1185) 1`] = `
Program {
"children": [
ExpressionStatement {
"expression": OffsetLookup {
"kind": "offsetlookup",
"loc": Location {
"end": Position {
"column": 13,
"line": 1,
"offset": 13,
},
"source": null,
"start": Position {
"column": 6,
"line": 1,
"offset": 6,
},
},
"offset": Variable {
"curly": false,
"kind": "variable",
"loc": Location {
"end": Position {
"column": 12,
"line": 1,
"offset": 12,
},
"source": null,
"start": Position {
"column": 10,
"line": 1,
"offset": 10,
},
},
"name": "a",
},
"what": Call {
"arguments": [],
"kind": "call",
"loc": Location {
"end": Position {
"column": 9,
"line": 1,
"offset": 9,
},
"source": null,
"start": Position {
"column": 6,
"line": 1,
"offset": 6,
},
},
"what": Name {
"kind": "name",
"loc": Location {
"end": Position {
"column": 7,
"line": 1,
"offset": 7,
},
"source": null,
"start": Position {
"column": 6,
"line": 1,
"offset": 6,
},
},
"name": "f",
"resolution": "uqn",
},
},
},
"kind": "expressionstatement",
"loc": Location {
"end": Position {
"column": 13,
"line": 1,
"offset": 13,
},
"source": null,
"start": Position {
"column": 6,
"line": 1,
"offset": 6,
},
},
},
ExpressionStatement {
"expression": undefined,
"kind": "expressionstatement",
"loc": Location {
"end": Position {
"column": 14,
"line": 1,
"offset": 14,
},
"source": null,
"start": Position {
"column": 13,
"line": 1,
"offset": 13,
},
},
},
],
"errors": [
Error {
"expected": "}",
"kind": "error",
"line": 1,
"loc": Location {
"end": Position {
"column": 13,
"line": 1,
"offset": 13,
},
"source": null,
"start": Position {
"column": 12,
"line": 1,
"offset": 12,
},
},
"message": "Parse Error : syntax error, unexpected ';', expecting '}' on line 1",
"token": "';'",
},
Error {
"expected": "EXPR",
"kind": "error",
"line": 1,
"loc": Location {
"end": Position {
"column": 14,
"line": 1,
"offset": 14,
},
"source": null,
"start": Position {
"column": 13,
"line": 1,
"offset": 13,
},
},
"message": "Parse Error : syntax error, unexpected '}' on line 1",
"token": "'}'",
},
],
"kind": "program",
"loc": Location {
"end": Position {
"column": 14,
"line": 1,
"offset": 14,
},
"source": null,
"start": Position {
"column": 0,
"line": 1,
"offset": 0,
},
},
}
`;

exports[`Test graceful mode suppressErrors with withPositions should not throw on silent expression with incomplete binary (issue #1185) 1`] = `
Program {
"children": [
ExpressionStatement {
"expression": Bin {
"kind": "bin",
"left": Silent {
"expr": Variable {
"curly": false,
"kind": "variable",
"loc": Location {
"end": Position {
"column": 9,
"line": 1,
"offset": 9,
},
"source": null,
"start": Position {
"column": 7,
"line": 1,
"offset": 7,
},
},
"name": "a",
},
"kind": "silent",
"loc": Location {
"end": Position {
"column": 9,
"line": 1,
"offset": 9,
},
"source": null,
"start": Position {
"column": 6,
"line": 1,
"offset": 6,
},
},
},
"loc": Location {
"end": Position {
"column": 12,
"line": 1,
"offset": 12,
},
"source": null,
"start": Position {
"column": 7,
"line": 1,
"offset": 7,
},
},
"right": undefined,
"type": "-",
},
"kind": "expressionstatement",
"loc": Location {
"end": Position {
"column": 12,
"line": 1,
"offset": 12,
},
"source": null,
"start": Position {
"column": 7,
"line": 1,
"offset": 7,
},
},
},
],
"errors": [
Error {
"expected": "EXPR",
"kind": "error",
"line": 1,
"loc": Location {
"end": Position {
"column": 12,
"line": 1,
"offset": 12,
},
"source": null,
"start": Position {
"column": 11,
"line": 1,
"offset": 11,
},
},
"message": "Parse Error : syntax error, unexpected ';' on line 1",
"token": "';'",
},
],
"kind": "program",
"loc": Location {
"end": Position {
"column": 12,
"line": 1,
"offset": 12,
},
"source": null,
"start": Position {
"column": 0,
"line": 1,
"offset": 0,
},
},
}
`;

exports[`Test graceful mode to suppress errors interface 1`] = `
Program {
"children": [
Expand Down
19 changes: 19 additions & 0 deletions test/snapshot/graceful.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
const parser = require("../main");

describe("Test graceful mode", function () {
describe("suppressErrors with withPositions", function () {
const test = parser.create({
parser: {
suppressErrors: true,
},
ast: {
withPositions: true,
},
});

it("should not throw on call-like expression followed by block (issue #1185)", function () {
expect(test.parseCode("<?php f(){$a;}")).toMatchSnapshot();
});

it("should not throw on silent expression with incomplete binary (issue #1185)", function () {
expect(test.parseCode("<?php @$a -;")).toMatchSnapshot();
});
});

describe("to suppress errors", function () {
const test = parser.create({
parser: {
Expand Down
Loading