summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/node_modules/espree/espree.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/node_modules/espree/espree.js')
-rw-r--r--tools/node_modules/eslint/node_modules/espree/espree.js565
1 files changed, 39 insertions, 526 deletions
diff --git a/tools/node_modules/eslint/node_modules/espree/espree.js b/tools/node_modules/eslint/node_modules/espree/espree.js
index e50fc5666f..dea35ef083 100644
--- a/tools/node_modules/eslint/node_modules/espree/espree.js
+++ b/tools/node_modules/eslint/node_modules/espree/espree.js
@@ -58,271 +58,38 @@
"use strict";
-var astNodeTypes = require("./lib/ast-node-types"),
- commentAttachment = require("./lib/comment-attachment"),
- TokenTranslator = require("./lib/token-translator"),
- acornJSX = require("acorn-jsx/inject"),
- rawAcorn = require("acorn");
-
-
-var acorn = acornJSX(rawAcorn);
-var DEFAULT_ECMA_VERSION = 5;
-var lookahead,
- extra,
- lastToken;
-
-/**
- * Resets the extra object to its default.
- * @returns {void}
- * @private
- */
-function resetExtra() {
- extra = {
- tokens: null,
- range: false,
- loc: false,
- comment: false,
- comments: [],
- tolerant: false,
- errors: [],
- strict: false,
- ecmaFeatures: {},
- ecmaVersion: DEFAULT_ECMA_VERSION,
- isModule: false
- };
-}
-
-
-
-var tt = acorn.tokTypes,
- getLineInfo = acorn.getLineInfo;
-
-// custom type for JSX attribute values
-tt.jsxAttrValueToken = {};
-
-/**
- * Normalize ECMAScript version from the initial config
- * @param {number} ecmaVersion ECMAScript version from the initial config
- * @returns {number} normalized ECMAScript version
- */
-function normalizeEcmaVersion(ecmaVersion) {
- if (typeof ecmaVersion === "number") {
- var version = ecmaVersion;
-
- // Calculate ECMAScript edition number from official year version starting with
- // ES2015, which corresponds with ES6 (or a difference of 2009).
- if (version >= 2015) {
- version -= 2009;
- }
-
- switch (version) {
- case 3:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- return version;
-
- default:
- throw new Error("Invalid ecmaVersion.");
- }
- } else {
- return DEFAULT_ECMA_VERSION;
- }
-}
-
-/**
- * Determines if a node is valid given the set of ecmaFeatures.
- * @param {ASTNode} node The node to check.
- * @returns {boolean} True if the node is allowed, false if not.
- * @private
- */
-function isValidNode(node) {
- switch (node.type) {
- case "ImportDeclaration":
- case "ExportNamedDeclaration":
- case "ExportDefaultDeclaration":
- case "ExportAllDeclaration":
- return extra.isModule;
-
- default:
- return true;
- }
-}
-
-/**
- * Performs last-minute Esprima-specific compatibility checks and fixes.
- * @param {ASTNode} result The node to check.
- * @returns {ASTNode} The finished node.
- * @private
- * @this acorn.Parser
- */
-function esprimaFinishNode(result) {
- // ensure that parsed node was allowed through ecmaFeatures
- if (!isValidNode(result)) {
- this.unexpected(result.start);
- }
-
- // Acorn doesn't count the opening and closing backticks as part of templates
- // so we have to adjust ranges/locations appropriately.
- if (result.type === "TemplateElement") {
-
- // additional adjustment needed if ${ is the last token
- var terminalDollarBraceL = this.input.slice(result.end, result.end + 2) === "${";
-
- if (result.range) {
- result.range[0]--;
- result.range[1] += (terminalDollarBraceL ? 2 : 1);
- }
-
- if (result.loc) {
- result.loc.start.column--;
- result.loc.end.column += (terminalDollarBraceL ? 2 : 1);
- }
- }
-
- if (extra.attachComment) {
- commentAttachment.processComment(result);
+const acorn = require("acorn");
+const jsx = require("acorn-jsx");
+const astNodeTypes = require("./lib/ast-node-types");
+const espree = require("./lib/espree");
+
+// To initialize lazily.
+const parsers = {
+ _regular: null,
+ _jsx: null,
+
+ get regular() {
+ if (this._regular === null) {
+ this._regular = acorn.Parser.extend(espree());
+ }
+ return this._regular;
+ },
+
+ get jsx() {
+ if (this._jsx === null) {
+ this._jsx = acorn.Parser.extend(jsx(), espree());
+ }
+ return this._jsx;
+ },
+
+ get(options) {
+ const useJsx = Boolean(
+ options &&
+ options.ecmaFeatures &&
+ options.ecmaFeatures.jsx
+ );
+ return useJsx ? this.jsx : this.regular;
}
-
- if (result.type.indexOf("Function") > -1 && !result.generator) {
- result.generator = false;
- }
-
- return result;
-}
-
-/**
- * Determines if a token is valid given the set of ecmaFeatures.
- * @param {acorn.Parser} parser The parser to check.
- * @returns {boolean} True if the token is allowed, false if not.
- * @private
- */
-function isValidToken(parser) {
- var ecma = extra.ecmaFeatures;
- var type = parser.type;
-
- switch (type) {
- case tt.jsxName:
- case tt.jsxText:
- case tt.jsxTagStart:
- case tt.jsxTagEnd:
- return ecma.jsx;
-
- // https://github.com/ternjs/acorn/issues/363
- case tt.regexp:
- if (extra.ecmaVersion < 6 && parser.value.flags && parser.value.flags.indexOf("y") > -1) {
- return false;
- }
-
- return true;
-
- default:
- return true;
- }
-}
-
-/**
- * Injects esprimaFinishNode into the finishNode process.
- * @param {Function} finishNode Original finishNode function.
- * @returns {ASTNode} The finished node.
- * @private
- */
-function wrapFinishNode(finishNode) {
- return /** @this acorn.Parser */ function(node, type, pos, loc) {
- var result = finishNode.call(this, node, type, pos, loc);
- return esprimaFinishNode.call(this, result);
- };
-}
-
-acorn.plugins.espree = function(instance) {
-
- instance.extend("finishNode", wrapFinishNode);
-
- instance.extend("finishNodeAt", wrapFinishNode);
-
- instance.extend("next", function(next) {
- return /** @this acorn.Parser */ function() {
- if (!isValidToken(this)) {
- this.unexpected();
- }
- return next.call(this);
- };
- });
-
- instance.extend("parseTopLevel", function(parseTopLevel) {
- return /** @this acorn.Parser */ function(node) {
- if (extra.ecmaFeatures.impliedStrict && this.options.ecmaVersion >= 5) {
- this.strict = true;
- }
- return parseTopLevel.call(this, node);
- };
- });
-
- /**
- * Overwrites the default raise method to throw Esprima-style errors.
- * @param {int} pos The position of the error.
- * @param {string} message The error message.
- * @throws {SyntaxError} A syntax error.
- * @returns {void}
- */
- instance.raise = instance.raiseRecoverable = function(pos, message) {
- var loc = getLineInfo(this.input, pos);
- var err = new SyntaxError(message);
- err.index = pos;
- err.lineNumber = loc.line;
- err.column = loc.column + 1; // acorn uses 0-based columns
- throw err;
- };
-
- /**
- * Overwrites the default unexpected method to throw Esprima-style errors.
- * @param {int} pos The position of the error.
- * @throws {SyntaxError} A syntax error.
- * @returns {void}
- */
- instance.unexpected = function(pos) {
- var message = "Unexpected token";
-
- if (pos !== null && pos !== undefined) {
- this.pos = pos;
-
- if (this.options.locations) {
- while (this.pos < this.lineStart) {
- this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1;
- --this.curLine;
- }
- }
-
- this.nextToken();
- }
-
- if (this.end > this.start) {
- message += " " + this.input.slice(this.start, this.end);
- }
-
- this.raise(this.start, message);
- };
-
- /*
- * Esprima-FB represents JSX strings as tokens called "JSXText", but Acorn-JSX
- * uses regular tt.string without any distinction between this and regular JS
- * strings. As such, we intercept an attempt to read a JSX string and set a flag
- * on extra so that when tokens are converted, the next token will be switched
- * to JSXText via onToken.
- */
- instance.extend("jsx_readString", function(jsxReadString) {
- return /** @this acorn.Parser */ function(quote) {
- var result = jsxReadString.call(this, quote);
- if (this.type === tt.string) {
- extra.jsxAttrValueToken = true;
- }
-
- return result;
- };
- });
};
//------------------------------------------------------------------------------
@@ -338,266 +105,30 @@ acorn.plugins.espree = function(instance) {
* @private
*/
function tokenize(code, options) {
- var toString,
- tokens,
- impliedStrict,
- translator = new TokenTranslator(tt, code);
+ const Parser = parsers.get(options);
- toString = String;
- if (typeof code !== "string" && !(code instanceof String)) {
- code = toString(code);
+ // Ensure to collect tokens.
+ if (!options || options.tokens !== true) {
+ options = Object.assign({}, options, { tokens: true });
}
- lookahead = null;
-
- // Options matching.
- options = Object.assign({}, options);
-
- var acornOptions = {
- ecmaVersion: DEFAULT_ECMA_VERSION,
- plugins: {
- espree: true
- }
- };
-
- resetExtra();
-
- // Of course we collect tokens here.
- options.tokens = true;
- extra.tokens = [];
-
- extra.range = (typeof options.range === "boolean") && options.range;
- acornOptions.ranges = extra.range;
-
- extra.loc = (typeof options.loc === "boolean") && options.loc;
- acornOptions.locations = extra.loc;
-
- extra.comment = typeof options.comment === "boolean" && options.comment;
-
- if (extra.comment) {
- acornOptions.onComment = function() {
- var comment = convertAcornCommentToEsprimaComment.apply(this, arguments);
- extra.comments.push(comment);
- };
- }
-
- extra.tolerant = typeof options.tolerant === "boolean" && options.tolerant;
-
- acornOptions.ecmaVersion = extra.ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
-
- // apply parsing flags
- if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
- extra.ecmaFeatures = Object.assign({}, options.ecmaFeatures);
- impliedStrict = extra.ecmaFeatures.impliedStrict;
- extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict;
- }
-
- try {
- var tokenizer = acorn.tokenizer(code, acornOptions);
- while ((lookahead = tokenizer.getToken()).type !== tt.eof) {
- translator.onToken(lookahead, extra);
- }
-
- // filterTokenLocation();
- tokens = extra.tokens;
-
- if (extra.comment) {
- tokens.comments = extra.comments;
- }
- if (extra.tolerant) {
- tokens.errors = extra.errors;
- }
- } catch (e) {
- throw e;
- }
- return tokens;
+ return new Parser(options, code).tokenize();
}
//------------------------------------------------------------------------------
// Parser
//------------------------------------------------------------------------------
-
-
-/**
- * Converts an Acorn comment to a Esprima comment.
- * @param {boolean} block True if it's a block comment, false if not.
- * @param {string} text The text of the comment.
- * @param {int} start The index at which the comment starts.
- * @param {int} end The index at which the comment ends.
- * @param {Location} startLoc The location at which the comment starts.
- * @param {Location} endLoc The location at which the comment ends.
- * @returns {Object} The comment object.
- * @private
- */
-function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc) {
- var comment = {
- type: block ? "Block" : "Line",
- value: text
- };
-
- if (typeof start === "number") {
- comment.start = start;
- comment.end = end;
- comment.range = [start, end];
- }
-
- if (typeof startLoc === "object") {
- comment.loc = {
- start: startLoc,
- end: endLoc
- };
- }
-
- return comment;
-}
-
/**
* Parses the given code.
* @param {string} code The code to tokenize.
* @param {Object} options Options defining how to tokenize.
* @returns {ASTNode} The "Program" AST node.
* @throws {SyntaxError} If the input code is invalid.
- * @private
*/
function parse(code, options) {
- var program,
- toString = String,
- translator,
- impliedStrict,
- acornOptions = {
- ecmaVersion: DEFAULT_ECMA_VERSION,
- plugins: {
- espree: true
- }
- };
-
- lastToken = null;
-
- if (typeof code !== "string" && !(code instanceof String)) {
- code = toString(code);
- }
-
- resetExtra();
- commentAttachment.reset();
-
- if (typeof options !== "undefined") {
- extra.range = (typeof options.range === "boolean") && options.range;
- extra.loc = (typeof options.loc === "boolean") && options.loc;
- extra.attachComment = (typeof options.attachComment === "boolean") && options.attachComment;
-
- if (extra.loc && options.source !== null && options.source !== undefined) {
- extra.source = toString(options.source);
- }
-
- if (typeof options.tokens === "boolean" && options.tokens) {
- extra.tokens = [];
- translator = new TokenTranslator(tt, code);
- }
- if (typeof options.comment === "boolean" && options.comment) {
- extra.comment = true;
- extra.comments = [];
- }
- if (typeof options.tolerant === "boolean" && options.tolerant) {
- extra.errors = [];
- }
- if (extra.attachComment) {
- extra.range = true;
- extra.comments = [];
- commentAttachment.reset();
- }
-
- acornOptions.ecmaVersion = extra.ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
-
- if (options.sourceType === "module") {
- extra.isModule = true;
-
- // modules must be in 6 at least
- if (acornOptions.ecmaVersion < 6) {
- acornOptions.ecmaVersion = 6;
- extra.ecmaVersion = 6;
- }
-
- acornOptions.sourceType = "module";
- }
-
- // apply parsing flags after sourceType to allow overriding
- if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
- extra.ecmaFeatures = Object.assign({}, options.ecmaFeatures);
- impliedStrict = extra.ecmaFeatures.impliedStrict;
- extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict;
- if (options.ecmaFeatures.globalReturn) {
- acornOptions.allowReturnOutsideFunction = true;
- }
- }
-
-
- acornOptions.onToken = function(token) {
- if (extra.tokens) {
- translator.onToken(token, extra);
- }
- if (token.type !== tt.eof) {
- lastToken = token;
- }
- };
-
- if (extra.attachComment || extra.comment) {
- acornOptions.onComment = function() {
- var comment = convertAcornCommentToEsprimaComment.apply(this, arguments);
- extra.comments.push(comment);
-
- if (extra.attachComment) {
- commentAttachment.addComment(comment);
- }
- };
- }
-
- if (extra.range) {
- acornOptions.ranges = true;
- }
-
- if (extra.loc) {
- acornOptions.locations = true;
- }
-
- if (extra.ecmaFeatures.jsx) {
- // Should process jsx plugin before espree plugin.
- acornOptions.plugins = {
- jsx: true,
- espree: true
- };
- }
- }
-
- program = acorn.parse(code, acornOptions);
- program.sourceType = extra.isModule ? "module" : "script";
-
- if (extra.comment || extra.attachComment) {
- program.comments = extra.comments;
- }
-
- if (extra.tokens) {
- program.tokens = extra.tokens;
- }
-
- /*
- * Adjust opening and closing position of program to match Esprima.
- * Acorn always starts programs at range 0 whereas Esprima starts at the
- * first AST node's start (the only real difference is when there's leading
- * whitespace or leading comments). Acorn also counts trailing whitespace
- * as part of the program whereas Esprima only counts up to the last token.
- */
- if (program.range) {
- program.range[0] = program.body.length ? program.body[0].range[0] : program.range[0];
- program.range[1] = lastToken ? lastToken.range[1] : program.range[1];
- }
-
- if (program.loc) {
- program.loc.start = program.body.length ? program.body[0].loc.start : program.loc.start;
- program.loc.end = lastToken ? lastToken.loc.end : program.loc.end;
- }
-
- return program;
+ const Parser = parsers.get(options);
+ return new Parser(options, code).parse();
}
//------------------------------------------------------------------------------
@@ -634,23 +165,5 @@ exports.Syntax = (function() {
/* istanbul ignore next */
exports.VisitorKeys = (function() {
- var visitorKeys = require("./lib/visitor-keys");
- var name,
- keys = {};
-
- if (typeof Object.create === "function") {
- keys = Object.create(null);
- }
-
- for (name in visitorKeys) {
- if (visitorKeys.hasOwnProperty(name)) {
- keys[name] = visitorKeys[name];
- }
- }
-
- if (typeof Object.freeze === "function") {
- Object.freeze(keys);
- }
-
- return keys;
+ return require("eslint-visitor-keys").KEYS;
}());