From 1a3c58fb1638565f755db07c1587fc5212f3021a Mon Sep 17 00:00:00 2001 From: sosukesuzuki Date: Tue, 25 Jan 2022 22:21:00 +0900 Subject: [PATCH] [New] `no-dynamic-require`: support dynamic import with espree --- src/rules/no-dynamic-require.js | 13 +- tests/src/rules/no-dynamic-require.js | 206 +++++++++++++++++--------- 2 files changed, 144 insertions(+), 75 deletions(-) diff --git a/src/rules/no-dynamic-require.js b/src/rules/no-dynamic-require.js index 8267fd26e9..27e9a957a7 100644 --- a/src/rules/no-dynamic-require.js +++ b/src/rules/no-dynamic-require.js @@ -19,6 +19,8 @@ function isStaticValue(arg) { (arg.type === 'TemplateLiteral' && arg.expressions.length === 0); } +const dynamicImportErrorMessage = 'Calls to import() should use string literals'; + module.exports = { meta: { type: 'suggestion', @@ -55,10 +57,19 @@ module.exports = { if (options.esmodule && isDynamicImport(node)) { return context.report({ node, - message: 'Calls to import() should use string literals', + message: dynamicImportErrorMessage, }); } }, + ImportExpression(node) { + if (!options.esmodule || isStaticValue(node.source)) { + return; + } + return context.report({ + node, + message: dynamicImportErrorMessage, + }); + }, }; }, }; diff --git a/tests/src/rules/no-dynamic-require.js b/tests/src/rules/no-dynamic-require.js index 368ec11935..0b141ccd76 100644 --- a/tests/src/rules/no-dynamic-require.js +++ b/tests/src/rules/no-dynamic-require.js @@ -1,6 +1,7 @@ -import { parsers, test } from '../utils'; +import { parsers, test, testVersion } from '../utils'; import { RuleTester } from 'eslint'; +import flatMap from 'array.prototype.flatmap'; const ruleTester = new RuleTester(); const rule = require('rules/no-dynamic-require'); @@ -28,56 +29,93 @@ ruleTester.run('no-dynamic-require', rule, { test({ code: 'var foo = require("@scope/foo")' }), //dynamic import - test({ - code: 'import("foo")', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import(`foo`)', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import("./foo")', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import("@scope/foo")', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'var foo = import("foo")', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'var foo = import(`foo`)', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'var foo = import("./foo")', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'var foo = import("@scope/foo")', - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import("../" + name)', - errors: [dynamicImportError], - parser: parsers.BABEL_OLD, - options: [{ esmodule: false }], - }), - test({ - code: 'import(`../${name}`)', - errors: [dynamicImportError], - parser: parsers.BABEL_OLD, + ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => { + const _test = + parser === parsers.ESPREE + ? (testObj) => testVersion('>= 6.2.0', () => testObj) + : (testObj) => test(testObj); + return [].concat( + _test({ + code: 'import("foo")', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import(`foo`)', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import("./foo")', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import("@scope/foo")', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'var foo = import("foo")', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'var foo = import(`foo`)', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'var foo = import("./foo")', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'var foo = import("@scope/foo")', + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import("../" + name)', + errors: [dynamicImportError], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import(`../${name}`)', + errors: [dynamicImportError], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + ); }), ], invalid: [ @@ -104,29 +142,49 @@ ruleTester.run('no-dynamic-require', rule, { }), // dynamic import - test({ - code: 'import("../" + name)', - errors: [dynamicImportError], - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import(`../${name}`)', - errors: [dynamicImportError], - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import(name)', - errors: [dynamicImportError], - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], - }), - test({ - code: 'import(name())', - errors: [dynamicImportError], - parser: parsers.BABEL_OLD, - options: [{ esmodule: true }], + ...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => { + const _test = + parser === parsers.ESPREE + ? (testObj) => testVersion('>= 6.2.0', () => testObj) + : (testObj) => test(testObj); + return [].concat( + _test({ + code: 'import("../" + name)', + errors: [dynamicImportError], + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import(`../${name}`)', + errors: [dynamicImportError], + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import(name)', + errors: [dynamicImportError], + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + _test({ + code: 'import(name())', + errors: [dynamicImportError], + options: [{ esmodule: true }], + parser, + parserOptions: { + ecmaVersion: 2020, + }, + }), + ); }), test({ code: 'require(`foo${x}`)',