-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathno-import-module-exports.js
86 lines (78 loc) · 2.92 KB
/
no-import-module-exports.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import minimatch from 'minimatch';
import path from 'path';
import { getPhysicalFilename, getSourceCode } from 'eslint-module-utils/contextCompat';
import pkgUp from 'eslint-module-utils/pkgUp';
function getEntryPoint(context) {
const pkgPath = pkgUp({ cwd: getPhysicalFilename(context) });
try {
return require.resolve(path.dirname(pkgPath));
} catch (error) {
// Assume the package has no entrypoint (e.g. CLI packages)
// in which case require.resolve would throw.
return null;
}
}
function findScope(context, identifier) {
const { scopeManager } = getSourceCode(context);
return scopeManager && scopeManager.scopes.slice().reverse().find((scope) => scope.variables.some((variable) => variable.identifiers.some((node) => node.name === identifier)));
}
function findDefinition(objectScope, identifier) {
const variable = objectScope.variables.find((variable) => variable.name === identifier);
return variable.defs.find((def) => def.name.name === identifier);
}
module.exports = {
meta: {
type: 'problem',
docs: {
category: 'Module systems',
description: 'Forbid import statements with CommonJS module.exports.',
recommended: true,
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {
exceptions: { type: 'array' },
},
additionalProperties: false,
},
],
},
create(context) {
const importDeclarations = [];
const entryPoint = getEntryPoint(context);
const options = context.options[0] || {};
let alreadyReported = false;
function report(node) {
const fileName = getPhysicalFilename(context);
const isEntryPoint = entryPoint === fileName;
const isIdentifier = node.object.type === 'Identifier';
const hasKeywords = (/^(module|exports)$/).test(node.object.name);
const objectScope = hasKeywords && findScope(context, node.object.name);
const variableDefinition = objectScope && findDefinition(objectScope, node.object.name);
const isImportBinding = variableDefinition && variableDefinition.type === 'ImportBinding';
const hasCJSExportReference = hasKeywords && (!objectScope || objectScope.type === 'module');
const isException = !!options.exceptions && options.exceptions.some((glob) => minimatch(fileName, glob));
if (isIdentifier && hasCJSExportReference && !isEntryPoint && !isException && !isImportBinding) {
importDeclarations.forEach((importDeclaration) => {
context.report({
node: importDeclaration,
message: `Cannot use import declarations in modules that export using CommonJS (module.exports = 'foo' or exports.bar = 'hi')`,
});
});
alreadyReported = true;
}
}
return {
ImportDeclaration(node) {
importDeclarations.push(node);
},
MemberExpression(node) {
if (!alreadyReported) {
report(node);
}
},
};
},
};