|
9 | 9 | typescriptPkg = require('typescript/package.json'); // eslint-disable-line import/no-extraneous-dependencies
|
10 | 10 | } catch (e) { /**/ }
|
11 | 11 |
|
12 |
| -function checkImports(imported, context) { |
13 |
| - for (const [module, nodes] of imported.entries()) { |
14 |
| - if (nodes.length > 1) { |
15 |
| - const message = `'${module}' imported multiple times.`; |
16 |
| - const [first, ...rest] = nodes; |
17 |
| - const sourceCode = context.getSourceCode(); |
18 |
| - const fix = getFix(first, rest, sourceCode, context); |
| 12 | +function isPunctuator(node, value) { |
| 13 | + return node.type === 'Punctuator' && node.value === value; |
| 14 | +} |
19 | 15 |
|
20 |
| - context.report({ |
21 |
| - node: first.source, |
22 |
| - message, |
23 |
| - fix, // Attach the autofix (if any) to the first import. |
24 |
| - }); |
| 16 | +// Get the name of the default import of `node`, if any. |
| 17 | +function getDefaultImportName(node) { |
| 18 | + const defaultSpecifier = node.specifiers |
| 19 | + .find((specifier) => specifier.type === 'ImportDefaultSpecifier'); |
| 20 | + return defaultSpecifier != null ? defaultSpecifier.local.name : undefined; |
| 21 | +} |
25 | 22 |
|
26 |
| - for (const node of rest) { |
27 |
| - context.report({ |
28 |
| - node: node.source, |
29 |
| - message, |
30 |
| - }); |
31 |
| - } |
32 |
| - } |
33 |
| - } |
| 23 | +// Checks whether `node` has a namespace import. |
| 24 | +function hasNamespace(node) { |
| 25 | + const specifiers = node.specifiers |
| 26 | + .filter((specifier) => specifier.type === 'ImportNamespaceSpecifier'); |
| 27 | + return specifiers.length > 0; |
| 28 | +} |
| 29 | + |
| 30 | +// Checks whether `node` has any non-default specifiers. |
| 31 | +function hasSpecifiers(node) { |
| 32 | + const specifiers = node.specifiers |
| 33 | + .filter((specifier) => specifier.type === 'ImportSpecifier'); |
| 34 | + return specifiers.length > 0; |
| 35 | +} |
| 36 | + |
| 37 | +// Checks whether `node` has a comment (that ends) on the previous line or on |
| 38 | +// the same line as `node` (starts). |
| 39 | +function hasCommentBefore(node, sourceCode) { |
| 40 | + return sourceCode.getCommentsBefore(node) |
| 41 | + .some((comment) => comment.loc.end.line >= node.loc.start.line - 1); |
| 42 | +} |
| 43 | + |
| 44 | +// Checks whether `node` has a comment (that starts) on the same line as `node` |
| 45 | +// (ends). |
| 46 | +function hasCommentAfter(node, sourceCode) { |
| 47 | + return sourceCode.getCommentsAfter(node) |
| 48 | + .some((comment) => comment.loc.start.line === node.loc.end.line); |
| 49 | +} |
| 50 | + |
| 51 | +// Checks whether `node` has any comments _inside,_ except inside the `{...}` |
| 52 | +// part (if any). |
| 53 | +function hasCommentInsideNonSpecifiers(node, sourceCode) { |
| 54 | + const tokens = sourceCode.getTokens(node); |
| 55 | + const openBraceIndex = tokens.findIndex((token) => isPunctuator(token, '{')); |
| 56 | + const closeBraceIndex = tokens.findIndex((token) => isPunctuator(token, '}')); |
| 57 | + // Slice away the first token, since we're no looking for comments _before_ |
| 58 | + // `node` (only inside). If there's a `{...}` part, look for comments before |
| 59 | + // the `{`, but not before the `}` (hence the `+1`s). |
| 60 | + const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0 |
| 61 | + ? tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1)) |
| 62 | + : tokens.slice(1); |
| 63 | + return someTokens.some((token) => sourceCode.getCommentsBefore(token).length > 0); |
| 64 | +} |
| 65 | + |
| 66 | +// It's not obvious what the user wants to do with comments associated with |
| 67 | +// duplicate imports, so skip imports with comments when autofixing. |
| 68 | +function hasProblematicComments(node, sourceCode) { |
| 69 | + return ( |
| 70 | + hasCommentBefore(node, sourceCode) |
| 71 | + || hasCommentAfter(node, sourceCode) |
| 72 | + || hasCommentInsideNonSpecifiers(node, sourceCode) |
| 73 | + ); |
34 | 74 | }
|
35 | 75 |
|
36 | 76 | function getFix(first, rest, sourceCode, context) {
|
@@ -203,68 +243,28 @@ function getFix(first, rest, sourceCode, context) {
|
203 | 243 | };
|
204 | 244 | }
|
205 | 245 |
|
206 |
| -function isPunctuator(node, value) { |
207 |
| - return node.type === 'Punctuator' && node.value === value; |
208 |
| -} |
209 |
| - |
210 |
| -// Get the name of the default import of `node`, if any. |
211 |
| -function getDefaultImportName(node) { |
212 |
| - const defaultSpecifier = node.specifiers |
213 |
| - .find((specifier) => specifier.type === 'ImportDefaultSpecifier'); |
214 |
| - return defaultSpecifier != null ? defaultSpecifier.local.name : undefined; |
215 |
| -} |
216 |
| - |
217 |
| -// Checks whether `node` has a namespace import. |
218 |
| -function hasNamespace(node) { |
219 |
| - const specifiers = node.specifiers |
220 |
| - .filter((specifier) => specifier.type === 'ImportNamespaceSpecifier'); |
221 |
| - return specifiers.length > 0; |
222 |
| -} |
223 |
| - |
224 |
| -// Checks whether `node` has any non-default specifiers. |
225 |
| -function hasSpecifiers(node) { |
226 |
| - const specifiers = node.specifiers |
227 |
| - .filter((specifier) => specifier.type === 'ImportSpecifier'); |
228 |
| - return specifiers.length > 0; |
229 |
| -} |
230 |
| - |
231 |
| -// It's not obvious what the user wants to do with comments associated with |
232 |
| -// duplicate imports, so skip imports with comments when autofixing. |
233 |
| -function hasProblematicComments(node, sourceCode) { |
234 |
| - return ( |
235 |
| - hasCommentBefore(node, sourceCode) |
236 |
| - || hasCommentAfter(node, sourceCode) |
237 |
| - || hasCommentInsideNonSpecifiers(node, sourceCode) |
238 |
| - ); |
239 |
| -} |
240 |
| - |
241 |
| -// Checks whether `node` has a comment (that ends) on the previous line or on |
242 |
| -// the same line as `node` (starts). |
243 |
| -function hasCommentBefore(node, sourceCode) { |
244 |
| - return sourceCode.getCommentsBefore(node) |
245 |
| - .some((comment) => comment.loc.end.line >= node.loc.start.line - 1); |
246 |
| -} |
| 246 | +function checkImports(imported, context) { |
| 247 | + for (const [module, nodes] of imported.entries()) { |
| 248 | + if (nodes.length > 1) { |
| 249 | + const message = `'${module}' imported multiple times.`; |
| 250 | + const [first, ...rest] = nodes; |
| 251 | + const sourceCode = context.getSourceCode(); |
| 252 | + const fix = getFix(first, rest, sourceCode, context); |
247 | 253 |
|
248 |
| -// Checks whether `node` has a comment (that starts) on the same line as `node` |
249 |
| -// (ends). |
250 |
| -function hasCommentAfter(node, sourceCode) { |
251 |
| - return sourceCode.getCommentsAfter(node) |
252 |
| - .some((comment) => comment.loc.start.line === node.loc.end.line); |
253 |
| -} |
| 254 | + context.report({ |
| 255 | + node: first.source, |
| 256 | + message, |
| 257 | + fix, // Attach the autofix (if any) to the first import. |
| 258 | + }); |
254 | 259 |
|
255 |
| -// Checks whether `node` has any comments _inside,_ except inside the `{...}` |
256 |
| -// part (if any). |
257 |
| -function hasCommentInsideNonSpecifiers(node, sourceCode) { |
258 |
| - const tokens = sourceCode.getTokens(node); |
259 |
| - const openBraceIndex = tokens.findIndex((token) => isPunctuator(token, '{')); |
260 |
| - const closeBraceIndex = tokens.findIndex((token) => isPunctuator(token, '}')); |
261 |
| - // Slice away the first token, since we're no looking for comments _before_ |
262 |
| - // `node` (only inside). If there's a `{...}` part, look for comments before |
263 |
| - // the `{`, but not before the `}` (hence the `+1`s). |
264 |
| - const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0 |
265 |
| - ? tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1)) |
266 |
| - : tokens.slice(1); |
267 |
| - return someTokens.some((token) => sourceCode.getCommentsBefore(token).length > 0); |
| 260 | + for (const node of rest) { |
| 261 | + context.report({ |
| 262 | + node: node.source, |
| 263 | + message, |
| 264 | + }); |
| 265 | + } |
| 266 | + } |
| 267 | + } |
268 | 268 | }
|
269 | 269 |
|
270 | 270 | module.exports = {
|
|
0 commit comments