@@ -392,21 +392,37 @@ namespace ts {
392392 getModifiedTime ( fileName : string ) : Date | undefined ;
393393 setModifiedTime ( fileName : string , date : Date ) : void ;
394394 deleteFile ( fileName : string ) : void ;
395+
396+ reportDiagnostic : DiagnosticReporter ; // Technically we want to move it out and allow steps of actions on Solution, but for now just merge stuff in build host here
397+ reportSolutionBuilderStatus : DiagnosticReporter ;
395398 }
396399
397400 export interface SolutionBuilderWithWatchHost extends SolutionBuilderHost , WatchHost {
398401 }
399402
400- export function createSolutionBuilderHost ( system = sys ) {
403+ /**
404+ * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
405+ */
406+ export function createBuilderStatusReporter ( system : System , pretty ?: boolean ) : DiagnosticReporter {
407+ return diagnostic => {
408+ let output = pretty ? `[${ formatColorAndReset ( new Date ( ) . toLocaleTimeString ( ) , ForegroundColorEscapeSequences . Grey ) } ] ` : `${ new Date ( ) . toLocaleTimeString ( ) } - ` ;
409+ output += `${ flattenDiagnosticMessageText ( diagnostic . messageText , system . newLine ) } ${ system . newLine + system . newLine } ` ;
410+ system . write ( output ) ;
411+ } ;
412+ }
413+
414+ export function createSolutionBuilderHost ( system = sys , reportDiagnostic ?: DiagnosticReporter , reportSolutionBuilderStatus ?: DiagnosticReporter ) {
401415 const host = createCompilerHost ( { } , /*setParentNodes*/ undefined , system ) as SolutionBuilderHost ;
402416 host . getModifiedTime = system . getModifiedTime ? path => system . getModifiedTime ! ( path ) : ( ) => undefined ;
403417 host . setModifiedTime = system . setModifiedTime ? ( path , date ) => system . setModifiedTime ! ( path , date ) : noop ;
404418 host . deleteFile = system . deleteFile ? path => system . deleteFile ! ( path ) : noop ;
419+ host . reportDiagnostic = reportDiagnostic || createDiagnosticReporter ( system ) ;
420+ host . reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter ( system ) ;
405421 return host ;
406422 }
407423
408- export function createSolutionBuilderWithWatchHost ( system = sys , reportWatchStatus ?: WatchStatusReporter ) {
409- const host = createSolutionBuilderHost ( system ) as SolutionBuilderWithWatchHost ;
424+ export function createSolutionBuilderWithWatchHost ( system = sys , reportDiagnostic ?: DiagnosticReporter , reportSolutionBuilderStatus ?: DiagnosticReporter , reportWatchStatus ?: WatchStatusReporter ) {
425+ const host = createSolutionBuilderHost ( system , reportDiagnostic , reportSolutionBuilderStatus ) as SolutionBuilderWithWatchHost ;
410426 const watchHost = createWatchHost ( system , reportWatchStatus ) ;
411427 host . onWatchStatusChange = watchHost . onWatchStatusChange ;
412428 host . watchFile = watchHost . watchFile ;
@@ -422,7 +438,7 @@ namespace ts {
422438 * TODO: use SolutionBuilderWithWatchHost => watchedSolution
423439 * use SolutionBuilderHost => Solution
424440 */
425- export function createSolutionBuilder ( host : SolutionBuilderHost , buildHost : BuildHost , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) {
441+ export function createSolutionBuilder ( host : SolutionBuilderHost , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) {
426442 const hostWithWatch = host as SolutionBuilderWithWatchHost ;
427443 const configFileCache = createConfigFileCache ( host ) ;
428444 let context = createBuildContext ( defaultOptions ) ;
@@ -445,6 +461,10 @@ namespace ts {
445461 startWatching
446462 } ;
447463
464+ function reportStatus ( message : DiagnosticMessage , ...args : string [ ] ) {
465+ host . reportSolutionBuilderStatus ( createCompilerDiagnostic ( message , ...args ) ) ;
466+ }
467+
448468 function startWatching ( ) {
449469 const graph = getGlobalDependencyGraph ( ) ! ;
450470 if ( ! graph . buildQueue ) {
@@ -743,7 +763,7 @@ namespace ts {
743763 verboseReportProjectStatus ( next , status ) ;
744764
745765 if ( status . type === UpToDateStatusType . UpstreamBlocked ) {
746- if ( context . options . verbose ) buildHost . verbose ( Diagnostics . Skipping_build_of_project_0_because_its_dependency_1_has_errors , resolved , status . upstreamProjectName ) ;
766+ if ( context . options . verbose ) reportStatus ( Diagnostics . Skipping_build_of_project_0_because_its_dependency_1_has_errors , resolved , status . upstreamProjectName ) ;
747767 continue ;
748768 }
749769
@@ -780,7 +800,7 @@ namespace ts {
780800 if ( temporaryMarks [ projPath ] ) {
781801 if ( ! inCircularContext ) {
782802 hadError = true ;
783- buildHost . error ( Diagnostics . Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0 , circularityReportStack . join ( "\r\n" ) ) ;
803+ reportStatus ( Diagnostics . Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0 , circularityReportStack . join ( "\r\n" ) ) ;
784804 return ;
785805 }
786806 }
@@ -812,11 +832,11 @@ namespace ts {
812832
813833 function buildSingleProject ( proj : ResolvedConfigFileName ) : BuildResultFlags {
814834 if ( context . options . dry ) {
815- buildHost . message ( Diagnostics . A_non_dry_build_would_build_project_0 , proj ) ;
835+ reportStatus ( Diagnostics . A_non_dry_build_would_build_project_0 , proj ) ;
816836 return BuildResultFlags . Success ;
817837 }
818838
819- if ( context . options . verbose ) buildHost . verbose ( Diagnostics . Building_project_0 , proj ) ;
839+ if ( context . options . verbose ) reportStatus ( Diagnostics . Building_project_0 , proj ) ;
820840
821841 let resultFlags = BuildResultFlags . None ;
822842 resultFlags |= BuildResultFlags . DeclarationOutputUnchanged ;
@@ -850,7 +870,7 @@ namespace ts {
850870 if ( syntaxDiagnostics . length ) {
851871 resultFlags |= BuildResultFlags . SyntaxErrors ;
852872 for ( const diag of syntaxDiagnostics ) {
853- buildHost . errorDiagnostic ( diag ) ;
873+ host . reportDiagnostic ( diag ) ;
854874 }
855875 context . projectStatus . setValue ( proj , { type : UpToDateStatusType . Unbuildable , reason : "Syntactic errors" } ) ;
856876 return resultFlags ;
@@ -862,7 +882,7 @@ namespace ts {
862882 if ( declDiagnostics . length ) {
863883 resultFlags |= BuildResultFlags . DeclarationEmitErrors ;
864884 for ( const diag of declDiagnostics ) {
865- buildHost . errorDiagnostic ( diag ) ;
885+ host . reportDiagnostic ( diag ) ;
866886 }
867887 context . projectStatus . setValue ( proj , { type : UpToDateStatusType . Unbuildable , reason : "Declaration file errors" } ) ;
868888 return resultFlags ;
@@ -874,7 +894,7 @@ namespace ts {
874894 if ( semanticDiagnostics . length ) {
875895 resultFlags |= BuildResultFlags . TypeErrors ;
876896 for ( const diag of semanticDiagnostics ) {
877- buildHost . errorDiagnostic ( diag ) ;
897+ host . reportDiagnostic ( diag ) ;
878898 }
879899 context . projectStatus . setValue ( proj , { type : UpToDateStatusType . Unbuildable , reason : "Semantic errors" } ) ;
880900 return resultFlags ;
@@ -913,11 +933,11 @@ namespace ts {
913933
914934 function updateOutputTimestamps ( proj : ParsedCommandLine ) {
915935 if ( context . options . dry ) {
916- return buildHost . message ( Diagnostics . A_non_dry_build_would_build_project_0 , proj . options . configFilePath ! ) ;
936+ return reportStatus ( Diagnostics . A_non_dry_build_would_build_project_0 , proj . options . configFilePath ! ) ;
917937 }
918938
919939 if ( context . options . verbose ) {
920- buildHost . verbose ( Diagnostics . Updating_output_timestamps_of_project_0 , proj . options . configFilePath ! ) ;
940+ reportStatus ( Diagnostics . Updating_output_timestamps_of_project_0 , proj . options . configFilePath ! ) ;
921941 }
922942
923943 const now = new Date ( ) ;
@@ -970,18 +990,18 @@ namespace ts {
970990 function cleanAllProjects ( ) {
971991 const resolvedNames : ReadonlyArray < ResolvedConfigFileName > | undefined = getAllProjectsInScope ( ) ;
972992 if ( resolvedNames === undefined ) {
973- buildHost . message ( Diagnostics . Skipping_clean_because_not_all_projects_could_be_located ) ;
993+ reportStatus ( Diagnostics . Skipping_clean_because_not_all_projects_could_be_located ) ;
974994 return ExitStatus . DiagnosticsPresent_OutputsSkipped ;
975995 }
976996
977997 const filesToDelete = getFilesToClean ( resolvedNames ) ;
978998 if ( filesToDelete === undefined ) {
979- buildHost . message ( Diagnostics . Skipping_clean_because_not_all_projects_could_be_located ) ;
999+ reportStatus ( Diagnostics . Skipping_clean_because_not_all_projects_could_be_located ) ;
9801000 return ExitStatus . DiagnosticsPresent_OutputsSkipped ;
9811001 }
9821002
9831003 if ( context . options . dry ) {
984- buildHost . message ( Diagnostics . A_non_dry_build_would_delete_the_following_files_Colon_0 , filesToDelete . map ( f => `\r\n * ${ f } ` ) . join ( "" ) ) ;
1004+ reportStatus ( Diagnostics . A_non_dry_build_would_delete_the_following_files_Colon_0 , filesToDelete . map ( f => `\r\n * ${ f } ` ) . join ( "" ) ) ;
9851005 return ExitStatus . Success ;
9861006 }
9871007
@@ -1001,7 +1021,7 @@ namespace ts {
10011021 if ( host . fileExists ( fullPathWithTsconfig ) ) {
10021022 return fullPathWithTsconfig as ResolvedConfigFileName ;
10031023 }
1004- buildHost . error ( Diagnostics . File_0_not_found , relName ( fullPath ) ) ;
1024+ host . reportDiagnostic ( createCompilerDiagnostic ( Diagnostics . File_0_not_found , relName ( fullPath ) ) ) ;
10051025 return undefined ;
10061026 }
10071027
@@ -1039,7 +1059,7 @@ namespace ts {
10391059 // Up to date, skip
10401060 if ( defaultOptions . dry ) {
10411061 // In a dry build, inform the user of this fact
1042- buildHost . message ( Diagnostics . Project_0_is_up_to_date , projName ) ;
1062+ reportStatus ( Diagnostics . Project_0_is_up_to_date , projName ) ;
10431063 }
10441064 continue ;
10451065 }
@@ -1051,7 +1071,7 @@ namespace ts {
10511071 }
10521072
10531073 if ( status . type === UpToDateStatusType . UpstreamBlocked ) {
1054- if ( context . options . verbose ) buildHost . verbose ( Diagnostics . Skipping_build_of_project_0_because_its_dependency_1_has_errors , projName , status . upstreamProjectName ) ;
1074+ if ( context . options . verbose ) reportStatus ( Diagnostics . Skipping_build_of_project_0_because_its_dependency_1_has_errors , projName , status . upstreamProjectName ) ;
10551075 continue ;
10561076 }
10571077
@@ -1076,23 +1096,19 @@ namespace ts {
10761096 for ( const name of graph . buildQueue ) {
10771097 names . push ( name ) ;
10781098 }
1079- if ( context . options . verbose ) buildHost . verbose ( Diagnostics . Projects_in_this_build_Colon_0 , names . map ( s => "\r\n * " + relName ( s ) ) . join ( "" ) ) ;
1099+ if ( context . options . verbose ) reportStatus ( Diagnostics . Projects_in_this_build_Colon_0 , names . map ( s => "\r\n * " + relName ( s ) ) . join ( "" ) ) ;
10801100 }
10811101
10821102 function relName ( path : string ) : string {
10831103 return convertToRelativePath ( path , host . getCurrentDirectory ( ) , f => host . getCanonicalFileName ( f ) ) ;
10841104 }
10851105
1086- function reportVerbose ( message : DiagnosticMessage , ...args : string [ ] ) {
1087- buildHost . verbose ( message , ...args ) ;
1088- }
1089-
10901106 /**
10911107 * Report the up-to-date status of a project if we're in verbose mode
10921108 */
10931109 function verboseReportProjectStatus ( configFileName : string , status : UpToDateStatus ) {
10941110 if ( ! context . options . verbose ) return ;
1095- return formatUpToDateStatus ( configFileName , status , relName , reportVerbose ) ;
1111+ return formatUpToDateStatus ( configFileName , status , relName , reportStatus ) ;
10961112 }
10971113 }
10981114
0 commit comments