@@ -148,7 +148,7 @@ namespace ts {
148148 /**
149149 * true if build info is emitted
150150 */
151- emittedBuildInfo ? : boolean ;
151+ buildInfoEmitPending : boolean ;
152152 /**
153153 * Already seen emitted files
154154 */
@@ -250,14 +250,14 @@ namespace ts {
250250 BuilderState . getAllFilesExcludingDefaultLibraryFile ( state , newProgram , /*firstSourceFile*/ undefined )
251251 . forEach ( file => state . changedFilesSet . set ( file . resolvedPath , true ) ) ;
252252 }
253- else if ( oldCompilerOptions && compilerOptionsAffectEmit ( compilerOptions , oldCompilerOptions ) ) {
253+ else if ( oldCompilerOptions && ! outFile ( compilerOptions ) && compilerOptionsAffectEmit ( compilerOptions , oldCompilerOptions ) ) {
254254 // Add all files to affectedFilesPendingEmit since emit changed
255255 newProgram . getSourceFiles ( ) . forEach ( f => addToAffectedFilesPendingEmit ( state , f . resolvedPath , BuilderFileEmit . Full ) ) ;
256256 Debug . assert ( ! state . seenAffectedFiles || ! state . seenAffectedFiles . size ) ;
257257 state . seenAffectedFiles = state . seenAffectedFiles || createMap < true > ( ) ;
258258 }
259259
260- state . emittedBuildInfo = ! state . changedFilesSet . size && ! state . affectedFilesPendingEmit ;
260+ state . buildInfoEmitPending = ! ! state . changedFilesSet . size ;
261261 return state ;
262262 }
263263
@@ -611,7 +611,7 @@ namespace ts {
611611 isBuildInfoEmit ?: boolean
612612 ) {
613613 if ( isBuildInfoEmit ) {
614- state . emittedBuildInfo = true ;
614+ state . buildInfoEmitPending = false ;
615615 }
616616 else if ( affected === state . program ) {
617617 state . changedFilesSet . clear ( ) ;
@@ -624,6 +624,7 @@ namespace ts {
624624 }
625625 if ( isPendingEmit ) {
626626 state . affectedFilesPendingEmitIndex ! ++ ;
627+ state . buildInfoEmitPending = true ;
627628 }
628629 else {
629630 state . affectedFilesIndex ! ++ ;
@@ -688,12 +689,14 @@ namespace ts {
688689 }
689690
690691 export type ProgramBuildInfoDiagnostic = string | [ string , readonly ReusableDiagnostic [ ] ] ;
692+ export type ProgramBuilderInfoFilePendingEmit = [ string , BuilderFileEmit ] ;
691693 export interface ProgramBuildInfo {
692694 fileInfos : MapLike < BuilderState . FileInfo > ;
693695 options : CompilerOptions ;
694696 referencedMap ?: MapLike < string [ ] > ;
695697 exportedModulesMap ?: MapLike < string [ ] > ;
696698 semanticDiagnosticsPerFile ?: ProgramBuildInfoDiagnostic [ ] ;
699+ affectedFilesPendingEmit ?: ProgramBuilderInfoFilePendingEmit [ ] ;
697700 }
698701
699702 /**
@@ -751,6 +754,17 @@ namespace ts {
751754 result . semanticDiagnosticsPerFile = semanticDiagnosticsPerFile ;
752755 }
753756
757+ if ( state . affectedFilesPendingEmit ) {
758+ const affectedFilesPendingEmit : ProgramBuilderInfoFilePendingEmit [ ] = [ ] ;
759+ const seenFiles = createMap < true > ( ) ;
760+ for ( const path of state . affectedFilesPendingEmit . slice ( state . affectedFilesPendingEmitIndex ) . sort ( compareStringsCaseSensitive ) ) {
761+ if ( addToSeen ( seenFiles , path ) ) {
762+ affectedFilesPendingEmit . push ( [ relativeToBuildInfo ( path ) , state . affectedFilesPendingEmitKind ! . get ( path ) ! ] ) ;
763+ }
764+ }
765+ result . affectedFilesPendingEmit = affectedFilesPendingEmit ;
766+ }
767+
754768 return result ;
755769
756770 function relativeToBuildInfoEnsuringAbsolutePath ( path : string ) {
@@ -916,13 +930,23 @@ namespace ts {
916930 else if ( kind === BuilderProgramKind . EmitAndSemanticDiagnosticsBuilderProgram ) {
917931 ( builderProgram as EmitAndSemanticDiagnosticsBuilderProgram ) . getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile ;
918932 ( builderProgram as EmitAndSemanticDiagnosticsBuilderProgram ) . emitNextAffectedFile = emitNextAffectedFile ;
933+ builderProgram . emitBuildInfo = emitBuildInfo ;
919934 }
920935 else {
921936 notImplemented ( ) ;
922937 }
923938
924939 return builderProgram ;
925940
941+ function emitBuildInfo ( writeFile ?: WriteFileCallback , cancellationToken ?: CancellationToken ) : EmitResult {
942+ if ( state . buildInfoEmitPending ) {
943+ const result = Debug . checkDefined ( state . program ) . emitBuildInfo ( writeFile || maybeBind ( host , host . writeFile ) , cancellationToken ) ;
944+ state . buildInfoEmitPending = false ;
945+ return result ;
946+ }
947+ return emitSkippedWithNoDiagnostics ;
948+ }
949+
926950 /**
927951 * Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
928952 * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
@@ -936,7 +960,7 @@ namespace ts {
936960 if ( ! outFile ( state . compilerOptions ) ) {
937961 const pendingAffectedFile = getNextAffectedFilePendingEmit ( state ) ;
938962 if ( ! pendingAffectedFile ) {
939- if ( state . emittedBuildInfo ) {
963+ if ( ! state . buildInfoEmitPending ) {
940964 return undefined ;
941965 }
942966
@@ -993,7 +1017,7 @@ namespace ts {
9931017 function emit ( targetSourceFile ?: SourceFile , writeFile ?: WriteFileCallback , cancellationToken ?: CancellationToken , emitOnlyDtsFiles ?: boolean , customTransformers ?: CustomTransformers ) : EmitResult {
9941018 if ( kind === BuilderProgramKind . EmitAndSemanticDiagnosticsBuilderProgram ) {
9951019 assertSourceFileOkWithoutNextAffectedCall ( state , targetSourceFile ) ;
996- const result = handleNoEmitOptions ( builderProgram , targetSourceFile , cancellationToken ) ;
1020+ const result = handleNoEmitOptions ( builderProgram , targetSourceFile , writeFile , cancellationToken ) ;
9971021 if ( result ) return result ;
9981022 if ( ! targetSourceFile ) {
9991023 // Emit and report any errors we ran into.
@@ -1142,7 +1166,10 @@ namespace ts {
11421166 referencedMap : getMapOfReferencedSet ( program . referencedMap , toPath ) ,
11431167 exportedModulesMap : getMapOfReferencedSet ( program . exportedModulesMap , toPath ) ,
11441168 semanticDiagnosticsPerFile : program . semanticDiagnosticsPerFile && arrayToMap ( program . semanticDiagnosticsPerFile , value => toPath ( isString ( value ) ? value : value [ 0 ] ) , value => isString ( value ) ? emptyArray : value [ 1 ] ) ,
1145- hasReusableDiagnostic : true
1169+ hasReusableDiagnostic : true ,
1170+ affectedFilesPendingEmit : map ( program . affectedFilesPendingEmit , value => toPath ( value [ 0 ] ) ) ,
1171+ affectedFilesPendingEmitKind : program . affectedFilesPendingEmit && arrayToMap ( program . affectedFilesPendingEmit , value => toPath ( value [ 0 ] ) , value => value [ 1 ] ) ,
1172+ affectedFilesPendingEmitIndex : program . affectedFilesPendingEmit && 0 ,
11461173 } ;
11471174 return {
11481175 getState : ( ) => state ,
@@ -1165,6 +1192,7 @@ namespace ts {
11651192 getCurrentDirectory : notImplemented ,
11661193 emitNextAffectedFile : notImplemented ,
11671194 getSemanticDiagnosticsOfNextAffectedFile : notImplemented ,
1195+ emitBuildInfo : notImplemented ,
11681196 close : noop ,
11691197 } ;
11701198
@@ -1195,6 +1223,7 @@ namespace ts {
11951223 getDeclarationDiagnostics : ( sourceFile , cancellationToken ) => getProgram ( ) . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ,
11961224 getSemanticDiagnostics : ( sourceFile , cancellationToken ) => getProgram ( ) . getSemanticDiagnostics ( sourceFile , cancellationToken ) ,
11971225 emit : ( sourceFile , writeFile , cancellationToken , emitOnlyDts , customTransformers ) => getProgram ( ) . emit ( sourceFile , writeFile , cancellationToken , emitOnlyDts , customTransformers ) ,
1226+ emitBuildInfo : ( writeFile , cancellationToken ) => getProgram ( ) . emitBuildInfo ( writeFile , cancellationToken ) ,
11981227 getAllDependencies : notImplemented ,
11991228 getCurrentDirectory : ( ) => getProgram ( ) . getCurrentDirectory ( ) ,
12001229 close : noop ,
0 commit comments