Replace strictSemicolons and allowTrailingCommas with onInsertedSemicolon and onTrailingComma
This commit is contained in:
parent
9fb3a4f5ce
commit
ba750b253b
12
README.md
12
README.md
@ -54,12 +54,14 @@ object referring to that same position.
|
||||
either 3, 5, or 6. This influences support for strict mode, the set
|
||||
of reserved words, and support for new syntax features. Default is 5.
|
||||
|
||||
- **strictSemicolons**: If `true`, prevents the parser from doing
|
||||
automatic semicolon insertion, and statements that do not end with
|
||||
a semicolon will generate an error. Defaults to `false`.
|
||||
- **onInsertedSemicolon**: If given a callback, that callback will be
|
||||
called whenever a missing semicolon is inserted by the parser. The
|
||||
callback will be given the character offset of the point where the
|
||||
semicolon is inserted as argument, and if `locations` is on, also a
|
||||
`{line, column}` object representing this position.
|
||||
|
||||
- **allowTrailingCommas**: If `false`, the parser will not allow
|
||||
trailing commas in array and object literals. Default is `true`.
|
||||
- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing
|
||||
commas.
|
||||
|
||||
- **forbidReserved**: If `true`, using a reserved word will generate
|
||||
an error. Defaults to `false`. When given the value `"everywhere"`,
|
||||
|
||||
56
acorn.js
56
acorn.js
@ -51,12 +51,15 @@
|
||||
// mode, the set of reserved words, support for getters and
|
||||
// setters and other features.
|
||||
ecmaVersion: 5,
|
||||
// Turn on `strictSemicolons` to prevent the parser from doing
|
||||
// automatic semicolon insertion.
|
||||
strictSemicolons: false,
|
||||
// When `allowTrailingCommas` is false, the parser will not allow
|
||||
// trailing commas in array and object literals.
|
||||
allowTrailingCommas: true,
|
||||
// `onInsertedSemicolon` can be a callback that will be called
|
||||
// when a semicolon is automatically inserted. It will be passed
|
||||
// th position of the comma as an offset, and if `locations` is
|
||||
// enabled, it is given the location as a `{line, column}` object
|
||||
// as second argument.
|
||||
onInsertedSemicolon: null,
|
||||
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
|
||||
// trailing commas.
|
||||
onTrailingComma: null,
|
||||
// By default, reserved words are not enforced. Enable
|
||||
// `forbidReserved` to enforce them. When this option has the
|
||||
// value "everywhere", reserved words and keywords can also not be
|
||||
@ -566,7 +569,7 @@
|
||||
this.startLoc = this.endLoc = null;
|
||||
|
||||
// Position information for the previous token
|
||||
this.lastTokEndLoc = null;
|
||||
this.lastTokEndLoc = this.lastTokStartLoc = null;
|
||||
this.lastTokStart = this.lastTokEnd = this.pos;
|
||||
|
||||
// The context stack is used to superficially track syntactic
|
||||
@ -611,6 +614,7 @@
|
||||
this.lastTokEnd = this.end;
|
||||
this.lastTokStart = this.start;
|
||||
this.lastTokEndLoc = this.endLoc;
|
||||
this.lastTokStartLoc = this.startLoc;
|
||||
this.nextToken();
|
||||
};
|
||||
|
||||
@ -1453,15 +1457,33 @@
|
||||
// Test whether a semicolon can be inserted at the current position.
|
||||
|
||||
pp.canInsertSemicolon = function() {
|
||||
return !this.options.strictSemicolons &&
|
||||
(this.type === tt.eof || this.type === tt.braceR || newline.test(this.input.slice(this.lastTokEnd, this.start)));
|
||||
return this.type === tt.eof ||
|
||||
this.type === tt.braceR ||
|
||||
newline.test(this.input.slice(this.lastTokEnd, this.start));
|
||||
};
|
||||
|
||||
pp.insertSemicolon = function() {
|
||||
if (this.canInsertSemicolon()) {
|
||||
if (this.options.onInsertedSemicolon)
|
||||
this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc)
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Consume a semicolon, or, failing that, see if we are allowed to
|
||||
// pretend that there is a semicolon at this position.
|
||||
|
||||
pp.semicolon = function() {
|
||||
if (!this.eat(tt.semi) && !this.canInsertSemicolon()) this.unexpected();
|
||||
if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected();
|
||||
};
|
||||
|
||||
pp.afterTrailingComma = function(tokType) {
|
||||
if (this.type == tokType) {
|
||||
if (this.options.onTrailingComma)
|
||||
this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc);
|
||||
this.next();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Expect a token of a given type. If found, consume it, otherwise,
|
||||
@ -1800,7 +1822,7 @@
|
||||
pp.parseBreakContinueStatement = function(node, keyword) {
|
||||
var isBreak = keyword == "break";
|
||||
this.next();
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) node.label = null;
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null;
|
||||
else if (this.type !== tt.name) this.unexpected();
|
||||
else {
|
||||
node.label = this.parseIdent();
|
||||
@ -1897,7 +1919,7 @@
|
||||
// optional arguments, we eagerly look for a semicolon or the
|
||||
// possibility to insert one.
|
||||
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) node.argument = null;
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null;
|
||||
else { node.argument = this.parseExpression(); this.semicolon(); }
|
||||
return this.finishNode(node, "ReturnStatement");
|
||||
};
|
||||
@ -2459,7 +2481,7 @@
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.options.allowTrailingCommas && this.eat(tt.braceR)) break;
|
||||
if (this.afterTrailingComma(tt.braceR)) break;
|
||||
} else first = false;
|
||||
|
||||
var prop = this.startNode(), isGenerator, start;
|
||||
@ -2657,7 +2679,7 @@
|
||||
while (!this.eat(close)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (allowTrailingComma && this.options.allowTrailingCommas && this.eat(close)) break;
|
||||
if (allowTrailingComma && this.afterTrailingComma(close)) break;
|
||||
} else first = false;
|
||||
|
||||
if (allowEmpty && this.type === tt.comma) {
|
||||
@ -2745,7 +2767,7 @@
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.options.allowTrailingCommas && this.eat(tt.braceR)) break;
|
||||
if (this.afterTrailingComma(tt.braceR)) break;
|
||||
} else first = false;
|
||||
|
||||
var node = this.startNode();
|
||||
@ -2799,7 +2821,7 @@
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.options.allowTrailingCommas && this.eat(tt.braceR)) break;
|
||||
if (this.afterTrailingComma(tt.braceR)) break;
|
||||
} else first = false;
|
||||
|
||||
var node = this.startNode();
|
||||
@ -2816,7 +2838,7 @@
|
||||
pp.parseYield = function() {
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) {
|
||||
node.delegate = false;
|
||||
node.argument = null;
|
||||
} else {
|
||||
|
||||
@ -28946,3 +28946,22 @@ test("function f() {} / 1 /", {
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
var semicolons = []
|
||||
testAssert("var x\nreturn\n10", function() {
|
||||
var result = semicolons.join(" ");
|
||||
semicolons.length = 0;
|
||||
if (result != "5 12 15")
|
||||
return "Unexpected result for onInsertedSemicolon: " + result;
|
||||
}, {onInsertedSemicolon: function(pos) { semicolons.push(pos); },
|
||||
allowReturnOutsideFunction: true,
|
||||
loose: false})
|
||||
|
||||
var trailingCommas = []
|
||||
testAssert("[1,2,] + {foo: 1,}", function() {
|
||||
var result = trailingCommas.join(" ");
|
||||
trailingCommas.length = 0;
|
||||
if (result != "4 16")
|
||||
return "Unexpected result for onTrailingComma: " + result;
|
||||
}, {onTrailingComma: function(pos) { trailingCommas.push(pos); },
|
||||
loose: false})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user