@@ -54,6 +54,71 @@ export default createRule('prefer-svelte-reactivity', {
5454 const returnedFunctionCalls : Map < FunctionLike , TSESTree . MethodDefinition [ ] > = new Map ( ) ;
5555 const returnedVariables : Map < FunctionLike , VariableLike [ ] > = new Map ( ) ;
5656 const exportedVars : TSESTree . Node [ ] = [ ] ;
57+
58+ function recordReturnedIdentifiers ( node : TSESTree . Identifier | TSESTree . PrivateIdentifier ) {
59+ function recordVariable ( enclosingFunction : FunctionLike , variable : VariableLike ) : void {
60+ if ( variable === null ) {
61+ return ;
62+ }
63+ if ( ! returnedVariables . has ( enclosingFunction ) ) {
64+ returnedVariables . set ( enclosingFunction , [ ] ) ;
65+ }
66+ returnedVariables . get ( enclosingFunction ) ?. push ( variable ) ;
67+ }
68+
69+ function recordFunctionCall (
70+ enclosingFunction : FunctionLike ,
71+ functionCall : TSESTree . MethodDefinition
72+ ) : void {
73+ if ( functionCall === null ) {
74+ return ;
75+ }
76+ if ( ! returnedFunctionCalls . has ( enclosingFunction ) ) {
77+ returnedFunctionCalls . set ( enclosingFunction , [ ] ) ;
78+ }
79+ returnedFunctionCalls . get ( enclosingFunction ) ?. push ( functionCall ) ;
80+ }
81+
82+ const enclosingReturn = findEnclosingReturn ( node ) ;
83+ if ( enclosingReturn === null ) {
84+ return ;
85+ }
86+ const enclosingFunction = findEnclosingFunction ( enclosingReturn ) ;
87+ if ( enclosingFunction === null ) {
88+ return ;
89+ }
90+ if ( node . parent . type === 'MemberExpression' ) {
91+ const enclosingClassBody = findEnclosingClassBody ( node ) ;
92+ for ( const classElement of enclosingClassBody ?. body ?? [ ] ) {
93+ if (
94+ classElement . type === 'PropertyDefinition' &&
95+ ( classElement . key . type === 'Identifier' ||
96+ classElement . key . type === 'PrivateIdentifier' ) &&
97+ node . name === classElement . key . name
98+ ) {
99+ recordVariable ( enclosingFunction , classElement ) ;
100+ }
101+ if (
102+ classElement . type === 'MethodDefinition' &&
103+ ( classElement . key . type === 'Identifier' ||
104+ classElement . key . type === 'PrivateIdentifier' ) &&
105+ node . name === classElement . key . name
106+ ) {
107+ recordFunctionCall ( enclosingFunction , classElement ) ;
108+ }
109+ }
110+ } else if ( node . type === 'Identifier' ) {
111+ const variable = findVariable ( context , node ) ;
112+ if (
113+ variable !== null &&
114+ variable . identifiers . length > 0 &&
115+ variable . identifiers [ 0 ] . parent . type === 'VariableDeclarator'
116+ ) {
117+ recordVariable ( enclosingFunction , variable . identifiers [ 0 ] . parent ) ;
118+ }
119+ }
120+ }
121+
57122 return {
58123 ...( getSvelteContext ( context ) ?. svelteFileType === '.svelte.[js|ts]' && {
59124 ExportNamedDeclaration ( node ) {
@@ -81,67 +146,8 @@ export default createRule('prefer-svelte-reactivity', {
81146 }
82147 }
83148 } ) ,
84- 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-
108- const enclosingReturn = findEnclosingReturn ( node ) ;
109- if ( enclosingReturn === null ) {
110- return ;
111- }
112- const enclosingFunction = findEnclosingFunction ( enclosingReturn ) ;
113- if ( enclosingFunction === null ) {
114- return ;
115- }
116- if ( node . parent . type === 'MemberExpression' ) {
117- const enclosingClassBody = findEnclosingClassBody ( node ) ;
118- for ( const classElement of enclosingClassBody ?. body ?? [ ] ) {
119- if (
120- classElement . type === 'PropertyDefinition' &&
121- classElement . key . type === 'Identifier' &&
122- node . name === classElement . key . name
123- ) {
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 ) ;
132- }
133- }
134- } else {
135- const variable = findVariable ( context , node ) ;
136- if (
137- variable !== null &&
138- variable . identifiers . length > 0 &&
139- variable . identifiers [ 0 ] . parent . type === 'VariableDeclarator'
140- ) {
141- recordVariable ( enclosingFunction , variable . identifiers [ 0 ] . parent ) ;
142- }
143- }
144- } ,
149+ Identifier : recordReturnedIdentifiers ,
150+ PrivateIdentifier : recordReturnedIdentifiers ,
145151 'Program:exit' ( ) {
146152 const referenceTracker = new ReferenceTracker ( context . sourceCode . scopeManager . globalScope ! ) ;
147153 for ( const { node, path } of referenceTracker . iterateGlobalReferences ( {
@@ -320,13 +326,13 @@ function isPropertyEncapsulated(
320326 returnedFunctionCalls : Map < FunctionLike , TSESTree . MethodDefinition [ ] > ,
321327 returnedVariables : Map < FunctionLike , VariableLike [ ] >
322328) : boolean {
323- if ( node . accessibility === 'public' ) {
329+ if ( isPublic ( node ) ) {
324330 return false ;
325331 }
326332 for ( const classElement of node . parent . body ) {
327333 if (
328334 classElement . type === 'MethodDefinition' &&
329- classElement . accessibility === 'public' &&
335+ isPublic ( classElement ) &&
330336 methodReturnsProperty ( classElement , node , returnedFunctionCalls , returnedVariables )
331337 ) {
332338 return false ;
@@ -335,6 +341,13 @@ function isPropertyEncapsulated(
335341 return true ;
336342}
337343
344+ function isPublic ( node : TSESTree . MethodDefinition | TSESTree . PropertyDefinition ) : boolean {
345+ return (
346+ ( node . accessibility === undefined && node . key . type !== 'PrivateIdentifier' ) ||
347+ node . accessibility === 'public'
348+ ) ;
349+ }
350+
338351function isDateMutable ( referenceTracker : ReferenceTracker , ctorNode : TSESTree . Expression ) : boolean {
339352 return ! referenceTracker
340353 . iteratePropertyReferences ( ctorNode , {
0 commit comments