From f1e2cca76701606124971f1f6e545824e731e356 Mon Sep 17 00:00:00 2001 From: Henry Zhu Date: Wed, 1 Mar 2017 10:57:06 -0500 Subject: [PATCH] Add back ranges property (#363) * Add back ranges property * Correctly adjust range in flow plugin * Make it an option --- src/options.js | 12 +- src/parser/node.js | 24 +- src/plugins/flow.js | 3 +- src/util/location.js | 4 +- .../fixtures/core/opts/ranges-false/actual.js | 3 + .../core/opts/ranges-false/expected.json | 207 ++++++++++++++ test/fixtures/core/opts/ranges-true/actual.js | 3 + .../core/opts/ranges-true/expected.json | 255 ++++++++++++++++++ .../core/opts/ranges-true/options.json | 3 + test/utils/runFixtureTests.js | 2 - 10 files changed, 504 insertions(+), 12 deletions(-) create mode 100644 test/fixtures/core/opts/ranges-false/actual.js create mode 100644 test/fixtures/core/opts/ranges-false/expected.json create mode 100644 test/fixtures/core/opts/ranges-true/actual.js create mode 100644 test/fixtures/core/opts/ranges-true/expected.json create mode 100644 test/fixtures/core/opts/ranges-true/options.json diff --git a/src/options.js b/src/options.js index 72c65f34a6..ad75996fce 100755 --- a/src/options.js +++ b/src/options.js @@ -9,7 +9,8 @@ export const defaultOptions: { allowImportExportEverywhere: boolean, allowSuperOutsideMethod: boolean, plugins: Array, - strictMode: any + strictMode: any, + ranges: boolean, } = { // Source type ("script" or "module") for different semantics sourceType: "script", @@ -30,6 +31,15 @@ export const defaultOptions: { plugins: [], // TODO strictMode: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, }; // Interpret and default an options object diff --git a/src/parser/node.js b/src/parser/node.js index 86f697c130..364323ec7f 100644 --- a/src/parser/node.js +++ b/src/parser/node.js @@ -1,5 +1,5 @@ import Parser from "./index"; -import { SourceLocation } from "../util/location"; +import { SourceLocation, type Position } from "../util/location"; // Start an AST node, attaching a start offset. @@ -7,12 +7,13 @@ const pp = Parser.prototype; const commentKeys = ["leadingComments", "trailingComments", "innerComments"]; class Node { - constructor(pos?: number, loc?: number, filename?: string) { + constructor(parser?: Parser, pos?: number, loc?: Position) { this.type = ""; this.start = pos; this.end = 0; this.loc = new SourceLocation(loc); - if (filename) this.loc.filename = filename; + if (parser && parser.options.ranges) this.range = [pos, 0]; + if (parser && parser.filename) this.loc.filename = parser.filename; } type: string; @@ -34,17 +35,18 @@ class Node { } pp.startNode = function () { - return new Node(this.state.start, this.state.startLoc, this.filename); + return new Node(this, this.state.start, this.state.startLoc); }; pp.startNodeAt = function (pos, loc) { - return new Node(pos, loc, this.filename); + return new Node(this, pos, loc); }; function finishNodeAt(node, type, pos, loc) { node.type = type; node.end = pos; node.loc.end = loc; + if (this.options.ranges) node.range[1] = pos; this.processComment(node); return node; } @@ -60,3 +62,15 @@ pp.finishNode = function (node, type) { pp.finishNodeAt = function (node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc); }; + + +/** + * Reset the start location of node to the start location of locationNode + */ +pp.resetStartLocationFromNode = function (node, locationNode) { + node.start = locationNode.start; + node.loc.start = locationNode.loc.start; + if (this.options.ranges) node.range[0] = locationNode.range[0]; + + return node; +}; diff --git a/src/plugins/flow.js b/src/plugins/flow.js index cd58319631..25483df19f 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1381,8 +1381,7 @@ export default function (instance) { arrowExpression = inner.apply(this, args); arrowExpression.typeParameters = typeParameters; - arrowExpression.start = typeParameters.start; - arrowExpression.loc.start = typeParameters.loc.start; + this.resetStartLocationFromNode(arrowExpression, typeParameters); } catch (err) { throw jsxError || err; } diff --git a/src/util/location.js b/src/util/location.js index 38137496c1..fb53aab1c5 100644 --- a/src/util/location.js +++ b/src/util/location.js @@ -4,14 +4,14 @@ import { lineBreakG } from "./whitespace"; // `startLoc` and `endLoc` properties. export class Position { - constructor(line, col) { + constructor(line: number, col: number) { this.line = line; this.column = col; } } export class SourceLocation { - constructor(start, end) { + constructor(start: Position, end?: Position) { this.start = start; this.end = end; } diff --git a/test/fixtures/core/opts/ranges-false/actual.js b/test/fixtures/core/opts/ranges-false/actual.js new file mode 100644 index 0000000000..a5433428e9 --- /dev/null +++ b/test/fixtures/core/opts/ranges-false/actual.js @@ -0,0 +1,3 @@ +var a = 1; + +var b = a + 1; diff --git a/test/fixtures/core/opts/ranges-false/expected.json b/test/fixtures/core/opts/ranges-false/expected.json new file mode 100644 index 0000000000..e8ab354792 --- /dev/null +++ b/test/fixtures/core/opts/ranges-false/expected.json @@ -0,0 +1,207 @@ +{ + "type": "File", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "sourceType": "script", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + }, + "identifierName": "a" + }, + "name": "a" + }, + "init": { + "type": "NumericLiteral", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + ], + "kind": "var" + }, + { + "type": "VariableDeclaration", + "start": 12, + "end": 26, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 16, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "id": { + "type": "Identifier", + "start": 16, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + }, + "identifierName": "b" + }, + "name": "b" + }, + "init": { + "type": "BinaryExpression", + "start": 20, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "left": { + "type": "Identifier", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "+", + "right": { + "type": "NumericLiteral", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + } + ], + "kind": "var" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/core/opts/ranges-true/actual.js b/test/fixtures/core/opts/ranges-true/actual.js new file mode 100644 index 0000000000..a5433428e9 --- /dev/null +++ b/test/fixtures/core/opts/ranges-true/actual.js @@ -0,0 +1,3 @@ +var a = 1; + +var b = a + 1; diff --git a/test/fixtures/core/opts/ranges-true/expected.json b/test/fixtures/core/opts/ranges-true/expected.json new file mode 100644 index 0000000000..c5e28e30ea --- /dev/null +++ b/test/fixtures/core/opts/ranges-true/expected.json @@ -0,0 +1,255 @@ +{ + "type": "File", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "range": [ + 0, + 26 + ], + "program": { + "type": "Program", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "range": [ + 0, + 26 + ], + "sourceType": "script", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "range": [ + 0, + 10 + ], + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "range": [ + 4, + 9 + ], + "id": { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + }, + "identifierName": "a" + }, + "range": [ + 4, + 5 + ], + "name": "a" + }, + "init": { + "type": "NumericLiteral", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "range": [ + 8, + 9 + ], + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + ], + "kind": "var" + }, + { + "type": "VariableDeclaration", + "start": 12, + "end": 26, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "range": [ + 12, + 26 + ], + "declarations": [ + { + "type": "VariableDeclarator", + "start": 16, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "range": [ + 16, + 25 + ], + "id": { + "type": "Identifier", + "start": 16, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + }, + "identifierName": "b" + }, + "range": [ + 16, + 17 + ], + "name": "b" + }, + "init": { + "type": "BinaryExpression", + "start": 20, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "range": [ + 20, + 25 + ], + "left": { + "type": "Identifier", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + }, + "identifierName": "a" + }, + "range": [ + 20, + 21 + ], + "name": "a" + }, + "operator": "+", + "right": { + "type": "NumericLiteral", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "range": [ + 24, + 25 + ], + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + } + ], + "kind": "var" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/core/opts/ranges-true/options.json b/test/fixtures/core/opts/ranges-true/options.json new file mode 100644 index 0000000000..7d108ad39d --- /dev/null +++ b/test/fixtures/core/opts/ranges-true/options.json @@ -0,0 +1,3 @@ +{ + "ranges": true +} diff --git a/test/utils/runFixtureTests.js b/test/utils/runFixtureTests.js index c391632f84..99b9787939 100644 --- a/test/utils/runFixtureTests.js +++ b/test/utils/runFixtureTests.js @@ -61,8 +61,6 @@ function save(test, ast) { function runTest(test, parseFunction) { var opts = test.options; - opts.locations = true; - opts.ranges = true; if (opts.throws && test.expect.code) { throw new Error("File expected.json exists although options specify throws. Remove expected.json.");