Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/eslint-plugin-import
Path: blob/main/utils/moduleVisitor.js
828 views
1
'use strict';
2
exports.__esModule = true;
3
4
/**
5
* Returns an object of node visitors that will call
6
* 'visitor' with every discovered module path.
7
*
8
* todo: correct function prototype for visitor
9
* @param {Function(String)} visitor [description]
10
* @param {[type]} options [description]
11
* @return {object}
12
*/
13
exports.default = function visitModules(visitor, options) {
14
// if esmodule is not explicitly disabled, it is assumed to be enabled
15
options = Object.assign({ esmodule: true }, options);
16
17
let ignoreRegExps = [];
18
if (options.ignore != null) {
19
ignoreRegExps = options.ignore.map(p => new RegExp(p));
20
}
21
22
function checkSourceValue(source, importer) {
23
if (source == null) return; //?
24
25
// handle ignore
26
if (ignoreRegExps.some(re => re.test(source.value))) return;
27
28
// fire visitor
29
visitor(source, importer);
30
}
31
32
// for import-y declarations
33
function checkSource(node) {
34
checkSourceValue(node.source, node);
35
}
36
37
// for esmodule dynamic `import()` calls
38
function checkImportCall(node) {
39
let modulePath;
40
// refs https://github.com/estree/estree/blob/HEAD/es2020.md#importexpression
41
if (node.type === 'ImportExpression') {
42
modulePath = node.source;
43
} else if (node.type === 'CallExpression') {
44
if (node.callee.type !== 'Import') return;
45
if (node.arguments.length !== 1) return;
46
47
modulePath = node.arguments[0];
48
}
49
50
if (modulePath.type !== 'Literal') return;
51
if (typeof modulePath.value !== 'string') return;
52
53
checkSourceValue(modulePath, node);
54
}
55
56
// for CommonJS `require` calls
57
// adapted from @mctep: https://git.io/v4rAu
58
function checkCommon(call) {
59
if (call.callee.type !== 'Identifier') return;
60
if (call.callee.name !== 'require') return;
61
if (call.arguments.length !== 1) return;
62
63
const modulePath = call.arguments[0];
64
if (modulePath.type !== 'Literal') return;
65
if (typeof modulePath.value !== 'string') return;
66
67
checkSourceValue(modulePath, call);
68
}
69
70
function checkAMD(call) {
71
if (call.callee.type !== 'Identifier') return;
72
if (call.callee.name !== 'require' &&
73
call.callee.name !== 'define') return;
74
if (call.arguments.length !== 2) return;
75
76
const modules = call.arguments[0];
77
if (modules.type !== 'ArrayExpression') return;
78
79
for (const element of modules.elements) {
80
if (element.type !== 'Literal') continue;
81
if (typeof element.value !== 'string') continue;
82
83
if (element.value === 'require' ||
84
element.value === 'exports') continue; // magic modules: https://git.io/vByan
85
86
checkSourceValue(element, element);
87
}
88
}
89
90
const visitors = {};
91
if (options.esmodule) {
92
Object.assign(visitors, {
93
'ImportDeclaration': checkSource,
94
'ExportNamedDeclaration': checkSource,
95
'ExportAllDeclaration': checkSource,
96
'CallExpression': checkImportCall,
97
'ImportExpression': checkImportCall,
98
});
99
}
100
101
if (options.commonjs || options.amd) {
102
const currentCallExpression = visitors['CallExpression'];
103
visitors['CallExpression'] = function (call) {
104
if (currentCallExpression) currentCallExpression(call);
105
if (options.commonjs) checkCommon(call);
106
if (options.amd) checkAMD(call);
107
};
108
}
109
110
return visitors;
111
};
112
113
/**
114
* make an options schema for the module visitor, optionally
115
* adding extra fields.
116
*/
117
function makeOptionsSchema(additionalProperties) {
118
const base = {
119
'type': 'object',
120
'properties': {
121
'commonjs': { 'type': 'boolean' },
122
'amd': { 'type': 'boolean' },
123
'esmodule': { 'type': 'boolean' },
124
'ignore': {
125
'type': 'array',
126
'minItems': 1,
127
'items': { 'type': 'string' },
128
'uniqueItems': true,
129
},
130
},
131
'additionalProperties': false,
132
};
133
134
if (additionalProperties) {
135
for (const key in additionalProperties) {
136
base.properties[key] = additionalProperties[key];
137
}
138
}
139
140
return base;
141
}
142
exports.makeOptionsSchema = makeOptionsSchema;
143
144
/**
145
* json schema object for options parameter. can be used to build
146
* rule options schema object.
147
* @type {Object}
148
*/
149
exports.optionsSchema = makeOptionsSchema();
150
151