@@ -42,6 +42,46 @@ const getRootIdentifier = expression => {
4242 return expression ?. type === 'Identifier' ? expression : undefined ;
4343} ;
4444
45+ const hasRestElement = pattern => {
46+ switch ( pattern ?. type ) {
47+ case 'RestElement' : {
48+ return true ;
49+ }
50+
51+ case 'AssignmentPattern' : {
52+ return hasRestElement ( pattern . left ) ;
53+ }
54+
55+ case 'ObjectPattern' : {
56+ return pattern . properties . some ( property =>
57+ hasRestElement ( property . type === 'Property' ? property . value : property ) ,
58+ ) ;
59+ }
60+
61+ case 'ArrayPattern' : {
62+ return pattern . elements . some ( element =>
63+ hasRestElement ( element ) ,
64+ ) ;
65+ }
66+
67+ default : {
68+ return false ;
69+ }
70+ }
71+ } ;
72+
73+ const isIdentifierProperty = property =>
74+ property . type === 'Property'
75+ && property . key . type === 'Identifier' ;
76+
77+ const isMemberDestructuredInNestedPatternWithRest = ( objectPattern , memberName ) =>
78+ objectPattern . properties . some ( property =>
79+ isIdentifierProperty ( property )
80+ && property . key . name === memberName
81+ && property . value . type !== 'Identifier'
82+ && hasRestElement ( property . value ) ,
83+ ) ;
84+
4585const isRootVariableReassigned = ( declaration , memberExpressionNode , memberScope , sourceCode ) => {
4686 if ( ! declaration . rootVariable ) {
4787 return false ;
@@ -135,24 +175,31 @@ const create = context => {
135175 return ;
136176 }
137177
138- const destructurings = objectPattern . properties . filter ( property =>
139- property . type === 'Property'
140- && property . key . type === 'Identifier'
178+ const member = sourceCode . getText ( node . property ) ;
179+
180+ // If the member is already destructured via a nested pattern with rest,
181+ // don't suggest adding a separate top-level destructuring for the same member.
182+ const memberDestructuredInNestedPattern = isMemberDestructuredInNestedPatternWithRest ( objectPattern , member ) ;
183+
184+ const destructuredProperties = objectPattern . properties . filter ( property =>
185+ isIdentifierProperty ( property )
141186 && property . value . type === 'Identifier' ,
142187 ) ;
143- const lastProperty = objectPattern . properties . at ( - 1 ) ;
144-
145- const hasRest = lastProperty && lastProperty . type === 'RestElement' ;
146188
189+ const lastProperty = objectPattern . properties . at ( - 1 ) ;
190+ const hasRest = lastProperty ?. type === 'RestElement' ;
147191 const expression = sourceCode . getText ( node ) ;
148- const member = sourceCode . getText ( node . property ) ;
149192
150193 // Member might already be destructured
151- const destructuredMember = destructurings . find ( property =>
194+ const destructuredMember = destructuredProperties . find ( property =>
152195 property . key . name === member ,
153196 ) ;
154197
155198 if ( ! destructuredMember ) {
199+ if ( memberDestructuredInNestedPattern ) {
200+ return ;
201+ }
202+
156203 // Don't destructure additional members when rest is used
157204 if ( hasRest ) {
158205 return ;
0 commit comments