From 6ebc21947166399a0b4918d4a1beb9d610650336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 4 Nov 2018 23:18:47 +0800 Subject: [PATCH] Upgrade: eslint & eslint-config-eslint (#387) --- Makefile.js | 45 +++------- espree.js | 7 +- lib/comment-attachment.js | 13 +-- lib/espree.js | 18 ++-- lib/token-translator.js | 28 +++--- lib/visitor-keys.js | 123 ++++++++++++++++++++++++++ package.json | 5 +- tests/lib/acorn-after-espree.js | 15 ++-- tests/lib/attach-comments.js | 26 +++--- tests/lib/ecma-features.js | 35 ++++---- tests/lib/ecma-version.js | 83 +++++++++--------- tests/lib/libraries.js | 21 +++-- tests/lib/parse.js | 40 ++++----- tests/lib/tester.js | 12 +-- tests/lib/tokenize.js | 149 +++++++++++++++++--------------- tools/convert.js | 1 - tools/generate-test-fixture.js | 2 +- tools/update-tests.js | 3 +- 18 files changed, 375 insertions(+), 251 deletions(-) create mode 100644 lib/visitor-keys.js diff --git a/Makefile.js b/Makefile.js index 90b582aa..9273a0ab 100644 --- a/Makefile.js +++ b/Makefile.js @@ -2,7 +2,7 @@ * @fileoverview Build file * @author nzakas */ -/* global cp, echo, exit, find, mkdir, rm, target, test */ +/* global cp, echo, exit, mkdir, rm, target, test */ "use strict"; @@ -13,41 +13,24 @@ require("shelljs/make"); -var nodeCLI = require("shelljs-nodecli"); +const nodeCLI = require("shelljs-nodecli"); +const path = require("path"); //------------------------------------------------------------------------------ // Data //------------------------------------------------------------------------------ -var NODE_MODULES = "./node_modules/", +const NODE_MODULES = "./node_modules/", TEMP_DIR = "./tmp/", BUILD_DIR = "./build/", // Utilities - intentional extra space at the end of each string - MOCHA = NODE_MODULES + "mocha/bin/_mocha ", + MOCHA = `${NODE_MODULES}mocha/bin/_mocha `, // Files MAKEFILE = "./Makefile.js", - /* eslint-disable no-use-before-define */ - JS_FILES = find("lib/").filter(fileType("js")).join(" ") + " espree.js", - TEST_FILES = find("tests/lib/").filter(fileType("js")).join(" "); - /* eslint-enable no-use-before-define */ - -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -/** - * Generates a function that matches files with a particular extension. - * @param {string} extension The file extension (i.e. "js") - * @returns {Function} The function to pass into a filter method. - * @private - */ -function fileType(extension) { - return function(filename) { - return filename.substring(filename.lastIndexOf(".") + 1) === extension; - }; -} + JS_FILES = "\"lib/**/*.js\" \"espree.js\"", + TEST_FILES = "tests/lib/**/*.js"; //------------------------------------------------------------------------------ // Tasks @@ -58,7 +41,7 @@ target.all = function() { }; target.lint = function() { - var errors = 0, + let errors = 0, lastReturn; echo("Validating Makefile.js"); @@ -85,12 +68,12 @@ target.lint = function() { }; target.test = function() { + // target.lint(); - var errors = 0, - lastReturn; + let errors = 0; - lastReturn = nodeCLI.exec("nyc", MOCHA, "--color", "--reporter progress", "--timeout 30000", TEST_FILES); + const lastReturn = nodeCLI.exec("nyc", MOCHA, "--color", "--reporter progress", "--timeout 30000", TEST_FILES); if (lastReturn.code !== 0) { errors++; @@ -112,7 +95,7 @@ target.browserify = function() { // 1. create temp and build directory if (!test("-d", TEMP_DIR)) { mkdir(TEMP_DIR); - mkdir(TEMP_DIR + "/lib"); + mkdir(path.join(TEMP_DIR, "lib")); } if (!test("-d", BUILD_DIR)) { @@ -120,13 +103,13 @@ target.browserify = function() { } // 2. copy files into temp directory - cp("-r", "lib/*", TEMP_DIR + "/lib"); + cp("-r", "lib/*", path.join(TEMP_DIR, "lib")); cp("espree.js", TEMP_DIR); cp("package.json", TEMP_DIR); // 3. browserify the temp directory - nodeCLI.exec("browserify", TEMP_DIR + "espree.js", "-o", BUILD_DIR + "espree.js", "-s espree"); + nodeCLI.exec("browserify", path.join(TEMP_DIR, "espree.js"), "-o", path.join(BUILD_DIR, "espree.js"), "-s espree"); // 4. remove temp directory rm("-r", TEMP_DIR); diff --git a/espree.js b/espree.js index dea35ef0..7c16b696 100644 --- a/espree.js +++ b/espree.js @@ -88,6 +88,7 @@ const parsers = { options.ecmaFeatures && options.ecmaFeatures.jsx ); + return useJsx ? this.jsx : this.regular; } }; @@ -109,7 +110,7 @@ function tokenize(code, options) { // Ensure to collect tokens. if (!options || options.tokens !== true) { - options = Object.assign({}, options, { tokens: true }); + options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign } return new Parser(options, code).tokenize(); @@ -128,6 +129,7 @@ function tokenize(code, options) { */ function parse(code, options) { const Parser = parsers.get(options); + return new Parser(options, code).parse(); } @@ -144,7 +146,8 @@ exports.parse = parse; // Deep copy. /* istanbul ignore next */ exports.Syntax = (function() { - var name, types = {}; + let name, + types = {}; if (typeof Object.create === "function") { types = Object.create(null); diff --git a/lib/comment-attachment.js b/lib/comment-attachment.js index b82b5f1c..5179c6ce 100644 --- a/lib/comment-attachment.js +++ b/lib/comment-attachment.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -var astNodeTypes = require("./ast-node-types"); +const astNodeTypes = require("./ast-node-types"); //------------------------------------------------------------------------------ // Private //------------------------------------------------------------------------------ -var extra = { +const extra = { trailingComments: [], leadingComments: [], bottomRightStack: [], @@ -28,20 +28,20 @@ var extra = { module.exports = { - reset: function() { + reset() { extra.trailingComments = []; extra.leadingComments = []; extra.bottomRightStack = []; extra.previousNode = null; }, - addComment: function(comment) { + addComment(comment) { extra.trailingComments.push(comment); extra.leadingComments.push(comment); }, - processComment: function(node) { - var lastChild, + processComment(node) { + let lastChild, trailingComments, i, j; @@ -95,6 +95,7 @@ module.exports = { node.leadingComments = lastChild.leadingComments; delete lastChild.leadingComments; } else { + // A leading comment for an anonymous class had been stolen by its first MethodDefinition, // so this takes back the leading comment. // See Also: https://github.com/eslint/espree/issues/158 diff --git a/lib/espree.js b/lib/espree.js index 3b4d1eab..c72c4d7b 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -1,5 +1,6 @@ "use strict"; +/* eslint-disable no-param-reassign*/ const acorn = require("acorn"); const jsx = require("acorn-jsx"); const commentAttachment = require("./comment-attachment"); @@ -89,9 +90,9 @@ module.exports = () => Parser => class Espree extends Parser { const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); const isModule = options.sourceType === "module"; const tokenTranslator = - options.tokens === true ? - new TokenTranslator(tokTypes, code) : - null; + options.tokens === true + ? new TokenTranslator(tokTypes, code) + : null; // Initialize acorn parser. super({ @@ -104,8 +105,9 @@ module.exports = () => Parser => class Espree extends Parser { allowReturnOutsideFunction: Boolean(ecmaFeatures.globalReturn), // Collect tokens - onToken: (token) => { + onToken: token => { if (tokenTranslator) { + // Use `tokens`, `ecmaVersion`, and `jsxAttrValueToken` in the state. tokenTranslator.onToken(token, this[STATE]); } @@ -118,6 +120,7 @@ module.exports = () => Parser => class Espree extends Parser { onComment: (block, text, start, end, startLoc, endLoc) => { if (this[STATE].comments) { const comment = convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc); + this[STATE].comments.push(comment); if (options.attachComment === true) { @@ -159,11 +162,13 @@ module.exports = () => Parser => class Espree extends Parser { finishNode(...args) { const result = super.finishNode(...args); + return this[ESPRIMA_FINISH_NODE](result); } finishNodeAt(...args) { const result = super.finishNodeAt(...args); + return this[ESPRIMA_FINISH_NODE](result); } @@ -216,6 +221,7 @@ module.exports = () => Parser => class Espree extends Parser { raise(pos, message) { const loc = acorn.getLineInfo(this.input, pos); const err = new SyntaxError(message); + err.index = pos; err.lineNumber = loc.line; err.column = loc.column + 1; // acorn uses 0-based columns @@ -256,7 +262,7 @@ module.exports = () => Parser => class Espree extends Parser { } if (this.end > this.start) { - message += " " + this.input.slice(this.start, this.end); + message += ` ${this.input.slice(this.start, this.end)}`; } this.raise(this.start, message); @@ -271,6 +277,7 @@ module.exports = () => Parser => class Espree extends Parser { */ jsx_readString(quote) { // eslint-disable-line camelcase const result = super.jsx_readString(quote); + if (this.type === tokTypes.string) { this[STATE].jsxAttrValueToken = true; } @@ -283,6 +290,7 @@ module.exports = () => Parser => class Espree extends Parser { * @returns {ASTNode} The finished node. */ [ESPRIMA_FINISH_NODE](result) { + // 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") { diff --git a/lib/token-translator.js b/lib/token-translator.js index f47b3621..9919e1af 100644 --- a/lib/token-translator.js +++ b/lib/token-translator.js @@ -18,7 +18,7 @@ // Esprima Token Types -var Token = { +const Token = { Boolean: "Boolean", EOF: "", Identifier: "Identifier", @@ -41,10 +41,10 @@ var Token = { * @private */ function convertTemplatePart(tokens, code) { - var firstToken = tokens[0], + const firstToken = tokens[0], lastTemplateToken = tokens[tokens.length - 1]; - var token = { + const token = { type: Token.Template, value: code.slice(firstToken.start, lastTemplateToken.end) }; @@ -99,9 +99,9 @@ TokenTranslator.prototype = { * @param {Object} extra Espree extra object. * @returns {EsprimaToken} The Esprima version of the token. */ - translate: function(token, extra) { + translate(token, extra) { - var type = token.type, + const type = token.type, tt = this._acornTokTypes; if (type === tt.name) { @@ -157,12 +157,13 @@ TokenTranslator.prototype = { token.value = this._code.slice(token.start, token.end); } else if (type === tt.regexp) { token.type = Token.RegularExpression; - var value = token.value; + const value = token.value; + token.regex = { flags: value.flags, pattern: value.pattern }; - token.value = "/" + value.pattern + "/" + value.flags; + token.value = `/${value.pattern}/${value.flags}`; } return token; @@ -174,9 +175,9 @@ TokenTranslator.prototype = { * @param {Object} extra The Espree extra object. * @returns {void} */ - onToken: function(token, extra) { + onToken(token, extra) { - var that = this, + const that = this, tt = this._acornTokTypes, tokens = extra.tokens, templateTokens = this._tokens; @@ -218,11 +219,13 @@ TokenTranslator.prototype = { } return; - } else if (token.type === tt.dollarBraceL) { + } + if (token.type === tt.dollarBraceL) { templateTokens.push(token); translateTemplateTokens(); return; - } else if (token.type === tt.braceR) { + } + if (token.type === tt.braceR) { // if there's already a curly, it's not part of the template if (this._curlyBrace) { @@ -232,7 +235,8 @@ TokenTranslator.prototype = { // store new curly for later this._curlyBrace = token; return; - } else if (token.type === tt.template || token.type === tt.invalidTemplate) { + } + if (token.type === tt.template || token.type === tt.invalidTemplate) { if (this._curlyBrace) { templateTokens.push(this._curlyBrace); this._curlyBrace = null; diff --git a/lib/visitor-keys.js b/lib/visitor-keys.js new file mode 100644 index 00000000..4216864f --- /dev/null +++ b/lib/visitor-keys.js @@ -0,0 +1,123 @@ +/** + * @fileoverview The visitor keys for the node types Espree supports + * @author Nicholas C. Zakas + * + * This file contains code from estraverse-fb. + * + * The MIT license. Copyright (c) 2014 Ingvar Stepanyan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +// None! + +//------------------------------------------------------------------------------ +// Public +//------------------------------------------------------------------------------ + +module.exports = { + + // ECMAScript + AssignmentExpression: ["left", "right"], + AssignmentPattern: ["left", "right"], + ArrayExpression: ["elements"], + ArrayPattern: ["elements"], + ArrowFunctionExpression: ["params", "body"], + BlockStatement: ["body"], + BinaryExpression: ["left", "right"], + BreakStatement: ["label"], + CallExpression: ["callee", "arguments"], + CatchClause: ["param", "body"], + ClassBody: ["body"], + ClassDeclaration: ["id", "superClass", "body"], + ClassExpression: ["id", "superClass", "body"], + ConditionalExpression: ["test", "consequent", "alternate"], + ContinueStatement: ["label"], + DebuggerStatement: [], + DirectiveStatement: [], + DoWhileStatement: ["body", "test"], + EmptyStatement: [], + ExportAllDeclaration: ["source"], + ExportDefaultDeclaration: ["declaration"], + ExportNamedDeclaration: ["declaration", "specifiers", "source"], + ExportSpecifier: ["exported", "local"], + ExpressionStatement: ["expression"], + ForStatement: ["init", "test", "update", "body"], + ForInStatement: ["left", "right", "body"], + ForOfStatement: ["left", "right", "body"], + FunctionDeclaration: ["id", "params", "body"], + FunctionExpression: ["id", "params", "body"], + Identifier: [], + IfStatement: ["test", "consequent", "alternate"], + ImportDeclaration: ["specifiers", "source"], + ImportDefaultSpecifier: ["local"], + ImportNamespaceSpecifier: ["local"], + ImportSpecifier: ["imported", "local"], + Literal: [], + LabeledStatement: ["label", "body"], + LogicalExpression: ["left", "right"], + MemberExpression: ["object", "property"], + MetaProperty: ["meta", "property"], + MethodDefinition: ["key", "value"], + ModuleSpecifier: [], + NewExpression: ["callee", "arguments"], + ObjectExpression: ["properties"], + ObjectPattern: ["properties"], + Program: ["body"], + Property: ["key", "value"], + RestElement: ["argument"], + ReturnStatement: ["argument"], + SequenceExpression: ["expressions"], + SpreadElement: ["argument"], + Super: [], + SwitchStatement: ["discriminant", "cases"], + SwitchCase: ["test", "consequent"], + TaggedTemplateExpression: ["tag", "quasi"], + TemplateElement: [], + TemplateLiteral: ["quasis", "expressions"], + ThisExpression: [], + ThrowStatement: ["argument"], + TryStatement: ["block", "handler", "finalizer"], + UnaryExpression: ["argument"], + UpdateExpression: ["argument"], + VariableDeclaration: ["declarations"], + VariableDeclarator: ["id", "init"], + WhileStatement: ["test", "body"], + WithStatement: ["object", "body"], + YieldExpression: ["argument"], + + // JSX + JSXIdentifier: [], + JSXNamespacedName: ["namespace", "name"], + JSXMemberExpression: ["object", "property"], + JSXEmptyExpression: [], + JSXExpressionContainer: ["expression"], + JSXElement: ["openingElement", "closingElement", "children"], + JSXClosingElement: ["name"], + JSXOpeningElement: ["name", "attributes"], + JSXAttribute: ["name", "value"], + JSXText: null, + JSXSpreadAttribute: ["argument"] +}; diff --git a/package.json b/package.json index befbf4b9..a101253f 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,9 @@ "devDependencies": { "browserify": "^7.0.0", "chai": "^1.10.0", - "eslint": "^2.13.1", - "eslint-config-eslint": "^3.0.0", + "eslint": "^5.7.0", + "eslint-config-eslint": "^5.0.1", + "eslint-plugin-node": "^7.0.1", "eslint-release": "^1.0.0", "esprima": "latest", "esprima-fb": "^8001.2001.0-dev-harmony-fb", diff --git a/tests/lib/acorn-after-espree.js b/tests/lib/acorn-after-espree.js index b5b2d968..0c72e2c3 100644 --- a/tests/lib/acorn-after-espree.js +++ b/tests/lib/acorn-after-espree.js @@ -10,19 +10,20 @@ // Requirements //------------------------------------------------------------------------------ -var acorn = require("acorn"), - assert = require("chai").assert; +const acorn = require("acorn"), + assert = require("assert"); //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ -describe("acorn", function() { - it("acorn.parse() should work after espree was loaded.", function() { - var before = acorn.parse("var foo = bar /*world*/;"); +describe("acorn", () => { + it("acorn.parse() should work after espree was loaded.", () => { + const before = acorn.parse("var foo = bar /*world*/;"); + require("../../espree"); - var after = acorn.parse("var foo = bar /*world*/;"); + const after = acorn.parse("var foo = bar /*world*/;"); - assert.deepEqual(after, before); + assert.deepStrictEqual(after, before); }); }); diff --git a/tests/lib/attach-comments.js b/tests/lib/attach-comments.js index 5e2aa49f..ea809892 100644 --- a/tests/lib/attach-comments.js +++ b/tests/lib/attach-comments.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("chai").assert, +const assert = require("assert"), leche = require("leche"), path = require("path"), espree = require("../../espree"), @@ -20,25 +20,21 @@ var assert = require("chai").assert, // Setup //------------------------------------------------------------------------------ -var testFiles = shelljs.find("./tests/fixtures/attach-comments").filter(function(filename) { - return filename.indexOf(".src.js") > -1; -}).map(function(filename) { - return filename.substring(0, filename.length - 7); // strip off ".src.js" -// }).filter(function(filename) { -// return /line-and-block/.test(filename); -}); +const testFiles = shelljs.find("./tests/fixtures/attach-comments") + .filter(filename => filename.indexOf(".src.js") > -1) + .map(filename => filename.slice(0, filename.length - 7)); //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ -describe("attachComment: true", function() { +describe("attachComment: true", () => { - leche.withData(testFiles, function(filename) { - it("should produce correct AST when parsed with attachComments", function() { - var output = require(path.resolve(__dirname, "../../", filename + ".result.js")); - var input = shelljs.cat(filename + ".src.js"); - var result; + leche.withData(testFiles, filename => { + it("should produce correct AST when parsed with attachComments", () => { + const output = require(path.resolve(__dirname, "../../", `${filename}.result.js`)); + const input = shelljs.cat(`${filename}.src.js`); + let result; if (output.sourceType === "script") { result = espree.parse(input, { @@ -57,7 +53,7 @@ describe("attachComment: true", function() { }); } - assert.deepEqual(tester.getRaw(result), output); + assert.deepStrictEqual(tester.getRaw(result), output); }); }); diff --git a/tests/lib/ecma-features.js b/tests/lib/ecma-features.js index 15b0806e..cc5bd28b 100644 --- a/tests/lib/ecma-features.js +++ b/tests/lib/ecma-features.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("chai").assert, +const assert = require("assert"), leche = require("leche"), path = require("path"), espree = require("../../espree"), @@ -21,15 +21,11 @@ var assert = require("chai").assert, // Setup //------------------------------------------------------------------------------ -var FIXTURES_DIR = "./tests/fixtures/ecma-features"; +const FIXTURES_DIR = "./tests/fixtures/ecma-features"; -var testFiles = shelljs.find(FIXTURES_DIR).filter(function(filename) { - return filename.indexOf(".src.js") > -1; -}).map(function(filename) { - return filename.substring(FIXTURES_DIR.length - 1, filename.length - 7); // strip off ".src.js" -// }).filter(function(filename) { -// return /experimental/.test(filename); -}); +const testFiles = shelljs.find(FIXTURES_DIR) + .filter(filename => filename.indexOf(".src.js") > -1) + .map(filename => filename.slice(FIXTURES_DIR.length - 1, filename.length - 7)); //------------------------------------------------------------------------------ @@ -45,11 +41,11 @@ function shouldThrowInTestsWhenEnabled(feature) { return (feature === "impliedStrict"); } -describe("ecmaFeatures", function() { +describe("ecmaFeatures", () => { - var config; + let config; - beforeEach(function() { + beforeEach(() => { config = { loc: true, range: true, @@ -59,24 +55,25 @@ describe("ecmaFeatures", function() { }; }); - leche.withData(testFiles, function(filename) { + leche.withData(testFiles, filename => { + // Uncomment and fill in filename to focus on a single file // var filename = "jsx/invalid-matching-placeholder-in-closing-tag"; - var feature = path.dirname(filename), + const feature = path.dirname(filename), isPermissive = !shouldThrowInTestsWhenEnabled(feature), - code = shelljs.cat(path.resolve(FIXTURES_DIR, filename) + ".src.js"); + code = shelljs.cat(`${path.resolve(FIXTURES_DIR, filename)}.src.js`); - it("should parse correctly when " + feature + " is " + isPermissive, function() { + it(`should parse correctly when ${feature} is ${isPermissive}`, () => { config.ecmaFeatures[feature] = isPermissive; - var expected = require(path.resolve(__dirname, "../../", FIXTURES_DIR, filename) + ".result.js"); + const expected = require(`${path.resolve(__dirname, "../../", FIXTURES_DIR, filename)}.result.js`); tester.assertMatches(code, config, expected); }); - it("should throw an error when " + feature + " is " + !isPermissive, function() { + it(`should throw an error when ${feature} is ${!isPermissive}`, () => { config.ecmaFeatures[feature] = !isPermissive; - assert.throws(function() { + assert.throws(() => { espree.parse(code, config); }); diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index f15f7e15..bd533d4e 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -9,43 +9,38 @@ // Requirements //------------------------------------------------------------------------------ -var leche = require("leche"), +const leche = require("leche"), path = require("path"), shelljs = require("shelljs"), tester = require("./tester"), espree = require("../../espree"), - assert = require("chai").assert; + assert = require("assert"); // var espree = require("esprima-fb"); //------------------------------------------------------------------------------ // Setup //------------------------------------------------------------------------------ -var FIXTURES_DIR = "./tests/fixtures/ecma-version/"; +const FIXTURES_DIR = "./tests/fixtures/ecma-version/"; -var allTestFiles = shelljs.find(FIXTURES_DIR).filter(function(filename) { - return filename.indexOf(".src.js") > -1; -}).map(function(filename) { - return filename.substring(FIXTURES_DIR.length - 2, filename.length - 7); // strip off ".src.js" -}); +const allTestFiles = shelljs.find(FIXTURES_DIR) + .filter(filename => filename.indexOf(".src.js") > -1) + .map(filename => filename.slice(FIXTURES_DIR.length - 2, filename.length - 7)); // strip off ".src.js" -var scriptOnlyTestFiles = allTestFiles.filter(function(filename) { - return filename.indexOf("modules") === -1; -}); -var moduleTestFiles = allTestFiles.filter(function(filename) { - return filename.indexOf("not-strict") === -1 && filename.indexOf("edge-cases") === -1; -}); +const scriptOnlyTestFiles = allTestFiles.filter(filename => filename.indexOf("modules") === -1); + +const moduleTestFiles = allTestFiles.filter(filename => filename.indexOf("not-strict") === -1 && filename.indexOf("edge-cases") === -1); //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ -describe("ecmaVersion", function() { +describe("ecmaVersion", () => { - var config; + let config; - beforeEach(function() { + beforeEach(() => { config = { loc: true, range: true, @@ -54,19 +49,19 @@ describe("ecmaVersion", function() { }; }); - describe("Scripts", function() { + describe("Scripts", () => { - leche.withData(scriptOnlyTestFiles, function(filename) { + leche.withData(scriptOnlyTestFiles, filename => { - var version = filename.substring(0, filename.indexOf("/")); + const version = filename.slice(0, filename.indexOf("/")); // Uncomment and fill in filename to focus on a single file // var filename = "newTarget/simple-new-target"; - var code = shelljs.cat(path.resolve(FIXTURES_DIR, filename) + ".src.js"); + const code = shelljs.cat(`${path.resolve(FIXTURES_DIR, filename)}.src.js`); - it("should parse correctly when sourceType is script", function() { + it("should parse correctly when sourceType is script", () => { config.ecmaVersion = Number(version); - var expected = require(path.resolve(__dirname, "../../", FIXTURES_DIR, filename) + ".result.js"); + const expected = require(`${path.resolve(__dirname, "../../", FIXTURES_DIR, filename)}.result.js`); tester.assertMatches(code, config, expected); }); @@ -75,20 +70,20 @@ describe("ecmaVersion", function() { }); - describe("Modules", function() { + describe("Modules", () => { - leche.withData(moduleTestFiles, function(filename) { + leche.withData(moduleTestFiles, filename => { - var version = filename.substring(0, filename.indexOf("/")); - var code = shelljs.cat(path.resolve(FIXTURES_DIR, filename) + ".src.js"); + const version = filename.slice(0, filename.indexOf("/")); + const code = shelljs.cat(`${path.resolve(FIXTURES_DIR, filename)}.src.js`); - it("should parse correctly when sourceType is module", function() { - var expected; + it("should parse correctly when sourceType is module", () => { + let expected; try { - expected = require(path.resolve(__dirname, "../../", FIXTURES_DIR, filename) + ".module-result.js"); + expected = require(`${path.resolve(__dirname, "../../", FIXTURES_DIR, filename)}.module-result.js`); } catch (err) { - expected = require(path.resolve(__dirname, "../../", FIXTURES_DIR, filename) + ".result.js"); + expected = require(`${path.resolve(__dirname, "../../", FIXTURES_DIR, filename)}.result.js`); } config.ecmaVersion = Number(version); @@ -105,9 +100,9 @@ describe("ecmaVersion", function() { }); }); - describe("general", function() { - it("Should parse using 2015 instead of 6", function() { - var ast = espree.parse("let foo = bar;", { + describe("general", () => { + it("Should parse using 2015 instead of 6", () => { + const ast = espree.parse("let foo = bar;", { ecmaVersion: 2015, comment: true, tokens: true, @@ -115,11 +110,11 @@ describe("ecmaVersion", function() { loc: true }); - assert.deepEqual(tester.getRaw(ast), require("../fixtures/parse/all-pieces.json")); + assert.deepStrictEqual(tester.getRaw(ast), require("../fixtures/parse/all-pieces.json")); }); - it("Should throw error using invalid number", function() { - assert.throws(function() { + it("Should throw error using invalid number", () => { + assert.throws(() => { espree.parse( "let foo = bar;", { ecmaVersion: 32, @@ -127,12 +122,13 @@ describe("ecmaVersion", function() { tokens: true, range: true, loc: true - }); - }, "Invalid ecmaVersion."); + } + ); + }, /Invalid ecmaVersion/); }); - it("Should throw error using invalid year", function() { - assert.throws(function() { + it("Should throw error using invalid year", () => { + assert.throws(() => { espree.parse( "let foo = bar;", { ecmaVersion: 2050, @@ -140,8 +136,9 @@ describe("ecmaVersion", function() { tokens: true, range: true, loc: true - }); - }, "Invalid ecmaVersion."); + } + ); + }, /Invalid ecmaVersion/); }); }); diff --git a/tests/lib/libraries.js b/tests/lib/libraries.js index 40b1f14a..1aa4b20c 100644 --- a/tests/lib/libraries.js +++ b/tests/lib/libraries.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("chai").assert, +const assert = require("assert"), leche = require("leche"), path = require("path"), espree = require("../../espree"), @@ -20,34 +20,33 @@ var assert = require("chai").assert, // Setup //------------------------------------------------------------------------------ -var testFiles = shelljs.find("./tests/fixtures/libraries").filter(function(filename) { - return path.extname(filename) === ".js"; -}); +const testFiles = shelljs.find("./tests/fixtures/libraries").filter(filename => path.extname(filename) === ".js"); //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ -describe("Libraries", function() { +describe("Libraries", () => { + + leche.withData(testFiles, filename => { - leche.withData(testFiles, function(filename) { // var filename = "angular-1.2.5.js"; it("should produce correct AST when parsed", function() { - this.timeout(10000); // eslint-disable-line no-invalid-this + this.timeout(10000); // eslint-disable-line no-invalid-this - var output = shelljs.cat(path.resolve(__dirname, "../../", filename + ".result.json")); - var input = shelljs.cat(filename); + const output = shelljs.cat(path.resolve(__dirname, "../../", `${filename}.result.json`)); + const input = shelljs.cat(filename); - var result = JSON.stringify(tester.getRaw(espree.parse(input, { + const result = JSON.stringify(tester.getRaw(espree.parse(input, { loc: true, range: true, tokens: true, attachComment: true }))); - assert.equal(result, output); + assert.strictEqual(result, output); }); }); diff --git a/tests/lib/parse.js b/tests/lib/parse.js index 9eb1970c..acae3b99 100644 --- a/tests/lib/parse.js +++ b/tests/lib/parse.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("chai").assert, +const assert = require("assert"), espree = require("../../espree"), tester = require("./tester"); @@ -17,42 +17,42 @@ var assert = require("chai").assert, // Tests //------------------------------------------------------------------------------ -describe("parse()", function() { +describe("parse()", () => { - describe("modules", function() { + describe("modules", () => { - it("should have correct column number when strict mode error occurs", function() { + it("should have correct column number when strict mode error occurs", () => { try { espree.parse("function fn(a, a) {\n}", { sourceType: "module" }); } catch (err) { - assert.equal(err.column, 16); + assert.strictEqual(err.column, 16); } }); }); - describe("ES5", function() { + describe("ES5", () => { - it("should throw an error when using the y regex flag", function() { + it("should throw an error when using the y regex flag", () => { - assert.throws(function() { + assert.throws(() => { espree.parse("/./y"); }); }); - it("should throw an error when using the u regex flag", function() { + it("should throw an error when using the u regex flag", () => { - assert.throws(function() { + assert.throws(() => { espree.parse("/./u"); }); }); }); - describe("general", function() { - it("should output tokens, comments, locs, and ranges when called with those options", function() { - var ast = espree.parse("let foo = bar;", { + describe("general", () => { + it("should output tokens, comments, locs, and ranges when called with those options", () => { + const ast = espree.parse("let foo = bar;", { ecmaVersion: 6, comment: true, tokens: true, @@ -60,24 +60,24 @@ describe("parse()", function() { loc: true }); - assert.deepEqual(tester.getRaw(ast), require("../fixtures/parse/all-pieces.json")); + assert.deepStrictEqual(tester.getRaw(ast), require("../fixtures/parse/all-pieces.json")); }); - it("should reset lastToken on each parse", function() { + it("should reset lastToken on each parse", () => { espree.parse("var foo = bar;"); - var ast = espree.parse("//foo", { + const ast = espree.parse("//foo", { comment: true, tokens: true, range: true, loc: true }); - assert.deepEqual(ast.range, [0, 5]); - assert.deepEqual([ast.loc.start.line, ast.loc.start.column], [1, 0]); - assert.deepEqual([ast.loc.end.line, ast.loc.end.column], [1, 5]); + assert.deepStrictEqual(ast.range, [0, 5]); + assert.deepStrictEqual([ast.loc.start.line, ast.loc.start.column], [1, 0]); + assert.deepStrictEqual([ast.loc.end.line, ast.loc.end.column], [1, 5]); }); - it("should not mutate config", function() { + it("should not mutate config", () => { espree.parse("foo", Object.freeze({ ecmaFeatures: Object.freeze({}) })); }); diff --git a/tests/lib/tester.js b/tests/lib/tester.js index fda3dd1e..048b9280 100644 --- a/tests/lib/tester.js +++ b/tests/lib/tester.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("chai").assert, +const assert = require("assert"), espree = require("../../espree"); //------------------------------------------------------------------------------ @@ -24,7 +24,7 @@ var assert = require("chai").assert, * @private */ function getRaw(ast) { - return JSON.parse(JSON.stringify(ast, function(key, value) { + return JSON.parse(JSON.stringify(ast, (key, value) => { if ((key === "start" || key === "end") && typeof value === "number") { return undefined; // eslint-disable-line no-undefined } @@ -38,10 +38,10 @@ function getRaw(ast) { //------------------------------------------------------------------------------ module.exports = { - getRaw: getRaw, + getRaw, - assertMatches: function(code, config, expected) { - var result; + assertMatches(code, config, expected) { + let result; try { result = espree.parse(code, config); @@ -58,6 +58,6 @@ module.exports = { } - assert.deepEqual(result, getRaw(expected)); + assert.deepStrictEqual(result, getRaw(expected)); } }; diff --git a/tests/lib/tokenize.js b/tests/lib/tokenize.js index 7042091e..784a0567 100644 --- a/tests/lib/tokenize.js +++ b/tests/lib/tokenize.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("chai").assert, +const assert = require("assert"), espree = require("../../espree"), tester = require("./tester"); @@ -17,172 +17,185 @@ var assert = require("chai").assert, // Tests //------------------------------------------------------------------------------ -describe("tokenize()", function() { +describe("tokenize()", () => { - it("should produce tokens when using let", function() { - var tokens = espree.tokenize("let foo = bar;", { + it("should produce tokens when using let", () => { + const tokens = espree.tokenize("let foo = bar;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/let-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/let-result.tokens.js")); }); - it("should produce tokens when using const", function() { - var tokens = espree.tokenize("const foo = bar;", { + it("should produce tokens when using const", () => { + const tokens = espree.tokenize("const foo = bar;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/const-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/const-result.tokens.js")); }); - it("should produce tokens when using regular expression u flag", function() { - var tokens = espree.tokenize("var foo = /foo/u;", { + it("should produce tokens when using regular expression u flag", () => { + const tokens = espree.tokenize("var foo = /foo/u;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/regexp-u-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/regexp-u-result.tokens.js")); }); - it("should produce tokens when using regular expression y flag", function() { - var tokens = espree.tokenize("var foo = /foo/y;", { + it("should produce tokens when using regular expression y flag", () => { + const tokens = espree.tokenize("var foo = /foo/y;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/regexp-y-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/regexp-y-result.tokens.js")); }); - describe("templateStrings", function() { - it("should produce tokens when tokenizing simple template string", function() { - var tokens = espree.tokenize("var foo = `hi`;", { + describe("templateStrings", () => { + it("should produce tokens when tokenizing simple template string", () => { + const tokens = espree.tokenize("var foo = `hi`;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-simple-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-simple-result.tokens.js")); }); - it("should produce tokens when tokenizing template string with embedded variable", function() { - var tokens = espree.tokenize("var foo = `hi${bar}`;", { + it("should produce tokens when tokenizing template string with embedded variable", () => { + const tokens = espree.tokenize("var foo = `hi${bar}`;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-embedded-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-embedded-result.tokens.js")); }); - it("should produce tokens when tokenizing template string with embedded variable in function call", function() { - var tokens = espree.tokenize("var a; console.log(`${a}`, \"a\");", { + it("should produce tokens when tokenizing template string with embedded variable in function call", () => { + const tokens = espree.tokenize("var a; console.log(`${a}`, \"a\");", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-embedded2-result.tokens.js")); + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-embedded2-result.tokens.js")); }); - it("should produce tokens when parsing template string with embedded variable in function call and with tokens options on", function() { - var ast = espree.parse("var a; console.log(`${a}`, \"a\");", { + it("should produce tokens when parsing template string with embedded variable in function call and with tokens options on", () => { + const ast = espree.parse("var a; console.log(`${a}`, \"a\");", { ecmaVersion: 6, tokens: true, loc: true, range: true }); - assert.deepEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/template-string-embedded2-result.tokens.js")); + assert.deepStrictEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/template-string-embedded2-result.tokens.js")); }); - it("should produce tokens when tokenizing template string with embedded expressions", function() { - var tokens = espree.tokenize("var foo = `Hello ${b}. a + 5 = ${a + 5}`;", { + it("should produce tokens when tokenizing template string with embedded expressions", () => { + const tokens = espree.tokenize("var foo = `Hello ${b}. a + 5 = ${a + 5}`;", { ecmaVersion: 6, loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-expressions-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/template-string-expressions-result.tokens.js")); }); }); // Make sure we don't introduce the same regex parsing error as Esprima - it("should produce tokens when using regular expression wrapped in parens", function() { - var tokens = espree.tokenize("(/foo/).test(bar);", { + it("should produce tokens when using regular expression wrapped in parens", () => { + const tokens = espree.tokenize("(/foo/).test(bar);", { loc: true, range: true }); - assert.deepEqual(tester.getRaw(tokens), require("../fixtures/tokenize/regex-in-parens-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(tokens), require("../fixtures/tokenize/regex-in-parens-result.tokens.js")); }); - it("should produce tokens when using regular expression wrapped in parens using parse()", function() { - var ast = espree.parse("(/foo/).test(bar);", { + it("should produce tokens when using regular expression wrapped in parens using parse()", () => { + const ast = espree.parse("(/foo/).test(bar);", { loc: true, range: true, tokens: true }); - assert.deepEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/regex-in-parens-result.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/regex-in-parens-result.tokens.js")); }); - it("should produce tokens when using not operator", function() { - var ast = espree.parse("!x", { + it("should produce tokens when using not operator", () => { + const ast = espree.parse("!x", { loc: true, range: true, tokens: true }); - assert.deepEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/not-operator.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/not-operator.tokens.js")); }); - it("should produce tokens when using tilde operator", function() { - var ast = espree.parse("~x", { + it("should produce tokens when using tilde operator", () => { + const ast = espree.parse("~x", { loc: true, range: true, tokens: true }); - assert.deepEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/tilde-operator.tokens.js")); + + assert.deepStrictEqual(tester.getRaw(ast.tokens), require("../fixtures/tokenize/tilde-operator.tokens.js")); }); - it("should produce tokens when using a single identifier", function() { - var tokens = espree.tokenize("a"); - assert.deepEqual(tester.getRaw(tokens), [ { type: "Identifier", value: "a"}]); + it("should produce tokens when using a single identifier", () => { + const tokens = espree.tokenize("a"); + + assert.deepStrictEqual(tester.getRaw(tokens), [{ type: "Identifier", value: "a" }]); }); - it("should not remove } token followed by a template literal.", function() { - var tokens = espree.tokenize("const obj = {}\n`template${{}}!`", {ecmaVersion: 6}); - assert.deepEqual( + it("should not remove } token followed by a template literal.", () => { + let tokens = espree.tokenize("const obj = {}\n`template${{}}!`", { ecmaVersion: 6 }); + + assert.deepStrictEqual( tester.getRaw(tokens), [ - {type: "Keyword", value: "const"}, - {type: "Identifier", value: "obj"}, - {type: "Punctuator", value: "="}, - {type: "Punctuator", value: "{"}, - {type: "Punctuator", value: "}"}, - {type: "Template", value: "`template${"}, - {type: "Punctuator", value: "{"}, - {type: "Punctuator", value: "}"}, - {type: "Template", value: "}!`"} + { type: "Keyword", value: "const" }, + { type: "Identifier", value: "obj" }, + { type: "Punctuator", value: "=" }, + { type: "Punctuator", value: "{" }, + { type: "Punctuator", value: "}" }, + { type: "Template", value: "`template${" }, + { type: "Punctuator", value: "{" }, + { type: "Punctuator", value: "}" }, + { type: "Template", value: "}!`" } ] ); - tokens = espree.tokenize("if (a) { b }\n`template`", {ecmaVersion: 6}); - assert.deepEqual( + tokens = espree.tokenize("if (a) { b }\n`template`", { ecmaVersion: 6 }); + assert.deepStrictEqual( tester.getRaw(tokens), [ - {type: "Keyword", value: "if"}, - {type: "Punctuator", value: "("}, - {type: "Identifier", value: "a"}, - {type: "Punctuator", value: ")"}, - {type: "Punctuator", value: "{"}, - {type: "Identifier", value: "b"}, - {type: "Punctuator", value: "}"}, - {type: "Template", value: "`template`"} + { type: "Keyword", value: "if" }, + { type: "Punctuator", value: "(" }, + { type: "Identifier", value: "a" }, + { type: "Punctuator", value: ")" }, + { type: "Punctuator", value: "{" }, + { type: "Identifier", value: "b" }, + { type: "Punctuator", value: "}" }, + { type: "Template", value: "`template`" } ] ); }); - it("should not mutate config", function() { + it("should not mutate config", () => { espree.tokenize("foo", Object.freeze({ ecmaFeatures: Object.freeze({}) })); }); diff --git a/tools/convert.js b/tools/convert.js index ae28c522..292304e2 100644 --- a/tools/convert.js +++ b/tools/convert.js @@ -1,6 +1,5 @@ // simple script to convert the old Esprima giant file tests into small ones -var shelljs = require("shelljs"); var tests = require("../test/test"); Object.keys(tests).forEach(function(key) { diff --git a/tools/generate-test-fixture.js b/tools/generate-test-fixture.js index ac7d8293..c8b9de8e 100644 --- a/tools/generate-test-fixture.js +++ b/tools/generate-test-fixture.js @@ -232,7 +232,7 @@ } function jo(object, key) { - var stepback, partial, fin, separator, + var stepback, partial, fin, startStr = 'start', endStr = 'end', lineStr = 'line', colStr = 'column'; if (printStrictJSON) { diff --git a/tools/update-tests.js b/tools/update-tests.js index 21d1b7ad..113537e7 100644 --- a/tools/update-tests.js +++ b/tools/update-tests.js @@ -122,8 +122,7 @@ testFiles.forEach(function(filename) { versionFiles.forEach(function(filename) { - var feature = path.dirname(filename), - version = Number(filename.substring(0, filename.indexOf("/"))), + var version = Number(filename.substring(0, filename.indexOf("/"))), code = shelljs.cat(path.resolve(FIXTURES_VERSION_DIR, filename) + ".src.js"), config = { loc: true,