1
- import ts from "typescript" ;
1
+ import ts , { type SourceFile } from "typescript" ;
2
2
3
3
interface InlinerOptions {
4
4
allowComplexExpressions ?: boolean ;
@@ -86,11 +86,9 @@ class ExpressionAnalyzer {
86
86
87
87
let result = false ;
88
88
89
- ts . forEachChild ( node , ( child ) => {
90
- if ( hasSideEffects ( child ) ) {
91
- result = true ;
92
- }
93
- } ) ;
89
+ ts . forEachChild ( node , ( child ) =>
90
+ hasSideEffects ( child ) ? ( result = true ) : null ,
91
+ ) ;
94
92
95
93
return result ;
96
94
} ;
@@ -122,21 +120,17 @@ class ExpressionAnalyzer {
122
120
}
123
121
124
122
if ( ts . isBinaryExpression ( node ) ) {
125
- const op = node . operatorToken . kind ;
126
-
127
123
// Division could throw
128
- if ( op === ts . SyntaxKind . SlashToken ) {
124
+ if ( node . operatorToken . kind === ts . SyntaxKind . SlashToken ) {
129
125
return true ;
130
126
}
131
127
}
132
128
133
129
let result = false ;
134
130
135
- ts . forEachChild ( node , ( child ) => {
136
- if ( hasRuntimeRisks ( child ) ) {
137
- result = true ;
138
- }
139
- } ) ;
131
+ ts . forEachChild ( node , ( child ) =>
132
+ hasRuntimeRisks ( child ) ? ( result = true ) : null ,
133
+ ) ;
140
134
141
135
return result ;
142
136
} ;
@@ -174,6 +168,7 @@ class ScopeAnalyzer {
174
168
if ( ts . isVariableDeclaration ( child ) ) {
175
169
this . collectBindings ( child . name , scope ) ;
176
170
}
171
+
177
172
ts . forEachChild ( child , visitNode ) ;
178
173
} ;
179
174
@@ -209,8 +204,10 @@ class ScopeAnalyzer {
209
204
if ( scope ?. has ( symbol ) ) {
210
205
return true ;
211
206
}
207
+
212
208
current = current . parent ;
213
209
}
210
+
214
211
return false ;
215
212
}
216
213
}
@@ -281,36 +278,34 @@ class VariableInliner {
281
278
}
282
279
283
280
if ( ts . isArrayBindingPattern ( pattern ) ) {
284
- const elements : ts . Expression [ ] = pattern . elements . map (
285
- ( element ) => {
281
+ return ts . factory . createArrayLiteralExpression (
282
+ pattern . elements . map ( ( element ) => {
286
283
if ( ts . isBindingElement ( element ) ) {
287
284
return (
288
285
element . initializer ||
289
286
ts . factory . createIdentifier ( "undefined" )
290
287
) ;
291
288
}
289
+
292
290
return ts . factory . createIdentifier ( "undefined" ) ;
293
- } ,
291
+ } ) ,
294
292
) ;
295
-
296
- return ts . factory . createArrayLiteralExpression ( elements ) ;
297
293
}
298
294
299
295
throw new Error ( "Unsupported binding pattern type" ) ;
300
296
}
301
297
302
298
private shouldInlineExpression ( node : ts . Expression ) : boolean {
303
- const analysis = this . expressionAnalyzer . analyzeComplexity ( node ) ;
304
-
305
- if ( ! analysis . safe ) {
299
+ if ( ! this . expressionAnalyzer . analyzeComplexity ( node ) . safe ) {
306
300
this . statistics . skippedVariables . complexity ++ ;
307
301
308
302
return false ;
309
303
}
310
304
311
- const size = this . expressionAnalyzer . getExpressionSize ( node ) ;
312
-
313
- if ( size > this . options . maxExpressionSize ) {
305
+ if (
306
+ this . expressionAnalyzer . getExpressionSize ( node ) >
307
+ this . options . maxExpressionSize
308
+ ) {
314
309
this . statistics . skippedVariables . size ++ ;
315
310
316
311
return false ;
@@ -345,11 +340,7 @@ class VariableInliner {
345
340
this . statistics . totalVariables +=
346
341
node . declarationList . declarations . length ;
347
342
348
- return this . transformVariableStatement (
349
- node ,
350
- typeChecker ,
351
- context ,
352
- ) ;
343
+ return this . transformVariableStatement ( node , typeChecker ) ;
353
344
}
354
345
355
346
return ts . visitEachChild ( node , visit , context ) ;
@@ -358,23 +349,21 @@ class VariableInliner {
358
349
return visit ;
359
350
} ;
360
351
361
- const transformed = ts . transform ( sourceFile , [ transformer ] )
362
- . transformed [ 0 ] ;
363
-
364
352
// Generate output
365
- const printer = ts . createPrinter ( {
366
- newLine : ts . NewLineKind . LineFeed ,
367
- removeComments : ! this . options . preserveComments ,
368
- } ) ;
369
-
370
353
this . statistics . optimizationTime = Date . now ( ) - startTime ;
371
354
372
355
const result : TransformationResult = {
373
- code : printer . printNode (
374
- ts . EmitHint . SourceFile ,
375
- transformed ,
376
- sourceFile ,
377
- ) ,
356
+ code : ts
357
+ . createPrinter ( {
358
+ newLine : ts . NewLineKind . LineFeed ,
359
+ removeComments : ! this . options . preserveComments ,
360
+ } )
361
+ . printNode (
362
+ ts . EmitHint . SourceFile ,
363
+ ts . transform ( sourceFile , [ transformer ] )
364
+ . transformed [ 0 ] as SourceFile ,
365
+ sourceFile ,
366
+ ) ,
378
367
statistics : this . statistics ,
379
368
} ;
380
369
@@ -385,6 +374,7 @@ class VariableInliner {
385
374
386
375
return result ;
387
376
}
377
+
388
378
private transformVariableStatement (
389
379
node : ts . VariableStatement ,
390
380
typeChecker : ts . TypeChecker ,
@@ -396,16 +386,20 @@ class VariableInliner {
396
386
if ( ts . isIdentifier ( name ) ) {
397
387
if ( this . isVariableExcluded ( name . text ) ) {
398
388
this . statistics . skippedVariables . excluded ++ ;
389
+
399
390
return true ;
400
391
}
401
392
402
393
const symbol = typeChecker . getSymbolAtLocation ( name ) ;
403
- if ( ! symbol ) return true ;
394
+
395
+ if ( ! symbol ) {
396
+ return true ;
397
+ }
404
398
405
399
// Check usage count
406
- const references = this . findReferences ( symbol , typeChecker ) ;
407
- if ( references . length !== 1 ) {
400
+ if ( this . findReferences ( symbol , typeChecker ) . length !== 1 ) {
408
401
this . statistics . skippedVariables . multiple ++ ;
402
+
409
403
return true ;
410
404
}
411
405
@@ -415,30 +409,29 @@ class VariableInliner {
415
409
this . shouldInlineExpression ( decl . initializer )
416
410
) {
417
411
this . statistics . inlinedVariables ++ ;
412
+
418
413
return false ;
419
414
}
420
415
} else if (
421
416
( ts . isArrayBindingPattern ( name ) ||
422
417
ts . isObjectBindingPattern ( name ) ) &&
423
418
this . options . inlineDestructuring
424
419
) {
425
- if ( ! decl . initializer ) return true ;
420
+ if ( ! decl . initializer ) {
421
+ return true ;
422
+ }
426
423
427
424
// Check if we can inline the destructuring pattern
428
425
if ( this . canInlineDestructuring ( name , decl . initializer ) ) {
429
426
try {
430
427
// Transform the destructuring pattern and check if it's safe to inline
431
- const transformedExpression =
432
- this . handleDestructuring (
433
- name ,
434
- decl . initializer ,
435
- ) ;
436
428
if (
437
429
this . shouldInlineExpression (
438
- transformedExpression ,
430
+ this . handleDestructuring ( name ) ,
439
431
)
440
432
) {
441
433
this . statistics . inlinedVariables ++ ;
434
+
442
435
return false ; // Remove this declaration from the list
443
436
}
444
437
} catch ( error ) {
@@ -447,11 +440,13 @@ class VariableInliner {
447
440
"Failed to transform destructuring pattern:" ,
448
441
error ,
449
442
) ;
443
+
450
444
return true ;
451
445
}
452
446
}
453
447
454
448
this . statistics . skippedVariables . complexity ++ ;
449
+
455
450
return true ;
456
451
}
457
452
@@ -496,6 +491,7 @@ class VariableInliner {
496
491
ts . isCallExpression ( initializer )
497
492
) ;
498
493
}
494
+
499
495
return false ;
500
496
}
501
497
@@ -541,6 +537,7 @@ class VariableInliner {
541
537
if ( ts . isArrayBindingPattern ( pattern ) ) {
542
538
for ( const element of pattern . elements ) {
543
539
if ( ts . isOmittedExpression ( element ) ) continue ;
540
+
544
541
if ( element . dotDotDotToken ) {
545
542
// Spread operators make inlining more complex
546
543
return false ;
@@ -559,7 +556,9 @@ class VariableInliner {
559
556
560
557
const root = symbol . declarations ?. [ 0 ] ?. getSourceFile ( ) ;
561
558
562
- if ( ! root ) return references ;
559
+ if ( ! root ) {
560
+ return references ;
561
+ }
563
562
564
563
const visit = ( node : ts . Node ) => {
565
564
if ( ts . isIdentifier ( node ) ) {
@@ -569,6 +568,7 @@ class VariableInliner {
569
568
references . push ( node ) ;
570
569
}
571
570
}
571
+
572
572
ts . forEachChild ( node , visit ) ;
573
573
} ;
574
574
@@ -581,6 +581,7 @@ class VariableInliner {
581
581
if ( this . options . includeVariables . length > 0 ) {
582
582
return ! this . options . includeVariables . includes ( name ) ;
583
583
}
584
+
584
585
return this . options . excludeVariables . includes ( name ) ;
585
586
}
586
587
@@ -608,9 +609,7 @@ async function optimizeTypeScriptFile(
608
609
throw new Error ( `Source file '${ filePath } ' not found` ) ;
609
610
}
610
611
611
- const inliner = new VariableInliner ( options ) ;
612
-
613
- return inliner . transform ( sourceFile , program ) ;
612
+ return new VariableInliner ( options ) . transform ( sourceFile , program ) ;
614
613
}
615
614
616
615
export {
0 commit comments