@@ -66,25 +66,25 @@ export function useComponentCollector(
6666) {
6767 const jsxCtx = { getScope : ( node : TSESTree . Node ) => context . sourceCode . getScope ( node ) } as const ;
6868 const components = new Map < string , ERFunctionComponent > ( ) ;
69- const functionStack : [
70- key : string ,
71- node : AST . TSESTreeFunction ,
72- isComponent : boolean ,
73- hookCalls : TSESTree . CallExpression [ ] ,
74- ] [ ] = [ ] ;
69+ const functionStack : {
70+ key : string ;
71+ node : AST . TSESTreeFunction ;
72+ hookCalls : TSESTree . CallExpression [ ] ;
73+ isComponent : boolean ;
74+ } [ ] = [ ] ;
7575 const getCurrentFunction = ( ) => O . fromNullable ( functionStack . at ( - 1 ) ) ;
7676 const onFunctionEnter = ( node : AST . TSESTreeFunction ) => {
7777 const key = getId ( ) ;
78- functionStack . push ( [ key , node , false , [ ] ] ) ;
78+ functionStack . push ( { key, node, hookCalls : [ ] , isComponent : false } ) ;
7979 } ;
8080 const onFunctionExit = ( ) => {
81- const [ key , fn , isComponent ] = functionStack . at ( - 1 ) ?? [ ] ;
82- if ( ! key || ! fn || ! isComponent ) return functionStack . pop ( ) ;
83- const shouldDrop = AST . getNestedReturnStatements ( fn . body )
81+ const { key, node , isComponent } = functionStack . at ( - 1 ) ?? { } ;
82+ if ( ! key || ! node || ! isComponent ) return functionStack . pop ( ) ;
83+ const shouldDrop = AST . getNestedReturnStatements ( node . body )
8484 . slice ( )
8585 . reverse ( )
8686 . some ( r => {
87- return context . sourceCode . getScope ( r ) . block === fn
87+ return context . sourceCode . getScope ( r ) . block === node
8888 && r . argument !== null
8989 && ! JSX . isJSXValue ( r . argument , jsxCtx , hint ) ;
9090 } ) ;
@@ -106,83 +106,90 @@ export function useComponentCollector(
106106 ":function[type]" : onFunctionEnter ,
107107 ":function[type]:exit" : onFunctionExit ,
108108 "ArrowFunctionExpression[type][body.type!='BlockStatement']" ( ) {
109- const maybeCurrentFn = getCurrentFunction ( ) ;
110- if ( O . isNone ( maybeCurrentFn ) ) return ;
111- const [ _key , currentFn , _isComponent , hookCalls ] = maybeCurrentFn . value ;
112- const { body } = currentFn ;
113- const isComponent = hasNoneOrValidComponentName ( currentFn , context )
114- && JSX . isJSXValue ( body , jsxCtx , hint )
115- && hasValidHierarchy ( currentFn , context , hint ) ;
116- if ( ! isComponent ) return ;
117- const initPath = AST . getFunctionInitPath ( currentFn ) ;
118- const id = getFunctionComponentIdentifier ( currentFn , context ) ;
119- const name = O . flatMapNullable ( id , getComponentNameFromIdentifier ) ;
120- const key = getId ( ) ;
121- components . set ( key , {
122- _ : key ,
123- id,
124- kind : "function" ,
125- name,
126- node : currentFn ,
127- displayName : O . none ( ) ,
128- flag : getComponentFlag ( initPath ) ,
129- hint,
130- hookCalls,
131- initPath,
109+ O . match ( getCurrentFunction ( ) , {
110+ onNone ( ) { } ,
111+ onSome ( a ) {
112+ const { body } = a . node ;
113+ const isComponent = hasNoneOrValidComponentName ( a . node , context )
114+ && JSX . isJSXValue ( body , jsxCtx , hint )
115+ && hasValidHierarchy ( a . node , context , hint ) ;
116+ if ( ! isComponent ) return ;
117+ const initPath = AST . getFunctionInitPath ( a . node ) ;
118+ const id = getFunctionComponentIdentifier ( a . node , context ) ;
119+ const name = O . flatMapNullable ( id , getComponentNameFromIdentifier ) ;
120+ const key = getId ( ) ;
121+ components . set ( key , {
122+ _ : key ,
123+ id,
124+ kind : "function" ,
125+ name,
126+ node : a . node ,
127+ displayName : O . none ( ) ,
128+ flag : getComponentFlag ( initPath ) ,
129+ hint,
130+ hookCalls : a . hookCalls ,
131+ initPath,
132+ } ) ;
133+ } ,
132134 } ) ;
133135 } ,
134136 "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']" (
135- node : TSESTree . Node ,
137+ node : TSESTree . AssignmentExpression & { left : TSESTree . MemberExpression } ,
136138 ) {
137- if ( node . type !== AST_NODE_TYPES . AssignmentExpression ) return ;
138139 const { left, right } = node ;
139- if ( left . type !== AST_NODE_TYPES . MemberExpression ) return ;
140- const maybeComponentName = match ( left . object )
140+ const componentName = match ( left . object )
141141 . with ( { type : AST_NODE_TYPES . Identifier } , n => O . some ( n . name ) )
142142 . otherwise ( O . none ) ;
143- if ( O . isNone ( maybeComponentName ) ) return ;
144- const component = Array
145- . from ( components . values ( ) )
146- . findLast ( ( { name } ) => O . exists ( name , n => n === maybeComponentName . value ) ) ;
147- if ( ! component ) return ;
148- components . set ( component . _ , {
149- ...component ,
150- displayName : O . some ( right ) ,
143+ O . match ( componentName , {
144+ onNone ( ) { } ,
145+ onSome ( a ) {
146+ const component = Array
147+ . from ( components . values ( ) )
148+ . findLast ( ( { name } ) => O . exists ( name , n => n === a ) ) ;
149+ if ( ! component ) return ;
150+ components . set ( component . _ , {
151+ ...component ,
152+ displayName : O . some ( right ) ,
153+ } ) ;
154+ } ,
151155 } ) ;
152156 } ,
153157 "CallExpression[type]:exit" ( node : TSESTree . CallExpression ) {
154158 if ( ! isReactHookCall ( node ) ) return ;
155- const maybeCurrentFn = getCurrentFunction ( ) ;
156- if ( O . isNone ( maybeCurrentFn ) ) return ;
157- const [ key , currentFn , isComponent , hookCalls ] = maybeCurrentFn . value ;
158- functionStack . pop ( ) ;
159- functionStack . push ( [ key , currentFn , isComponent , [ ...hookCalls , node ] ] ) ;
159+ O . match ( getCurrentFunction ( ) , {
160+ onNone ( ) { } ,
161+ onSome ( a ) {
162+ functionStack . pop ( ) ;
163+ functionStack . push ( { ...a , hookCalls : [ ...a . hookCalls , node ] } ) ;
164+ } ,
165+ } ) ;
160166 } ,
161167 "ReturnStatement[type]" ( node : TSESTree . ReturnStatement ) {
162- const maybeCurrentFn = getCurrentFunction ( ) ;
163- if ( O . isNone ( maybeCurrentFn ) ) return ;
164- const [ key , currentFn , isKnown , hookCalls ] = maybeCurrentFn . value ;
165- if ( isKnown ) return ;
166- const isComponent = hasNoneOrValidComponentName ( currentFn , context )
167- && JSX . isJSXValue ( node . argument , jsxCtx , hint )
168- && hasValidHierarchy ( currentFn , context , hint ) ;
169- if ( ! isComponent ) return ;
170- functionStack . pop ( ) ;
171- functionStack . push ( [ key , currentFn , true , [ ] ] ) ;
172- const initPath = AST . getFunctionInitPath ( currentFn ) ;
173- const id = getFunctionComponentIdentifier ( currentFn , context ) ;
174- const name = O . flatMapNullable ( id , getComponentNameFromIdentifier ) ;
175- components . set ( key , {
176- _ : key ,
177- id,
178- kind : "function" ,
179- name,
180- node : currentFn ,
181- displayName : O . none ( ) ,
182- flag : getComponentFlag ( initPath ) ,
183- hint,
184- hookCalls,
185- initPath,
168+ O . match ( getCurrentFunction ( ) , {
169+ onNone ( ) { } ,
170+ onSome ( a ) {
171+ const isComponent = hasNoneOrValidComponentName ( a . node , context )
172+ && JSX . isJSXValue ( node . argument , jsxCtx , hint )
173+ && hasValidHierarchy ( a . node , context , hint ) ;
174+ if ( ! isComponent ) return ;
175+ functionStack . pop ( ) ;
176+ functionStack . push ( { ...a , isComponent } ) ;
177+ const initPath = AST . getFunctionInitPath ( a . node ) ;
178+ const id = getFunctionComponentIdentifier ( a . node , context ) ;
179+ const name = O . flatMapNullable ( id , getComponentNameFromIdentifier ) ;
180+ components . set ( a . key , {
181+ _ : a . key ,
182+ id,
183+ kind : "function" ,
184+ name,
185+ node : a . node ,
186+ displayName : O . none ( ) ,
187+ flag : getComponentFlag ( initPath ) ,
188+ hint,
189+ hookCalls : a . hookCalls ,
190+ initPath,
191+ } ) ;
192+ } ,
186193 } ) ;
187194 } ,
188195 } as const satisfies ESLintUtils . RuleListener ;
0 commit comments