33namespace ts {
44 let currentTime = 100 ;
55 const bfs = new vfs . FileSystem ( /*ignoreCase*/ false , { time } ) ;
6- const lastDiagnostics : Diagnostic [ ] = [ ] ;
6+ let lastDiagnostics : Diagnostic [ ] = [ ] ;
77 const reportDiagnostic : DiagnosticReporter = diagnostic => lastDiagnostics . push ( diagnostic ) ;
88
99 const sampleRoot = resolvePath ( __dirname , "../../tests/projects/sample1" ) ;
@@ -12,47 +12,109 @@ namespace ts {
1212 bfs . writeFileSync ( "/lib/lib.d.ts" , Harness . IO . readFile ( combinePaths ( Harness . libFolder , "lib.d.ts" ) ) ) ;
1313 bfs . meta . set ( "defaultLibLocation" , "/lib" ) ;
1414 bfs . makeReadonly ( ) ;
15+ tick ( ) ;
1516
1617 describe ( "tsbuild tests" , ( ) => {
17- it ( "builds the referenced project" , ( ) => {
18+ it ( "can build the sample project 'tests' without error " , ( ) => {
1819 const fs = bfs . shadow ( ) ;
1920 const host = new fakes . CompilerHost ( fs ) ;
20- const builder = createSolutionBuilder ( host , reportDiagnostic , createBuildContext ( { dry : false , force : false , verbose : false } ) ) ;
21+ const builder = createSolutionBuilder ( host , reportDiagnostic , { dry : false , force : false , verbose : false } ) ;
2122
2223 fs . chdir ( "/src/tests" ) ;
23- fs . debugPrint ( ) ;
2424 builder . buildProjects ( [ "." ] ) ;
25- printDiagnostics ( ) ;
26- fs . debugPrint ( ) ;
27- assertDiagnosticMessages ( Diagnostics . File_0_does_not_exist ) ;
25+ assertDiagnosticMessages ( /*empty*/ ) ;
26+ } ) ;
27+
28+ it ( "can detect when and what to rebuild" , ( ) => {
29+ const fs = bfs . shadow ( ) ;
30+ const host = new fakes . CompilerHost ( fs ) ;
31+ const builder = createSolutionBuilder ( host , reportDiagnostic , { dry : false , force : false , verbose : true } ) ;
32+
33+ fs . chdir ( "/src/tests" ) ;
34+ builder . buildProjects ( [ "." ] ) ;
35+ assertDiagnosticMessages ( Diagnostics . Sorted_list_of_input_projects_Colon_0 ,
36+ Diagnostics . Project_0_is_out_of_date_because_output_file_1_does_not_exist ,
37+ Diagnostics . Building_project_0 ,
38+ Diagnostics . Project_0_is_out_of_date_because_output_file_1_does_not_exist ,
39+ Diagnostics . Building_project_0 ,
40+ Diagnostics . Project_0_is_out_of_date_because_output_file_1_does_not_exist ,
41+ Diagnostics . Building_project_0 ) ;
42+ tick ( ) ;
43+
44+ // All three projects are up to date
45+ clearDiagnostics ( ) ;
46+ builder . buildProjects ( [ "." ] ) ;
47+ assertDiagnosticMessages ( Diagnostics . Sorted_list_of_input_projects_Colon_0 ,
48+ Diagnostics . Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2 ,
49+ Diagnostics . Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2 ,
50+ Diagnostics . Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2 ) ;
51+ tick ( ) ;
2852
53+ // Update a file in the leaf node (tests), only it should rebuild the last one
54+ clearDiagnostics ( ) ;
55+ fs . writeFileSync ( "/src/tests/index.ts" , "const m = 10;" ) ;
56+ builder . buildProjects ( [ "." ] ) ;
57+
58+ assertDiagnosticMessages ( Diagnostics . Sorted_list_of_input_projects_Colon_0 ,
59+ Diagnostics . Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2 ,
60+ Diagnostics . Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2 ,
61+ Diagnostics . Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2 ,
62+ Diagnostics . Building_project_0 ) ;
2963 tick ( ) ;
64+
65+ // Update a file in the parent (without affecting types), should get fast downstream builds
66+ clearDiagnostics ( ) ;
67+ replaceText ( fs , "/src/core/index.ts" , "HELLO WORLD" , "WELCOME PLANET" ) ;
68+ builder . buildProjects ( [ "." ] ) ;
69+
70+ assertDiagnosticMessages ( Diagnostics . Sorted_list_of_input_projects_Colon_0 ,
71+ Diagnostics . Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2 ,
72+ Diagnostics . Building_project_0 ,
73+ Diagnostics . Project_0_is_up_to_date_with_its_upstream_types ,
74+ Diagnostics . Updating_output_timestamps_of_project_0 ,
75+ Diagnostics . Project_0_is_up_to_date_with_its_upstream_types ,
76+ Diagnostics . Updating_output_timestamps_of_project_0 ) ;
3077 } ) ;
3178 } ) ;
3279
80+ function replaceText ( fs : vfs . FileSystem , path : string , oldText : string , newText : string ) {
81+ if ( ! fs . statSync ( path ) . isFile ( ) ) {
82+ throw new Error ( `File ${ path } does not exist` ) ;
83+ }
84+ const old = fs . readFileSync ( path , 'utf-8' ) ;
85+ if ( old . indexOf ( oldText ) < 0 ) {
86+ throw new Error ( `Text "${ oldText } " does not exist in file ${ path } ` ) ;
87+ }
88+ const newContent = old . replace ( oldText , newText ) ;
89+ fs . writeFileSync ( path , newContent , 'utf-8' ) ;
90+ }
91+
3392 function assertDiagnosticMessages ( ...expected : DiagnosticMessage [ ] ) {
3493 const actual = lastDiagnostics . slice ( ) ;
35- actual . sort ( ( a , b ) => b . code - a . code ) ;
36- expected . sort ( ( a , b ) => b . code - a . code ) ;
3794 if ( actual . length !== expected . length ) {
38- assert . fail < any > ( actual , expected , `Diagnostic arrays did not match - expected ${ actual . join ( ", " ) } , got ${ expected . join ( ", " ) } ` ) ;
95+ assert . fail < any > ( actual , expected , `Diagnostic arrays did not match - expected\r\n ${ actual . map ( a => " " + a . messageText ) . join ( "\r\n " ) } \r\ngot\r\n ${ expected . map ( e => " " + e . message ) . join ( "\r\n " ) } ` ) ;
3996 }
4097 for ( let i = 0 ; i < actual . length ; i ++ ) {
4198 if ( actual [ i ] . code !== expected [ i ] . code ) {
42- assert . fail ( actual [ i ] . messageText , expected [ i ] . message , " Mismatched error code" ) ;
99+ assert . fail ( actual [ i ] . messageText , expected [ i ] . message , ` Mismatched error code - expected diagnostic ${ i } " ${ actual [ i ] . messageText } " to match ${ expected [ i ] . message } ` ) ;
43100 }
44101 }
45102 }
46103
47- export function printDiagnostics ( ) {
104+ function clearDiagnostics ( ) {
105+ lastDiagnostics = [ ] ;
106+ }
107+
108+ export function printDiagnostics ( header = "== Diagnostics ==" ) {
48109 const out = createDiagnosticReporter ( sys ) ;
110+ sys . write ( header + "\r\n" ) ;
49111 for ( const d of lastDiagnostics ) {
50112 out ( d ) ;
51113 }
52114 }
53115
54116 function tick ( ) {
55- currentTime += 10 ;
117+ currentTime += 100000 ;
56118 }
57119 function time ( ) {
58120 return currentTime ;
0 commit comments