@@ -283,30 +283,6 @@ namespace ts {
283
283
/*@internal */ buildNextInvalidatedProject ( ) : void ;
284
284
}
285
285
286
- const enum InvalidatedProjectKind {
287
- BuildProject ,
288
- UpdateBundle ,
289
- UpdateOutputFileStamps
290
- }
291
-
292
- interface UpdateOutputFileStampsProject {
293
- readonly kind : InvalidatedProjectKind . UpdateOutputFileStamps ;
294
- readonly project : ResolvedConfigFileName ;
295
- readonly projectPath : ResolvedConfigFilePath ;
296
- readonly config : ParsedCommandLine ;
297
- }
298
-
299
- interface BuildOrUpdateBundleProject {
300
- readonly kind : InvalidatedProjectKind . BuildProject | InvalidatedProjectKind . UpdateBundle ;
301
- readonly project : ResolvedConfigFileName ;
302
- readonly projectPath : ResolvedConfigFilePath ;
303
- readonly projectIndex : number ;
304
- readonly config : ParsedCommandLine ;
305
- readonly buildOrder : readonly ResolvedConfigFileName [ ] ;
306
- }
307
-
308
- type InvalidatedProject = UpdateOutputFileStampsProject | BuildOrUpdateBundleProject ;
309
-
310
286
/**
311
287
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
312
288
*/
@@ -678,6 +654,121 @@ namespace ts {
678
654
}
679
655
}
680
656
657
+ const enum InvalidatedProjectKind {
658
+ Build ,
659
+ UpdateBundle ,
660
+ UpdateOutputFileStamps
661
+ }
662
+
663
+ interface InvalidatedProjectBase {
664
+ readonly kind : InvalidatedProjectKind ;
665
+ readonly project : ResolvedConfigFileName ;
666
+ readonly projectPath : ResolvedConfigFilePath ;
667
+ /**
668
+ * To dispose this project and ensure that all the necessary actions are taken and state is updated accordingly
669
+ */
670
+ done ( cancellationToken ?: CancellationToken ) : void ;
671
+ }
672
+
673
+ interface UpdateOutputFileStampsProject extends InvalidatedProjectBase {
674
+ readonly kind : InvalidatedProjectKind . UpdateOutputFileStamps ;
675
+ updateOutputFileStatmps ( ) : void ;
676
+ }
677
+
678
+ interface BuildInvalidedProject extends InvalidatedProjectBase {
679
+ readonly kind : InvalidatedProjectKind . Build ;
680
+ build ( cancellationToken ?: CancellationToken ) : BuildResultFlags ;
681
+ }
682
+
683
+ interface UpdateBundleProject extends InvalidatedProjectBase {
684
+ readonly kind : InvalidatedProjectKind . UpdateBundle ;
685
+ updateBundle ( cancellationToken ?: CancellationToken ) : BuildResultFlags ;
686
+ }
687
+
688
+ type InvalidatedProject = UpdateOutputFileStampsProject | BuildInvalidedProject | UpdateBundleProject ;
689
+
690
+ function createUpdateOutputFileStampsProject ( state : SolutionBuilderState , project : ResolvedConfigFileName , projectPath : ResolvedConfigFilePath , config : ParsedCommandLine ) : UpdateOutputFileStampsProject {
691
+ let updateOutputFileStampsPending = true ;
692
+ return {
693
+ kind : InvalidatedProjectKind . UpdateOutputFileStamps ,
694
+ project,
695
+ projectPath,
696
+ updateOutputFileStatmps : ( ) => {
697
+ updateOutputTimestamps ( state , config , projectPath ) ;
698
+ updateOutputFileStampsPending = false ;
699
+ } ,
700
+ done : ( ) => {
701
+ if ( updateOutputFileStampsPending ) {
702
+ updateOutputTimestamps ( state , config , projectPath ) ;
703
+ }
704
+ state . projectPendingBuild . delete ( projectPath ) ;
705
+ }
706
+ } ;
707
+ }
708
+
709
+ function createBuildInvalidedProject (
710
+ state : SolutionBuilderState ,
711
+ project : ResolvedConfigFileName ,
712
+ projectPath : ResolvedConfigFilePath ,
713
+ projectIndex : number ,
714
+ config : ParsedCommandLine ,
715
+ buildOrder : readonly ResolvedConfigFileName [ ]
716
+ ) : BuildInvalidedProject {
717
+ let buildPending = true ;
718
+ return {
719
+ kind : InvalidatedProjectKind . Build ,
720
+ project,
721
+ projectPath,
722
+ build,
723
+ done : cancellationToken => {
724
+ if ( buildPending ) build ( cancellationToken ) ;
725
+ state . projectPendingBuild . delete ( projectPath ) ;
726
+ }
727
+ } ;
728
+
729
+ function build ( cancellationToken ?: CancellationToken ) {
730
+ const buildResult = buildSingleProject ( state , project , projectPath , config , cancellationToken ) ;
731
+ queueReferencingProjects ( state , project , projectPath , projectIndex , config , buildOrder , buildResult ) ;
732
+ buildPending = false ;
733
+ return buildResult ;
734
+ }
735
+ }
736
+
737
+ function createUpdateBundleProject (
738
+ state : SolutionBuilderState ,
739
+ project : ResolvedConfigFileName ,
740
+ projectPath : ResolvedConfigFilePath ,
741
+ projectIndex : number ,
742
+ config : ParsedCommandLine ,
743
+ buildOrder : readonly ResolvedConfigFileName [ ]
744
+ ) : UpdateBundleProject {
745
+ let updatePending = true ;
746
+ return {
747
+ kind : InvalidatedProjectKind . UpdateBundle ,
748
+ project,
749
+ projectPath,
750
+ updateBundle : update ,
751
+ done : cancellationToken => {
752
+ if ( updatePending ) update ( cancellationToken ) ;
753
+ state . projectPendingBuild . delete ( projectPath ) ;
754
+ }
755
+ } ;
756
+
757
+ function update ( cancellationToken ?: CancellationToken ) {
758
+ const buildResult = updateBundle ( state , project , projectPath , config , cancellationToken ) ;
759
+ queueReferencingProjects ( state , project , projectPath , projectIndex , config , buildOrder , buildResult ) ;
760
+ updatePending = false ;
761
+ return buildResult ;
762
+ }
763
+ }
764
+
765
+ function needsBuild ( { options } : SolutionBuilderState , status : UpToDateStatus , config : ParsedCommandLine ) {
766
+ if ( status . type !== UpToDateStatusType . OutOfDateWithPrepend || options . force ) return true ;
767
+ return config . fileNames . length === 0 ||
768
+ ! ! config . errors . length ||
769
+ ! isIncrementalCompilation ( config . options ) ;
770
+ }
771
+
681
772
function getNextInvalidatedProject ( state : SolutionBuilderState , buildOrder : readonly ResolvedConfigFileName [ ] ) : InvalidatedProject | undefined {
682
773
if ( ! state . projectPendingBuild . size ) return undefined ;
683
774
@@ -724,14 +815,12 @@ namespace ts {
724
815
725
816
if ( status . type === UpToDateStatusType . UpToDateWithUpstreamTypes ) {
726
817
reportAndStoreErrors ( state , projectPath , config . errors ) ;
727
- return {
728
- kind : InvalidatedProjectKind . UpdateOutputFileStamps ,
818
+ return createUpdateOutputFileStampsProject (
819
+ state ,
729
820
project ,
730
821
projectPath ,
731
822
config
732
- } ;
733
-
734
- continue ;
823
+ ) ;
735
824
}
736
825
}
737
826
@@ -749,17 +838,9 @@ namespace ts {
749
838
continue ;
750
839
}
751
840
752
-
753
- return {
754
- kind : needsBuild ( state , status , config ) ?
755
- InvalidatedProjectKind . BuildProject :
756
- InvalidatedProjectKind . UpdateBundle ,
757
- project,
758
- projectPath,
759
- projectIndex,
760
- config,
761
- buildOrder
762
- } ;
841
+ return needsBuild ( state , status , config ) ?
842
+ createBuildInvalidedProject ( state , project , projectPath , projectIndex , config , buildOrder ) :
843
+ createUpdateBundleProject ( state , project , projectPath , projectIndex , config , buildOrder ) ;
763
844
}
764
845
765
846
return undefined ;
@@ -1307,46 +1388,19 @@ namespace ts {
1307
1388
} ) ;
1308
1389
}
1309
1390
1310
- function needsBuild ( { options } : SolutionBuilderState , status : UpToDateStatus , config : ParsedCommandLine ) {
1311
- if ( status . type !== UpToDateStatusType . OutOfDateWithPrepend || options . force ) return true ;
1312
- return config . fileNames . length === 0 ||
1313
- ! ! config . errors . length ||
1314
- ! isIncrementalCompilation ( config . options ) ;
1315
- }
1316
-
1317
- function buildInvalidatedProject (
1318
- state : SolutionBuilderState ,
1319
- invalidatedProject : InvalidatedProject ,
1320
- cancellationToken ?: CancellationToken
1321
- ) {
1322
- const { projectPendingBuild } = state ;
1323
- if ( invalidatedProject . kind === InvalidatedProjectKind . UpdateOutputFileStamps ) {
1324
- // Fake that files have been built by updating output file stamps
1325
- const { projectPath, config } = invalidatedProject ;
1326
- updateOutputTimestamps ( state , config , projectPath ) ;
1327
- projectPendingBuild . delete ( projectPath ) ;
1328
- return ;
1329
- }
1330
-
1331
- const { kind, project, projectPath, projectIndex, config, buildOrder } = invalidatedProject ;
1332
- const buildResult = kind === InvalidatedProjectKind . BuildProject ?
1333
- buildSingleProject ( state , project , projectPath , config , cancellationToken ) : // Actual build
1334
- updateBundle ( state , project , projectPath , config , cancellationToken ) ; // Fake that files have been built by manipulating prepend and existing output
1335
- projectPendingBuild . delete ( projectPath ) ;
1336
- // Only composite projects can be referenced by other projects
1337
- if ( ! ( buildResult & BuildResultFlags . AnyErrors ) && config . options . composite ) {
1338
- queueReferencingProjects ( state , project , projectPath , projectIndex , buildOrder , ! ( buildResult & BuildResultFlags . DeclarationOutputUnchanged ) ) ;
1339
- }
1340
- }
1341
-
1342
1391
function queueReferencingProjects (
1343
1392
state : SolutionBuilderState ,
1344
1393
project : ResolvedConfigFileName ,
1345
1394
projectPath : ResolvedConfigFilePath ,
1346
1395
projectIndex : number ,
1396
+ config : ParsedCommandLine ,
1347
1397
buildOrder : readonly ResolvedConfigFileName [ ] ,
1348
- declarationOutputChanged : boolean
1398
+ buildResult : BuildResultFlags
1349
1399
) {
1400
+ // Queue only if there are no errors
1401
+ if ( buildResult & BuildResultFlags . AnyErrors ) return ;
1402
+ // Only composite projects can be referenced by other projects
1403
+ if ( ! config . options . composite ) return ;
1350
1404
// Always use build order to queue projects
1351
1405
for ( let index = projectIndex + 1 ; index < buildOrder . length ; index ++ ) {
1352
1406
const nextProject = buildOrder [ index ] ;
@@ -1365,7 +1419,7 @@ namespace ts {
1365
1419
if ( status ) {
1366
1420
switch ( status . type ) {
1367
1421
case UpToDateStatusType . UpToDate :
1368
- if ( ! declarationOutputChanged ) {
1422
+ if ( buildResult & BuildResultFlags . DeclarationOutputUnchanged ) {
1369
1423
if ( ref . prepend ) {
1370
1424
state . projectStatus . set ( nextProjectPath , {
1371
1425
type : UpToDateStatusType . OutOfDateWithPrepend ,
@@ -1382,7 +1436,7 @@ namespace ts {
1382
1436
// falls through
1383
1437
case UpToDateStatusType . UpToDateWithUpstreamTypes :
1384
1438
case UpToDateStatusType . OutOfDateWithPrepend :
1385
- if ( declarationOutputChanged ) {
1439
+ if ( ! ( buildResult & BuildResultFlags . DeclarationOutputUnchanged ) ) {
1386
1440
state . projectStatus . set ( nextProjectPath , {
1387
1441
type : UpToDateStatusType . OutOfDateWithUpstream ,
1388
1442
outOfDateOutputFileName : status . type === UpToDateStatusType . OutOfDateWithPrepend ? status . outOfDateOutputFileName : status . oldestOutputFileName ,
@@ -1409,7 +1463,7 @@ namespace ts {
1409
1463
const invalidatedProject = getNextInvalidatedProject ( state , getBuildOrder ( state ) ) ;
1410
1464
if ( ! invalidatedProject ) return undefined ;
1411
1465
1412
- buildInvalidatedProject ( state , invalidatedProject , cancellationToken ) ;
1466
+ invalidatedProject . done ( cancellationToken ) ;
1413
1467
return {
1414
1468
project : invalidatedProject . project ,
1415
1469
result : state . diagnostics . has ( invalidatedProject . projectPath ) ?
@@ -1429,7 +1483,7 @@ namespace ts {
1429
1483
while ( true ) {
1430
1484
const invalidatedProject = getNextInvalidatedProject ( state , buildOrder ) ;
1431
1485
if ( ! invalidatedProject ) break ;
1432
- buildInvalidatedProject ( state , invalidatedProject , cancellationToken ) ;
1486
+ invalidatedProject . done ( cancellationToken ) ;
1433
1487
if ( state . diagnostics . has ( invalidatedProject . projectPath ) ) {
1434
1488
errorProjects ++ ;
1435
1489
}
@@ -1521,7 +1575,7 @@ namespace ts {
1521
1575
}
1522
1576
const invalidatedProject = getNextInvalidatedProject ( state , getBuildOrder ( state ) ) ;
1523
1577
if ( invalidatedProject ) {
1524
- buildInvalidatedProject ( state , invalidatedProject ) ;
1578
+ invalidatedProject . done ( ) ;
1525
1579
if ( state . projectPendingBuild . size ) {
1526
1580
// Schedule next project for build
1527
1581
if ( state . watch && ! state . timerToBuildInvalidatedProject ) {
0 commit comments