Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c2325fc

Browse files
ljqxljharb
authored andcommittedNov 19, 2018
[Fix] [Generic Import Callback] Make callback for all import once in rules
Fixes #1230.
1 parent e4850df commit c2325fc

10 files changed

+176
-95
lines changed
 

‎src/core/addForGenericImport.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import isStaticRequire from './staticRequire'
2+
3+
function noop() {}
4+
5+
export default function addForGenericImport(allCallbacks, genericImportCallback) {
6+
const {
7+
ImportDeclaration = noop,
8+
ExportNamedDeclaration = noop,
9+
ExportAllDeclaration = noop,
10+
CallExpression = noop,
11+
} = allCallbacks
12+
13+
return Object.assign({}, allCallbacks, {
14+
ImportDeclaration(node) {
15+
ImportDeclaration(node)
16+
genericImportCallback(node.source, node)
17+
},
18+
ExportNamedDeclaration(node) {
19+
ExportNamedDeclaration(node)
20+
const { source } = node
21+
// bail if the declaration doesn't have a source, e.g. "export { foo };"
22+
if (source) {
23+
genericImportCallback(source, node)
24+
}
25+
},
26+
ExportAllDeclaration(node) {
27+
ExportAllDeclaration(node)
28+
genericImportCallback(node.source, node)
29+
},
30+
CallExpression(node) {
31+
CallExpression(node)
32+
if (isStaticRequire(node)) {
33+
genericImportCallback(node.arguments[0], node)
34+
}
35+
},
36+
})
37+
}

‎src/rules/extensions.js

+3-10
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, isExternalModuleMain, isScopedMain } from '../core/importType'
5+
import addForGenericImport from '../core/addForGenericImport'
56
import docsUrl from '../docsUrl'
67

78
const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] }
@@ -121,12 +122,7 @@ module.exports = {
121122
return resolvedFileWithoutExtension === resolve(file, context)
122123
}
123124

124-
function checkFileExtension(node) {
125-
const { source } = node
126-
127-
// bail if the declaration doesn't have a source, e.g. "export { foo };"
128-
if (!source) return
129-
125+
function checkFileExtension(source) {
130126
const importPath = source.value
131127

132128
// don't enforce anything on builtins
@@ -162,9 +158,6 @@ module.exports = {
162158
}
163159
}
164160

165-
return {
166-
ImportDeclaration: checkFileExtension,
167-
ExportNamedDeclaration: checkFileExtension,
168-
}
161+
return addForGenericImport({}, checkFileExtension)
169162
},
170163
}

‎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 addForGenericImport from '../core/addForGenericImport'
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 addForGenericImport({
5340
'Program:exit': function () {
5441
countDependencies(dependencies, lastNode, context)
5542
},
56-
}
43+
}, (source) => {
44+
dependencies.add(source.value)
45+
lastNode = source
46+
})
5747
},
5848
}

‎src/rules/no-extraneous-dependencies.js

+4-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import readPkgUp from 'read-pkg-up'
55
import minimatch from 'minimatch'
66
import resolve from 'eslint-module-utils/resolve'
77
import importType from '../core/importType'
8-
import isStaticRequire from '../core/staticRequire'
8+
import addForGenericImport from '../core/addForGenericImport'
99
import docsUrl from '../docsUrl'
1010

1111
function hasKeys(obj = {}) {
@@ -189,15 +189,8 @@ module.exports = {
189189
}
190190

191191
// todo: use module visitor from module-utils core
192-
return {
193-
ImportDeclaration: function (node) {
194-
reportIfMissing(context, deps, depsOptions, node, node.source.value)
195-
},
196-
CallExpression: function handleRequires(node) {
197-
if (isStaticRequire(node)) {
198-
reportIfMissing(context, deps, depsOptions, node, node.arguments[0].value)
199-
}
200-
},
201-
}
192+
return addForGenericImport({}, (source, node) => {
193+
reportIfMissing(context, deps, depsOptions, node, source.value)
194+
})
202195
},
203196
}

‎src/rules/no-internal-modules.js

+4-12
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 addForGenericImport from '../core/addForGenericImport'
66
import docsUrl from '../docsUrl'
77

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

90-
return {
91-
ImportDeclaration(node) {
92-
checkImportForReaching(node.source.value, node.source)
93-
},
94-
CallExpression(node) {
95-
if (isStaticRequire(node)) {
96-
const [ firstArgument ] = node.arguments
97-
checkImportForReaching(firstArgument.value, firstArgument)
98-
}
99-
},
100-
}
90+
return addForGenericImport({}, (source) => {
91+
checkImportForReaching(source.value, source)
92+
})
10193
},
10294
}

‎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 addForGenericImport from '../core/addForGenericImport'
33
import docsUrl from '../docsUrl'
44

