@@ -39,13 +39,16 @@ interface NamedRange {
3939 range : DecorationSegment
4040}
4141
42+ interface LocalComponent {
43+ kind : Exclude < ComponentKind , 'unknown' >
44+ range : DecorationSegment
45+ }
46+
4247interface FileAnalysis {
4348 exportReferences : NamedRange [ ]
44- importReferences : NamedRange [ ]
45- imports : Map < string , string >
49+ imports : Map < string , { range : DecorationSegment ; source : string } >
4650 jsxTags : JsxTagReference [ ]
47- localComponentDeclarations : NamedRange [ ]
48- localComponentKinds : Map < string , Exclude < ComponentKind , 'unknown' > >
51+ localComponents : Map < string , LocalComponent >
4952 ownComponentKind : Exclude < ComponentKind , 'unknown' >
5053 typeIdentifiers : TypeIdentifier [ ]
5154}
@@ -106,15 +109,18 @@ export class ComponentLensAnalyzer {
106109 if ( scope . element || scope . import ) {
107110 const uniqueFilePaths = new Set < string > ( )
108111
109- for ( const [ lookupName , source ] of analysis . imports ) {
112+ for ( const [ lookupName , entry ] of analysis . imports ) {
110113 if (
111- analysis . localComponentKinds . has ( lookupName ) ||
114+ analysis . localComponents . has ( lookupName ) ||
112115 resolvedPaths . has ( lookupName )
113116 ) {
114117 continue
115118 }
116119
117- const resolvedFilePath = this . resolver . resolveImport ( filePath , source )
120+ const resolvedFilePath = this . resolver . resolveImport (
121+ filePath ,
122+ entry . source ,
123+ )
118124 if ( resolvedFilePath ) {
119125 resolvedPaths . set ( lookupName , resolvedFilePath )
120126 uniqueFilePaths . add ( resolvedFilePath )
@@ -132,11 +138,10 @@ export class ComponentLensAnalyzer {
132138
133139 if ( scope . element ) {
134140 for ( const jsxTag of analysis . jsxTags ) {
135- if ( analysis . localComponentKinds . has ( jsxTag . lookupName ) ) {
141+ const localComponent = analysis . localComponents . get ( jsxTag . lookupName )
142+ if ( localComponent ) {
136143 usages . push ( {
137- kind :
138- analysis . localComponentKinds . get ( jsxTag . lookupName ) ??
139- analysis . ownComponentKind ,
144+ kind : localComponent . kind ,
140145 ranges : jsxTag . ranges ,
141146 sourceFilePath : filePath ,
142147 tagName : jsxTag . tagName ,
@@ -164,8 +169,8 @@ export class ComponentLensAnalyzer {
164169 }
165170
166171 if ( scope . import ) {
167- for ( const ref of analysis . importReferences ) {
168- const resolvedFilePath = resolvedPaths . get ( ref . name )
172+ for ( const [ name , entry ] of analysis . imports ) {
173+ const resolvedFilePath = resolvedPaths . get ( name )
169174 if ( ! resolvedFilePath ) {
170175 continue
171176 }
@@ -177,22 +182,20 @@ export class ComponentLensAnalyzer {
177182
178183 usages . push ( {
179184 kind : componentKind ,
180- ranges : [ ref . range ] ,
185+ ranges : [ entry . range ] ,
181186 sourceFilePath : resolvedFilePath ,
182- tagName : ref . name ,
187+ tagName : name ,
183188 } )
184189 }
185190 }
186191
187192 if ( scope . declaration ) {
188- for ( const declaration of analysis . localComponentDeclarations ) {
193+ for ( const [ name , component ] of analysis . localComponents ) {
189194 usages . push ( {
190- kind :
191- analysis . localComponentKinds . get ( declaration . name ) ??
192- analysis . ownComponentKind ,
193- ranges : [ declaration . range ] ,
195+ kind : component . kind ,
196+ ranges : [ component . range ] ,
194197 sourceFilePath : filePath ,
195- tagName : declaration . name ,
198+ tagName : name ,
196199 } )
197200 }
198201 }
@@ -207,7 +210,7 @@ export class ComponentLensAnalyzer {
207210 for ( const typeId of analysis . typeIdentifiers ) {
208211 if ( typeId . enclosingComponent ) {
209212 const kind =
210- analysis . localComponentKinds . get ( typeId . enclosingComponent ) ??
213+ analysis . localComponents . get ( typeId . enclosingComponent ) ?. kind ??
211214 analysis . ownComponentKind
212215 if ( ! typeUsageKinds . has ( typeId . name ) || kind === 'client' ) {
213216 typeUsageKinds . set ( typeId . name , kind )
@@ -307,13 +310,11 @@ function parseFileAnalysis(filePath: string, sourceText: string): FileAnalysis {
307310 const asyncComponents = new Set < string > ( )
308311 const componentRanges : { end : number ; name : string ; start : number } [ ] = [ ]
309312 const exportReferences : NamedRange [ ] = [ ]
310- const importReferences : NamedRange [ ] = [ ]
311- const imports = new Map < string , string > ( )
312- const localComponentDeclarations : NamedRange [ ] = [ ]
313- const localComponentKinds = new Map <
313+ const imports = new Map <
314314 string ,
315- Exclude < ComponentKind , 'unknown' >
315+ { range : DecorationSegment ; source : string }
316316 > ( )
317+ const localComponents = new Map < string , LocalComponent > ( )
317318 const typeIdentifiers : TypeIdentifier [ ] = [ ]
318319 let ownComponentKind : Exclude < ComponentKind , 'unknown' > = 'server'
319320 let statementIndex = 0
@@ -328,8 +329,10 @@ function parseFileAnalysis(filePath: string, sourceText: string): FileAnalysis {
328329 nameNode : ts . Node ,
329330 scopeNode : ts . Node ,
330331 ) : void => {
331- localComponentDeclarations . push ( { name, range : nodeRange ( nameNode ) } )
332- localComponentKinds . set ( name , ownComponentKind )
332+ localComponents . set ( name , {
333+ kind : ownComponentKind ,
334+ range : nodeRange ( nameNode ) ,
335+ } )
333336 componentRanges . push ( {
334337 end : scopeNode . getEnd ( ) ,
335338 name,
@@ -339,8 +342,7 @@ function parseFileAnalysis(filePath: string, sourceText: string): FileAnalysis {
339342
340343 const hasAsyncModifier = (
341344 modifiers : ts . NodeArray < ts . ModifierLike > | undefined ,
342- ) : boolean =>
343- modifiers ?. some ( ( m ) => m . kind === ts . SyntaxKind . AsyncKeyword ) ?? false
345+ ) : boolean => modifiers ?. some ( ( m ) => m . kind === ASYNC_KEYWORD ) ?? false
344346
345347 for ( ; statementIndex < sourceFile . statements . length ; statementIndex ++ ) {
346348 const statement = sourceFile . statements [ statementIndex ] !
@@ -366,11 +368,10 @@ function parseFileAnalysis(filePath: string, sourceText: string): FileAnalysis {
366368 ) {
367369 const source = statement . moduleSpecifier . text
368370 const addImport = ( identifier : ts . Identifier ) : void => {
369- imports . set ( identifier . text , source )
370371 if ( isComponentIdentifier ( identifier . text ) ) {
371- importReferences . push ( {
372- name : identifier . text ,
372+ imports . set ( identifier . text , {
373373 range : nodeRange ( identifier ) ,
374+ source,
374375 } )
375376 }
376377 }
@@ -493,23 +494,23 @@ function parseFileAnalysis(filePath: string, sourceText: string): FileAnalysis {
493494 sourceFile ,
494495 componentRanges ,
495496 typeIdentifiers ,
496- localComponentKinds ,
497+ localComponents ,
497498 asyncComponents ,
498499 ownComponentKind === 'server' ,
499500 )
500501
501502 return {
502503 exportReferences,
503- importReferences,
504504 imports,
505505 jsxTags,
506- localComponentDeclarations,
507- localComponentKinds,
506+ localComponents,
508507 ownComponentKind,
509508 typeIdentifiers,
510509 }
511510}
512511
512+ const ASYNC_KEYWORD = ts . SyntaxKind . AsyncKeyword
513+
513514const COMPONENT_WRAPPER_NAMES = new Set ( [
514515 'forwardRef' ,
515516 'memo' ,
@@ -584,7 +585,7 @@ function collectSourceElements(
584585 sourceFile : ts . SourceFile ,
585586 componentRanges : { end : number ; name : string ; start : number } [ ] ,
586587 typeIdentifiers : TypeIdentifier [ ] ,
587- localComponentKinds : Map < string , Exclude < ComponentKind , 'unknown' > > ,
588+ localComponents : Map < string , LocalComponent > ,
588589 asyncComponents : Set < string > ,
589590 inferClientKind : boolean ,
590591) : JsxTagReference [ ] {
@@ -595,11 +596,14 @@ function collectSourceElements(
595596 componentByStart . set ( range . start , range )
596597 }
597598
598- const perComponentFuncs = new Map < string , Map < string , boolean > > ( )
599- const perComponentRefs = new Map < string , string [ ] > ( )
600- const componentsWithInlineFn = new Set < string > ( )
599+ let perComponentFuncs : Map < string , Map < string , boolean > > | undefined
600+ let perComponentRefs : Map < string , string [ ] > | undefined
601+ let componentsWithInlineFn : Set < string > | undefined
601602
602603 if ( inferClientKind ) {
604+ perComponentFuncs = new Map ( )
605+ perComponentRefs = new Map ( )
606+ componentsWithInlineFn = new Set ( )
603607 for ( const range of componentRanges ) {
604608 if ( ! asyncComponents . has ( range . name ) ) {
605609 perComponentFuncs . set ( range . name , new Map ( ) )
@@ -647,8 +651,8 @@ function collectSourceElements(
647651
648652 if (
649653 currentComponent &&
650- perComponentFuncs . has ( currentComponent ) &&
651- ! componentsWithInlineFn . has ( currentComponent )
654+ perComponentFuncs ? .has ( currentComponent ) &&
655+ ! componentsWithInlineFn ! . has ( currentComponent )
652656 ) {
653657 if ( ts . isFunctionDeclaration ( node ) && node . name ) {
654658 perComponentFuncs
@@ -676,9 +680,9 @@ function collectSourceElements(
676680 ( ts . isArrowFunction ( expr ) || ts . isFunctionExpression ( expr ) ) &&
677681 ! hasUseServerDirective ( expr )
678682 ) {
679- componentsWithInlineFn . add ( currentComponent )
683+ componentsWithInlineFn ! . add ( currentComponent )
680684 } else if ( ts . isIdentifier ( expr ) ) {
681- perComponentRefs . get ( currentComponent ) ! . push ( expr . text )
685+ perComponentRefs ! . get ( currentComponent ) ! . push ( expr . text )
682686 }
683687 }
684688 }
@@ -691,14 +695,18 @@ function collectSourceElements(
691695 }
692696 ts . forEachChild ( sourceFile , visit )
693697
698+ if ( ! perComponentFuncs ) {
699+ return jsxTags
700+ }
701+
694702 for ( const [ name , funcs ] of perComponentFuncs ) {
695- if ( componentsWithInlineFn . has ( name ) ) {
696- localComponentKinds . set ( name , 'client' )
703+ if ( componentsWithInlineFn ! . has ( name ) ) {
704+ localComponents . get ( name ) ! . kind = 'client'
697705 continue
698706 }
699- const refs = perComponentRefs . get ( name ) !
707+ const refs = perComponentRefs ! . get ( name ) !
700708 if ( refs . some ( ( ref ) => funcs . has ( ref ) && ! funcs . get ( ref ) ) ) {
701- localComponentKinds . set ( name , 'client' )
709+ localComponents . get ( name ) ! . kind = 'client'
702710 }
703711 }
704712
0 commit comments