@@ -145,8 +145,6 @@ namespace ts {
145145 // Testing only
146146 /*@internal */ getUpToDateStatusOfProject ( project : string ) : UpToDateStatus ;
147147 /*@internal */ invalidateProject ( configFilePath : ResolvedConfigFilePath , reloadLevel ?: ConfigFileProgramReloadLevel ) : void ;
148- /*@internal */ buildNextInvalidatedProject ( ) : void ;
149- /*@internal */ getAllParsedConfigs ( ) : readonly ParsedCommandLine [ ] ;
150148 /*@internal */ close ( ) : void ;
151149 }
152150
@@ -250,7 +248,6 @@ namespace ts {
250248 allProjectBuildPending : boolean ;
251249 needsSummary : boolean ;
252250 watchAllProjectsPending : boolean ;
253- currentInvalidatedProject : InvalidatedProject < T > | undefined ;
254251
255252 // Watch state
256253 readonly watch : boolean ;
@@ -332,7 +329,6 @@ namespace ts {
332329 allProjectBuildPending : true ,
333330 needsSummary : true ,
334331 watchAllProjectsPending : watch ,
335- currentInvalidatedProject : undefined ,
336332
337333 // Watch state
338334 watch,
@@ -684,7 +680,6 @@ namespace ts {
684680 projectPath : ResolvedConfigFilePath
685681 ) {
686682 state . projectPendingBuild . delete ( projectPath ) ;
687- state . currentInvalidatedProject = undefined ;
688683 return state . diagnostics . has ( projectPath ) ?
689684 ExitStatus . DiagnosticsPresent_OutputsSkipped :
690685 ExitStatus . Success ;
@@ -1171,19 +1166,22 @@ namespace ts {
11711166 ! isIncrementalCompilation ( config . options ) ;
11721167 }
11731168
1174- function getNextInvalidatedProject < T extends BuilderProgram > (
1169+ interface InvalidateProjectCreateInfo {
1170+ kind : InvalidatedProjectKind ;
1171+ status : UpToDateStatus ;
1172+ project : ResolvedConfigFileName ;
1173+ projectPath : ResolvedConfigFilePath ;
1174+ projectIndex : number ;
1175+ config : ParsedCommandLine ;
1176+ }
1177+
1178+ function getNextInvalidatedProjectCreateInfo < T extends BuilderProgram > (
11751179 state : SolutionBuilderState < T > ,
11761180 buildOrder : AnyBuildOrder ,
11771181 reportQueue : boolean
1178- ) : InvalidatedProject < T > | undefined {
1182+ ) : InvalidateProjectCreateInfo | undefined {
11791183 if ( ! state . projectPendingBuild . size ) return undefined ;
11801184 if ( isCircularBuildOrder ( buildOrder ) ) return undefined ;
1181- if ( state . currentInvalidatedProject ) {
1182- // Only if same buildOrder the currentInvalidated project can be sent again
1183- return arrayIsEqualTo ( state . currentInvalidatedProject . buildOrder , buildOrder ) ?
1184- state . currentInvalidatedProject :
1185- undefined ;
1186- }
11871185
11881186 const { options, projectPendingBuild } = state ;
11891187 for ( let projectIndex = 0 ; projectIndex < buildOrder . length ; projectIndex ++ ) {
@@ -1220,9 +1218,9 @@ namespace ts {
12201218 }
12211219
12221220 const status = getUpToDateStatus ( state , config , projectPath ) ;
1223- verboseReportProjectStatus ( state , project , status ) ;
12241221 if ( ! options . force ) {
12251222 if ( status . type === UpToDateStatusType . UpToDate ) {
1223+ verboseReportProjectStatus ( state , project , status ) ;
12261224 reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
12271225 projectPendingBuild . delete ( projectPath ) ;
12281226 // Up to date, skip
@@ -1235,17 +1233,19 @@ namespace ts {
12351233
12361234 if ( status . type === UpToDateStatusType . UpToDateWithUpstreamTypes ) {
12371235 reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
1238- return createUpdateOutputFileStampsProject (
1239- state ,
1236+ return {
1237+ kind : InvalidatedProjectKind . UpdateOutputFileStamps ,
1238+ status,
12401239 project,
12411240 projectPath,
1242- config ,
1243- buildOrder
1244- ) ;
1241+ projectIndex ,
1242+ config
1243+ } ;
12451244 }
12461245 }
12471246
12481247 if ( status . type === UpToDateStatusType . UpstreamBlocked ) {
1248+ verboseReportProjectStatus ( state , project , status ) ;
12491249 reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
12501250 projectPendingBuild . delete ( projectPath ) ;
12511251 if ( options . verbose ) {
@@ -1262,28 +1262,63 @@ namespace ts {
12621262 }
12631263
12641264 if ( status . type === UpToDateStatusType . ContainerOnly ) {
1265+ verboseReportProjectStatus ( state , project , status ) ;
12651266 reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
12661267 projectPendingBuild . delete ( projectPath ) ;
12671268 // Do nothing
12681269 continue ;
12691270 }
12701271
1271- return createBuildOrUpdateInvalidedProject (
1272- needsBuild ( state , status , config ) ?
1272+ return {
1273+ kind : needsBuild ( state , status , config ) ?
12731274 InvalidatedProjectKind . Build :
12741275 InvalidatedProjectKind . UpdateBundle ,
1275- state ,
1276+ status ,
12761277 project,
12771278 projectPath,
12781279 projectIndex,
12791280 config,
1280- buildOrder ,
1281- ) ;
1281+ } ;
12821282 }
12831283
12841284 return undefined ;
12851285 }
12861286
1287+ function createInvalidatedProjectWithInfo < T extends BuilderProgram > (
1288+ state : SolutionBuilderState < T > ,
1289+ info : InvalidateProjectCreateInfo ,
1290+ buildOrder : AnyBuildOrder ,
1291+ ) {
1292+ verboseReportProjectStatus ( state , info . project , info . status ) ;
1293+ return info . kind !== InvalidatedProjectKind . UpdateOutputFileStamps ?
1294+ createBuildOrUpdateInvalidedProject (
1295+ info . kind ,
1296+ state ,
1297+ info . project ,
1298+ info . projectPath ,
1299+ info . projectIndex ,
1300+ info . config ,
1301+ buildOrder as BuildOrder ,
1302+ ) :
1303+ createUpdateOutputFileStampsProject (
1304+ state ,
1305+ info . project ,
1306+ info . projectPath ,
1307+ info . config ,
1308+ buildOrder as BuildOrder
1309+ ) ;
1310+ }
1311+
1312+ function getNextInvalidatedProject < T extends BuilderProgram > (
1313+ state : SolutionBuilderState < T > ,
1314+ buildOrder : AnyBuildOrder ,
1315+ reportQueue : boolean
1316+ ) : InvalidatedProject < T > | undefined {
1317+ const info = getNextInvalidatedProjectCreateInfo ( state , buildOrder , reportQueue ) ;
1318+ if ( ! info ) return info ;
1319+ return createInvalidatedProjectWithInfo ( state , info , buildOrder ) ;
1320+ }
1321+
12871322 function listEmittedFile ( { write } : SolutionBuilderState , proj : ParsedCommandLine , file : string ) {
12881323 if ( write && proj . options . listEmittedFiles ) {
12891324 write ( `TSFILE: ${ file } ` ) ;
@@ -1769,37 +1804,47 @@ namespace ts {
17691804 function invalidateProjectAndScheduleBuilds ( state : SolutionBuilderState , resolvedPath : ResolvedConfigFilePath , reloadLevel : ConfigFileProgramReloadLevel ) {
17701805 state . reportFileChangeDetected = true ;
17711806 invalidateProject ( state , resolvedPath , reloadLevel ) ;
1772- scheduleBuildInvalidatedProject ( state ) ;
1807+ scheduleBuildInvalidatedProject ( state , 250 , /*changeDetected*/ true ) ;
17731808 }
17741809
1775- function scheduleBuildInvalidatedProject ( state : SolutionBuilderState ) {
1810+ function scheduleBuildInvalidatedProject ( state : SolutionBuilderState , time : number , changeDetected : boolean ) {
17761811 const { hostWithWatch } = state ;
17771812 if ( ! hostWithWatch . setTimeout || ! hostWithWatch . clearTimeout ) {
17781813 return ;
17791814 }
17801815 if ( state . timerToBuildInvalidatedProject ) {
17811816 hostWithWatch . clearTimeout ( state . timerToBuildInvalidatedProject ) ;
17821817 }
1783- state . timerToBuildInvalidatedProject = hostWithWatch . setTimeout ( buildNextInvalidatedProject , 250 , state ) ;
1818+ state . timerToBuildInvalidatedProject = hostWithWatch . setTimeout ( buildNextInvalidatedProject , time , state , changeDetected ) ;
17841819 }
17851820
1786- function buildNextInvalidatedProject ( state : SolutionBuilderState ) {
1821+ function buildNextInvalidatedProject ( state : SolutionBuilderState , changeDetected : boolean ) {
17871822 state . timerToBuildInvalidatedProject = undefined ;
17881823 if ( state . reportFileChangeDetected ) {
17891824 state . reportFileChangeDetected = false ;
17901825 state . projectErrorsReported . clear ( ) ;
17911826 reportWatchStatus ( state , Diagnostics . File_change_detected_Starting_incremental_compilation ) ;
17921827 }
1828+ let projectsBuilt = 0 ;
17931829 const buildOrder = getBuildOrder ( state ) ;
17941830 const invalidatedProject = getNextInvalidatedProject ( state , buildOrder , /*reportQueue*/ false ) ;
17951831 if ( invalidatedProject ) {
17961832 invalidatedProject . done ( ) ;
1797- if ( state . projectPendingBuild . size ) {
1798- // Schedule next project for build
1799- if ( state . watch && ! state . timerToBuildInvalidatedProject ) {
1800- scheduleBuildInvalidatedProject ( state ) ;
1833+ projectsBuilt ++ ;
1834+ while ( state . projectPendingBuild . size ) {
1835+ // If already scheduled, skip
1836+ if ( state . timerToBuildInvalidatedProject ) return ;
1837+ // Before scheduling check if the next project needs build
1838+ const info = getNextInvalidatedProjectCreateInfo ( state , buildOrder , /*reportQueue*/ false ) ;
1839+ if ( ! info ) break ; // Nothing to build any more
1840+ if ( info . kind !== InvalidatedProjectKind . UpdateOutputFileStamps && ( changeDetected || projectsBuilt === 5 ) ) {
1841+ // Schedule next project for build
1842+ scheduleBuildInvalidatedProject ( state , 100 , /*changeDetected*/ false ) ;
1843+ return ;
18011844 }
1802- return ;
1845+ const project = createInvalidatedProjectWithInfo ( state , info , buildOrder ) ;
1846+ project . done ( ) ;
1847+ if ( info . kind !== InvalidatedProjectKind . UpdateOutputFileStamps ) projectsBuilt ++ ;
18031848 }
18041849 }
18051850 disableCache ( state ) ;
@@ -1961,11 +2006,6 @@ namespace ts {
19612006 return getUpToDateStatus ( state , parseConfigFile ( state , configFileName , configFilePath ) , configFilePath ) ;
19622007 } ,
19632008 invalidateProject : ( configFilePath , reloadLevel ) => invalidateProject ( state , configFilePath , reloadLevel || ConfigFileProgramReloadLevel . None ) ,
1964- buildNextInvalidatedProject : ( ) => buildNextInvalidatedProject ( state ) ,
1965- getAllParsedConfigs : ( ) => arrayFrom ( mapDefinedIterator (
1966- state . configFileCache . values ( ) ,
1967- config => isParsedCommandLine ( config ) ? config : undefined
1968- ) ) ,
19692009 close : ( ) => stopWatching ( state ) ,
19702010 } ;
19712011 }
0 commit comments