@@ -31,6 +31,10 @@ export default createRule('prefer-svelte-reactivity', {
3131 ]
3232 } ,
3333 create ( context ) {
34+ const returnedVariables : Map <
35+ TSESTree . ArrowFunctionExpression | TSESTree . FunctionDeclaration ,
36+ TSESTree . VariableDeclarator [ ]
37+ > = new Map ( ) ;
3438 const exportedVars : TSESTree . Node [ ] = [ ] ;
3539 return {
3640 ...( getSvelteContext ( context ) ?. svelteFileType === '.svelte.[js|ts]' && {
@@ -59,6 +63,28 @@ export default createRule('prefer-svelte-reactivity', {
5963 }
6064 }
6165 } ) ,
66+ Identifier ( node ) {
67+ const enclosingReturn = findEnclosingReturn ( node ) ;
68+ if ( enclosingReturn === null ) {
69+ return ;
70+ }
71+ const enclosingFunction = findEnclosingFunction ( enclosingReturn ) ;
72+ if ( enclosingFunction === null ) {
73+ return ;
74+ }
75+ const variable = findVariable ( context , node ) ;
76+ if (
77+ variable === null ||
78+ variable . identifiers . length < 1 ||
79+ variable . identifiers [ 0 ] . parent . type !== 'VariableDeclarator'
80+ ) {
81+ return ;
82+ }
83+ if ( ! returnedVariables . has ( enclosingFunction ) ) {
84+ returnedVariables . set ( enclosingFunction , [ ] ) ;
85+ }
86+ returnedVariables . get ( enclosingFunction ) ?. push ( variable . identifiers [ 0 ] . parent ) ;
87+ } ,
6288 'Program:exit' ( ) {
6389 const referenceTracker = new ReferenceTracker ( context . sourceCode . scopeManager . globalScope ! ) ;
6490 for ( const { node, path } of referenceTracker . iterateGlobalReferences ( {
@@ -96,6 +122,20 @@ export default createRule('prefer-svelte-reactivity', {
96122 } ) ;
97123 }
98124 }
125+ for ( const returnedVar of Array . from ( returnedVariables . values ( ) ) . flat ( ) ) {
126+ if ( isIn ( node , returnedVar ) ) {
127+ context . report ( {
128+ messageId,
129+ node
130+ } ) ;
131+ }
132+ }
133+ if ( findEnclosingReturn ( node ) !== null ) {
134+ context . report ( {
135+ messageId,
136+ node
137+ } ) ;
138+ }
99139 if ( path [ 0 ] === 'Date' && isDateMutable ( referenceTracker , node as TSESTree . Expression ) ) {
100140 context . report ( {
101141 messageId : 'mutableDateUsed' ,
@@ -135,6 +175,33 @@ export default createRule('prefer-svelte-reactivity', {
135175 }
136176} ) ;
137177
178+ function findAncestorOfTypes < T extends string > (
179+ node : TSESTree . Node ,
180+ types : string [ ]
181+ ) : ( TSESTree . Node & { type : T } ) | null {
182+ if ( types . includes ( node . type ) ) {
183+ return node as TSESTree . Node & { type : T } ;
184+ }
185+ if ( node . parent === undefined || node . parent === null ) {
186+ return null ;
187+ }
188+ return findAncestorOfTypes ( node . parent , types ) ;
189+ }
190+
191+ function findEnclosingReturn ( node : TSESTree . Node ) : TSESTree . ReturnStatement | null {
192+ return findAncestorOfTypes ( node , [ 'ReturnStatement' ] ) ;
193+ }
194+
195+ function findEnclosingFunction (
196+ node : TSESTree . Node
197+ ) : TSESTree . ArrowFunctionExpression | TSESTree . FunctionDeclaration | null {
198+ return findAncestorOfTypes ( node , [
199+ 'ArrowFunctionExpression' ,
200+ 'FunctionDeclaration' ,
201+ 'MethodDefinition'
202+ ] ) ;
203+ }
204+
138205function isDateMutable ( referenceTracker : ReferenceTracker , ctorNode : TSESTree . Expression ) : boolean {
139206 return ! referenceTracker
140207 . iteratePropertyReferences ( ctorNode , {
0 commit comments