@@ -119,6 +119,92 @@ export default createRule('prefer-svelte-reactivity', {
119119 }
120120 }
121121
122+ function checkNonReactiveUsage (
123+ node : TSESTree . Node ,
124+ objectType : 'Date' | 'Map' | 'Set' | 'URL' | 'URLSearchParams' ,
125+ referenceTracker : ReferenceTracker
126+ ) {
127+ const messageId = `mutable${ objectType } Used` ;
128+
129+ function report ( ) {
130+ context . report ( {
131+ messageId,
132+ node
133+ } ) ;
134+ }
135+
136+ // Report all values directly returned from functions
137+ if ( findEnclosingReturn ( node ) !== null ) {
138+ report ( ) ;
139+ return ;
140+ }
141+
142+ // Report all exported variables
143+ for ( const exportedVar of exportedVars ) {
144+ if ( isIn ( node , exportedVar ) ) {
145+ report ( ) ;
146+ return ;
147+ }
148+ }
149+
150+ // Report all returned variables
151+ for ( const [ fn , fnReturnVars ] of returnedVariables . entries ( ) ) {
152+ for ( const returnedVar of fnReturnVars ) {
153+ if ( fn . type === 'MethodDefinition' && returnedVar . type === 'PropertyDefinition' ) {
154+ continue ;
155+ }
156+ if ( isIn ( node , returnedVar ) ) {
157+ report ( ) ;
158+ return ;
159+ }
160+ }
161+ }
162+
163+ // Report all encapsulated class properties
164+ const enclosingPropertyDefinition = findEnclosingPropertyDefinition ( node ) ;
165+ if (
166+ enclosingPropertyDefinition !== null &&
167+ ( ! ignoreEncapsulatedLocalVariables ||
168+ ! isPropertyEncapsulated (
169+ enclosingPropertyDefinition ,
170+ returnedFunctionCalls ,
171+ returnedVariables
172+ ) )
173+ ) {
174+ report ( ) ;
175+ return ;
176+ }
177+
178+ // Ignore all variables encapsulated in functions
179+ if ( ignoreEncapsulatedLocalVariables && isLocalVarEncapsulated ( returnedVariables , node ) ) {
180+ return ;
181+ }
182+
183+ // Report all other mutable variables
184+ if ( objectType === 'Date' && isDateMutable ( referenceTracker , node as TSESTree . Expression ) ) {
185+ report ( ) ;
186+ return ;
187+ }
188+ if ( objectType === 'Map' && isMapMutable ( referenceTracker , node as TSESTree . Expression ) ) {
189+ report ( ) ;
190+ return ;
191+ }
192+ if ( objectType === 'Set' && isSetMutable ( referenceTracker , node as TSESTree . Expression ) ) {
193+ report ( ) ;
194+ return ;
195+ }
196+ if ( objectType === 'URL' && isURLMutable ( referenceTracker , node as TSESTree . Expression ) ) {
197+ report ( ) ;
198+ return ;
199+ }
200+ if (
201+ objectType === 'URLSearchParams' &&
202+ isURLSearchParamsMutable ( referenceTracker , node as TSESTree . Expression )
203+ ) {
204+ report ( ) ;
205+ }
206+ }
207+
122208 return {
123209 ...( getSvelteContext ( context ) ?. svelteFileType === '.svelte.[js|ts]' && {
124210 ExportNamedDeclaration ( node ) {
@@ -167,89 +253,11 @@ export default createRule('prefer-svelte-reactivity', {
167253 [ ReferenceTracker . CONSTRUCT ] : true
168254 }
169255 } ) ) {
170- const messageId =
171- path [ 0 ] === 'Date'
172- ? 'mutableDateUsed'
173- : path [ 0 ] === 'Map'
174- ? 'mutableMapUsed'
175- : path [ 0 ] === 'Set'
176- ? 'mutableSetUsed'
177- : path [ 0 ] === 'URL'
178- ? 'mutableURLUsed'
179- : 'mutableURLSearchParamsUsed' ;
180- for ( const exportedVar of exportedVars ) {
181- if ( isIn ( node , exportedVar ) ) {
182- context . report ( {
183- messageId,
184- node
185- } ) ;
186- }
187- }
188- for ( const [ fn , fnReturnVars ] of returnedVariables . entries ( ) ) {
189- for ( const returnedVar of fnReturnVars ) {
190- if ( fn . type === 'MethodDefinition' && returnedVar . type === 'PropertyDefinition' ) {
191- continue ;
192- }
193- if ( isIn ( node , returnedVar ) ) {
194- context . report ( {
195- messageId,
196- node
197- } ) ;
198- }
199- }
200- }
201- const enclosingPropertyDefinition = findEnclosingPropertyDefinition ( node ) ;
202- if (
203- findEnclosingReturn ( node ) !== null ||
204- ( enclosingPropertyDefinition !== null &&
205- ( ! ignoreEncapsulatedLocalVariables ||
206- ! isPropertyEncapsulated (
207- enclosingPropertyDefinition ,
208- returnedFunctionCalls ,
209- returnedVariables
210- ) ) )
211- ) {
212- context . report ( {
213- messageId,
214- node
215- } ) ;
216- }
217- if ( ignoreEncapsulatedLocalVariables && isLocalVarEncapsulated ( returnedVariables , node ) ) {
218- continue ;
219- }
220- if ( path [ 0 ] === 'Date' && isDateMutable ( referenceTracker , node as TSESTree . Expression ) ) {
221- context . report ( {
222- messageId : 'mutableDateUsed' ,
223- node
224- } ) ;
225- }
226- if ( path [ 0 ] === 'Map' && isMapMutable ( referenceTracker , node as TSESTree . Expression ) ) {
227- context . report ( {
228- messageId : 'mutableMapUsed' ,
229- node
230- } ) ;
231- }
232- if ( path [ 0 ] === 'Set' && isSetMutable ( referenceTracker , node as TSESTree . Expression ) ) {
233- context . report ( {
234- messageId : 'mutableSetUsed' ,
235- node
236- } ) ;
237- }
238- if ( path [ 0 ] === 'URL' && isURLMutable ( referenceTracker , node as TSESTree . Expression ) ) {
239- context . report ( {
240- messageId : 'mutableURLUsed' ,
241- node
242- } ) ;
243- }
244- if (
245- path [ 0 ] === 'URLSearchParams' &&
246- isURLSearchParamsMutable ( referenceTracker , node as TSESTree . Expression )
247- ) {
248- context . report ( {
249- messageId : 'mutableURLSearchParamsUsed' ,
250- node
251- } ) ;
252- }
256+ checkNonReactiveUsage (
257+ node ,
258+ path [ 0 ] as 'Date' | 'Map' | 'Set' | 'URL' | 'URLSearchParams' ,
259+ referenceTracker
260+ ) ;
253261 }
254262 }
255263 } ;
0 commit comments