5
5
6
6
'use strict' ;
7
7
8
- const fsMetaData = require ( './data/fsFunctionData.json' ) ;
8
+ const fsMetaData = require ( '../utils /data/fsFunctionData.json' ) ;
9
9
const funcNames = Object . keys ( fsMetaData ) ;
10
10
const fsPackageNames = [ 'fs' , 'node:fs' , 'fs/promises' , 'node:fs/promises' , 'fs-extra' ] ;
11
11
12
- const { getImportDeclaration , getVariableDeclaration } = require ( './utils/import-utils' ) ;
12
+ const { getImportAccessPath } = require ( '. ./utils/import-utils' ) ;
13
13
14
14
//------------------------------------------------------------------------------
15
15
// Utils
@@ -21,189 +21,9 @@ function getIndices(node, argMeta) {
21
21
22
22
function generateReport ( { context, node, packageName, methodName, indices } ) {
23
23
if ( ! indices || indices . length === 0 ) {
24
- return null ;
24
+ return ;
25
25
}
26
- return context . report ( { node, message : `Found ${ methodName } from package "${ packageName } " with non literal argument at index ${ indices . join ( ',' ) } ` } ) ;
27
- }
28
-
29
- /**
30
- * Detects:
31
- * | var something = require('fs').readFile;
32
- * | something(a);
33
- */
34
- function detectOnRequireWithProperty ( { context, methodName, node, program } ) {
35
- const declaration = getVariableDeclaration ( {
36
- condition : ( declaration ) => declaration . init . parent . id . name === methodName ,
37
- hasObject : true ,
38
- methodName,
39
- packageNames : fsPackageNames ,
40
- program,
41
- } ) ;
42
-
43
- if ( ! declaration ) {
44
- return null ;
45
- }
46
-
47
- // we found the require for our method!
48
- const fsFunction = declaration . init . property . name ;
49
- const packageName = declaration . init . object . arguments [ 0 ] . value ;
50
- const fnName = declaration . init . property . name ;
51
-
52
- const indices = getIndices ( node , fsMetaData [ fsFunction ] ) ;
53
-
54
- return generateReport ( {
55
- context,
56
- node,
57
- packageName,
58
- methodName : fnName ,
59
- indices,
60
- } ) ;
61
- }
62
-
63
- /**
64
- * Detects:
65
- * | var something = require('fs');
66
- * | something.readFile(c);
67
- */
68
- function detectOnMethodCall ( { context, node, program, methodName } ) {
69
- const declaration = getVariableDeclaration ( {
70
- packageNames : fsPackageNames ,
71
- hasObject : false ,
72
- program,
73
- } ) ;
74
-
75
- if ( ! declaration ) {
76
- return null ;
77
- }
78
-
79
- const indices = getIndices ( node . parent , fsMetaData [ methodName ] ) ;
80
-
81
- return generateReport ( {
82
- context,
83
- node,
84
- packageName : declaration . init . arguments [ 0 ] . value ,
85
- methodName,
86
- indices,
87
- } ) ;
88
- }
89
-
90
- /**
91
- * Detects:
92
- * | var { readFile: something } = require('fs')
93
- * | readFile(filename)
94
- */
95
- function detectOnDestructuredRequire ( { context, methodName, node, program } ) {
96
- const declaration = getVariableDeclaration ( {
97
- condition : ( declaration ) => declaration && declaration . id && declaration . id . properties && declaration . id . properties . some ( ( p ) => p . value . name === methodName ) ,
98
- hasObject : false ,
99
- methodName,
100
- packageNames : fsPackageNames ,
101
- program,
102
- } ) ;
103
-
104
- if ( ! declaration ) {
105
- return null ;
106
- }
107
-
108
- const realMethodName = declaration . id . properties . find ( ( p ) => p . value . name === methodName ) . key . name ;
109
-
110
- const meta = fsMetaData [ realMethodName ] ;
111
- const indices = getIndices ( node , meta ) ;
112
-
113
- return generateReport ( {
114
- context,
115
- node,
116
- packageName : declaration . init . arguments [ 0 ] . value ,
117
- methodName : realMethodName ,
118
- indices,
119
- } ) ;
120
- }
121
-
122
- /**
123
- * Detects:
124
- * | import { readFile as something } from 'fs';
125
- * | something(filename);
126
- */
127
- function detectOnDestructuredImport ( { context, methodName, node, program } ) {
128
- const importDeclaration = getImportDeclaration ( { methodName, packageNames : fsPackageNames , program } ) ;
129
-
130
- const specifier = importDeclaration && importDeclaration . specifiers && importDeclaration . specifiers . find ( ( s ) => ! ! funcNames . includes ( s . imported . name ) ) ;
131
-
132
- if ( ! specifier ) {
133
- return null ;
134
- }
135
-
136
- const fnName = specifier . imported . name ;
137
- const meta = fsMetaData [ fnName ] ;
138
- const indices = getIndices ( node , meta ) ;
139
-
140
- return generateReport ( {
141
- context,
142
- node,
143
- packageName : specifier . parent . source . value ,
144
- methodName : fnName ,
145
- indices,
146
- } ) ;
147
- }
148
-
149
- /**
150
- * Detects:
151
- * | import * as something from 'fs';
152
- * | something.readFile(c);
153
- */
154
- function detectOnDefaultImport ( { context, methodName, node, objectName, program } ) {
155
- if ( ! funcNames . includes ( methodName ) ) {
156
- return null ;
157
- }
158
-
159
- const importDeclaration = getImportDeclaration ( { methodName : objectName , packageNames : fsPackageNames , program } ) ;
160
-
161
- if ( ! importDeclaration ) {
162
- return null ;
163
- }
164
-
165
- const meta = fsMetaData [ methodName ] ;
166
- const indices = getIndices ( node . parent , meta ) ;
167
-
168
- return generateReport ( {
169
- context,
170
- node,
171
- packageName : importDeclaration . source . value ,
172
- methodName,
173
- indices,
174
- } ) ;
175
- }
176
-
177
- /**
178
- * Detects:
179
- * | var something = require('fs').promises;
180
- * | something.readFile(filename)
181
- */
182
- function detectOnPromiseProperty ( { context, methodName, node, objectName, program } ) {
183
- const declaration = program . body
184
- . filter ( ( entry ) => entry . type === 'VariableDeclaration' )
185
- . flatMap ( ( entry ) => entry . declarations )
186
- . find (
187
- ( declaration ) =>
188
- declaration . id . name === objectName &&
189
- declaration . init . type === 'MemberExpression' &&
190
- // package name is fs / fs-extra
191
- fsPackageNames . includes ( declaration . init . object . arguments [ 0 ] . value )
192
- ) ;
193
-
194
- if ( ! declaration ) {
195
- return null ;
196
- }
197
- const meta = fsMetaData [ methodName ] ;
198
- const indices = getIndices ( node . parent , meta ) ;
199
-
200
- return generateReport ( {
201
- context,
202
- node,
203
- packageName : declaration . init . object . arguments [ 0 ] . value ,
204
- methodName,
205
- indices,
206
- } ) ;
26
+ context . report ( { node, message : `Found ${ methodName } from package "${ packageName } " with non literal argument at index ${ indices . join ( ',' ) } ` } ) ;
207
27
}
208
28
209
29
//------------------------------------------------------------------------------
@@ -223,87 +43,59 @@ module.exports = {
223
43
create : function ( context ) {
224
44
return {
225
45
CallExpression : function ( node ) {
226
- // readFile/open/... (but might be renamed)
227
- const localMethodName = node . callee . name ;
228
-
229
46
// don't check require. If all arguments are Literals, it's surely safe!
230
- if ( ! localMethodName || localMethodName === 'require' || node . arguments . every ( ( argument ) => argument . type === 'Literal' ) ) {
47
+ if ( ( node . callee . type === 'Identifier' && node . callee . name === 'require' ) || node . arguments . every ( ( argument ) => argument . type === 'Literal' ) ) {
231
48
return ;
232
49
}
233
50
234
- // this only works, when imports are on top level!
235
- const program = context . getAncestors ( ) [ 0 ] ;
236
-
237
- const requireReport = detectOnRequireWithProperty ( {
238
- context,
239
- methodName : localMethodName ,
240
- node,
241
- program,
242
- } ) ;
243
- if ( requireReport ) {
244
- return requireReport ;
245
- }
246
-
247
- const destructuredRequireReport = detectOnDestructuredRequire ( {
248
- context,
249
- methodName : localMethodName ,
250
- node,
251
- program,
51
+ const pathInfo = getImportAccessPath ( {
52
+ node : node . callee ,
53
+ scope : context . getScope ( ) ,
54
+ packageNames : fsPackageNames ,
252
55
} ) ;
253
- if ( destructuredRequireReport ) {
254
- return destructuredRequireReport ;
56
+ if ( ! pathInfo ) {
57
+ return ;
255
58
}
256
-
257
- const importReport = detectOnDestructuredImport ( {
258
- context,
259
- methodName : localMethodName ,
260
- node,
261
- program,
262
- } ) ;
263
- if ( importReport ) {
264
- return importReport ;
59
+ let fnName ;
60
+ if ( pathInfo . path . length === 1 ) {
61
+ // Check for:
62
+ // | var something = require('fs').readFile;
63
+ // | something(a);
64
+ // ,
65
+ // | var something = require('fs');
66
+ // | something.readFile(c);
67
+ // ,
68
+ // | var { readFile: something } = require('fs')
69
+ // | readFile(filename);
70
+ // ,
71
+ // | import { readFile as something } from 'fs';
72
+ // | something(filename);
73
+ // , or
74
+ // | import * as something from 'fs';
75
+ // | something.readFile(c);
76
+ fnName = pathInfo . path [ 0 ] ;
77
+ } else if ( pathInfo . path . length === 2 ) {
78
+ // Check for:
79
+ // | var something = require('fs').promises;
80
+ // | something.readFile(filename)
81
+ fnName = pathInfo . path [ 1 ] ;
82
+ } else {
83
+ return ;
265
84
}
266
- } ,
267
- MemberExpression : function ( node ) {
268
- const realMethodName = node . property . name ; // readFile/open/... (not renamed)
269
- const localObjectName = node . object . name ; // fs/node:fs/... (but might be renamed)
270
-
271
- // this only works, when imports are on top level!
272
- const program = context . getAncestors ( ) [ 0 ] ;
273
-
274
- const methodCallReport = detectOnMethodCall ( {
275
- context,
276
- methodName : realMethodName ,
277
- node,
278
- program,
279
- } ) ;
280
- if ( methodCallReport ) {
281
- return methodCallReport ;
85
+ if ( ! funcNames . includes ( fnName ) ) {
86
+ return false ;
282
87
}
88
+ const packageName = pathInfo . packageName ;
283
89
284
- const defaultImportReport = detectOnDefaultImport ( {
285
- program,
286
- objectName : localObjectName ,
287
- methodName : realMethodName ,
288
- context,
289
- node,
290
- } ) ;
291
-
292
- if ( defaultImportReport ) {
293
- return defaultImportReport ;
294
- }
90
+ const indices = getIndices ( node , fsMetaData [ fnName ] ) ;
295
91
296
- const promisePropertyReport = detectOnPromiseProperty ( {
92
+ generateReport ( {
297
93
context,
298
- methodName : realMethodName ,
299
94
node,
300
- objectName : localObjectName ,
301
- program,
95
+ packageName,
96
+ methodName : fnName ,
97
+ indices,
302
98
} ) ;
303
-
304
- if ( promisePropertyReport ) {
305
- return promisePropertyReport ;
306
- }
307
99
} ,
308
100
} ;
309
101
} ,
0 commit comments