@@ -5,8 +5,9 @@ import MagicString from 'magic-string';
55 * Collects all imports and module-level declarations to then find out which interfaces/types are hoistable.
66 */
77export class HoistableInterfaces {
8- private import_value_set : Set < string > = new Set ( ) ;
9- private import_type_set : Set < string > = new Set ( ) ;
8+ private module_types : Set < string > = new Set ( ) ;
9+ private disallowed_types = new Set < string > ( ) ;
10+ private disallowed_values = new Set < string > ( ) ;
1011 private interface_map : Map <
1112 string ,
1213 { type_deps : Set < string > ; value_deps : Set < string > ; node : ts . Node }
@@ -18,6 +19,7 @@ export class HoistableInterfaces {
1819 value_deps : new Set < string > ( )
1920 } ;
2021
22+ /** should be called before analyzeInstanceScriptNode */
2123 analyzeModuleScriptNode ( node : ts . Node ) {
2224 // Handle Import Declarations
2325 if ( ts . isImportDeclaration ( node ) && node . importClause ) {
@@ -30,9 +32,7 @@ export class HoistableInterfaces {
3032 node . importClause . namedBindings . elements . forEach ( ( element ) => {
3133 const import_name = element . name . text ;
3234 if ( is_type_only || element . isTypeOnly ) {
33- this . import_type_set . add ( import_name ) ;
34- } else {
35- this . import_value_set . add ( import_name ) ;
35+ this . module_types . add ( import_name ) ;
3636 }
3737 } ) ;
3838 }
@@ -41,9 +41,7 @@ export class HoistableInterfaces {
4141 if ( node . importClause . name ) {
4242 const default_import = node . importClause . name . text ;
4343 if ( is_type_only ) {
44- this . import_type_set . add ( default_import ) ;
45- } else {
46- this . import_value_set . add ( default_import ) ;
44+ this . module_types . add ( default_import ) ;
4745 }
4846 }
4947
@@ -54,40 +52,17 @@ export class HoistableInterfaces {
5452 ) {
5553 const namespace_import = node . importClause . namedBindings . name . text ;
5654 if ( is_type_only ) {
57- this . import_type_set . add ( namespace_import ) ;
58- } else {
59- this . import_value_set . add ( namespace_import ) ;
55+ this . module_types . add ( namespace_import ) ;
6056 }
6157 }
6258 }
6359
64- // Handle top-level declarations
65- if ( ts . isVariableStatement ( node ) ) {
66- node . declarationList . declarations . forEach ( ( declaration ) => {
67- if ( ts . isIdentifier ( declaration . name ) ) {
68- this . import_value_set . add ( declaration . name . text ) ;
69- }
70- } ) ;
71- }
72-
73- if ( ts . isFunctionDeclaration ( node ) && node . name ) {
74- this . import_value_set . add ( node . name . text ) ;
75- }
76-
77- if ( ts . isClassDeclaration ( node ) && node . name ) {
78- this . import_value_set . add ( node . name . text ) ;
79- }
80-
81- if ( ts . isEnumDeclaration ( node ) ) {
82- this . import_value_set . add ( node . name . text ) ;
83- }
84-
8560 if ( ts . isTypeAliasDeclaration ( node ) ) {
86- this . import_type_set . add ( node . name . text ) ;
61+ this . module_types . add ( node . name . text ) ;
8762 }
8863
8964 if ( ts . isInterfaceDeclaration ( node ) ) {
90- this . import_type_set . add ( node . name . text ) ;
65+ this . module_types . add ( node . name . text ) ;
9166 }
9267 }
9368
@@ -103,9 +78,7 @@ export class HoistableInterfaces {
10378 node . importClause . namedBindings . elements . forEach ( ( element ) => {
10479 const import_name = element . name . text ;
10580 if ( is_type_only ) {
106- this . import_type_set . add ( import_name ) ;
107- } else {
108- this . import_value_set . add ( import_name ) ;
81+ this . module_types . add ( import_name ) ;
10982 }
11083 } ) ;
11184 }
@@ -114,9 +87,7 @@ export class HoistableInterfaces {
11487 if ( node . importClause . name ) {
11588 const default_import = node . importClause . name . text ;
11689 if ( is_type_only ) {
117- this . import_type_set . add ( default_import ) ;
118- } else {
119- this . import_value_set . add ( default_import ) ;
90+ this . module_types . add ( default_import ) ;
12091 }
12192 }
12293
@@ -127,9 +98,7 @@ export class HoistableInterfaces {
12798 ) {
12899 const namespace_import = node . importClause . namedBindings . name . text ;
129100 if ( is_type_only ) {
130- this . import_type_set . add ( namespace_import ) ;
131- } else {
132- this . import_value_set . add ( namespace_import ) ;
101+ this . module_types . add ( namespace_import ) ;
133102 }
134103 }
135104 }
@@ -167,9 +136,9 @@ export class HoistableInterfaces {
167136 }
168137 } ) ;
169138
170- if ( this . import_type_set . has ( interface_name ) ) {
171- // shadowed; delete because we can't hoist
172- this . import_type_set . delete ( interface_name ) ;
139+ if ( this . module_types . has ( interface_name ) ) {
140+ // shadowed; we can't hoist
141+ this . disallowed_types . add ( interface_name ) ;
173142 } else {
174143 this . interface_map . set ( interface_name , {
175144 type_deps : type_dependencies ,
@@ -193,9 +162,9 @@ export class HoistableInterfaces {
193162 generics
194163 ) ;
195164
196- if ( this . import_type_set . has ( alias_name ) ) {
197- // shadowed; delete because we can't hoist
198- this . import_type_set . delete ( alias_name ) ;
165+ if ( this . module_types . has ( alias_name ) ) {
166+ // shadowed; we can't hoist
167+ this . disallowed_types . add ( alias_name ) ;
199168 } else {
200169 this . interface_map . set ( alias_name , {
201170 type_deps : type_dependencies ,
@@ -209,29 +178,21 @@ export class HoistableInterfaces {
209178 if ( ts . isVariableStatement ( node ) ) {
210179 node . declarationList . declarations . forEach ( ( declaration ) => {
211180 if ( ts . isIdentifier ( declaration . name ) ) {
212- this . import_value_set . delete ( declaration . name . text ) ;
181+ this . disallowed_values . add ( declaration . name . text ) ;
213182 }
214183 } ) ;
215184 }
216185
217186 if ( ts . isFunctionDeclaration ( node ) && node . name ) {
218- this . import_value_set . delete ( node . name . text ) ;
187+ this . disallowed_values . add ( node . name . text ) ;
219188 }
220189
221190 if ( ts . isClassDeclaration ( node ) && node . name ) {
222- this . import_value_set . delete ( node . name . text ) ;
191+ this . disallowed_values . add ( node . name . text ) ;
223192 }
224193
225194 if ( ts . isEnumDeclaration ( node ) ) {
226- this . import_value_set . delete ( node . name . text ) ;
227- }
228-
229- if ( ts . isTypeAliasDeclaration ( node ) ) {
230- this . import_type_set . delete ( node . name . text ) ;
231- }
232-
233- if ( ts . isInterfaceDeclaration ( node ) ) {
234- this . import_type_set . delete ( node . name . text ) ;
195+ this . disallowed_values . add ( node . name . text ) ;
235196 }
236197 }
237198
@@ -281,13 +242,26 @@ export class HoistableInterfaces {
281242 continue ;
282243 }
283244
284- const can_hoist = [ ...deps . type_deps , ...deps . value_deps ] . every ( ( dep ) => {
285- return (
286- this . import_type_set . has ( dep ) ||
287- this . import_value_set . has ( dep ) ||
288- hoistable_interfaces . has ( dep )
289- ) ;
290- } ) ;
245+ let can_hoist = true ;
246+
247+ for ( const dep of deps . type_deps ) {
248+ if ( this . disallowed_types . has ( dep ) ) {
249+ this . disallowed_types . add ( interface_name ) ;
250+ can_hoist = false ;
251+ break ;
252+ }
253+ if ( this . interface_map . has ( dep ) && ! hoistable_interfaces . has ( dep ) ) {
254+ can_hoist = false ;
255+ }
256+ }
257+
258+ for ( const dep of deps . value_deps ) {
259+ if ( this . disallowed_values . has ( dep ) ) {
260+ this . disallowed_types . add ( interface_name ) ;
261+ can_hoist = false ;
262+ break ;
263+ }
264+ }
291265
292266 if ( can_hoist ) {
293267 hoistable_interfaces . set ( interface_name , deps . node ) ;
@@ -301,11 +275,7 @@ export class HoistableInterfaces {
301275 ...this . props_interface . type_deps ,
302276 ...this . props_interface . value_deps
303277 ] . every ( ( dep ) => {
304- return (
305- this . import_type_set . has ( dep ) ||
306- this . import_value_set . has ( dep ) ||
307- hoistable_interfaces . has ( dep )
308- ) ;
278+ return ! this . disallowed_types . has ( dep ) && ! this . disallowed_values . has ( dep ) ;
309279 } ) ;
310280
311281 if ( can_hoist ) {
@@ -328,7 +298,7 @@ export class HoistableInterfaces {
328298 if ( ! this . props_interface . name ) return ;
329299
330300 for ( const generic of generics ) {
331- this . import_type_set . delete ( generic ) ;
301+ this . disallowed_types . add ( generic ) ;
332302 }
333303
334304 const hoistable = this . determineHoistableInterfaces ( ) ;
@@ -362,8 +332,8 @@ export class HoistableInterfaces {
362332 }
363333 }
364334
365- getAllowedValues ( ) {
366- return this . import_value_set ;
335+ isAllowedReference ( reference : string ) {
336+ return ! this . disallowed_values . has ( reference ) ;
367337 }
368338
369339 /**
0 commit comments