55
function reportIfMissing(context, node, allowed, name) {
@@ -20,15 +20,8 @@ module.exports = {
2020
const options = context.options[0] || {}
2121
const allowed = options.allow || []
2222

23-
return {
24-
ImportDeclaration: function handleImports(node) {
25-
reportIfMissing(context, node, allowed, node.source.value)
26-
},
27-
CallExpression: function handleRequires(node) {
28-
if (isStaticRequire(node)) {
29-
reportIfMissing(context, node, allowed, node.arguments[0].value)
30-
}
31-
},
32-
}
23+
return addForGenericImport({}, (source, node) => {
24+
reportIfMissing(context, node, allowed, source.value)
25+
})
3326
},
3427
}

‎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 addForGenericImport from '../core/addForGenericImport'
66
import docsUrl from '../docsUrl'
77

88
module.exports = {
@@ -65,17 +65,8 @@ module.exports = {
6565
})
6666
}
6767

68-
return {
69-
ImportDeclaration(node) {
70-
checkForRestrictedImportPath(node.source.value, node.source)
71-
},
72-
CallExpression(node) {
73-
if (isStaticRequire(node)) {
74-
const [ firstArgument ] = node.arguments
75-
76-
checkForRestrictedImportPath(firstArgument.value, firstArgument)
77-
}
78-
},
79-
}
68+
return addForGenericImport({}, (source) => {
69+
checkForRestrictedImportPath(source.value, source)
70+
})
8071
},
8172
}

‎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 addForGenericImport from '../core/addForGenericImport'
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 addForGenericImport({}, (source, node) => {
35+
isImportingSelf(context, node, source.value)
36+
})
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 addForGenericImport from '../core/addForGenericImport'
22
import docsUrl from '../docsUrl'
33

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

2020
create: function (context) {
21-
return {
22-
ImportDeclaration: function handleImports(node) {
23-
reportIfNonStandard(context, node, node.source.value)
24-
},
25-
CallExpression: function handleRequires(node) {
26-
if (isStaticRequire(node)) {
27-
reportIfNonStandard(context, node, node.arguments[0].value)
28-
}
29-
},
30-
}
21+
return addForGenericImport({}, (source, node) => {
22+
reportIfNonStandard(context, node, source.value)
23+
})
3124
},
3225
}

‎tests/src/rules/extensions.js

+106
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,22 @@ ruleTester.run('extensions', rule, {
330330
options: [ 'never', {ignorePackages: true} ],
331331
}),
332332

333+
test({
334+
code: `
335+
import foo from './foo.js'
336+
import bar from './bar.json'
337+
import Component from './Component.jsx'
338+
`,
339+
errors: [
340+
{
341+
message: 'Unexpected use of file extension "jsx" for "./Component.jsx"',
342+
line: 4,
343+
column: 31,
344+
},
345+
],
346+
options: [ 'always', {pattern: {jsx: 'never'}} ],
347+
}),
348+
333349
// export (#964)
334350
test({
335351
code: [
@@ -359,5 +375,95 @@ ruleTester.run('extensions', rule, {
359375
},
360376
],
361377
}),
378+
379+
// require (#1230)
380+
test({
381+
code: [
382+
'const { foo } = require("./foo")',
383+
'export { bar }',
384+
].join('\n'),
385+
options: [ 'always' ],
386+
errors: [
387+
{
388+
message: 'Missing file extension for "./foo"',
389+
line: 1,
390+
column: 25,
391+
},
392+
],
393+
}),
394+
test({
395+
code: [
396+
'const { foo } = require("./foo.js")',
397+
'export { bar }',
398+
].join('\n'),
399+
options: [ 'never' ],
400+
errors: [
401+
{
402+
message: 'Unexpected use of file extension "js" for "./foo.js"',
403+
line: 1,
404+
column: 25,
405+
},
406+
],
407+
}),
408+
409+
// export { } from
410+
test({
411+
code: [
412+
'export { foo } from "./foo"',
413+
'export { bar }',
414+
].join('\n'),
415+
options: [ 'always' ],
416+
errors: [
417+
{
418+
message: 'Missing file extension for "./foo"',
419+
line: 1,
420+
column: 21,
421+
},
422+
],
423+
}),
424+
test({
425+
code: [
426+
'export { foo } from "./foo.js"',
427+
'export { bar }',
428+
].join('\n'),
429+
options: [ 'never' ],
430+
errors: [
431+
{
432+
message: 'Unexpected use of file extension "js" for "./foo.js"',
433+
line: 1,
434+
column: 21,
435+
},
436+
],
437+
}),
438+
439+
// export * from
440+
test({
441+
code: [
442+
'export * from "./foo"',
443+
'export { bar }',
444+
].join('\n'),
445+
options: [ 'always' ],
446+
errors: [
447+
{
448+
message: 'Missing file extension for "./foo"',
449+
line: 1,
450+
column: 15,
451+
},
452+
],
453+
}),
454+
test({
455+
code: [
456+
'export * from "./foo.js"',
457+
'export { bar }',
458+
].join('\n'),
459+
options: [ 'never' ],
460+
errors: [
461+
{
462+
message: 'Unexpected use of file extension "js" for "./foo.js"',
463+
line: 1,
464+
column: 15,
465+
},
466+
],
467+
}),
362468
],
363469
})

0 commit comments

Comments
 (0)
Please sign in to comment.