@@ -145,8 +145,6 @@ namespace ts {
145
145
// Testing only
146
146
/*@internal */ getUpToDateStatusOfProject ( project : string ) : UpToDateStatus ;
147
147
/*@internal */ invalidateProject ( configFilePath : ResolvedConfigFilePath , reloadLevel ?: ConfigFileProgramReloadLevel ) : void ;
148
- /*@internal */ buildNextInvalidatedProject ( ) : void ;
149
- /*@internal */ getAllParsedConfigs ( ) : readonly ParsedCommandLine [ ] ;
150
148
/*@internal */ close ( ) : void ;
151
149
}
152
150
@@ -250,7 +248,6 @@ namespace ts {
250
248
allProjectBuildPending : boolean ;
251
249
needsSummary : boolean ;
252
250
watchAllProjectsPending : boolean ;
253
- currentInvalidatedProject : InvalidatedProject < T > | undefined ;
254
251
255
252
// Watch state
256
253
readonly watch : boolean ;
@@ -332,7 +329,6 @@ namespace ts {
332
329
allProjectBuildPending : true ,
333
330
needsSummary : true ,
334
331
watchAllProjectsPending : watch ,
335
- currentInvalidatedProject : undefined ,
336
332
337
333
// Watch state
338
334
watch,
@@ -684,7 +680,6 @@ namespace ts {
684
680
projectPath : ResolvedConfigFilePath
685
681
) {
686
682
state . projectPendingBuild . delete ( projectPath ) ;
687
- state . currentInvalidatedProject = undefined ;
688
683
return state . diagnostics . has ( projectPath ) ?
689
684
ExitStatus . DiagnosticsPresent_OutputsSkipped :
690
685
ExitStatus . Success ;
@@ -1171,19 +1166,22 @@ namespace ts {
1171
1166
! isIncrementalCompilation ( config . options ) ;
1172
1167
}
1173
1168
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 > (
1175
1179
state : SolutionBuilderState < T > ,
1176
1180
buildOrder : AnyBuildOrder ,
1177
1181
reportQueue : boolean
1178
- ) : InvalidatedProject < T > | undefined {
1182
+ ) : InvalidateProjectCreateInfo | undefined {
1179
1183
if ( ! state . projectPendingBuild . size ) return undefined ;
1180
1184
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
- }
1187
1185
1188
1186
const { options, projectPendingBuild } = state ;
1189
1187
for ( let projectIndex = 0 ; projectIndex < buildOrder . length ; projectIndex ++ ) {
@@ -1220,9 +1218,9 @@ namespace ts {
1220
1218
}
1221
1219
1222
1220
const status = getUpToDateStatus ( state , config , projectPath ) ;
1223
- verboseReportProjectStatus ( state , project , status ) ;
1224
1221
if ( ! options . force ) {
1225
1222
if ( status . type === UpToDateStatusType . UpToDate ) {
1223
+ verboseReportProjectStatus ( state , project , status ) ;
1226
1224
reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
1227
1225
projectPendingBuild . delete ( projectPath ) ;
1228
1226
// Up to date, skip
@@ -1235,17 +1233,19 @@ namespace ts {
1235
1233
1236
1234
if ( status . type === UpToDateStatusType . UpToDateWithUpstreamTypes ) {
1237
1235
reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
1238
- return createUpdateOutputFileStampsProject (
1239
- state ,
1236
+ return {
1237
+ kind : InvalidatedProjectKind . UpdateOutputFileStamps ,
1238
+ status,
1240
1239
project,
1241
1240
projectPath,
1242
- config ,
1243
- buildOrder
1244
- ) ;
1241
+ projectIndex ,
1242
+ config
1243
+ } ;
1245
1244
}
1246
1245
}
1247
1246
1248
1247
if ( status . type === UpToDateStatusType . UpstreamBlocked ) {
1248
+ verboseReportProjectStatus ( state , project , status ) ;
1249
1249
reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
1250
1250
projectPendingBuild . delete ( projectPath ) ;
1251
1251
if ( options . verbose ) {
@@ -1262,28 +1262,63 @@ namespace ts {
1262
1262
}
1263
1263
1264
1264
if ( status . type === UpToDateStatusType . ContainerOnly ) {
1265
+ verboseReportProjectStatus ( state , project , status ) ;
1265
1266
reportAndStoreErrors ( state , projectPath , getConfigFileParsingDiagnostics ( config ) ) ;
1266
1267
projectPendingBuild . delete ( projectPath ) ;
1267
1268
// Do nothing
1268
1269
continue ;
1269
1270
}
1270
1271
1271
- return createBuildOrUpdateInvalidedProject (
1272
- needsBuild ( state , status , config ) ?
1272
+ return {
1273
+ kind : needsBuild ( state , status , config ) ?
1273
1274
InvalidatedProjectKind . Build :
1274
1275
InvalidatedProjectKind . UpdateBundle ,
1275
- state ,
1276
+ status ,
1276
1277
project,
1277
1278
projectPath,
1278
1279
projectIndex,
1279
1280
config,
1280
- buildOrder ,
1281
- ) ;
1281
+ } ;
1282
1282
}
1283
1283
1284
1284
return undefined ;
1285
1285
}
1286
1286
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
+
1287
1322
function listEmittedFile ( { write } : SolutionBuilderState , proj : ParsedCommandLine , file : string ) {
1288
1323
if ( write && proj . options . listEmittedFiles ) {
1289
1324
write ( `TSFILE: ${ file } ` ) ;
@@ -1769,37 +1804,47 @@ namespace ts {
1769
1804
function invalidateProjectAndScheduleBuilds ( state : SolutionBuilderState , resolvedPath : ResolvedConfigFilePath , reloadLevel : ConfigFileProgramReloadLevel ) {
1770
1805
state . reportFileChangeDetected = true ;
1771
1806
invalidateProject ( state , resolvedPath , reloadLevel ) ;
1772
- scheduleBuildInvalidatedProject ( state ) ;
1807
+ scheduleBuildInvalidatedProject ( state , 250 , /*changeDetected*/ true ) ;
1773
1808
}
1774
1809
1775
- function scheduleBuildInvalidatedProject ( state : SolutionBuilderState ) {
1810
+ function scheduleBuildInvalidatedProject ( state : SolutionBuilderState , time : number , changeDetected : boolean ) {
1776
1811
const { hostWithWatch } = state ;
1777
1812
if ( ! hostWithWatch . setTimeout || ! hostWithWatch . clearTimeout ) {
1778
1813
return ;
1779
1814
}
1780
1815
if ( state . timerToBuildInvalidatedProject ) {
1781
1816
hostWithWatch . clearTimeout ( state . timerToBuildInvalidatedProject ) ;
1782
1817
}
1783
- state . timerToBuildInvalidatedProject = hostWithWatch . setTimeout ( buildNextInvalidatedProject , 250 , state ) ;
1818
+ state . timerToBuildInvalidatedProject = hostWithWatch . setTimeout ( buildNextInvalidatedProject , time , state , changeDetected ) ;
1784
1819
}
1785
1820
1786
- function buildNextInvalidatedProject ( state : SolutionBuilderState ) {
1821
+ function buildNextInvalidatedProject ( state : SolutionBuilderState , changeDetected : boolean ) {
1787
1822
state . timerToBuildInvalidatedProject = undefined ;
1788
1823
if ( state . reportFileChangeDetected ) {
1789
1824
state . reportFileChangeDetected = false ;
1790
1825
state . projectErrorsReported . clear ( ) ;
1791
1826
reportWatchStatus ( state , Diagnostics . File_change_detected_Starting_incremental_compilation ) ;
1792
1827
}
1828
+ let projectsBuilt = 0 ;
1793
1829
const buildOrder = getBuildOrder ( state ) ;
1794
1830
const invalidatedProject = getNextInvalidatedProject ( state , buildOrder , /*reportQueue*/ false ) ;
1795
1831
if ( invalidatedProject ) {
1796
1832
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 ;
1801
1844
}
1802
- return ;
1845
+ const project = createInvalidatedProjectWithInfo ( state , info , buildOrder ) ;
1846
+ project . done ( ) ;
1847
+ if ( info . kind !== InvalidatedProjectKind . UpdateOutputFileStamps ) projectsBuilt ++ ;
1803
1848
}
1804
1849
}
1805
1850
disableCache ( state ) ;
@@ -1961,11 +2006,6 @@ namespace ts {
1961
2006
return getUpToDateStatus ( state , parseConfigFile ( state , configFileName , configFilePath ) , configFilePath ) ;
1962
2007
} ,
1963
2008
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
- ) ) ,
1969
2009
close : ( ) => stopWatching ( state ) ,
1970
2010
} ;
1971
2011
}
0 commit comments