@@ -74,6 +74,7 @@ function hasProblematicComments(node, sourceCode) {
7474 ) ;
7575}
7676
77+ /** @type {(first: import('estree').ImportDeclaration, rest: import('estree').ImportDeclaration[], sourceCode: import('eslint').SourceCode.SourceCode, context: import('eslint').Rule.RuleContext) => import('eslint').Rule.ReportFixer | undefined } */
7778function getFix ( first , rest , sourceCode , context ) {
7879 // Sorry ESLint <= 3 users, no autofix for you. Autofixing duplicate imports
7980 // requires multiple `fixer.whatever()` calls in the `fix`: We both need to
@@ -123,7 +124,7 @@ function getFix(first, rest, sourceCode, context) {
123124 isEmpty : ! hasSpecifiers ( node ) ,
124125 } ;
125126 } )
126- . filter ( Boolean ) ;
127+ . filter ( ( x ) => ! ! x ) ;
127128
128129 const unnecessaryImports = restWithoutComments . filter ( ( node ) => ! hasSpecifiers ( node )
129130 && ! hasNamespace ( node )
@@ -139,6 +140,7 @@ function getFix(first, rest, sourceCode, context) {
139140 return undefined ;
140141 }
141142
143+ /** @type {import('eslint').Rule.ReportFixer } */
142144 return ( fixer ) => {
143145 const tokens = sourceCode . getTokens ( first ) ;
144146 const openBrace = tokens . find ( ( token ) => isPunctuator ( token , '{' ) ) ;
@@ -185,6 +187,7 @@ function getFix(first, rest, sourceCode, context) {
185187 [ '' , ! firstHasTrailingComma && ! firstIsEmpty , firstExistingIdentifiers ] ,
186188 ) ;
187189
190+ /** @type {import('eslint').Rule.Fix[] } */
188191 const fixes = [ ] ;
189192
190193 if ( shouldAddSpecifiers && preferInline && first . importKind === 'type' ) {
@@ -228,7 +231,7 @@ function getFix(first, rest, sourceCode, context) {
228231 }
229232
230233 // Remove imports whose specifiers have been moved into the first import.
231- for ( const specifier of specifiers ) {
234+ specifiers . forEach ( ( specifier ) => {
232235 const importNode = specifier . importNode ;
233236 fixes . push ( fixer . remove ( importNode ) ) ;
234237
@@ -237,25 +240,26 @@ function getFix(first, rest, sourceCode, context) {
237240 if ( charAfterImport === '\n' ) {
238241 fixes . push ( fixer . removeRange ( charAfterImportRange ) ) ;
239242 }
240- }
243+ } ) ;
241244
242245 // Remove imports whose default import has been moved to the first import,
243246 // and side-effect-only imports that are unnecessary due to the first
244247 // import.
245- for ( const node of unnecessaryImports ) {
248+ unnecessaryImports . forEach ( ( node ) => {
246249 fixes . push ( fixer . remove ( node ) ) ;
247250
248251 const charAfterImportRange = [ node . range [ 1 ] , node . range [ 1 ] + 1 ] ;
249252 const charAfterImport = sourceCode . text . substring ( charAfterImportRange [ 0 ] , charAfterImportRange [ 1 ] ) ;
250253 if ( charAfterImport === '\n' ) {
251254 fixes . push ( fixer . removeRange ( charAfterImportRange ) ) ;
252255 }
253- }
256+ } ) ;
254257
255258 return fixes ;
256259 } ;
257260}
258261
262+ /** @type {(imported: Map<string, import('estree').ImportDeclaration[]>, context: import('eslint').Rule.RuleContext) => void } */
259263function checkImports ( imported , context ) {
260264 for ( const [ module , nodes ] of imported . entries ( ) ) {
261265 if ( nodes . length > 1 ) {
@@ -270,16 +274,17 @@ function checkImports(imported, context) {
270274 fix, // Attach the autofix (if any) to the first import.
271275 } ) ;
272276
273- for ( const node of rest ) {
277+ rest . forEach ( ( node ) => {
274278 context . report ( {
275279 node : node . source ,
276280 message,
277281 } ) ;
278- }
282+ } ) ;
279283 }
280284 }
281285}
282286
287+ /** @type {import('eslint').Rule.RuleModule } */
283288module . exports = {
284289 meta : {
285290 type : 'problem' ,
@@ -305,10 +310,13 @@ module.exports = {
305310 ] ,
306311 } ,
307312
313+ /** @param {import('eslint').Rule.RuleContext } context */
308314 create ( context ) {
315+ /** @type {boolean } */
309316 // Prepare the resolver from options.
310- const considerQueryStringOption = context . options [ 0 ]
311- && context . options [ 0 ] . considerQueryString ;
317+ const considerQueryStringOption = context . options [ 0 ] && context . options [ 0 ] . considerQueryString ;
318+ /** @type {boolean } */
319+ const preferInline = context . options [ 0 ] && context . options [ 0 ] [ 'prefer-inline' ] ;
312320 const defaultResolver = ( sourcePath ) => resolve ( sourcePath , context ) || sourcePath ;
313321 const resolver = considerQueryStringOption ? ( sourcePath ) => {
314322 const parts = sourcePath . match ( / ^ ( [ ^ ? ] * ) \? ( .* ) $ / ) ;
@@ -318,19 +326,21 @@ module.exports = {
318326 return `${ defaultResolver ( parts [ 1 ] ) } ?${ parts [ 2 ] } ` ;
319327 } : defaultResolver ;
320328
329+ /** @type {Map<unknown, { imported: Map<string, import('estree').ImportDeclaration[]>, nsImported: Map<string, import('estree').ImportDeclaration[]>, defaultTypesImported: Map<string, import('estree').ImportDeclaration[]>, namedTypesImported: Map<string, import('estree').ImportDeclaration[]>}> } */
321330 const moduleMaps = new Map ( ) ;
322331
332+ /** @param {import('estree').ImportDeclaration } n */
333+ /** @returns {typeof moduleMaps[keyof typeof moduleMaps] } */
323334 function getImportMap ( n ) {
324335 if ( ! moduleMaps . has ( n . parent ) ) {
325- moduleMaps . set ( n . parent , {
336+ moduleMaps . set ( n . parent , /** @type { typeof moduleMaps } */ {
326337 imported : new Map ( ) ,
327338 nsImported : new Map ( ) ,
328339 defaultTypesImported : new Map ( ) ,
329340 namedTypesImported : new Map ( ) ,
330341 } ) ;
331342 }
332343 const map = moduleMaps . get ( n . parent ) ;
333- const preferInline = context . options [ 0 ] && context . options [ 0 ] [ 'prefer-inline' ] ;
334344 if ( ! preferInline && n . importKind === 'type' ) {
335345 return n . specifiers . length > 0 && n . specifiers [ 0 ] . type === 'ImportDefaultSpecifier' ? map . defaultTypesImported : map . namedTypesImported ;
336346 }
@@ -342,7 +352,9 @@ module.exports = {
342352 }
343353
344354 return {
355+ /** @param {import('estree').ImportDeclaration } n */
345356 ImportDeclaration ( n ) {
357+ /** @type {string } */
346358 // resolved path will cover aliased duplicates
347359 const resolvedPath = resolver ( n . source . value ) ;
348360 const importMap = getImportMap ( n ) ;
0 commit comments