From 9c12ae2496fc9875df90da0823fe4020df307e39 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Mon, 3 Jul 2023 02:07:18 +0200 Subject: [PATCH 1/2] refactor: switch to eslint flat config --- .eslintignore | 4 --- .eslintrc.cjs | 38 -------------------- .gitignore | 1 + eslint.config.js | 54 ++++++++++++++++++++++++++++ espree.js | 7 ++-- lib/espree.js | 9 ++--- lib/token-translator.js | 12 +++---- package.json | 10 +++--- tests/lib/acorn-after-espree.js | 1 - tests/lib/commonjs.cjs | 1 - tests/lib/conditional-regex-value.js | 3 +- tests/lib/ecma-features.js | 3 +- tests/lib/ecma-version.js | 5 +-- tests/lib/libraries.js | 2 +- tests/lib/tester-test.js | 10 +++--- tests/lib/tester.js | 4 ++- tools/create-test.js | 1 - tools/sync-docs.js | 4 +-- tools/update-ecma-version-tests.js | 4 +-- tools/update-tests.js | 8 ++--- 20 files changed, 95 insertions(+), 86 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.cjs create mode 100644 eslint.config.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index e269a9ac..00000000 --- a/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -/node_modules -/tests/fixtures -/dist -tools/create-test-example.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 10c67363..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; - -module.exports = { - root: true, - extends: "eslint", - env: { - es2020: true - }, - settings: { - jsdoc: { - mode: "typescript" - } - }, - parserOptions: { - ecmaVersion: 2020, - sourceType: "module" - }, - overrides: [ - { - files: ["*.cjs"], - parserOptions: { - sourceType: "script" - } - }, - { - files: ["tests/lib/**"], - env: { - mocha: true - } - }, - { - files: ["tools/**"], - rules: { - "no-console": "off" - } - } - ] -}; diff --git a/.gitignore b/.gitignore index c9e42c6d..45c931cf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ dist npm-debug.log _test.js .idea +.vscode .nyc_output .eslint-release-info.json yarn.lock diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..4eab0a3c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,54 @@ +import eslintConfigEslint from "eslint-config-eslint"; +import nodeRecommendedModule from "eslint-plugin-n/configs/recommended-module.js"; +import nodeRecommendedScript from "eslint-plugin-n/configs/recommended-script.js"; +import globals from "globals"; + +export default [ + { + ignores: [ + "tests/fixtures/", + "dist/", + "coverage/", + "tools/create-test-example.js" + ] + }, + + // eslintConfigEslint[3] is eslint-plugin-n's recommended-script config + ...eslintConfigEslint.slice(0, 3), + { + files: ["**/*.js"], + ...nodeRecommendedModule + }, + { + files: ["**/*.cjs"], + ...nodeRecommendedScript + }, + ...eslintConfigEslint.slice(4), + + { + settings: { + jsdoc: { + mode: "typescript" + } + } + }, + { + files: ["tests/lib/**"], + languageOptions: { + globals: { + ...globals.mocha + } + } + }, + { + files: ["tools/**"], + rules: { + "no-console": "off", + "n/no-process-exit": "off", + "n/no-unsupported-features/es-syntax": ["error", { + version: ">=16.0.0", + ignores: ["modules"] + }] + } + } +]; diff --git a/espree.js b/espree.js index 97bda4bd..e9b11188 100644 --- a/espree.js +++ b/espree.js @@ -1,3 +1,5 @@ +/* eslint-disable jsdoc/no-multi-asterisks -- needed to preserve original formatting of licences */ + /** * @fileoverview Main Espree file that converts Acorn into Esprima output. * @@ -54,7 +56,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* eslint no-undefined:0, no-use-before-define: 0 */ + +/* eslint-enable jsdoc/no-multi-asterisks -- needed to preserve original formatting of licences */ import * as acorn from "acorn"; import jsx from "acorn-jsx"; @@ -111,7 +114,7 @@ export function tokenize(code, options) { // Ensure to collect tokens. if (!options || options.tokens !== true) { - options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign + options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign -- stylistic choice } return new Parser(options, code).tokenize(); diff --git a/lib/espree.js b/lib/espree.js index 262dd276..2be1b56d 100644 --- a/lib/espree.js +++ b/lib/espree.js @@ -1,4 +1,5 @@ -/* eslint-disable no-param-reassign*/ +/* eslint no-param-reassign: 0 -- stylistic choice */ + import TokenTranslator from "./token-translator.js"; import { normalizeOptions } from "./options.js"; @@ -109,7 +110,7 @@ export default () => Parser => { allowReturnOutsideFunction: options.allowReturnOutsideFunction, // Collect tokens - onToken: token => { + onToken(token) { if (tokenTranslator) { // Use `tokens`, `ecmaVersion`, and `jsxAttrValueToken` in the state. @@ -121,7 +122,7 @@ export default () => Parser => { }, // Collect comments - onComment: (block, text, start, end, startLoc, endLoc) => { + onComment(block, text, start, end, startLoc, endLoc) { if (state.comments) { const comment = convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc, code); @@ -314,7 +315,7 @@ export default () => Parser => { * on extra so that when tokens are converted, the next token will be switched * to JSXText via onToken. */ - jsx_readString(quote) { // eslint-disable-line camelcase + jsx_readString(quote) { // eslint-disable-line camelcase -- required by API const result = super.jsx_readString(quote); if (this.type === tokTypes.string) { diff --git a/lib/token-translator.js b/lib/token-translator.js index 9aa5e22e..2a915fb5 100644 --- a/lib/token-translator.js +++ b/lib/token-translator.js @@ -2,7 +2,6 @@ * @fileoverview Translates tokens between Acorn format and Esprima format. * @author Nicholas C. Zakas */ -/* eslint no-underscore-dangle: 0 */ //------------------------------------------------------------------------------ // Requirements @@ -180,8 +179,7 @@ TokenTranslator.prototype = { */ onToken(token, extra) { - const that = this, - tt = this._acornTokTypes, + const tt = this._acornTokTypes, tokens = extra.tokens, templateTokens = this._tokens; @@ -191,10 +189,10 @@ TokenTranslator.prototype = { * @returns {void} * @private */ - function translateTemplateTokens() { - tokens.push(convertTemplatePart(that._tokens, that._code)); - that._tokens = []; - } + const translateTemplateTokens = () => { + tokens.push(convertTemplatePart(this._tokens, this._code)); + this._tokens = []; + }; if (token.type === tt.eof) { diff --git a/package.json b/package.json index 943fb59d..c10a7277 100644 --- a/package.json +++ b/package.json @@ -42,12 +42,12 @@ "@rollup/plugin-node-resolve": "^11.2.0", "c8": "^7.11.0", "chai": "^4.3.6", - "eslint": "^8.13.0", - "eslint-config-eslint": "^7.0.0", - "eslint-plugin-jsdoc": "^39.2.4", - "eslint-plugin-node": "^11.1.0", + "eslint": "^8.44.0", + "eslint-config-eslint": "^8.0.0", + "eslint-plugin-n": "^16.0.0", "eslint-release": "^3.2.0", "esprima-fb": "^8001.2001.0-dev-harmony-fb", + "globals": "^13.20.0", "lint-staged": "^13.2.0", "mocha": "^9.2.2", "npm-run-all": "^4.1.5", @@ -71,7 +71,7 @@ "unit:esm": "c8 mocha --color --reporter progress --timeout 30000 'tests/lib/**/*.js'", "unit:cjs": "mocha --color --reporter progress --timeout 30000 tests/lib/commonjs.cjs", "test": "npm-run-all -p unit lint", - "lint": "eslint .", + "lint": "eslint . --report-unused-disable-directives", "fixlint": "npm run lint -- --fix", "build": "rollup -c rollup.config.js", "build:debug": "npm run build -- -m", diff --git a/tests/lib/acorn-after-espree.js b/tests/lib/acorn-after-espree.js index d4214a1e..7aee31f4 100644 --- a/tests/lib/acorn-after-espree.js +++ b/tests/lib/acorn-after-espree.js @@ -19,7 +19,6 @@ describe("acorn", () => { it("acorn.parse() should work after espree was loaded.", async () => { const before = acorn.parse("var foo = bar /*world*/;", { ecmaVersion: 5 }); - // eslint-disable-next-line node/no-unsupported-features/es-syntax await import("../../espree.js"); const after = acorn.parse("var foo = bar /*world*/;", { ecmaVersion: 5 }); diff --git a/tests/lib/commonjs.cjs b/tests/lib/commonjs.cjs index 02f76202..ce892980 100644 --- a/tests/lib/commonjs.cjs +++ b/tests/lib/commonjs.cjs @@ -3,7 +3,6 @@ * @author Mike Reinstein */ -// eslint-disable-next-line strict "use strict"; //------------------------------------------------------------------------------ diff --git a/tests/lib/conditional-regex-value.js b/tests/lib/conditional-regex-value.js index 192df527..1ba3b951 100644 --- a/tests/lib/conditional-regex-value.js +++ b/tests/lib/conditional-regex-value.js @@ -16,8 +16,7 @@ export default function(literalNode) { if (literalNode.regex) { try { literalNode.value = new RegExp(literalNode.regex.pattern, literalNode.regex.flags); - /* eslint-disable no-unused-vars */ - } catch (e) { + } catch { literalNode.value = null; } } diff --git a/tests/lib/ecma-features.js b/tests/lib/ecma-features.js index 5ffeb200..6c44bb2c 100644 --- a/tests/lib/ecma-features.js +++ b/tests/lib/ecma-features.js @@ -15,7 +15,7 @@ import { fileURLToPath, pathToFileURL } from "url"; import tester from "./tester.js"; -// eslint-disable-next-line no-underscore-dangle +// eslint-disable-next-line no-underscore-dangle -- Conventional const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -68,7 +68,6 @@ describe("ecmaFeatures", () => { it(`should parse correctly when ${feature} is ${isPermissive}`, async () => { config.ecmaFeatures[feature] = isPermissive; - // eslint-disable-next-line node/no-unsupported-features/es-syntax const expected = await import(`${pathToFileURL(path.resolve(__dirname, "../../", FIXTURES_DIR, filename)).href}.result.js`); tester.assertMatches(code, config, expected.default); diff --git a/tests/lib/ecma-version.js b/tests/lib/ecma-version.js index 348cac0f..3f175e1d 100644 --- a/tests/lib/ecma-version.js +++ b/tests/lib/ecma-version.js @@ -16,7 +16,7 @@ import assert from "assert"; import { fileURLToPath, pathToFileURL } from "url"; -// eslint-disable-next-line no-underscore-dangle +// eslint-disable-next-line no-underscore-dangle -- Conventional const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -73,7 +73,6 @@ describe("ecmaVersion", () => { } const absolutePath = path.resolve(__dirname, FIXTURES_DIR, filename.slice(1)); - // eslint-disable-next-line node/no-unsupported-features/es-syntax const expected = await import(`${pathToFileURL(absolutePath).href}.result.js`); tester.assertMatches(code, config, expected.default); @@ -97,10 +96,8 @@ describe("ecmaVersion", () => { let expected; try { - // eslint-disable-next-line node/no-unsupported-features/es-syntax expected = await import(`${pathToFileURL(absolutePath).href}.module-result.js`); } catch { - // eslint-disable-next-line node/no-unsupported-features/es-syntax expected = await import(`${pathToFileURL(absolutePath).href}.result.js`); } diff --git a/tests/lib/libraries.js b/tests/lib/libraries.js index 6903853b..e1f88766 100644 --- a/tests/lib/libraries.js +++ b/tests/lib/libraries.js @@ -14,7 +14,7 @@ import * as espree from "../../espree.js"; import assert from "assert"; import { fileURLToPath } from "url"; -// eslint-disable-next-line no-underscore-dangle +// eslint-disable-next-line no-underscore-dangle -- Conventional const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/tests/lib/tester-test.js b/tests/lib/tester-test.js index 420c3ed8..42917346 100644 --- a/tests/lib/tester-test.js +++ b/tests/lib/tester-test.js @@ -42,9 +42,9 @@ describe("Tester", () => { it("should keep RegExp objects", () => { assert.deepStrictEqual( - // eslint-disable-next-line require-unicode-regexp + // eslint-disable-next-line require-unicode-regexp -- non-unicode regexp is needed for the test getRaw({ value: /foo/ }), - // eslint-disable-next-line require-unicode-regexp + // eslint-disable-next-line require-unicode-regexp -- non-unicode regexp is needed for the test { value: /foo/ } ); assert.deepStrictEqual( @@ -74,7 +74,7 @@ describe("Tester", () => { function test(ast) { const code = getAstCode(ast); - // eslint-disable-next-line no-new-func + // eslint-disable-next-line no-new-func -- it's okay to eval code in tests return Function(`return ${code};`)(); } @@ -115,9 +115,9 @@ describe("Tester", () => { it("should keep RegExp objects", () => { assert.deepStrictEqual( - // eslint-disable-next-line require-unicode-regexp + // eslint-disable-next-line require-unicode-regexp -- non-unicode regexp is needed for the test test({ value: /foo/ }), - // eslint-disable-next-line require-unicode-regexp + // eslint-disable-next-line require-unicode-regexp -- non-unicode regexp is needed for the test { value: /foo/ } ); assert.deepStrictEqual( diff --git a/tests/lib/tester.js b/tests/lib/tester.js index 4bbddd98..81e7e86c 100644 --- a/tests/lib/tester.js +++ b/tests/lib/tester.js @@ -36,13 +36,14 @@ const ReplacedStringLiteralPattern = new RegExp( * @returns {any} If `value` parameter is a value JSON cannot handle, this * function returns a string value. If `key` parameter is `"start"` or `"end"`, * returns `undefined`. Otherwise, returns `value` parameter as is. + * @throws {Error} If `value` is undefined * @private */ function replaceToSaveNonJSONValues(key, value) { // Remove `start` and `end` properties because of non-standard. if ((key === "start" || key === "end") && typeof value === "number") { - return undefined; // eslint-disable-line no-undefined + return void 0; } // Save the values JSON cannot handle. @@ -155,6 +156,7 @@ function getAstCode(ast) { * @param {Object} parserOptions The parser options to parse. * @param {Object} [options] The options. * @param {boolean} [options.rethrowSyntaxError = false] The flag to rethrow syntax errors. + * @throws {Error} If options.rethrowSyntaxError = true, rethrows syntax errors * @returns {Object} The normalized AST. */ function getExpectedResult(jsCodeText, parserOptions, { rethrowSyntaxError = false } = {}) { diff --git a/tools/create-test.js b/tools/create-test.js index 72adf0d2..20c731c0 100644 --- a/tools/create-test.js +++ b/tools/create-test.js @@ -1,4 +1,3 @@ -/* eslint-disable node/no-process-exit */ /** * @fileoverview A simple script to help generate test cases * @author Nicholas C. Zakas diff --git a/tools/sync-docs.js b/tools/sync-docs.js index e489e2a7..0457ebd0 100644 --- a/tools/sync-docs.js +++ b/tools/sync-docs.js @@ -2,15 +2,15 @@ * @fileoverview Build file * @author nzakas */ -/* global cp, echo, rm */ -/* eslint no-console: 0*/ //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ import "shelljs/make.js"; +/* global cp, echo, rm -- declared in `shelljs/make.js` */ + //------------------------------------------------------------------------------ // Data diff --git a/tools/update-ecma-version-tests.js b/tools/update-ecma-version-tests.js index bce50743..21068e6c 100644 --- a/tools/update-ecma-version-tests.js +++ b/tools/update-ecma-version-tests.js @@ -1,12 +1,12 @@ /** * @fileoverview Generate `.result.js` from `.src.js` in * `tests/fixtures/ecma-version//**` directory. - * @author Nicholas C. Zakas - * @author Toru Nagashima * * Usage: * node tools/update-ecma-version-tests.js * + * @author Nicholas C. Zakas + * @author Toru Nagashima */ //------------------------------------------------------------------------------ diff --git a/tools/update-tests.js b/tools/update-tests.js index 670cee3f..16aef31b 100644 --- a/tools/update-tests.js +++ b/tools/update-tests.js @@ -1,11 +1,11 @@ /** * @fileoverview A simple script to update existing tests to reflect new * parser changes. - * @author Nicholas C. Zakas * * Usage: * node tools/update-tests.js * + * @author Nicholas C. Zakas */ //------------------------------------------------------------------------------ @@ -31,7 +31,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); */ function getTestFilenames(directory) { return shelljs.find(directory).filter(filename => - filename.indexOf(".src.js") > -1).map(filename => + filename.includes(".src.js")).map(filename => filename.slice(directory.length - 1, filename.length - 7)); // strip off ".src.js" } @@ -42,8 +42,8 @@ function getTestFilenames(directory) { */ function getLibraryFilenames(directory) { return shelljs.find(directory).filter(filename => - filename.indexOf(".js") > -1 && - filename.indexOf(".result.js") === -1).map(filename => + filename.includes(".js") && + !filename.includes(".result.js")).map(filename => filename.slice(directory.length - 1)); // strip off directory } From ef5bdf26c758afdd0482c58a68b54a153aead930 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Tue, 4 Jul 2023 16:08:34 +0200 Subject: [PATCH 2/2] rename eslintConfigESLint variable --- eslint.config.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 4eab0a3c..1bdf5de1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,4 +1,4 @@ -import eslintConfigEslint from "eslint-config-eslint"; +import eslintConfigESLint from "eslint-config-eslint"; import nodeRecommendedModule from "eslint-plugin-n/configs/recommended-module.js"; import nodeRecommendedScript from "eslint-plugin-n/configs/recommended-script.js"; import globals from "globals"; @@ -13,8 +13,8 @@ export default [ ] }, - // eslintConfigEslint[3] is eslint-plugin-n's recommended-script config - ...eslintConfigEslint.slice(0, 3), + // eslintConfigESLint[3] is eslint-plugin-n's recommended-script config + ...eslintConfigESLint.slice(0, 3), { files: ["**/*.js"], ...nodeRecommendedModule @@ -23,7 +23,7 @@ export default [ files: ["**/*.cjs"], ...nodeRecommendedScript }, - ...eslintConfigEslint.slice(4), + ...eslintConfigESLint.slice(4), { settings: {