@@ -269,11 +269,12 @@ interface Symbol {
269269 tick : ( ) => void ;
270270 baseFs : vfs . FileSystem ;
271271 newSys : TscCompileSystem ;
272+ cleanBuildDescripencies : TscIncremental [ "cleanBuildDescripencies" ] ;
272273 }
273274 function verifyIncrementalCorrectness ( input : ( ) => VerifyIncrementalCorrectness , index : number ) {
274275 it ( `Verify emit output file text is same when built clean for incremental scenario at:: ${ index } ` , ( ) => {
275276 const {
276- scenario, subScenario, commandLineArgs,
277+ scenario, subScenario, commandLineArgs, cleanBuildDescripencies ,
277278 modifyFs, incrementalModifyFs,
278279 tick, baseFs, newSys
279280 } = input ( ) ;
@@ -288,54 +289,82 @@ interface Symbol {
288289 incrementalModifyFs ( fs ) ;
289290 } ,
290291 } ) ;
292+ const descripencies = cleanBuildDescripencies ?.( ) ;
291293 for ( const outputFile of arrayFrom ( sys . writtenFiles . keys ( ) ) ) {
292- const expectedText = sys . readFile ( outputFile ) ;
293- const actualText = newSys . readFile ( outputFile ) ;
294+ const cleanBuildText = sys . readFile ( outputFile ) ;
295+ const incrementalBuildText = newSys . readFile ( outputFile ) ;
296+ const descripencyInClean = descripencies ?. get ( outputFile ) ;
294297 if ( ! isBuildInfoFile ( outputFile ) ) {
295- assert . equal ( actualText , expectedText , `File: ${ outputFile } ` ) ;
298+ verifyTextEqual ( incrementalBuildText , cleanBuildText , descripencyInClean , `File: ${ outputFile } ` ) ;
296299 }
297- else if ( actualText !== expectedText ) {
300+ else if ( incrementalBuildText !== cleanBuildText ) {
298301 // Verify build info without affectedFilesPendingEmit
299- const { buildInfo : actualBuildInfo , affectedFilesPendingEmit : actualAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck ( actualText ) ;
300- const { buildInfo : expectedBuildInfo , affectedFilesPendingEmit : expectedAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck ( expectedText ) ;
301- assert . deepEqual ( actualBuildInfo , expectedBuildInfo , `TsBuild info text without affectedFilesPendingEmit: ${ outputFile } ::\nIncremental buildInfoText:: ${ actualText } \nClean buildInfoText:: ${ expectedText } ` ) ;
302+ const { buildInfo : incrementalBuildInfo , affectedFilesPendingEmit : incrementalBuildAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck ( incrementalBuildText ) ;
303+ const { buildInfo : cleanBuildInfo , affectedFilesPendingEmit : incrementalAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck ( cleanBuildText ) ;
304+ verifyTextEqual ( incrementalBuildInfo , cleanBuildInfo , descripencyInClean , `TsBuild info text without affectedFilesPendingEmit ${ subScenario } :: ${ outputFile } ::\nIncremental buildInfoText:: ${ incrementalBuildText } \nClean buildInfoText:: ${ cleanBuildText } ` ) ;
302305 // Verify that incrementally pending affected file emit are in clean build since clean build can contain more files compared to incremental depending of noEmitOnError option
303- if ( actualAffectedFilesPendingEmit ) {
304- assert . isDefined ( expectedAffectedFilesPendingEmit , `Incremental build contains affectedFilesPendingEmit, clean build should also have it: ${ outputFile } ::\nIncremental buildInfoText:: ${ actualText } \nClean buildInfoText:: ${ expectedText } ` ) ;
306+ if ( incrementalBuildAffectedFilesPendingEmit && descripencyInClean === undefined ) {
307+ assert . isDefined ( incrementalAffectedFilesPendingEmit , `Incremental build contains affectedFilesPendingEmit, clean build should also have it: ${ outputFile } ::\nIncremental buildInfoText:: ${ incrementalBuildText } \nClean buildInfoText:: ${ cleanBuildText } ` ) ;
305308 let expectedIndex = 0 ;
306- actualAffectedFilesPendingEmit . forEach ( ( [ actualFile ] ) => {
307- expectedIndex = findIndex ( expectedAffectedFilesPendingEmit ! , ( [ expectedFile ] ) => actualFile === expectedFile , expectedIndex ) ;
308- assert . notEqual ( expectedIndex , - 1 , `Incremental build contains ${ actualFile } file as pending emit, clean build should also have it: ${ outputFile } ::\nIncremental buildInfoText:: ${ actualText } \nClean buildInfoText:: ${ expectedText } ` ) ;
309+ incrementalBuildAffectedFilesPendingEmit . forEach ( ( [ actualFile ] ) => {
310+ expectedIndex = findIndex ( incrementalAffectedFilesPendingEmit ! , ( [ expectedFile ] ) => actualFile === expectedFile , expectedIndex ) ;
311+ assert . notEqual ( expectedIndex , - 1 , `Incremental build contains ${ actualFile } file as pending emit, clean build should also have it: ${ outputFile } ::\nIncremental buildInfoText:: ${ incrementalBuildText } \nClean buildInfoText:: ${ cleanBuildText } ` ) ;
309312 expectedIndex ++ ;
310313 } ) ;
311314 }
312315 }
313316 }
317+
318+ function verifyTextEqual ( incrementalText : string | undefined , cleanText : string | undefined , descripencyInClean : CleanBuildDescripency | undefined , message : string ) {
319+ if ( descripencyInClean === undefined ) {
320+ assert . equal ( incrementalText , cleanText , message ) ;
321+ return ;
322+ }
323+ switch ( descripencyInClean ) {
324+ case CleanBuildDescripency . CleanFileTextDifferent :
325+ assert . isDefined ( incrementalText , `Incremental file should be present:: ${ message } ` ) ;
326+ assert . isDefined ( cleanText , `Clean file should be present present:: ${ message } ` ) ;
327+ assert . notEqual ( incrementalText , cleanText , message ) ;
328+ return ;
329+ case CleanBuildDescripency . CleanFilePresent :
330+ assert . isUndefined ( incrementalText , `Incremental file should be absent:: ${ message } ` ) ;
331+ assert . isDefined ( cleanText , `Clean file should be present:: ${ message } ` ) ;
332+ return ;
333+ default :
334+ Debug . assertNever ( descripencyInClean ) ;
335+ }
336+ }
314337 } ) ;
315338 }
316339
317- function getBuildInfoForIncrementalCorrectnessCheck ( text : string | undefined ) : { buildInfo : BuildInfo | undefined ; affectedFilesPendingEmit ?: ProgramBuildInfo [ "affectedFilesPendingEmit" ] ; } {
340+ function getBuildInfoForIncrementalCorrectnessCheck ( text : string | undefined ) : { buildInfo : string | undefined ; affectedFilesPendingEmit ?: ProgramBuildInfo [ "affectedFilesPendingEmit" ] ; } {
318341 const buildInfo = text ? getBuildInfo ( text ) : undefined ;
319- if ( ! buildInfo ?. program ) return { buildInfo } ;
342+ if ( ! buildInfo ?. program ) return { buildInfo : text } ;
320343 // Ignore noEmit since that shouldnt be reason to emit the tsbuild info and presence of it in the buildinfo file does not matter
321344 const { program : { affectedFilesPendingEmit, options : { noEmit, ...optionsRest } , ...programRest } , ...rest } = buildInfo ;
322345 return {
323- buildInfo : {
346+ buildInfo : getBuildInfoText ( {
324347 ...rest ,
325348 program : {
326349 options : optionsRest ,
327350 ...programRest
328351 }
329- } ,
352+ } ) ,
330353 affectedFilesPendingEmit
331354 } ;
332355 }
333356
357+ export enum CleanBuildDescripency {
358+ CleanFileTextDifferent ,
359+ CleanFilePresent ,
360+ }
361+
334362 export interface TscIncremental {
335363 buildKind : BuildKind ;
336364 modifyFs : ( fs : vfs . FileSystem ) => void ;
337365 subScenario ?: string ;
338366 commandLineArgs ?: readonly string [ ] ;
367+ cleanBuildDescripencies ?: ( ) => ESMap < string , CleanBuildDescripency > ;
339368 }
340369
341370 export interface VerifyTsBuildInput extends VerifyTsBuildInputWorker {
@@ -395,7 +424,8 @@ interface Symbol {
395424 buildKind,
396425 modifyFs : incrementalModifyFs ,
397426 subScenario : incrementalSubScenario ,
398- commandLineArgs : incrementalCommandLineArgs
427+ commandLineArgs : incrementalCommandLineArgs ,
428+ cleanBuildDescripencies,
399429 } , index ) => {
400430 describe ( incrementalSubScenario || buildKind , ( ) => {
401431 let newSys : TscCompileSystem ;
@@ -424,10 +454,11 @@ interface Symbol {
424454 verifyTscBaseline ( ( ) => newSys ) ;
425455 verifyIncrementalCorrectness ( ( ) => ( {
426456 scenario,
427- subScenario,
457+ subScenario : incrementalSubScenario || subScenario ,
428458 baseFs,
429459 newSys,
430460 commandLineArgs : incrementalCommandLineArgs || commandLineArgs ,
461+ cleanBuildDescripencies,
431462 incrementalModifyFs,
432463 modifyFs,
433464 tick
@@ -519,12 +550,13 @@ interface Symbol {
519550 } ) ) ;
520551 } ) ;
521552 describe ( "incremental correctness" , ( ) => {
522- incrementalScenarios . forEach ( ( { commandLineArgs : incrementalCommandLineArgs } , index ) => verifyIncrementalCorrectness ( ( ) => ( {
553+ incrementalScenarios . forEach ( ( { commandLineArgs : incrementalCommandLineArgs , subScenario , buildKind , cleanBuildDescripencies } , index ) => verifyIncrementalCorrectness ( ( ) => ( {
523554 scenario,
524- subScenario,
555+ subScenario : subScenario || buildKind ,
525556 baseFs,
526557 newSys : incrementalSys [ index ] ,
527558 commandLineArgs : incrementalCommandLineArgs || commandLineArgs ,
559+ cleanBuildDescripencies,
528560 incrementalModifyFs : fs => {
529561 for ( let i = 0 ; i <= index ; i ++ ) {
530562 incrementalScenarios [ i ] . modifyFs ( fs ) ;
0 commit comments