@@ -26,35 +26,36 @@ export function processDeclarations(
2626 const defaultExport : string [ ] = [ ]
2727
2828 for ( const decl of exports ) {
29- const lines = decl . text . split ( '\n' ) . map ( line => line . trim ( ) ) . filter ( line => line )
30-
31- for ( const line of lines ) {
32- if ( line . startsWith ( 'export default' ) ) {
33- defaultExport . push ( line . endsWith ( ';' ) ? line : line + ';' )
34- } else if ( line . startsWith ( 'export type {' ) || line . startsWith ( 'export {' ) ) {
35- // Extract exported items from the line
36- const match = line . match ( / e x p o r t \s + (?: t y p e \s + ) ? \{ \s * ( [ ^ } ] + ) \s * \} / )
37- if ( match ) {
38- const items = match [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
39- for ( const item of items ) {
40- exportedItems . add ( item )
41- }
42- }
43- const statement = line . endsWith ( ';' ) ? line : line + ';'
44- if ( ! exportStatements . includes ( statement ) ) {
45- exportStatements . push ( statement )
46- }
47- } else if ( line . startsWith ( 'export ' ) ) {
48- const statement = line . endsWith ( ';' ) ? line : line + ';'
49- if ( ! exportStatements . includes ( statement ) ) {
50- exportStatements . push ( statement )
29+ if ( decl . text . startsWith ( 'export default' ) ) {
30+ const statement = decl . text . endsWith ( ';' ) ? decl . text : decl . text + ';'
31+ defaultExport . push ( statement )
32+ } else {
33+ // Handle multi-line export statements properly
34+ let exportText = decl . text . trim ( )
35+
36+ // Clean up the export text and ensure it ends with semicolon
37+ if ( ! exportText . endsWith ( ';' ) ) {
38+ exportText += ';'
39+ }
40+
41+ // Extract exported items for tracking
42+ const match = exportText . match ( / e x p o r t \s + (?: t y p e \s + ) ? \{ \s * ( [ ^ } ] + ) \s * \} / )
43+ if ( match ) {
44+ const items = match [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
45+ for ( const item of items ) {
46+ exportedItems . add ( item )
5147 }
5248 }
49+
50+ if ( ! exportStatements . includes ( exportText ) ) {
51+ exportStatements . push ( exportText )
52+ }
5353 }
5454 }
5555
5656 // Filter imports to only include those that are used in exports or declarations
5757 const usedImports = new Set < string > ( )
58+ const usedImportItems = new Set < string > ( )
5859
5960 // Check which imports are needed based on exported functions and types
6061 for ( const func of functions ) {
@@ -67,23 +68,59 @@ export function processDeclarations(
6768 const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
6869 for ( const item of importedItems ) {
6970 if ( funcDeclaration . includes ( item ) ) {
70- usedImports . add ( imp . text )
71+ usedImportItems . add ( item )
7172 }
7273 }
7374 }
7475 }
7576 }
7677 }
7778
78- // Check which imports are needed for interfaces and types (check all, not just exported)
79+ // Check which imports are needed for exported variables
80+ for ( const variable of variables ) {
81+ if ( variable . isExported ) {
82+ for ( const imp of imports ) {
83+ // Handle mixed imports like: import { collect, type Collection } from 'module'
84+ const importText = imp . text
85+ const typeMatches = importText . match ( / t y p e \s + ( [ A - Z a - z _ $ ] [ A - Z a - z 0 - 9 _ $ ] * ) / g)
86+ const valueMatches = importText . match ( / i m p o r t \s + \{ ( [ ^ } ] + ) \} / )
87+
88+ // Check type imports
89+ if ( typeMatches ) {
90+ for ( const typeMatch of typeMatches ) {
91+ const typeName = typeMatch . replace ( 'type ' , '' ) . trim ( )
92+ if ( variable . text . includes ( typeName ) ) {
93+ usedImportItems . add ( typeName )
94+ }
95+ }
96+ }
97+
98+ // Check value imports
99+ if ( valueMatches ) {
100+ const imports = valueMatches [ 1 ] . split ( ',' ) . map ( item =>
101+ item . replace ( / t y p e \s + / , '' ) . trim ( )
102+ )
103+ for ( const importName of imports ) {
104+ if ( variable . text . includes ( importName ) ) {
105+ usedImportItems . add ( importName )
106+ }
107+ }
108+ }
109+ }
110+ }
111+ }
112+
113+ // Check which imports are needed for interfaces and types (only exported ones)
79114 for ( const iface of interfaces ) {
80- for ( const imp of imports ) {
81- const importMatch = imp . text . match ( / i m p o r t \s + (?: t y p e \s + ) ? \{ ? \s * ( [ ^ } ] + ) \s * \} ? \s + f r o m / )
82- if ( importMatch ) {
83- const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
84- for ( const item of importedItems ) {
85- if ( iface . text . includes ( item ) ) {
86- usedImports . add ( imp . text )
115+ if ( iface . isExported ) {
116+ for ( const imp of imports ) {
117+ const importMatch = imp . text . match ( / i m p o r t \s + (?: t y p e \s + ) ? \{ ? \s * ( [ ^ } ] + ) \s * \} ? \s + f r o m / )
118+ if ( importMatch ) {
119+ const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
120+ for ( const item of importedItems ) {
121+ if ( iface . text . includes ( item ) ) {
122+ usedImportItems . add ( item )
123+ }
87124 }
88125 }
89126 }
@@ -98,7 +135,7 @@ export function processDeclarations(
98135 const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
99136 for ( const item of importedItems ) {
100137 if ( type . text . includes ( item ) ) {
101- usedImports . add ( imp . text )
138+ usedImportItems . add ( item )
102139 }
103140 }
104141 }
@@ -110,30 +147,58 @@ export function processDeclarations(
110147 for ( const item of exportedItems ) {
111148 for ( const imp of imports ) {
112149 if ( imp . text . includes ( item ) ) {
113- usedImports . add ( imp . text )
150+ // Extract the specific items from this import
151+ const importMatch = imp . text . match ( / i m p o r t \s + (?: t y p e \s + ) ? \{ ? \s * ( [ ^ } ] + ) \s * \} ? \s + f r o m / )
152+ if ( importMatch ) {
153+ const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
154+ for ( const importedItem of importedItems ) {
155+ if ( item === importedItem ) {
156+ usedImportItems . add ( importedItem )
157+ }
158+ }
159+ }
114160 }
115161 }
116162 }
117163
118164 // Also check for value imports that are re-exported
119165 for ( const exp of exports ) {
120- if ( exp . text . includes ( 'export { generate }' ) ) {
121- // Find the import for generate
122- for ( const imp of imports ) {
123- if ( imp . text . includes ( '{ generate }' ) ) {
124- usedImports . add ( imp . text )
166+ for ( const imp of imports ) {
167+ const importMatch = imp . text . match ( / i m p o r t \s + (?: t y p e \s + ) ? \{ ? \s * ( [ ^ } ] + ) \s * \} ? \s + f r o m / )
168+ if ( importMatch ) {
169+ const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
170+ for ( const importedItem of importedItems ) {
171+ if ( exp . text . includes ( importedItem ) ) {
172+ usedImportItems . add ( importedItem )
173+ }
125174 }
126175 }
127176 }
128177 }
129178
130- // Process and add used imports first
179+ // Create filtered imports based on actually used items
131180 const processedImports : string [ ] = [ ]
132181 for ( const imp of imports ) {
133- if ( usedImports . has ( imp . text ) ) {
134- const processed = processImportDeclaration ( imp )
135- if ( processed && processed . trim ( ) ) {
136- processedImports . push ( processed )
182+ const importMatch = imp . text . match ( / i m p o r t \s + (?: t y p e \s + ) ? \{ ? \s * ( [ ^ } ] + ) \s * \} ? \s + f r o m \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / )
183+ if ( importMatch ) {
184+ const importedItems = importMatch [ 1 ] . split ( ',' ) . map ( item => item . trim ( ) )
185+ const usedItems = importedItems . filter ( item => {
186+ const cleanItem = item . replace ( / ^ t y p e \s + / , '' ) . trim ( )
187+ return usedImportItems . has ( cleanItem )
188+ } )
189+
190+ if ( usedItems . length > 0 ) {
191+ const source = importMatch [ 2 ]
192+ const hasTypeImports = usedItems . some ( item => item . startsWith ( 'type ' ) )
193+ const hasValueImports = usedItems . some ( item => ! item . startsWith ( 'type ' ) )
194+
195+ let importStatement = 'import '
196+ if ( hasTypeImports && ! hasValueImports ) {
197+ importStatement += 'type '
198+ }
199+ importStatement += `{ ${ usedItems . join ( ', ' ) } } from '${ source } ';`
200+
201+ processedImports . push ( importStatement )
137202 }
138203 }
139204 }
@@ -983,4 +1048,4 @@ function inferFunctionType(value: string, inUnion: boolean = false): string {
9831048
9841049 const funcType = '() => unknown'
9851050 return inUnion ? `(${ funcType } )` : funcType
986- }
1051+ }
0 commit comments