Skip to content

Commit 93e060f

Browse files
ljqxljharb
authored andcommitted
[Fix] [Generic Import Callback] Make callback for all imports once in rules
Fixes #1230.
1 parent 2ae68c1 commit 93e060f

10 files changed

+130
-93
lines changed

CHANGELOG.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
1515
- [`no-unused-modules`]: make type imports mark a module as used (fixes #1924) ([#1974], thanks [@cherryblossom000])
1616
- [`import/no-cycle`]: fix perf regression ([#1944], thanks [@Blasz])
1717

18+
### Changed
19+
- [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx])
20+
1821
## [2.22.1] - 2020-09-27
1922
### Fixed
2023
- [`default`]/TypeScript: avoid crash on `export =` with a MemberExpression ([#1841], thanks [@ljharb])
@@ -867,6 +870,7 @@ for info on changes for earlier releases.
867870
[#1253]: https://github.com/benmosher/eslint-plugin-import/pull/1253
868871
[#1248]: https://github.com/benmosher/eslint-plugin-import/pull/1248
869872
[#1238]: https://github.com/benmosher/eslint-plugin-import/pull/1238
873+
[#1237]: https://github.com/benmosher/eslint-plugin-import/pull/1237
870874
[#1235]: https://github.com/benmosher/eslint-plugin-import/pull/1235
871875
[#1234]: https://github.com/benmosher/eslint-plugin-import/pull/1234
872876
[#1232]: https://github.com/benmosher/eslint-plugin-import/pull/1232
@@ -1295,4 +1299,4 @@ for info on changes for earlier releases.
12951299
[@straub]: https://github.com/straub
12961300
[@andreubotella]: https://github.com/andreubotella
12971301
[@cherryblossom000]: https://github.com/cherryblossom000
1298-
[@Blasz]: https://github.com/Blasz
1302+
[@Blasz]: https://github.com/Blasz

src/rules/extensions.js

+4-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from 'path';
22

33
import resolve from 'eslint-module-utils/resolve';
44
import { isBuiltIn, isExternalModule, isScoped, isScopedModule } from '../core/importType';
5+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
56
import docsUrl from '../docsUrl';
67

78
const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] };
@@ -134,12 +135,10 @@ module.exports = {
134135
return false;
135136
}
136137

137-
function checkFileExtension(node) {
138-
const { source } = node;
139-
138+
function checkFileExtension(source) {
140139
// bail if the declaration doesn't have a source, e.g. "export { foo };"
141140
if (!source) return;
142-
141+
143142
const importPathWithQueryString = source.value;
144143

145144
// don't enforce anything on builtins
@@ -181,9 +180,6 @@ module.exports = {
181180
}
182181
}
183182

184-
return {
185-
ImportDeclaration: checkFileExtension,
186-
ExportNamedDeclaration: checkFileExtension,
187-
};
183+
return moduleVisitor(checkFileExtension, { commonjs: true });
188184
},
189185
};

src/rules/max-dependencies.js

+6-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import isStaticRequire from '../core/staticRequire';
1+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
22
import docsUrl from '../docsUrl';
33

44
const DEFAULT_MAX = 10;
@@ -36,23 +36,13 @@ module.exports = {
3636
const dependencies = new Set(); // keep track of dependencies
3737
let lastNode; // keep track of the last node to report on
3838

39-
return {
40-
ImportDeclaration(node) {
41-
dependencies.add(node.source.value);
42-
lastNode = node.source;
43-
},
44-
45-
CallExpression(node) {
46-
if (isStaticRequire(node)) {
47-
const [ requirePath ] = node.arguments;
48-
dependencies.add(requirePath.value);
49-
lastNode = node;
50-
}
51-
},
52-
39+
return Object.assign({
5340
'Program:exit': function () {
5441
countDependencies(dependencies, lastNode, context);
5542
},
56-
};
43+
}, moduleVisitor((source) => {
44+
dependencies.add(source.value);
45+
lastNode = source;
46+
}, { commonjs: true }));
5747
},
5848
};

src/rules/no-extraneous-dependencies.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ module.exports = {
207207
allowBundledDeps: testConfig(options.bundledDependencies, filename) !== false,
208208
};
209209

210-
return moduleVisitor(node => {
211-
reportIfMissing(context, deps, depsOptions, node, node.value);
210+
return moduleVisitor((source, node) => {
211+
reportIfMissing(context, deps, depsOptions, node, source.value);
212212
}, { commonjs: true });
213213
},
214214
};

src/rules/no-internal-modules.js

+4-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import minimatch from 'minimatch';
22

33
import resolve from 'eslint-module-utils/resolve';
44
import importType from '../core/importType';
5-
import isStaticRequire from '../core/staticRequire';
5+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
66
import docsUrl from '../docsUrl';
77

88
module.exports = {
@@ -87,24 +87,8 @@ module.exports = {
8787
}
8888
}
8989

90-
return {
91-
ImportDeclaration(node) {
92-
checkImportForReaching(node.source.value, node.source);
93-
},
94-
ExportAllDeclaration(node) {
95-
checkImportForReaching(node.source.value, node.source);
96-
},
97-
ExportNamedDeclaration(node) {
98-
if (node.source) {
99-
checkImportForReaching(node.source.value, node.source);
100-
}
101-
},
102-
CallExpression(node) {
103-
if (isStaticRequire(node)) {
104-
const [ firstArgument ] = node.arguments;
105-
checkImportForReaching(firstArgument.value, firstArgument);
106-
}
107-
},
108-
};
90+
return moduleVisitor((source) => {
91+
checkImportForReaching(source.value, source);
92+
}, { commonjs: true });
10993
},
11094
};

src/rules/no-nodejs-modules.js

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import importType from '../core/importType';
2-
import isStaticRequire from '../core/staticRequire';
2+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
33
import docsUrl from '../docsUrl';
44

55
function reportIfMissing(context, node, allowed, name) {
@@ -35,15 +35,8 @@ module.exports = {
3535
const options = context.options[0] || {};
3636
const allowed = options.allow || [];
3737

38-
return {
39-
ImportDeclaration: function handleImports(node) {
40-
reportIfMissing(context, node, allowed, node.source.value);
41-
},
42-
CallExpression: function handleRequires(node) {
43-
if (isStaticRequire(node)) {
44-
reportIfMissing(context, node, allowed, node.arguments[0].value);
45-
}
46-
},
47-
};
38+
return moduleVisitor((source, node) => {
39+
reportIfMissing(context, node, allowed, source.value);
40+
}, { commonjs: true });
4841
},
4942
};

src/rules/no-restricted-paths.js

+4-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import containsPath from 'contains-path';
22
import path from 'path';
33

44
import resolve from 'eslint-module-utils/resolve';
5-
import isStaticRequire from '../core/staticRequire';
5+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
66
import docsUrl from '../docsUrl';
77
import importType from '../core/importType';
88

@@ -109,17 +109,8 @@ module.exports = {
109109
});
110110
}
111111

112-
return {
113-
ImportDeclaration(node) {
114-
checkForRestrictedImportPath(node.source.value, node.source);
115-
},
116-
CallExpression(node) {
117-
if (isStaticRequire(node)) {
118-
const [ firstArgument ] = node.arguments;
119-
120-
checkForRestrictedImportPath(firstArgument.value, firstArgument);
121-
}
122-
},
123-
};
112+
return moduleVisitor((source) => {
113+
checkForRestrictedImportPath(source.value, source);
114+
}, { commonjs: true });
124115
},
125116
};

src/rules/no-self-import.js

+4-11
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import resolve from 'eslint-module-utils/resolve';
7-
import isStaticRequire from '../core/staticRequire';
7+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
88
import docsUrl from '../docsUrl';
99

1010
function isImportingSelf(context, node, requireName) {
@@ -31,15 +31,8 @@ module.exports = {
3131
schema: [],
3232
},
3333
create: function (context) {
34-
return {
35-
ImportDeclaration(node) {
36-
isImportingSelf(context, node, node.source.value);
37-
},
38-
CallExpression(node) {
39-
if (isStaticRequire(node)) {
40-
isImportingSelf(context, node, node.arguments[0].value);
41-
}
42-
},
43-
};
34+
return moduleVisitor((source, node) => {
35+
isImportingSelf(context, node, source.value);
36+
}, { commonjs: true });
4437
},
4538
};

src/rules/no-webpack-loader-syntax.js

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import isStaticRequire from '../core/staticRequire';
1+
import moduleVisitor from 'eslint-module-utils/moduleVisitor';
22
import docsUrl from '../docsUrl';
33

44
function reportIfNonStandard(context, node, name) {
@@ -19,15 +19,8 @@ module.exports = {
1919
},
2020

2121
create: function (context) {
22-
return {
23-
ImportDeclaration: function handleImports(node) {
24-
reportIfNonStandard(context, node, node.source.value);
25-
},
26-
CallExpression: function handleRequires(node) {
27-
if (isStaticRequire(node)) {
28-
reportIfNonStandard(context, node, node.arguments[0].value);
29-
}
30-
},
31-
};
22+
return moduleVisitor((source, node) => {
23+
reportIfNonStandard(context, node, source.value);
24+
}, { commonjs: true });
3225
},
3326
};

tests/src/rules/extensions.js

+93
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,22 @@ ruleTester.run('extensions', rule, {
391391
options: [ 'never', { ignorePackages: true } ],
392392
}),
393393

394+
test({
395+
code: `
396+
import foo from './foo.js'
397+
import bar from './bar.json'
398+
import Component from './Component.jsx'
399+
`,
400+
errors: [
401+
{
402+
message: 'Unexpected use of file extension "jsx" for "./Component.jsx"',
403+
line: 4,
404+
column: 31,
405+
},
406+
],
407+
options: [ 'always', { pattern: { jsx: 'never' } } ],
408+
}),
409+
394410
// export (#964)
395411
test({
396412
code: [
@@ -444,6 +460,48 @@ ruleTester.run('extensions', rule, {
444460
},
445461
],
446462
}),
463+
// require (#1230)
464+
test({
465+
code: [
466+
'const { foo } = require("./foo")',
467+
'export { foo }',
468+
].join('\n'),
469+
options: [ 'always' ],
470+
errors: [
471+
{
472+
message: 'Missing file extension for "./foo"',
473+
line: 1,
474+
column: 25,
475+
},
476+
],
477+
}),
478+
test({
479+
code: [
480+
'const { foo } = require("./foo.js")',
481+
'export { foo }',
482+
].join('\n'),
483+
options: [ 'never' ],
484+
errors: [
485+
{
486+
message: 'Unexpected use of file extension "js" for "./foo.js"',
487+
line: 1,
488+
column: 25,
489+
},
490+
],
491+
}),
492+
493+
// export { } from
494+
test({
495+
code: 'export { foo } from "./foo"',
496+
options: [ 'always' ],
497+
errors: [
498+
{
499+
message: 'Missing file extension for "./foo"',
500+
line: 1,
501+
column: 21,
502+
},
503+
],
504+
}),
447505
test({
448506
code: 'import foo from "@/ImNotAScopedModule"',
449507
options: ['always'],
@@ -454,5 +512,40 @@ ruleTester.run('extensions', rule, {
454512
},
455513
],
456514
}),
515+
test({
516+
code: 'export { foo } from "./foo.js"',
517+
options: [ 'never' ],
518+
errors: [
519+
{
520+
message: 'Unexpected use of file extension "js" for "./foo.js"',
521+
line: 1,
522+
column: 21,
523+
},
524+
],
525+
}),
526+
527+
// export * from
528+
test({
529+
code: 'export * from "./foo"',
530+
options: [ 'always' ],
531+
errors: [
532+
{
533+
message: 'Missing file extension for "./foo"',
534+
line: 1,
535+
column: 15,
536+
},
537+
],
538+
}),
539+
test({
540+
code: 'export * from "./foo.js"',
541+
options: [ 'never' ],
542+
errors: [
543+
{
544+
message: 'Unexpected use of file extension "js" for "./foo.js"',
545+
line: 1,
546+
column: 15,
547+
},
548+
],
549+
}),
457550
],
458551
});

0 commit comments

Comments
 (0)