@@ -60,6 +60,10 @@ namespace ts {
60
60
* Files pending to be emitted
61
61
*/
62
62
affectedFilesPendingEmit ?: ReadonlyArray < Path > | undefined ;
63
+ /**
64
+ * Files pending to be emitted kind.
65
+ */
66
+ affectedFilesPendingEmitKind ?: ReadonlyMap < BuilderFileEmit > | undefined ;
63
67
/**
64
68
* Current index to retrieve pending affected file
65
69
*/
@@ -70,6 +74,11 @@ namespace ts {
70
74
hasReusableDiagnostic ?: true ;
71
75
}
72
76
77
+ export const enum BuilderFileEmit {
78
+ DtsOnly ,
79
+ Full
80
+ }
81
+
73
82
/**
74
83
* State to store the changed files, affected files and cache semantic diagnostics
75
84
*/
@@ -127,7 +136,11 @@ namespace ts {
127
136
/**
128
137
* Files pending to be emitted
129
138
*/
130
- affectedFilesPendingEmit : ReadonlyArray < Path > | undefined ;
139
+ affectedFilesPendingEmit : Path [ ] | undefined ;
140
+ /**
141
+ * Files pending to be emitted kind.
142
+ */
143
+ affectedFilesPendingEmitKind : Map < BuilderFileEmit > | undefined ;
131
144
/**
132
145
* Current index to retrieve pending affected file
133
146
*/
@@ -139,7 +152,7 @@ namespace ts {
139
152
/**
140
153
* Already seen emitted files
141
154
*/
142
- seenEmittedFiles : Map < true > | undefined ;
155
+ seenEmittedFiles : Map < BuilderFileEmit > | undefined ;
143
156
/**
144
157
* true if program has been emitted
145
158
*/
@@ -186,7 +199,8 @@ namespace ts {
186
199
copyEntries ( changedFilesSet , state . changedFilesSet ) ;
187
200
}
188
201
if ( ! compilerOptions . outFile && ! compilerOptions . out && oldState ! . affectedFilesPendingEmit ) {
189
- state . affectedFilesPendingEmit = oldState ! . affectedFilesPendingEmit ;
202
+ state . affectedFilesPendingEmit = oldState ! . affectedFilesPendingEmit . slice ( ) ;
203
+ state . affectedFilesPendingEmitKind = cloneMapOrUndefined ( oldState ! . affectedFilesPendingEmitKind ) ;
190
204
state . affectedFilesPendingEmitIndex = oldState ! . affectedFilesPendingEmitIndex ;
191
205
}
192
206
}
@@ -233,7 +247,7 @@ namespace ts {
233
247
234
248
if ( oldCompilerOptions && compilerOptionsAffectEmit ( compilerOptions , oldCompilerOptions ) ) {
235
249
// Add all files to affectedFilesPendingEmit since emit changed
236
- addToAffectedFilesPendingEmit ( state , newProgram . getSourceFiles ( ) . map ( f => f . path ) ) ;
250
+ newProgram . getSourceFiles ( ) . forEach ( f => addToAffectedFilesPendingEmit ( state , f . path , BuilderFileEmit . Full ) ) ;
237
251
Debug . assert ( state . seenAffectedFiles === undefined ) ;
238
252
state . seenAffectedFiles = createMap < true > ( ) ;
239
253
}
@@ -295,7 +309,8 @@ namespace ts {
295
309
newState . semanticDiagnosticsFromOldState = cloneMapOrUndefined ( state . semanticDiagnosticsFromOldState ) ;
296
310
newState . program = state . program ;
297
311
newState . compilerOptions = state . compilerOptions ;
298
- newState . affectedFilesPendingEmit = state . affectedFilesPendingEmit ;
312
+ newState . affectedFilesPendingEmit = state . affectedFilesPendingEmit && state . affectedFilesPendingEmit . slice ( ) ;
313
+ newState . affectedFilesPendingEmitKind = cloneMapOrUndefined ( state . affectedFilesPendingEmitKind ) ;
299
314
newState . affectedFilesPendingEmitIndex = state . affectedFilesPendingEmitIndex ;
300
315
newState . seenEmittedFiles = cloneMapOrUndefined ( state . seenEmittedFiles ) ;
301
316
newState . programEmitComplete = state . programEmitComplete ;
@@ -373,19 +388,24 @@ namespace ts {
373
388
/**
374
389
* Returns next file to be emitted from files that retrieved semantic diagnostics but did not emit yet
375
390
*/
376
- function getNextAffectedFilePendingEmit ( state : BuilderProgramState ) : SourceFile | undefined {
391
+ function getNextAffectedFilePendingEmit ( state : BuilderProgramState ) {
377
392
const { affectedFilesPendingEmit } = state ;
378
393
if ( affectedFilesPendingEmit ) {
379
394
const seenEmittedFiles = state . seenEmittedFiles || ( state . seenEmittedFiles = createMap ( ) ) ;
380
395
for ( let i = state . affectedFilesPendingEmitIndex ! ; i < affectedFilesPendingEmit . length ; i ++ ) {
381
396
const affectedFile = Debug . assertDefined ( state . program ) . getSourceFileByPath ( affectedFilesPendingEmit [ i ] ) ;
382
- if ( affectedFile && ! seenEmittedFiles . has ( affectedFile . path ) ) {
383
- // emit this file
384
- state . affectedFilesPendingEmitIndex = i ;
385
- return affectedFile ;
397
+ if ( affectedFile ) {
398
+ const seenKind = seenEmittedFiles . get ( affectedFile . path ) ;
399
+ const emitKind = Debug . assertDefined ( Debug . assertDefined ( state . affectedFilesPendingEmitKind ) . get ( affectedFile . path ) ) ;
400
+ if ( seenKind === undefined || seenKind < emitKind ) {
401
+ // emit this file
402
+ state . affectedFilesPendingEmitIndex = i ;
403
+ return { affectedFile, emitKind } ;
404
+ }
386
405
}
387
406
}
388
407
state . affectedFilesPendingEmit = undefined ;
408
+ state . affectedFilesPendingEmitKind = undefined ;
389
409
state . affectedFilesPendingEmitIndex = undefined ;
390
410
}
391
411
return undefined ;
@@ -442,7 +462,7 @@ namespace ts {
442
462
) ;
443
463
// If not dts emit, nothing more to do
444
464
if ( getEmitDeclarations ( state . compilerOptions ) ) {
445
- addToAffectedFilesPendingEmit ( state , [ path ] ) ;
465
+ addToAffectedFilesPendingEmit ( state , path , BuilderFileEmit . DtsOnly ) ;
446
466
}
447
467
}
448
468
}
@@ -548,7 +568,13 @@ namespace ts {
548
568
* This is called after completing operation on the next affected file.
549
569
* The operations here are postponed to ensure that cancellation during the iteration is handled correctly
550
570
*/
551
- function doneWithAffectedFile ( state : BuilderProgramState , affected : SourceFile | Program , isPendingEmit ?: boolean , isBuildInfoEmit ?: boolean , isEmitResult ?: boolean ) {
571
+ function doneWithAffectedFile (
572
+ state : BuilderProgramState ,
573
+ affected : SourceFile | Program ,
574
+ emitKind ?: BuilderFileEmit ,
575
+ isPendingEmit ?: boolean ,
576
+ isBuildInfoEmit ?: boolean
577
+ ) {
552
578
if ( isBuildInfoEmit ) {
553
579
state . emittedBuildInfo = true ;
554
580
}
@@ -558,8 +584,8 @@ namespace ts {
558
584
}
559
585
else {
560
586
state . seenAffectedFiles ! . set ( ( affected as SourceFile ) . path , true ) ;
561
- if ( isEmitResult ) {
562
- ( state . seenEmittedFiles || ( state . seenEmittedFiles = createMap ( ) ) ) . set ( ( affected as SourceFile ) . path , true ) ;
587
+ if ( emitKind !== undefined ) {
588
+ ( state . seenEmittedFiles || ( state . seenEmittedFiles = createMap ( ) ) ) . set ( ( affected as SourceFile ) . path , emitKind ) ;
563
589
}
564
590
if ( isPendingEmit ) {
565
591
state . affectedFilesPendingEmitIndex ! ++ ;
@@ -573,16 +599,23 @@ namespace ts {
573
599
/**
574
600
* Returns the result with affected file
575
601
*/
576
- function toAffectedFileResult < T > ( state : BuilderProgramState , result : T , affected : SourceFile | Program , isPendingEmit ?: boolean , isBuildInfoEmit ?: boolean ) : AffectedFileResult < T > {
577
- doneWithAffectedFile ( state , affected , isPendingEmit , isBuildInfoEmit ) ;
602
+ function toAffectedFileResult < T > ( state : BuilderProgramState , result : T , affected : SourceFile | Program ) : AffectedFileResult < T > {
603
+ doneWithAffectedFile ( state , affected ) ;
578
604
return { result, affected } ;
579
605
}
580
606
581
607
/**
582
608
* Returns the result with affected file
583
609
*/
584
- function toAffectedFileEmitResult ( state : BuilderProgramState , result : EmitResult , affected : SourceFile | Program , isPendingEmit ?: boolean , isBuildInfoEmit ?: boolean ) : AffectedFileResult < EmitResult > {
585
- doneWithAffectedFile ( state , affected , isPendingEmit , isBuildInfoEmit , /*isEmitResult*/ true ) ;
610
+ function toAffectedFileEmitResult (
611
+ state : BuilderProgramState ,
612
+ result : EmitResult ,
613
+ affected : SourceFile | Program ,
614
+ emitKind : BuilderFileEmit ,
615
+ isPendingEmit ?: boolean ,
616
+ isBuildInfoEmit ?: boolean
617
+ ) : AffectedFileResult < EmitResult > {
618
+ doneWithAffectedFile ( state , affected , emitKind , isPendingEmit , isBuildInfoEmit ) ;
586
619
return { result, affected } ;
587
620
}
588
621
@@ -849,11 +882,12 @@ namespace ts {
849
882
*/
850
883
function emitNextAffectedFile ( writeFile ?: WriteFileCallback , cancellationToken ?: CancellationToken , emitOnlyDtsFiles ?: boolean , customTransformers ?: CustomTransformers ) : AffectedFileResult < EmitResult > {
851
884
let affected = getNextAffectedFile ( state , cancellationToken , computeHash ) ;
885
+ let emitKind = BuilderFileEmit . Full ;
852
886
let isPendingEmitFile = false ;
853
887
if ( ! affected ) {
854
888
if ( ! state . compilerOptions . out && ! state . compilerOptions . outFile ) {
855
- affected = getNextAffectedFilePendingEmit ( state ) ;
856
- if ( ! affected ) {
889
+ const pendingAffectedFile = getNextAffectedFilePendingEmit ( state ) ;
890
+ if ( ! pendingAffectedFile ) {
857
891
if ( state . emittedBuildInfo ) {
858
892
return undefined ;
859
893
}
@@ -865,10 +899,12 @@ namespace ts {
865
899
// Otherwise just affected file
866
900
affected . emitBuildInfo ( writeFile || maybeBind ( host , host . writeFile ) , cancellationToken ) ,
867
901
affected ,
902
+ /*emitKind*/ BuilderFileEmit . Full ,
868
903
/*isPendingEmitFile*/ false ,
869
904
/*isBuildInfoEmit*/ true
870
905
) ;
871
906
}
907
+ ( { affectedFile : affected , emitKind } = pendingAffectedFile ) ;
872
908
isPendingEmitFile = true ;
873
909
}
874
910
else {
@@ -886,10 +922,17 @@ namespace ts {
886
922
state ,
887
923
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
888
924
// Otherwise just affected file
889
- Debug . assertDefined ( state . program ) . emit ( affected === state . program ? undefined : affected as SourceFile , writeFile || maybeBind ( host , host . writeFile ) , cancellationToken , emitOnlyDtsFiles , customTransformers ) ,
925
+ Debug . assertDefined ( state . program ) . emit (
926
+ affected === state . program ? undefined : affected as SourceFile ,
927
+ writeFile || maybeBind ( host , host . writeFile ) ,
928
+ cancellationToken ,
929
+ emitOnlyDtsFiles || emitKind === BuilderFileEmit . DtsOnly ,
930
+ customTransformers
931
+ ) ,
890
932
affected ,
933
+ emitKind ,
891
934
isPendingEmitFile ,
892
- ) ;
935
+ ) ;
893
936
}
894
937
895
938
/**
@@ -953,7 +996,7 @@ namespace ts {
953
996
954
997
// Add file to affected file pending emit to handle for later emit time
955
998
if ( kind === BuilderProgramKind . EmitAndSemanticDiagnosticsBuilderProgram ) {
956
- addToAffectedFilesPendingEmit ( state , [ ( affected as SourceFile ) . path ] ) ;
999
+ addToAffectedFilesPendingEmit ( state , ( affected as SourceFile ) . path , BuilderFileEmit . Full ) ;
957
1000
}
958
1001
959
1002
// Get diagnostics for the affected file if its not ignored
@@ -1006,8 +1049,14 @@ namespace ts {
1006
1049
}
1007
1050
}
1008
1051
1009
- function addToAffectedFilesPendingEmit ( state : BuilderProgramState , affectedFilesPendingEmit : readonly Path [ ] ) {
1010
- state . affectedFilesPendingEmit = concatenate ( state . affectedFilesPendingEmit , affectedFilesPendingEmit ) ;
1052
+ function addToAffectedFilesPendingEmit ( state : BuilderProgramState , affectedFilePendingEmit : Path , kind : BuilderFileEmit ) {
1053
+ if ( ! state . affectedFilesPendingEmit ) state . affectedFilesPendingEmit = [ ] ;
1054
+ if ( ! state . affectedFilesPendingEmitKind ) state . affectedFilesPendingEmitKind = createMap ( ) ;
1055
+
1056
+ const existingKind = state . affectedFilesPendingEmitKind . get ( affectedFilePendingEmit ) ;
1057
+ state . affectedFilesPendingEmit . push ( affectedFilePendingEmit ) ;
1058
+ state . affectedFilesPendingEmitKind . set ( affectedFilePendingEmit , existingKind || kind ) ;
1059
+
1011
1060
// affectedFilesPendingEmitIndex === undefined
1012
1061
// - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
1013
1062
// so start from 0 as array would be affectedFilesPendingEmit
0 commit comments