@@ -2,6 +2,7 @@ import type { AST } from 'svelte-eslint-parser';
2
2
import { createRule } from '../utils' ;
3
3
import type { Scope , Variable , Reference , Definition } from '@typescript-eslint/scope-manager' ;
4
4
import type { TSESTree } from '@typescript-eslint/types' ;
5
+ import { findVariable , iterateIdentifiers } from '../utils/ast-utils' ;
5
6
6
7
export default createRule ( 'no-immutable-reactive-statements' , {
7
8
meta : {
@@ -104,31 +105,49 @@ export default createRule('no-immutable-reactive-statements', {
104
105
) {
105
106
return true ;
106
107
}
107
- if ( isMutableMember ( reference . identifier ) ) {
108
+ if ( hasWriteMember ( reference . identifier ) ) {
108
109
return true ;
109
110
}
110
111
}
111
112
return false ;
113
+ }
112
114
113
- function isMutableMember (
114
- expr : TSESTree . Identifier | TSESTree . JSXIdentifier | TSESTree . MemberExpression
115
- ) : boolean {
116
- if ( expr . type === 'JSXIdentifier' ) return false ;
117
- const parent = expr . parent ;
118
- if ( parent . type === 'AssignmentExpression' ) {
119
- return parent . left === expr ;
120
- }
121
- if ( parent . type === 'UpdateExpression' ) {
122
- return parent . argument === expr ;
123
- }
124
- if ( parent . type === 'UnaryExpression' ) {
125
- return parent . operator === 'delete' && parent . argument === expr ;
126
- }
127
- if ( parent . type === 'MemberExpression' ) {
128
- return parent . object === expr && isMutableMember ( parent ) ;
129
- }
130
- return false ;
115
+ /** Checks whether the given expression has writing to a member or not. */
116
+ function hasWriteMember (
117
+ expr : TSESTree . Identifier | TSESTree . JSXIdentifier | TSESTree . MemberExpression
118
+ ) : boolean {
119
+ if ( expr . type === 'JSXIdentifier' ) return false ;
120
+ const parent = expr . parent as TSESTree . Node | AST . SvelteNode ;
121
+ if ( parent . type === 'AssignmentExpression' ) {
122
+ return parent . left === expr ;
123
+ }
124
+ if ( parent . type === 'UpdateExpression' ) {
125
+ return parent . argument === expr ;
126
+ }
127
+ if ( parent . type === 'UnaryExpression' ) {
128
+ return parent . operator === 'delete' && parent . argument === expr ;
129
+ }
130
+ if ( parent . type === 'MemberExpression' ) {
131
+ return parent . object === expr && hasWriteMember ( parent ) ;
131
132
}
133
+ if ( parent . type === 'SvelteDirective' ) {
134
+ return parent . kind === 'Binding' && parent . expression === expr ;
135
+ }
136
+ if ( parent . type === 'SvelteEachBlock' ) {
137
+ return parent . expression === expr && hasWriteReference ( parent . context ) ;
138
+ }
139
+
140
+ return false ;
141
+ }
142
+
143
+ /** Checks whether the given pattern has writing or not. */
144
+ function hasWriteReference ( pattern : TSESTree . DestructuringPattern ) : boolean {
145
+ for ( const id of iterateIdentifiers ( pattern ) ) {
146
+ const variable = findVariable ( context , id ) ;
147
+ if ( variable && hasWrite ( variable ) ) return true ;
148
+ }
149
+
150
+ return false ;
132
151
}
133
152
134
153
/**
0 commit comments