@@ -6,7 +6,7 @@ import { findVariable } from '../utils/ast-utils.js';
66import { toRegExp } from '../utils/regexp.js' ;
77import { getFilename } from '../utils/compat.js' ;
88
9- type PropertyPath = string [ ] ;
9+ type PropertyPathArray = string [ ] ;
1010
1111let isRemovedWarningShown = false ;
1212
@@ -124,8 +124,8 @@ export default createRule('no-unused-props', {
124124 /**
125125 * Extracts property paths from member expressions.
126126 */
127- function getPropertyPath ( node : TSESTree . Identifier ) : PropertyPath {
128- const paths : PropertyPath = [ ] ;
127+ function getPropertyPath ( node : TSESTree . Identifier ) : PropertyPathArray {
128+ const paths : PropertyPathArray = [ ] ;
129129 let currentNode : TSESTree . Node = node ;
130130 let parentNode : TSESTree . Node | null = currentNode . parent ?? null ;
131131
@@ -150,11 +150,11 @@ export default createRule('no-unused-props', {
150150 /**
151151 * Finds all property access paths for a given variable.
152152 */
153- function getUsedNestedPropertyNames ( node : TSESTree . Identifier ) : PropertyPath [ ] {
153+ function getUsedNestedPropertyPathsArray ( node : TSESTree . Identifier ) : PropertyPathArray [ ] {
154154 const variable = findVariable ( context , node ) ;
155155 if ( ! variable ) return [ ] ;
156156
157- const paths : PropertyPath [ ] = [ ] ;
157+ const pathsArray : PropertyPathArray [ ] = [ ] ;
158158 for ( const reference of variable . references ) {
159159 if (
160160 'identifier' in reference &&
@@ -163,10 +163,10 @@ export default createRule('no-unused-props', {
163163 reference . identifier . range [ 1 ] !== node . range [ 1 ] )
164164 ) {
165165 const referencePath = getPropertyPath ( reference . identifier ) ;
166- paths . push ( referencePath ) ;
166+ pathsArray . push ( referencePath ) ;
167167 }
168168 }
169- return paths ;
169+ return pathsArray ;
170170 }
171171
172172 /**
@@ -183,7 +183,7 @@ export default createRule('no-unused-props', {
183183 return sourceFile . fileName . includes ( 'node_modules/typescript/lib/' ) ;
184184 }
185185
186- function getUsedPropertiesFromPattern ( pattern : TSESTree . ObjectPattern ) : Set < string > {
186+ function getUsedPropertyNamesFromPattern ( pattern : TSESTree . ObjectPattern ) : Set < string > {
187187 const usedProps = new Set < string > ( ) ;
188188 for ( const prop of pattern . properties ) {
189189 if ( prop . type === 'Property' && prop . key . type === 'Identifier' ) {
@@ -219,41 +219,49 @@ export default createRule('no-unused-props', {
219219 /**
220220 * Recursively checks for unused properties in a type.
221221 */
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+ } ) {
231239 // Skip checking if the type itself is a class
232- if ( isClassType ( type ) ) return ;
240+ if ( isClassType ( propsType ) ) return ;
233241
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 ;
238246
239- const properties = typeChecker . getPropertiesOfType ( type ) ;
240- const baseTypes = type . getBaseTypes ( ) ;
247+ const properties = typeChecker . getPropertiesOfType ( propsType ) ;
248+ const propsBaseTypes = propsType . getBaseTypes ( ) ;
241249
242- if ( ! properties . length && ( ! baseTypes || baseTypes . length === 0 ) ) {
250+ if ( ! properties . length && ( ! propsBaseTypes || propsBaseTypes . length === 0 ) ) {
243251 return ;
244252 }
245253
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 ,
252260 reportNode,
253261 parentPath,
254- checkedTypes ,
255- reportedProps
256- ) ;
262+ checkedPropsTypes ,
263+ reportedPropertyPaths
264+ } ) ;
257265 }
258266 }
259267
@@ -267,24 +275,23 @@ export default createRule('no-unused-props', {
267275 const currentPath = [ ...parentPath , propName ] ;
268276 const currentPathStr = [ ...parentPath , propName ] . join ( '.' ) ;
269277
270- if ( reportedProps . has ( currentPathStr ) ) continue ;
278+ if ( reportedPropertyPaths . has ( currentPathStr ) ) continue ;
271279
272280 const propType = typeChecker . getTypeOfSymbol ( prop ) ;
273281
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 ) => {
277284 return path . startsWith ( `${ currentPathStr } .` ) ;
278285 } ) ;
279286
280287 if ( isUsedThisInPath && ! isUsedInPath ) {
281288 continue ;
282289 }
283290
284- const isUsedInProps = usedProps . has ( propName ) ;
291+ const isUsedInProps = declaredPropertyNames . has ( propName ) ;
285292
286293 if ( ! isUsedInPath && ! isUsedInProps ) {
287- reportedProps . add ( currentPathStr ) ;
294+ reportedPropertyPaths . add ( currentPathStr ) ;
288295 context . report ( {
289296 node : reportNode ,
290297 messageId : parentPath . length ? 'unusedNestedProp' : 'unusedProp' ,
@@ -296,30 +303,30 @@ export default createRule('no-unused-props', {
296303 continue ;
297304 }
298305
299- const isUsedNested = joinedUsedPaths . some ( ( path ) => {
306+ const isUsedNested = usedPropertyPaths . some ( ( path ) => {
300307 return path . startsWith ( `${ currentPathStr } .` ) ;
301308 } ) ;
302309
303310 if ( isUsedNested || isUsedInProps ) {
304- checkUnusedProperties (
305- propType ,
306- usedPaths ,
307- usedProps ,
311+ checkUnusedProperties ( {
312+ propsType : propType ,
313+ usedPropertyPaths ,
314+ declaredPropertyNames ,
308315 reportNode,
309- currentPath ,
310- checkedTypes ,
311- reportedProps
312- ) ;
316+ parentPath : currentPath ,
317+ checkedPropsTypes ,
318+ reportedPropertyPaths
319+ } ) ;
313320 }
314321 }
315322
316323 // Check for unused index signatures only at the root level
317324 if ( parentPath . length === 0 ) {
318- const indexType = type . getStringIndexType ( ) ;
319- const numberIndexType = type . getNumberIndexType ( ) ;
325+ const indexType = propsType . getStringIndexType ( ) ;
326+ const numberIndexType = propsType . getNumberIndexType ( ) ;
320327 const hasIndexSignature = Boolean ( indexType ) || Boolean ( numberIndexType ) ;
321328
322- if ( hasIndexSignature && ! hasRestElement ( usedProps ) ) {
329+ if ( hasIndexSignature && ! hasRestElement ( declaredPropertyNames ) ) {
323330 context . report ( {
324331 node : reportNode ,
325332 messageId : 'unusedIndexSignature'
@@ -336,8 +343,8 @@ export default createRule('no-unused-props', {
336343 return usedProps . size === 0 ;
337344 }
338345
339- function normalizeUsedPaths ( paths : PropertyPath [ ] ) : PropertyPath [ ] {
340- const normalized : PropertyPath [ ] = [ ] ;
346+ function normalizeUsedPaths ( paths : PropertyPathArray [ ] ) : PropertyPathArray [ ] {
347+ const normalized : PropertyPathArray [ ] = [ ] ;
341348 for ( const path of paths . sort ( ( a , b ) => a . length - b . length ) ) {
342349 if ( path . length === 0 ) continue ;
343350 if ( normalized . some ( ( p ) => p . every ( ( part , idx ) => part === path [ idx ] ) ) ) {
@@ -362,13 +369,13 @@ export default createRule('no-unused-props', {
362369 const tsNode = tools . service . esTreeNodeToTSNodeMap . get ( node ) as ts . VariableDeclaration ;
363370 if ( ! tsNode || ! tsNode . type ) return ;
364371
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 > ( ) ;
368375
369376 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 ;
372379 const identifiers : TSESTree . Identifier [ ] = [ ] ;
373380 for ( const p of node . id . properties ) {
374381 if ( p . type !== 'Property' ) {
@@ -381,22 +388,24 @@ export default createRule('no-unused-props', {
381388 }
382389 }
383390 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 ] ) ) ;
386393 }
387394 } else if ( node . id . type === 'Identifier' ) {
388- usedPaths = getUsedNestedPropertyNames ( node . id ) ;
395+ usedPropertyPathsArray = getUsedNestedPropertyPathsArray ( node . id ) ;
389396 }
390397
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+ } ) ;
400409 }
401410 } ;
402411 }
0 commit comments