@@ -51,6 +51,7 @@ export default createRule('prefer-svelte-reactivity', {
5151 create ( context ) {
5252 const ignoreEncapsulatedLocalVariables =
5353 context . options [ 0 ] ?. ignoreEncapsulatedLocalVariables ?? true ;
54+ const returnedFunctionCalls : Map < FunctionLike , TSESTree . MethodDefinition [ ] > = new Map ( ) ;
5455 const returnedVariables : Map < FunctionLike , VariableLike [ ] > = new Map ( ) ;
5556 const exportedVars : TSESTree . Node [ ] = [ ] ;
5657 return {
@@ -81,6 +82,29 @@ export default createRule('prefer-svelte-reactivity', {
8182 }
8283 } ) ,
8384 Identifier ( node ) {
85+ function recordVariable ( enclosingFunction : FunctionLike , variable : VariableLike ) : void {
86+ if ( variable === null ) {
87+ return ;
88+ }
89+ if ( ! returnedVariables . has ( enclosingFunction ) ) {
90+ returnedVariables . set ( enclosingFunction , [ ] ) ;
91+ }
92+ returnedVariables . get ( enclosingFunction ) ?. push ( variable ) ;
93+ }
94+
95+ function recordFunctionCall (
96+ enclosingFunction : FunctionLike ,
97+ functionCall : TSESTree . MethodDefinition
98+ ) : void {
99+ if ( functionCall === null ) {
100+ return ;
101+ }
102+ if ( ! returnedFunctionCalls . has ( enclosingFunction ) ) {
103+ returnedFunctionCalls . set ( enclosingFunction , [ ] ) ;
104+ }
105+ returnedFunctionCalls . get ( enclosingFunction ) ?. push ( functionCall ) ;
106+ }
107+
84108 const enclosingReturn = findEnclosingReturn ( node ) ;
85109 if ( enclosingReturn === null ) {
86110 return ;
@@ -89,7 +113,6 @@ export default createRule('prefer-svelte-reactivity', {
89113 if ( enclosingFunction === null ) {
90114 return ;
91115 }
92- let variableDeclaration = null ;
93116 if ( node . parent . type === 'MemberExpression' ) {
94117 const enclosingClassBody = findEnclosingClassBody ( node ) ;
95118 for ( const classElement of enclosingClassBody ?. body ?? [ ] ) {
@@ -98,7 +121,14 @@ export default createRule('prefer-svelte-reactivity', {
98121 classElement . key . type === 'Identifier' &&
99122 node . name === classElement . key . name
100123 ) {
101- variableDeclaration = classElement ;
124+ recordVariable ( enclosingFunction , classElement ) ;
125+ }
126+ if (
127+ classElement . type === 'MethodDefinition' &&
128+ classElement . key . type === 'Identifier' &&
129+ node . name === classElement . key . name
130+ ) {
131+ recordFunctionCall ( enclosingFunction , classElement ) ;
102132 }
103133 }
104134 } else {
@@ -108,16 +138,9 @@ export default createRule('prefer-svelte-reactivity', {
108138 variable . identifiers . length > 0 &&
109139 variable . identifiers [ 0 ] . parent . type === 'VariableDeclarator'
110140 ) {
111- variableDeclaration = variable . identifiers [ 0 ] . parent ;
141+ recordVariable ( enclosingFunction , variable . identifiers [ 0 ] . parent ) ;
112142 }
113143 }
114- if ( variableDeclaration === null ) {
115- return ;
116- }
117- if ( ! returnedVariables . has ( enclosingFunction ) ) {
118- returnedVariables . set ( enclosingFunction , [ ] ) ;
119- }
120- returnedVariables . get ( enclosingFunction ) ?. push ( variableDeclaration ) ;
121144 } ,
122145 'Program:exit' ( ) {
123146 const referenceTracker = new ReferenceTracker ( context . sourceCode . scopeManager . globalScope ! ) ;
@@ -174,7 +197,11 @@ export default createRule('prefer-svelte-reactivity', {
174197 findEnclosingReturn ( node ) !== null ||
175198 ( enclosingPropertyDefinition !== null &&
176199 ( ! ignoreEncapsulatedLocalVariables ||
177- ! isPropertyEncapsulated ( enclosingPropertyDefinition , returnedVariables ) ) )
200+ ! isPropertyEncapsulated (
201+ enclosingPropertyDefinition ,
202+ returnedFunctionCalls ,
203+ returnedVariables
204+ ) ) )
178205 ) {
179206 context . report ( {
180207 messageId,
@@ -274,13 +301,23 @@ function isLocalVarEncapsulated(
274301function methodReturnsProperty (
275302 method : TSESTree . MethodDefinition ,
276303 property : TSESTree . PropertyDefinition ,
304+ returnedFunctionCalls : Map < FunctionLike , TSESTree . MethodDefinition [ ] > ,
277305 returnedVariables : Map < FunctionLike , VariableLike [ ] >
278306) : boolean {
279- return returnedVariables . get ( method ) ?. includes ( property ) ?? false ;
307+ return (
308+ ( returnedVariables . get ( method ) ?. includes ( property ) ?? false ) ||
309+ ( returnedFunctionCalls
310+ . get ( method )
311+ ?. some ( ( calledFn ) =>
312+ methodReturnsProperty ( calledFn , property , returnedFunctionCalls , returnedVariables )
313+ ) ??
314+ false )
315+ ) ;
280316}
281317
282318function isPropertyEncapsulated (
283319 node : TSESTree . PropertyDefinition ,
320+ returnedFunctionCalls : Map < FunctionLike , TSESTree . MethodDefinition [ ] > ,
284321 returnedVariables : Map < FunctionLike , VariableLike [ ] >
285322) : boolean {
286323 if ( node . accessibility === 'public' ) {
@@ -290,7 +327,7 @@ function isPropertyEncapsulated(
290327 if (
291328 classElement . type === 'MethodDefinition' &&
292329 classElement . accessibility === 'public' &&
293- methodReturnsProperty ( classElement , node , returnedVariables )
330+ methodReturnsProperty ( classElement , node , returnedFunctionCalls , returnedVariables )
294331 ) {
295332 return false ;
296333 }
0 commit comments