Skip to content

Commit 3d02b66

Browse files
sosukesuzukiljharb
authored andcommitted
[New] no-dynamic-require: support dynamic import with espree
1 parent a929394 commit 3d02b66

File tree

3 files changed

+146
-75
lines changed

3 files changed

+146
-75
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
88

99
### Added
1010
- [`no-named-default`, `no-default-export`, `prefer-default-export`, `no-named-export`, `export`, `named`, `namespace`, `no-unused-modules`]: support arbitrary module namespace names ([#2358], thanks [@sosukesuzuki])
11+
- [`no-dynamic-require`]: support dynamic import with espree ([#2371], thanks [@sosukesuzuki])
1112

1213
### Changed
1314
- [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
@@ -963,6 +964,7 @@ for info on changes for earlier releases.
963964

964965
[`memo-parser`]: ./memo-parser/README.md
965966

967+
[#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
966968
[#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
967969
[#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
968970
[#2358]: https://github.com/import-js/eslint-plugin-import/pull/2358

src/rules/no-dynamic-require.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ function isStaticValue(arg) {
1919
(arg.type === 'TemplateLiteral' && arg.expressions.length === 0);
2020
}
2121

22+
const dynamicImportErrorMessage = 'Calls to import() should use string literals';
23+
2224
module.exports = {
2325
meta: {
2426
type: 'suggestion',
@@ -55,10 +57,19 @@ module.exports = {
5557
if (options.esmodule && isDynamicImport(node)) {
5658
return context.report({
5759
node,
58-
message: 'Calls to import() should use string literals',
60+
message: dynamicImportErrorMessage,
5961
});
6062
}
6163
},
64+
ImportExpression(node) {
65+
if (!options.esmodule || isStaticValue(node.source)) {
66+
return;
67+
}
68+
return context.report({
69+
node,
70+
message: dynamicImportErrorMessage,
71+
});
72+
},
6273
};
6374
},
6475
};

tests/src/rules/no-dynamic-require.js

+132-74
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { parsers, test } from '../utils';
1+
import { parsers, test, testVersion } from '../utils';
22

33
import { RuleTester } from 'eslint';
4+
import flatMap from 'array.prototype.flatmap';
45

56
const ruleTester = new RuleTester();
67
const rule = require('rules/no-dynamic-require');
@@ -28,56 +29,93 @@ ruleTester.run('no-dynamic-require', rule, {
2829
test({ code: 'var foo = require("@scope/foo")' }),
2930

3031
//dynamic import
31-
test({
32-
code: 'import("foo")',
33-
parser: parsers.BABEL_OLD,
34-
options: [{ esmodule: true }],
35-
}),
36-
test({
37-
code: 'import(`foo`)',
38-
parser: parsers.BABEL_OLD,
39-
options: [{ esmodule: true }],
40-
}),
41-
test({
42-
code: 'import("./foo")',
43-
parser: parsers.BABEL_OLD,
44-
options: [{ esmodule: true }],
45-
}),
46-
test({
47-
code: 'import("@scope/foo")',
48-
parser: parsers.BABEL_OLD,
49-
options: [{ esmodule: true }],
50-
}),
51-
test({
52-
code: 'var foo = import("foo")',
53-
parser: parsers.BABEL_OLD,
54-
options: [{ esmodule: true }],
55-
}),
56-
test({
57-
code: 'var foo = import(`foo`)',
58-
parser: parsers.BABEL_OLD,
59-
options: [{ esmodule: true }],
60-
}),
61-
test({
62-
code: 'var foo = import("./foo")',
63-
parser: parsers.BABEL_OLD,
64-
options: [{ esmodule: true }],
65-
}),
66-
test({
67-
code: 'var foo = import("@scope/foo")',
68-
parser: parsers.BABEL_OLD,
69-
options: [{ esmodule: true }],
70-
}),
71-
test({
72-
code: 'import("../" + name)',
73-
errors: [dynamicImportError],
74-
parser: parsers.BABEL_OLD,
75-
options: [{ esmodule: false }],
76-
}),
77-
test({
78-
code: 'import(`../${name}`)',
79-
errors: [dynamicImportError],
80-
parser: parsers.BABEL_OLD,
32+
...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => {
33+
const _test =
34+
parser === parsers.ESPREE
35+
? (testObj) => testVersion('>= 6.2.0', () => testObj)
36+
: (testObj) => test(testObj);
37+
return [].concat(
38+
_test({
39+
code: 'import("foo")',
40+
options: [{ esmodule: true }],
41+
parser,
42+
parserOptions: {
43+
ecmaVersion: 2020,
44+
},
45+
}),
46+
_test({
47+
code: 'import(`foo`)',
48+
options: [{ esmodule: true }],
49+
parser,
50+
parserOptions: {
51+
ecmaVersion: 2020,
52+
},
53+
}),
54+
_test({
55+
code: 'import("./foo")',
56+
options: [{ esmodule: true }],
57+
parser,
58+
parserOptions: {
59+
ecmaVersion: 2020,
60+
},
61+
}),
62+
_test({
63+
code: 'import("@scope/foo")',
64+
options: [{ esmodule: true }],
65+
parser,
66+
parserOptions: {
67+
ecmaVersion: 2020,
68+
},
69+
}),
70+
_test({
71+
code: 'var foo = import("foo")',
72+
options: [{ esmodule: true }],
73+
parser,
74+
parserOptions: {
75+
ecmaVersion: 2020,
76+
},
77+
}),
78+
_test({
79+
code: 'var foo = import(`foo`)',
80+
options: [{ esmodule: true }],
81+
parser,
82+
parserOptions: {
83+
ecmaVersion: 2020,
84+
},
85+
}),
86+
_test({
87+
code: 'var foo = import("./foo")',
88+
options: [{ esmodule: true }],
89+
parser,
90+
parserOptions: {
91+
ecmaVersion: 2020,
92+
},
93+
}),
94+
_test({
95+
code: 'var foo = import("@scope/foo")',
96+
options: [{ esmodule: true }],
97+
parser,
98+
parserOptions: {
99+
ecmaVersion: 2020,
100+
},
101+
}),
102+
_test({
103+
code: 'import("../" + name)',
104+
errors: [dynamicImportError],
105+
parser,
106+
parserOptions: {
107+
ecmaVersion: 2020,
108+
},
109+
}),
110+
_test({
111+
code: 'import(`../${name}`)',
112+
errors: [dynamicImportError],
113+
parser,
114+
parserOptions: {
115+
ecmaVersion: 2020,
116+
},
117+
}),
118+
);
81119
}),
82120
],
83121
invalid: [
@@ -104,29 +142,49 @@ ruleTester.run('no-dynamic-require', rule, {
104142
}),
105143

106144
// dynamic import
107-
test({
108-
code: 'import("../" + name)',
109-
errors: [dynamicImportError],
110-
parser: parsers.BABEL_OLD,
111-
options: [{ esmodule: true }],
112-
}),
113-
test({
114-
code: 'import(`../${name}`)',
115-
errors: [dynamicImportError],
116-
parser: parsers.BABEL_OLD,
117-
options: [{ esmodule: true }],
118-
}),
119-
test({
120-
code: 'import(name)',
121-
errors: [dynamicImportError],
122-
parser: parsers.BABEL_OLD,
123-
options: [{ esmodule: true }],
124-
}),
125-
test({
126-
code: 'import(name())',
127-
errors: [dynamicImportError],
128-
parser: parsers.BABEL_OLD,
129-
options: [{ esmodule: true }],
145+
...flatMap([parsers.ESPREE, parsers.BABEL_OLD], (parser) => {
146+
const _test =
147+
parser === parsers.ESPREE
148+
? (testObj) => testVersion('>= 6.2.0', () => testObj)
149+
: (testObj) => test(testObj);
150+
return [].concat(
151+
_test({
152+
code: 'import("../" + name)',
153+
errors: [dynamicImportError],
154+
options: [{ esmodule: true }],
155+
parser,
156+
parserOptions: {
157+
ecmaVersion: 2020,
158+
},
159+
}),
160+
_test({
161+
code: 'import(`../${name}`)',
162+
errors: [dynamicImportError],
163+
options: [{ esmodule: true }],
164+
parser,
165+
parserOptions: {
166+
ecmaVersion: 2020,
167+
},
168+
}),
169+
_test({
170+
code: 'import(name)',
171+
errors: [dynamicImportError],
172+
options: [{ esmodule: true }],
173+
parser,
174+
parserOptions: {
175+
ecmaVersion: 2020,
176+
},
177+
}),
178+
_test({
179+
code: 'import(name())',
180+
errors: [dynamicImportError],
181+
options: [{ esmodule: true }],
182+
parser,
183+
parserOptions: {
184+
ecmaVersion: 2020,
185+
},
186+
}),
187+
);
130188
}),
131189
test({
132190
code: 'require(`foo${x}`)',

0 commit comments

Comments
 (0)