@@ -6,7 +6,7 @@ import { findVariable } from '../utils/ast-utils.js';
6
6
import { toRegExp } from '../utils/regexp.js' ;
7
7
import { getFilename } from '../utils/compat.js' ;
8
8
9
- type PropertyPath = string [ ] ;
9
+ type PropertyPathArray = string [ ] ;
10
10
11
11
let isRemovedWarningShown = false ;
12
12
@@ -124,8 +124,8 @@ export default createRule('no-unused-props', {
124
124
/**
125
125
* Extracts property paths from member expressions.
126
126
*/
127
- function getPropertyPath ( node : TSESTree . Identifier ) : PropertyPath {
128
- const paths : PropertyPath = [ ] ;
127
+ function getPropertyPath ( node : TSESTree . Identifier ) : PropertyPathArray {
128
+ const paths : PropertyPathArray = [ ] ;
129
129
let currentNode : TSESTree . Node = node ;
130
130
let parentNode : TSESTree . Node | null = currentNode . parent ?? null ;
131
131
@@ -150,11 +150,11 @@ export default createRule('no-unused-props', {
150
150
/**
151
151
* Finds all property access paths for a given variable.
152
152
*/
153
- function getUsedNestedPropertyNames ( node : TSESTree . Identifier ) : PropertyPath [ ] {
153
+ function getUsedNestedPropertyPathsArray ( node : TSESTree . Identifier ) : PropertyPathArray [ ] {
154
154
const variable = findVariable ( context , node ) ;
155
155
if ( ! variable ) return [ ] ;
156
156
157
- const paths : PropertyPath [ ] = [ ] ;
157
+ const pathsArray : PropertyPathArray [ ] = [ ] ;
158
158
for ( const reference of variable . references ) {
159
159
if (
160
160
'identifier' in reference &&
@@ -163,10 +163,10 @@ export default createRule('no-unused-props', {
163
163
reference . identifier . range [ 1 ] !== node . range [ 1 ] )
164
164
) {
165
165
const referencePath = getPropertyPath ( reference . identifier ) ;
166
- paths . push ( referencePath ) ;
166
+ pathsArray . push ( referencePath ) ;
167
167
}
168
168
}
169
- return paths ;
169
+ return pathsArray ;
170
170
}
171
171
172
172
/**
@@ -183,7 +183,7 @@ export default createRule('no-unused-props', {
183
183
return sourceFile . fileName . includes ( 'node_modules/typescript/lib/' ) ;
184
184
}
185
185
186
- function getUsedPropertiesFromPattern ( pattern : TSESTree . ObjectPattern ) : Set < string > {
186
+ function getUsedPropertyNamesFromPattern ( pattern : TSESTree . ObjectPattern ) : Set < string > {
187
187
const usedProps = new Set < string > ( ) ;
188
188
for ( const prop of pattern . properties ) {
189
189
if ( prop . type === 'Property' && prop . key . type === 'Identifier' ) {
@@ -219,41 +219,49 @@ export default createRule('no-unused-props', {
219
219
/**
220
220
* Recursively checks for unused properties in a type.
221
221
*/
222
- function checkUnusedProperties (
223
- type : ts . Type ,
224
- usedPaths : PropertyPath [ ] ,
225
- usedProps : Set < string > ,
226
- reportNode : TSESTree . Node ,
227
- parentPath : string [ ] ,
228
- checkedTypes : Set < string > ,
229
- reportedProps : Set < string >
230
- ) {
222
+ function checkUnusedProperties ( {
223
+ propsType,
224
+ usedPropertyPaths,
225
+ declaredPropertyNames,
226
+ reportNode,
227
+ parentPath,
228
+ checkedPropsTypes,
229
+ reportedPropertyPaths
230
+ } : {
231
+ propsType : ts . Type ;
232
+ usedPropertyPaths : string [ ] ;
233
+ declaredPropertyNames : Set < string > ;
234
+ reportNode : TSESTree . Node ;
235
+ parentPath : string [ ] ;
236
+ checkedPropsTypes : Set < string > ;
237
+ reportedPropertyPaths : Set < string > ;
238
+ } ) {
231
239
// Skip checking if the type itself is a class
232
- if ( isClassType ( type ) ) return ;
240
+ if ( isClassType ( propsType ) ) return ;
233
241
234
- const typeStr = typeChecker . typeToString ( type ) ;
235
- if ( checkedTypes . has ( typeStr ) ) return ;
236
- checkedTypes . add ( typeStr ) ;
237
- if ( shouldIgnoreType ( type ) ) return ;
242
+ const typeStr = typeChecker . typeToString ( propsType ) ;
243
+ if ( checkedPropsTypes . has ( typeStr ) ) return ;
244
+ checkedPropsTypes . add ( typeStr ) ;
245
+ if ( shouldIgnoreType ( propsType ) ) return ;
238
246
239
- const properties = typeChecker . getPropertiesOfType ( type ) ;
240
- const baseTypes = type . getBaseTypes ( ) ;
247
+ const properties = typeChecker . getPropertiesOfType ( propsType ) ;
248
+ const propsBaseTypes = propsType . getBaseTypes ( ) ;
241
249
242
- if ( ! properties . length && ( ! baseTypes || baseTypes . length === 0 ) ) {
250
+ if ( ! properties . length && ( ! propsBaseTypes || propsBaseTypes . length === 0 ) ) {
243
251
return ;
244
252
}
245
253
246
- if ( baseTypes ) {
247
- for ( const baseType of baseTypes ) {
248
- checkUnusedProperties (
249
- baseType ,
250
- usedPaths ,
251
- usedProps ,
254
+ if ( propsBaseTypes ) {
255
+ for ( const propsBaseType of propsBaseTypes ) {
256
+ checkUnusedProperties ( {
257
+ propsType : propsBaseType ,
258
+ usedPropertyPaths ,
259
+ declaredPropertyNames ,
252
260
reportNode,
253
261
parentPath,
254
- checkedTypes ,
255
- reportedProps
256
- ) ;
262
+ checkedPropsTypes ,
263
+ reportedPropertyPaths
264
+ } ) ;
257
265
}
258
266
}
259
267
@@ -267,24 +275,23 @@ export default createRule('no-unused-props', {
267
275
const currentPath = [ ...parentPath , propName ] ;
268
276
const currentPathStr = [ ...parentPath , propName ] . join ( '.' ) ;
269
277
270
- if ( reportedProps . has ( currentPathStr ) ) continue ;
278
+ if ( reportedPropertyPaths . has ( currentPathStr ) ) continue ;
271
279
272
280
const propType = typeChecker . getTypeOfSymbol ( prop ) ;
273
281
274
- const joinedUsedPaths = usedPaths . map ( ( path ) => path . join ( '.' ) ) ;
275
- const isUsedThisInPath = joinedUsedPaths . includes ( currentPathStr ) ;
276
- const isUsedInPath = joinedUsedPaths . some ( ( path ) => {
282
+ const isUsedThisInPath = usedPropertyPaths . includes ( currentPathStr ) ;
283
+ const isUsedInPath = usedPropertyPaths . some ( ( path ) => {
277
284
return path . startsWith ( `${ currentPathStr } .` ) ;
278
285
} ) ;
279
286
280
287
if ( isUsedThisInPath && ! isUsedInPath ) {
281
288
continue ;
282
289
}
283
290
284
- const isUsedInProps = usedProps . has ( propName ) ;
291
+ const isUsedInProps = declaredPropertyNames . has ( propName ) ;
285
292
286
293
if ( ! isUsedInPath && ! isUsedInProps ) {
287
- reportedProps . add ( currentPathStr ) ;
294
+ reportedPropertyPaths . add ( currentPathStr ) ;
288
295
context . report ( {
289
296
node : reportNode ,
290
297
messageId : parentPath . length ? 'unusedNestedProp' : 'unusedProp' ,
@@ -296,30 +303,30 @@ export default createRule('no-unused-props', {
296
303
continue ;
297
304
}
298
305
299
- const isUsedNested = joinedUsedPaths . some ( ( path ) => {
306
+ const isUsedNested = usedPropertyPaths . some ( ( path ) => {
300
307
return path . startsWith ( `${ currentPathStr } .` ) ;
301
308
} ) ;
302
309
303
310
if ( isUsedNested || isUsedInProps ) {
304
- checkUnusedProperties (
305
- propType ,
306
- usedPaths ,
307
- usedProps ,
311
+ checkUnusedProperties ( {
312
+ propsType : propType ,
313
+ usedPropertyPaths ,
314
+ declaredPropertyNames ,
308
315
reportNode,
309
- currentPath ,
310
- checkedTypes ,
311
- reportedProps
312
- ) ;
316
+ parentPath : currentPath ,
317
+ checkedPropsTypes ,
318
+ reportedPropertyPaths
319
+ } ) ;
313
320
}
314
321
}
315
322
316
323
// Check for unused index signatures only at the root level
317
324
if ( parentPath . length === 0 ) {
318
- const indexType = type . getStringIndexType ( ) ;
319
- const numberIndexType = type . getNumberIndexType ( ) ;
325
+ const indexType = propsType . getStringIndexType ( ) ;
326
+ const numberIndexType = propsType . getNumberIndexType ( ) ;
320
327
const hasIndexSignature = Boolean ( indexType ) || Boolean ( numberIndexType ) ;
321
328
322
- if ( hasIndexSignature && ! hasRestElement ( usedProps ) ) {
329
+ if ( hasIndexSignature && ! hasRestElement ( declaredPropertyNames ) ) {
323
330
context . report ( {
324
331
node : reportNode ,
325
332
messageId : 'unusedIndexSignature'
@@ -336,8 +343,8 @@ export default createRule('no-unused-props', {
336
343
return usedProps . size === 0 ;
337
344
}
338
345
339
- function normalizeUsedPaths ( paths : PropertyPath [ ] ) : PropertyPath [ ] {
340
- const normalized : PropertyPath [ ] = [ ] ;
346
+ function normalizeUsedPaths ( paths : PropertyPathArray [ ] ) : PropertyPathArray [ ] {
347
+ const normalized : PropertyPathArray [ ] = [ ] ;
341
348
for ( const path of paths . sort ( ( a , b ) => a . length - b . length ) ) {
342
349
if ( path . length === 0 ) continue ;
343
350
if ( normalized . some ( ( p ) => p . every ( ( part , idx ) => part === path [ idx ] ) ) ) {
@@ -362,13 +369,13 @@ export default createRule('no-unused-props', {
362
369
const tsNode = tools . service . esTreeNodeToTSNodeMap . get ( node ) as ts . VariableDeclaration ;
363
370
if ( ! tsNode || ! tsNode . type ) return ;
364
371
365
- const propType = typeChecker . getTypeFromTypeNode ( tsNode . type ) ;
366
- let usedPaths : PropertyPath [ ] = [ ] ;
367
- let usedProps = new Set < string > ( ) ;
372
+ const propsType = typeChecker . getTypeFromTypeNode ( tsNode . type ) ;
373
+ let usedPropertyPathsArray : PropertyPathArray [ ] = [ ] ;
374
+ let declaredPropertyNames = new Set < string > ( ) ;
368
375
369
376
if ( node . id . type === 'ObjectPattern' ) {
370
- usedProps = getUsedPropertiesFromPattern ( node . id ) ;
371
- if ( usedProps . size === 0 ) return ;
377
+ declaredPropertyNames = getUsedPropertyNamesFromPattern ( node . id ) ;
378
+ if ( declaredPropertyNames . size === 0 ) return ;
372
379
const identifiers : TSESTree . Identifier [ ] = [ ] ;
373
380
for ( const p of node . id . properties ) {
374
381
if ( p . type !== 'Property' ) {
@@ -381,22 +388,24 @@ export default createRule('no-unused-props', {
381
388
}
382
389
}
383
390
for ( const identifier of identifiers ) {
384
- const paths = getUsedNestedPropertyNames ( identifier ) ;
385
- usedPaths . push ( ...paths . map ( ( path ) => [ identifier . name , ...path ] ) ) ;
391
+ const paths = getUsedNestedPropertyPathsArray ( identifier ) ;
392
+ usedPropertyPathsArray . push ( ...paths . map ( ( path ) => [ identifier . name , ...path ] ) ) ;
386
393
}
387
394
} else if ( node . id . type === 'Identifier' ) {
388
- usedPaths = getUsedNestedPropertyNames ( node . id ) ;
395
+ usedPropertyPathsArray = getUsedNestedPropertyPathsArray ( node . id ) ;
389
396
}
390
397
391
- checkUnusedProperties (
392
- propType ,
393
- normalizeUsedPaths ( usedPaths ) ,
394
- usedProps ,
395
- node . id ,
396
- [ ] ,
397
- new Set < string > ( ) ,
398
- new Set < string > ( )
399
- ) ;
398
+ checkUnusedProperties ( {
399
+ propsType,
400
+ usedPropertyPaths : normalizeUsedPaths ( usedPropertyPathsArray ) . map ( ( pathArray ) => {
401
+ return pathArray . join ( '.' ) ;
402
+ } ) ,
403
+ declaredPropertyNames,
404
+ reportNode : node . id ,
405
+ parentPath : [ ] ,
406
+ checkedPropsTypes : new Set < string > ( ) ,
407
+ reportedPropertyPaths : new Set < string > ( )
408
+ } ) ;
400
409
}
401
410
} ;
402
411
}
0 commit comments