@@ -699,6 +699,18 @@ namespace ts {
699699 } ;
700700 }
701701
702+ enum BuildStep {
703+ CreateProgram ,
704+ SyntaxDiagnostics ,
705+ SemanticDiagnostics ,
706+ Emit ,
707+ EmitBundle ,
708+ EmitBuildInfo ,
709+ BuildInvalidatedProjectOfBundle ,
710+ QueueReferencingProjects ,
711+ Done
712+ }
713+
702714 function createBuildOrUpdateInvalidedProject < T extends BuilderProgram > (
703715 kind : InvalidatedProjectKind . Build | InvalidatedProjectKind . UpdateBundle ,
704716 state : SolutionBuilderState < T > ,
@@ -708,18 +720,7 @@ namespace ts {
708720 config : ParsedCommandLine ,
709721 buildOrder : readonly ResolvedConfigFileName [ ] ,
710722 ) : BuildInvalidedProject < T > | UpdateBundleProject < T > {
711- enum Step {
712- CreateProgram ,
713- SyntaxDiagnostics ,
714- SemanticDiagnostics ,
715- Emit ,
716- EmitBundle ,
717- BuildInvalidatedProjectOfBundle ,
718- QueueReferencingProjects ,
719- Done
720- }
721-
722- let step = kind === InvalidatedProjectKind . Build ? Step . CreateProgram : Step . EmitBundle ;
723+ let step = kind === InvalidatedProjectKind . Build ? BuildStep . CreateProgram : BuildStep . EmitBundle ;
723724 let program : T | undefined ;
724725 let buildResult : BuildResultFlags | undefined ;
725726 let invalidatedProjectOfBundle : BuildInvalidedProject < T > | undefined ;
@@ -781,8 +782,11 @@ namespace ts {
781782 program => program . emit ( targetSourceFile , writeFile , cancellationToken , emitOnlyDtsFiles , customTransformers )
782783 ) ;
783784 }
784- executeSteps ( Step . SemanticDiagnostics , cancellationToken ) ;
785- if ( step !== Step . Emit ) return undefined ;
785+ executeSteps ( BuildStep . SemanticDiagnostics , cancellationToken ) ;
786+ if ( step === BuildStep . EmitBuildInfo ) {
787+ return emitBuildInfo ( writeFile , cancellationToken ) ;
788+ }
789+ if ( step !== BuildStep . Emit ) return undefined ;
786790 return emit ( writeFile , cancellationToken , customTransformers ) ;
787791 } ,
788792 done
@@ -795,19 +799,19 @@ namespace ts {
795799 getCompilerOptions : ( ) => config . options ,
796800 getCurrentDirectory : ( ) => state . currentDirectory ,
797801 emit : ( writeFile : WriteFileCallback | undefined , customTransformers : CustomTransformers | undefined ) => {
798- if ( step !== Step . EmitBundle ) return invalidatedProjectOfBundle ;
802+ if ( step !== BuildStep . EmitBundle ) return invalidatedProjectOfBundle ;
799803 return emitBundle ( writeFile , customTransformers ) ;
800804 } ,
801805 done,
802806 } ;
803807
804808 function done ( cancellationToken ?: CancellationToken , writeFile ?: WriteFileCallback , customTransformers ?: CustomTransformers ) {
805- executeSteps ( Step . Done , cancellationToken , writeFile , customTransformers ) ;
809+ executeSteps ( BuildStep . Done , cancellationToken , writeFile , customTransformers ) ;
806810 return doneInvalidatedProject ( state , projectPath ) ;
807811 }
808812
809813 function withProgramOrUndefined < U > ( action : ( program : T ) => U | undefined ) : U | undefined {
810- executeSteps ( Step . CreateProgram ) ;
814+ executeSteps ( BuildStep . CreateProgram ) ;
811815 return program && action ( program ) ;
812816 }
813817
@@ -821,7 +825,7 @@ namespace ts {
821825 if ( state . options . dry ) {
822826 reportStatus ( state , Diagnostics . A_non_dry_build_would_build_project_0 , project ) ;
823827 buildResult = BuildResultFlags . Success ;
824- step = Step . QueueReferencingProjects ;
828+ step = BuildStep . QueueReferencingProjects ;
825829 return ;
826830 }
827831
@@ -831,7 +835,7 @@ namespace ts {
831835 reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
832836 // Nothing to build - must be a solution file, basically
833837 buildResult = BuildResultFlags . None ;
834- step = Step . QueueReferencingProjects ;
838+ step = BuildStep . QueueReferencingProjects ;
835839 return ;
836840 }
837841
@@ -854,16 +858,15 @@ namespace ts {
854858
855859 function handleDiagnostics ( diagnostics : readonly Diagnostic [ ] , errorFlags : BuildResultFlags , errorType : string ) {
856860 if ( diagnostics . length ) {
857- buildResult = buildErrors (
861+ ( { buildResult, step } = buildErrors (
858862 state ,
859863 projectPath ,
860864 program ,
861865 config ,
862866 diagnostics ,
863867 errorFlags ,
864868 errorType
865- ) ;
866- step = Step . QueueReferencingProjects ;
869+ ) ) ;
867870 }
868871 else {
869872 step ++ ;
@@ -894,7 +897,7 @@ namespace ts {
894897
895898 function emit ( writeFileCallback ?: WriteFileCallback , cancellationToken ?: CancellationToken , customTransformers ?: CustomTransformers ) : EmitResult {
896899 Debug . assertIsDefined ( program ) ;
897- Debug . assert ( step === Step . Emit ) ;
900+ Debug . assert ( step === BuildStep . Emit ) ;
898901 // Before emitting lets backup state, so we can revert it back if there are declaration errors to handle emit and declaration errors correctly
899902 program . backupState ( ) ;
900903 let declDiagnostics : Diagnostic [ ] | undefined ;
@@ -913,16 +916,15 @@ namespace ts {
913916 // Don't emit .d.ts if there are decl file errors
914917 if ( declDiagnostics ) {
915918 program . restoreState ( ) ;
916- buildResult = buildErrors (
919+ ( { buildResult, step } = buildErrors (
917920 state ,
918921 projectPath ,
919922 program ,
920923 config ,
921924 declDiagnostics ,
922925 BuildResultFlags . DeclarationEmitErrors ,
923926 "Declaration file"
924- ) ;
925- step = Step . QueueReferencingProjects ;
927+ ) ) ;
926928 return {
927929 emitSkipped : true ,
928930 diagnostics : emitResult . diagnostics
@@ -967,6 +969,24 @@ namespace ts {
967969 return emitResult ;
968970 }
969971
972+ function emitBuildInfo ( writeFileCallback ?: WriteFileCallback , cancellationToken ?: CancellationToken ) : EmitResult {
973+ Debug . assertIsDefined ( program ) ;
974+ Debug . assert ( step === BuildStep . EmitBuildInfo ) ;
975+ const emitResult = program . emitBuildInfo ( writeFileCallback , cancellationToken ) ;
976+ if ( emitResult . diagnostics . length ) {
977+ reportErrors ( state , emitResult . diagnostics ) ;
978+ state . diagnostics . set ( projectPath , [ ...state . diagnostics . get ( projectPath ) ! , ...emitResult . diagnostics ] ) ;
979+ buildResult = BuildResultFlags . EmitErrors & buildResult ! ;
980+ }
981+
982+ if ( emitResult . emittedFiles && state . writeFileName ) {
983+ emitResult . emittedFiles . forEach ( name => listEmittedFile ( state , config , name ) ) ;
984+ }
985+ afterProgramDone ( state , projectPath , program , config ) ;
986+ step = BuildStep . QueueReferencingProjects ;
987+ return emitResult ;
988+ }
989+
970990 function finishEmit (
971991 emitterDiagnostics : DiagnosticCollection ,
972992 emittedOutputs : FileMap < string > ,
@@ -977,22 +997,20 @@ namespace ts {
977997 ) {
978998 const emitDiagnostics = emitterDiagnostics . getDiagnostics ( ) ;
979999 if ( emitDiagnostics . length ) {
980- buildResult = buildErrors (
1000+ ( { buildResult, step } = buildErrors (
9811001 state ,
9821002 projectPath ,
9831003 program ,
9841004 config ,
9851005 emitDiagnostics ,
9861006 BuildResultFlags . EmitErrors ,
9871007 "Emit"
988- ) ;
989- step = Step . QueueReferencingProjects ;
1008+ ) ) ;
9901009 return emitDiagnostics ;
9911010 }
9921011
9931012 if ( state . writeFileName ) {
9941013 emittedOutputs . forEach ( name => listEmittedFile ( state , config , name ) ) ;
995- if ( program ) listFiles ( program , state . writeFileName ) ;
9961014 }
9971015
9981016 // Update time stamps for rest of the outputs
@@ -1006,8 +1024,7 @@ namespace ts {
10061024 oldestOutputFileName
10071025 } ) ;
10081026 afterProgramDone ( state , projectPath , program , config ) ;
1009- state . projectCompilerOptions = state . baseCompilerOptions ;
1010- step = Step . QueueReferencingProjects ;
1027+ step = BuildStep . QueueReferencingProjects ;
10111028 buildResult = resultFlags ;
10121029 return emitDiagnostics ;
10131030 }
@@ -1017,7 +1034,7 @@ namespace ts {
10171034 if ( state . options . dry ) {
10181035 reportStatus ( state , Diagnostics . A_non_dry_build_would_update_output_of_project_0 , project ) ;
10191036 buildResult = BuildResultFlags . Success ;
1020- step = Step . QueueReferencingProjects ;
1037+ step = BuildStep . QueueReferencingProjects ;
10211038 return undefined ;
10221039 }
10231040
@@ -1038,7 +1055,7 @@ namespace ts {
10381055
10391056 if ( isString ( outputFiles ) ) {
10401057 reportStatus ( state , Diagnostics . Cannot_update_output_of_project_0_because_there_was_error_reading_file_1 , project , relName ( state , outputFiles ) ) ;
1041- step = Step . BuildInvalidatedProjectOfBundle ;
1058+ step = BuildStep . BuildInvalidatedProjectOfBundle ;
10421059 return invalidatedProjectOfBundle = createBuildOrUpdateInvalidedProject (
10431060 InvalidatedProjectKind . Build ,
10441061 state ,
@@ -1070,44 +1087,48 @@ namespace ts {
10701087 return { emitSkipped : false , diagnostics : emitDiagnostics } ;
10711088 }
10721089
1073- function executeSteps ( till : Step , cancellationToken ?: CancellationToken , writeFile ?: WriteFileCallback , customTransformers ?: CustomTransformers ) {
1074- while ( step <= till && step < Step . Done ) {
1090+ function executeSteps ( till : BuildStep , cancellationToken ?: CancellationToken , writeFile ?: WriteFileCallback , customTransformers ?: CustomTransformers ) {
1091+ while ( step <= till && step < BuildStep . Done ) {
10751092 const currentStep = step ;
10761093 switch ( step ) {
1077- case Step . CreateProgram :
1094+ case BuildStep . CreateProgram :
10781095 createProgram ( ) ;
10791096 break ;
10801097
1081- case Step . SyntaxDiagnostics :
1098+ case BuildStep . SyntaxDiagnostics :
10821099 getSyntaxDiagnostics ( cancellationToken ) ;
10831100 break ;
10841101
1085- case Step . SemanticDiagnostics :
1102+ case BuildStep . SemanticDiagnostics :
10861103 getSemanticDiagnostics ( cancellationToken ) ;
10871104 break ;
10881105
1089- case Step . Emit :
1106+ case BuildStep . Emit :
10901107 emit ( writeFile , cancellationToken , customTransformers ) ;
10911108 break ;
10921109
1093- case Step . EmitBundle :
1110+ case BuildStep . EmitBuildInfo :
1111+ emitBuildInfo ( writeFile , cancellationToken ) ;
1112+ break ;
1113+
1114+ case BuildStep . EmitBundle :
10941115 emitBundle ( writeFile , customTransformers ) ;
10951116 break ;
10961117
1097- case Step . BuildInvalidatedProjectOfBundle :
1118+ case BuildStep . BuildInvalidatedProjectOfBundle :
10981119 Debug . checkDefined ( invalidatedProjectOfBundle ) . done ( cancellationToken ) ;
1099- step = Step . Done ;
1120+ step = BuildStep . Done ;
11001121 break ;
11011122
1102- case Step . QueueReferencingProjects :
1123+ case BuildStep . QueueReferencingProjects :
11031124 queueReferencingProjects ( state , project , projectPath , projectIndex , config , buildOrder , Debug . checkDefined ( buildResult ) ) ;
11041125 step ++ ;
11051126 break ;
11061127
11071128 // Should never be done
1108- case Step . Done :
1129+ case BuildStep . Done :
11091130 default :
1110- assertType < Step . Done > ( step ) ;
1131+ assertType < BuildStep . Done > ( step ) ;
11111132
11121133 }
11131134 Debug . assert ( step > currentStep ) ;
@@ -1247,23 +1268,25 @@ namespace ts {
12471268 }
12481269
12491270 function afterProgramDone < T extends BuilderProgram > (
1250- { host , watch , builderPrograms } : SolutionBuilderState < T > ,
1271+ state : SolutionBuilderState < T > ,
12511272 proj : ResolvedConfigFilePath ,
12521273 program : T | undefined ,
12531274 config : ParsedCommandLine
12541275 ) {
12551276 if ( program ) {
1256- if ( host . afterProgramEmitAndDiagnostics ) {
1257- host . afterProgramEmitAndDiagnostics ( program ) ;
1277+ if ( program && state . writeFileName ) listFiles ( program , state . writeFileName ) ;
1278+ if ( state . host . afterProgramEmitAndDiagnostics ) {
1279+ state . host . afterProgramEmitAndDiagnostics ( program ) ;
12581280 }
1259- if ( watch ) {
1281+ if ( state . watch ) {
12601282 program . releaseProgram ( ) ;
1261- builderPrograms . set ( proj , program ) ;
1283+ state . builderPrograms . set ( proj , program ) ;
12621284 }
12631285 }
1264- else if ( host . afterEmitBundle ) {
1265- host . afterEmitBundle ( config ) ;
1286+ else if ( state . host . afterEmitBundle ) {
1287+ state . host . afterEmitBundle ( config ) ;
12661288 }
1289+ state . projectCompilerOptions = state . baseCompilerOptions ;
12671290 }
12681291
12691292 function buildErrors < T extends BuilderProgram > (
@@ -1272,16 +1295,17 @@ namespace ts {
12721295 program : T | undefined ,
12731296 config : ParsedCommandLine ,
12741297 diagnostics : readonly Diagnostic [ ] ,
1275- errorFlags : BuildResultFlags ,
1276- errorType : string
1298+ buildResult : BuildResultFlags ,
1299+ errorType : string ,
12771300 ) {
1301+ const canEmitBuildInfo = ! ( buildResult & BuildResultFlags . SyntaxErrors ) && program && ! outFile ( program . getCompilerOptions ( ) ) ;
1302+
12781303 reportAndStoreErrors ( state , resolvedPath , diagnostics ) ;
12791304 // List files if any other build error using program (emit errors already report files)
1280- if ( program && state . writeFileName ) listFiles ( program , state . writeFileName ) ;
12811305 state . projectStatus . set ( resolvedPath , { type : UpToDateStatusType . Unbuildable , reason : `${ errorType } errors` } ) ;
1306+ if ( canEmitBuildInfo ) return { buildResult, step : BuildStep . EmitBuildInfo } ;
12821307 afterProgramDone ( state , resolvedPath , program , config ) ;
1283- state . projectCompilerOptions = state . baseCompilerOptions ;
1284- return errorFlags ;
1308+ return { buildResult, step : BuildStep . QueueReferencingProjects } ;
12851309 }
12861310
12871311 function updateModuleResolutionCache (
0 commit comments