@@ -31,6 +31,8 @@ export default createRule('prefer-svelte-reactivity', {
31
31
]
32
32
} ,
33
33
create ( context ) {
34
+ const returnedVariables : Map < TSESTree . FunctionDeclaration , TSESTree . VariableDeclarator [ ] > =
35
+ new Map ( ) ;
34
36
const exportedVars : TSESTree . Node [ ] = [ ] ;
35
37
return {
36
38
...( getSvelteContext ( context ) ?. svelteFileType === '.svelte.[js|ts]' && {
@@ -59,6 +61,28 @@ export default createRule('prefer-svelte-reactivity', {
59
61
}
60
62
}
61
63
} ) ,
64
+ Identifier ( node ) {
65
+ const enclosingReturn = findEnclosingReturn ( node ) ;
66
+ if ( enclosingReturn === null ) {
67
+ return ;
68
+ }
69
+ const enclosingFunction = findEnclosingFunction ( enclosingReturn ) ;
70
+ if ( enclosingFunction === null ) {
71
+ return ;
72
+ }
73
+ const variable = findVariable ( context , node ) ;
74
+ if (
75
+ variable === null ||
76
+ variable . identifiers . length < 1 ||
77
+ variable . identifiers [ 0 ] . parent . type !== 'VariableDeclarator'
78
+ ) {
79
+ return ;
80
+ }
81
+ if ( ! returnedVariables . has ( enclosingFunction ) ) {
82
+ returnedVariables . set ( enclosingFunction , [ ] ) ;
83
+ }
84
+ returnedVariables . get ( enclosingFunction ) ?. push ( variable . identifiers [ 0 ] . parent ) ;
85
+ } ,
62
86
'Program:exit' ( ) {
63
87
const referenceTracker = new ReferenceTracker ( context . sourceCode . scopeManager . globalScope ! ) ;
64
88
for ( const { node, path } of referenceTracker . iterateGlobalReferences ( {
@@ -96,6 +120,20 @@ export default createRule('prefer-svelte-reactivity', {
96
120
} ) ;
97
121
}
98
122
}
123
+ for ( const returnedVar of Array . from ( returnedVariables . values ( ) ) . flat ( ) ) {
124
+ if ( isIn ( node , returnedVar ) ) {
125
+ context . report ( {
126
+ messageId,
127
+ node
128
+ } ) ;
129
+ }
130
+ }
131
+ if ( findEnclosingReturn ( node ) !== null ) {
132
+ context . report ( {
133
+ messageId,
134
+ node
135
+ } ) ;
136
+ }
99
137
if ( path [ 0 ] === 'Date' && isDateMutable ( referenceTracker , node as TSESTree . Expression ) ) {
100
138
context . report ( {
101
139
messageId : 'mutableDateUsed' ,
@@ -135,6 +173,24 @@ export default createRule('prefer-svelte-reactivity', {
135
173
}
136
174
} ) ;
137
175
176
+ function findAncestorOfType < T > ( node : TSESTree . Node , type : T ) : ( TSESTree . Node & { type : T } ) | null {
177
+ if ( node . type === type ) {
178
+ return node as TSESTree . Node & { type : T } ;
179
+ }
180
+ if ( node . parent === undefined || node . parent === null ) {
181
+ return null ;
182
+ }
183
+ return findAncestorOfType ( node . parent , type ) ;
184
+ }
185
+
186
+ function findEnclosingReturn ( node : TSESTree . Node ) : TSESTree . ReturnStatement | null {
187
+ return findAncestorOfType ( node , 'ReturnStatement' ) ;
188
+ }
189
+
190
+ function findEnclosingFunction ( node : TSESTree . Node ) : TSESTree . FunctionDeclaration | null {
191
+ return findAncestorOfType ( node , 'FunctionDeclaration' ) ;
192
+ }
193
+
138
194
function isDateMutable ( referenceTracker : ReferenceTracker , ctorNode : TSESTree . Expression ) : boolean {
139
195
return ! referenceTracker
140
196
. iteratePropertyReferences ( ctorNode , {
0 commit comments