@@ -264,15 +264,10 @@ namespace ts {
264
264
export interface SolutionBuilderWithWatchHost < T extends BuilderProgram > extends SolutionBuilderHostBase < T > , WatchHost {
265
265
}
266
266
267
- export interface SolutionBuilderResult < T > {
268
- project : ResolvedConfigFileName ;
269
- result : T ;
270
- }
271
-
272
- export interface SolutionBuilder {
267
+ export interface SolutionBuilder < T extends BuilderProgram > {
273
268
build ( project ?: string , cancellationToken ?: CancellationToken ) : ExitStatus ;
274
269
clean ( project ?: string ) : ExitStatus ;
275
- buildNextProject ( cancellationToken ?: CancellationToken ) : SolutionBuilderResult < ExitStatus > | undefined ;
270
+ getNextInvalidatedProject ( cancellationToken ?: CancellationToken ) : InvalidatedProject < T > | undefined ;
276
271
277
272
// Currently used for testing but can be made public if needed:
278
273
/*@internal */ getBuildOrder ( ) : ReadonlyArray < ResolvedConfigFileName > ;
@@ -325,11 +320,11 @@ namespace ts {
325
320
return result ;
326
321
}
327
322
328
- export function createSolutionBuilder < T extends BuilderProgram > ( host : SolutionBuilderHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder {
323
+ export function createSolutionBuilder < T extends BuilderProgram > ( host : SolutionBuilderHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder < T > {
329
324
return createSolutionBuilderWorker ( /*watch*/ false , host , rootNames , defaultOptions ) ;
330
325
}
331
326
332
- export function createSolutionBuilderWithWatch < T extends BuilderProgram > ( host : SolutionBuilderWithWatchHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder {
327
+ export function createSolutionBuilderWithWatch < T extends BuilderProgram > ( host : SolutionBuilderWithWatchHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder < T > {
333
328
return createSolutionBuilderWorker ( /*watch*/ true , host , rootNames , defaultOptions ) ;
334
329
}
335
330
@@ -380,6 +375,7 @@ namespace ts {
380
375
allProjectBuildPending : boolean ;
381
376
needsSummary : boolean ;
382
377
watchAllProjectsPending : boolean ;
378
+ currentInvalidatedProject : InvalidatedProject < T > | undefined ;
383
379
384
380
// Watch state
385
381
readonly watch : boolean ;
@@ -452,6 +448,7 @@ namespace ts {
452
448
allProjectBuildPending : true ,
453
449
needsSummary : true ,
454
450
watchAllProjectsPending : watch ,
451
+ currentInvalidatedProject : undefined ,
455
452
456
453
// Watch state
457
454
watch,
@@ -654,36 +651,38 @@ namespace ts {
654
651
}
655
652
}
656
653
657
- const enum InvalidatedProjectKind {
654
+ export enum InvalidatedProjectKind {
658
655
Build ,
659
656
UpdateBundle ,
660
657
UpdateOutputFileStamps
661
658
}
662
659
663
- interface InvalidatedProjectBase {
660
+ export interface InvalidatedProjectBase {
664
661
readonly kind : InvalidatedProjectKind ;
665
662
readonly project : ResolvedConfigFileName ;
666
- readonly projectPath : ResolvedConfigFilePath ;
663
+ /*@internal */ readonly projectPath : ResolvedConfigFilePath ;
664
+ /*@internal */ readonly buildOrder : readonly ResolvedConfigFileName [ ] ;
667
665
/**
668
666
* To dispose this project and ensure that all the necessary actions are taken and state is updated accordingly
669
667
*/
670
- done ( cancellationToken ?: CancellationToken ) : void ;
668
+ done ( cancellationToken ?: CancellationToken ) : ExitStatus ;
669
+ getCompilerOptions ( ) : CompilerOptions ;
670
+ getCurrentDirectory ( ) : string ;
671
671
}
672
672
673
- interface UpdateOutputFileStampsProject extends InvalidatedProjectBase {
673
+ export interface UpdateOutputFileStampsProject extends InvalidatedProjectBase {
674
674
readonly kind : InvalidatedProjectKind . UpdateOutputFileStamps ;
675
675
updateOutputFileStatmps ( ) : void ;
676
676
}
677
677
678
- interface BuildInvalidedProject < T extends BuilderProgram = BuilderProgram > extends InvalidatedProjectBase {
678
+ export interface BuildInvalidedProject < T extends BuilderProgram > extends InvalidatedProjectBase {
679
679
readonly kind : InvalidatedProjectKind . Build ;
680
680
/*
681
681
* Emitting with this builder program without the api provided for this project
682
682
* can result in build system going into invalid state as files written reflect the state of the project
683
683
*/
684
684
getBuilderProgram ( ) : T | undefined ;
685
685
getProgram ( ) : Program | undefined ;
686
- getCompilerOptions ( ) : CompilerOptions ;
687
686
getSourceFile ( fileName : string ) : SourceFile | undefined ;
688
687
getSourceFiles ( ) : ReadonlyArray < SourceFile > ;
689
688
getOptionsDiagnostics ( cancellationToken ?: CancellationToken ) : ReadonlyArray < Diagnostic > ;
@@ -704,22 +703,41 @@ namespace ts {
704
703
emit ( targetSourceFile ?: SourceFile , writeFile ?: WriteFileCallback , cancellationToken ?: CancellationToken , emitOnlyDtsFiles ?: boolean , customTransformers ?: CustomTransformers ) : EmitResult | undefined ;
705
704
// TODO(shkamat):: investigate later if we can emit even when there are declaration diagnostics
706
705
// emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult>;
707
- getCurrentDirectory ( ) : string ;
708
706
}
709
707
710
- interface UpdateBundleProject < T extends BuilderProgram = BuilderProgram > extends InvalidatedProjectBase {
708
+ export interface UpdateBundleProject < T extends BuilderProgram > extends InvalidatedProjectBase {
711
709
readonly kind : InvalidatedProjectKind . UpdateBundle ;
712
710
emit ( writeFile ?: WriteFileCallback , customTransformers ?: CustomTransformers ) : EmitResult | BuildInvalidedProject < T > | undefined ;
713
711
}
714
712
715
- type InvalidatedProject < T extends BuilderProgram = BuilderProgram > = UpdateOutputFileStampsProject | BuildInvalidedProject < T > | UpdateBundleProject < T > ;
713
+ export type InvalidatedProject < T extends BuilderProgram > = UpdateOutputFileStampsProject | BuildInvalidedProject < T > | UpdateBundleProject < T > ;
716
714
717
- function createUpdateOutputFileStampsProject ( state : SolutionBuilderState , project : ResolvedConfigFileName , projectPath : ResolvedConfigFilePath , config : ParsedCommandLine ) : UpdateOutputFileStampsProject {
715
+ function doneInvalidatedProject (
716
+ state : SolutionBuilderState ,
717
+ projectPath : ResolvedConfigFilePath
718
+ ) {
719
+ state . projectPendingBuild . delete ( projectPath ) ;
720
+ state . currentInvalidatedProject = undefined ;
721
+ return state . diagnostics . has ( projectPath ) ?
722
+ ExitStatus . DiagnosticsPresent_OutputsSkipped :
723
+ ExitStatus . Success ;
724
+ }
725
+
726
+ function createUpdateOutputFileStampsProject (
727
+ state : SolutionBuilderState ,
728
+ project : ResolvedConfigFileName ,
729
+ projectPath : ResolvedConfigFilePath ,
730
+ config : ParsedCommandLine ,
731
+ buildOrder : readonly ResolvedConfigFileName [ ]
732
+ ) : UpdateOutputFileStampsProject {
718
733
let updateOutputFileStampsPending = true ;
719
734
return {
720
735
kind : InvalidatedProjectKind . UpdateOutputFileStamps ,
721
736
project,
722
737
projectPath,
738
+ buildOrder,
739
+ getCompilerOptions : ( ) => config . options ,
740
+ getCurrentDirectory : ( ) => state . currentDirectory ,
723
741
updateOutputFileStatmps : ( ) => {
724
742
updateOutputTimestamps ( state , config , projectPath ) ;
725
743
updateOutputFileStampsPending = false ;
@@ -728,7 +746,7 @@ namespace ts {
728
746
if ( updateOutputFileStampsPending ) {
729
747
updateOutputTimestamps ( state , config , projectPath ) ;
730
748
}
731
- state . projectPendingBuild . delete ( projectPath ) ;
749
+ return doneInvalidatedProject ( state , projectPath ) ;
732
750
}
733
751
} ;
734
752
}
@@ -763,12 +781,14 @@ namespace ts {
763
781
kind,
764
782
project,
765
783
projectPath,
784
+ buildOrder,
785
+ getCompilerOptions : ( ) => config . options ,
786
+ getCurrentDirectory : ( ) => state . currentDirectory ,
766
787
getBuilderProgram : ( ) => withProgramOrUndefined ( identity ) ,
767
788
getProgram : ( ) =>
768
789
withProgramOrUndefined (
769
790
program => program . getProgramOrUndefined ( )
770
791
) ,
771
- getCompilerOptions : ( ) => config . options ,
772
792
getSourceFile : fileName =>
773
793
withProgramOrUndefined (
774
794
program => program . getSourceFile ( fileName )
@@ -817,26 +837,27 @@ namespace ts {
817
837
if ( step !== Step . Emit ) return undefined ;
818
838
return emit ( writeFile , cancellationToken , customTransformers ) ;
819
839
} ,
820
- getCurrentDirectory : ( ) => state . currentDirectory ,
821
- done : cancellationToken => {
822
- executeSteps ( Step . Done , cancellationToken ) ;
823
- state . projectPendingBuild . delete ( projectPath ) ;
824
- }
840
+ done
825
841
} :
826
842
{
827
843
kind,
828
844
project,
829
845
projectPath,
846
+ buildOrder,
847
+ getCompilerOptions : ( ) => config . options ,
848
+ getCurrentDirectory : ( ) => state . currentDirectory ,
830
849
emit : ( writeFile : WriteFileCallback | undefined , customTransformers : CustomTransformers | undefined ) => {
831
850
if ( step !== Step . EmitBundle ) return invalidatedProjectOfBundle ;
832
851
return emitBundle ( writeFile , customTransformers ) ;
833
852
} ,
834
- done : cancellationToken => {
835
- executeSteps ( Step . Done , cancellationToken ) ;
836
- state . projectPendingBuild . delete ( projectPath ) ;
837
- }
853
+ done,
838
854
} ;
839
855
856
+ function done ( cancellationToken ?: CancellationToken ) {
857
+ executeSteps ( Step . Done , cancellationToken ) ;
858
+ return doneInvalidatedProject ( state , projectPath ) ;
859
+ }
860
+
840
861
function withProgramOrUndefined < U > ( action : ( program : T ) => U | undefined ) : U | undefined {
841
862
executeSteps ( Step . CreateProgram ) ;
842
863
return program && action ( program ) ;
@@ -1152,6 +1173,12 @@ namespace ts {
1152
1173
1153
1174
function getNextInvalidatedProject < T extends BuilderProgram > ( state : SolutionBuilderState < T > , buildOrder : readonly ResolvedConfigFileName [ ] ) : InvalidatedProject < T > | undefined {
1154
1175
if ( ! state . projectPendingBuild . size ) return undefined ;
1176
+ if ( state . currentInvalidatedProject ) {
1177
+ // Only if same buildOrder the currentInvalidated project can be sent again
1178
+ return arrayIsEqualTo ( state . currentInvalidatedProject . buildOrder , buildOrder ) ?
1179
+ state . currentInvalidatedProject :
1180
+ undefined ;
1181
+ }
1155
1182
1156
1183
const { options, projectPendingBuild } = state ;
1157
1184
for ( let projectIndex = 0 ; projectIndex < buildOrder . length ; projectIndex ++ ) {
@@ -1200,7 +1227,8 @@ namespace ts {
1200
1227
state ,
1201
1228
project ,
1202
1229
projectPath ,
1203
- config
1230
+ config ,
1231
+ buildOrder
1204
1232
) ;
1205
1233
}
1206
1234
}
@@ -1635,20 +1663,6 @@ namespace ts {
1635
1663
}
1636
1664
}
1637
1665
1638
- function buildNextProject ( state : SolutionBuilderState , cancellationToken ?: CancellationToken ) : SolutionBuilderResult < ExitStatus > | undefined {
1639
- setupInitialBuild ( state , cancellationToken ) ;
1640
- const invalidatedProject = getNextInvalidatedProject ( state , getBuildOrder ( state ) ) ;
1641
- if ( ! invalidatedProject ) return undefined ;
1642
-
1643
- invalidatedProject . done ( cancellationToken ) ;
1644
- return {
1645
- project : invalidatedProject . project ,
1646
- result : state . diagnostics . has ( invalidatedProject . projectPath ) ?
1647
- ExitStatus . DiagnosticsPresent_OutputsSkipped :
1648
- ExitStatus . Success
1649
- } ;
1650
- }
1651
-
1652
1666
function build ( state : SolutionBuilderState , project ?: string , cancellationToken ?: CancellationToken ) : ExitStatus {
1653
1667
const buildOrder = getBuildOrderFor ( state , project ) ;
1654
1668
if ( ! buildOrder ) return ExitStatus . InvalidProject_OutputsSkipped ;
@@ -1883,14 +1897,17 @@ namespace ts {
1883
1897
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
1884
1898
* can dynamically add/remove other projects based on changes on the rootNames' references
1885
1899
*/
1886
- function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : false , host : SolutionBuilderHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder ;
1887
- function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : true , host : SolutionBuilderWithWatchHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder ;
1888
- function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : boolean , hostOrHostWithWatch : SolutionBuilderHost < T > | SolutionBuilderWithWatchHost < T > , rootNames : ReadonlyArray < string > , options : BuildOptions ) : SolutionBuilder {
1900
+ function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : false , host : SolutionBuilderHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder < T > ;
1901
+ function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : true , host : SolutionBuilderWithWatchHost < T > , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) : SolutionBuilder < T > ;
1902
+ function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : boolean , hostOrHostWithWatch : SolutionBuilderHost < T > | SolutionBuilderWithWatchHost < T > , rootNames : ReadonlyArray < string > , options : BuildOptions ) : SolutionBuilder < T > {
1889
1903
const state = createSolutionBuilderState ( watch , hostOrHostWithWatch , rootNames , options ) ;
1890
1904
return {
1891
1905
build : ( project , cancellationToken ) => build ( state , project , cancellationToken ) ,
1892
1906
clean : project => clean ( state , project ) ,
1893
- buildNextProject : cancellationToken => buildNextProject ( state , cancellationToken ) ,
1907
+ getNextInvalidatedProject : cancellationToken => {
1908
+ setupInitialBuild ( state , cancellationToken ) ;
1909
+ return getNextInvalidatedProject ( state , getBuildOrder ( state ) ) ;
1910
+ } ,
1894
1911
getBuildOrder : ( ) => getBuildOrder ( state ) ,
1895
1912
getUpToDateStatusOfProject : project => {
1896
1913
const configFileName = resolveProjectName ( state , project ) ;
0 commit comments