@@ -128,4 +128,119 @@ namespace ts.tscWatch {
128128 checkProgramActualFiles ( watch . getProgram ( ) . getProgram ( ) , [ mainFile . path , otherFile . path , libFile . path , other2 ] ) ;
129129 } ) ;
130130 } ) ;
131+
132+ describe ( "unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticDiagnosticsBuilderProgram" , ( ) => {
133+ function getWatch < T extends BuilderProgram > ( config : File , optionsToExtend : CompilerOptions | undefined , sys : System , createProgram : CreateProgram < T > ) {
134+ const watchCompilerHost = createWatchCompilerHost ( config . path , optionsToExtend , sys , createProgram ) ;
135+ return createWatchProgram ( watchCompilerHost ) ;
136+ }
137+
138+ function setup < T extends BuilderProgram > ( createProgram : CreateProgram < T > , configText : string ) {
139+ const config : File = {
140+ path : `${ projectRoot } /tsconfig.json` ,
141+ content : configText
142+ } ;
143+ const mainFile : File = {
144+ path : `${ projectRoot } /main.ts` ,
145+ content : "export const x = 10;"
146+ } ;
147+ const otherFile : File = {
148+ path : `${ projectRoot } /other.ts` ,
149+ content : "export const y = 10;"
150+ } ;
151+ const sys = createWatchedSystem ( [ config , mainFile , otherFile , libFile ] ) ;
152+ const watch = getWatch ( config , { noEmit : true } , sys , createProgram ) ;
153+ return { sys, watch, mainFile, otherFile, config } ;
154+ }
155+
156+ function verifyOutputs ( sys : System , emitSys : System ) {
157+ for ( const output of [ `${ projectRoot } /main.js` , `${ projectRoot } /main.d.ts` , `${ projectRoot } /other.js` , `${ projectRoot } /other.d.ts` , `${ projectRoot } /tsconfig.tsbuildinfo` ] ) {
158+ assert . strictEqual ( sys . readFile ( output ) , emitSys . readFile ( output ) , `Output file text for ${ output } ` ) ;
159+ }
160+ }
161+
162+ function verifyBuilder < T extends BuilderProgram , U extends BuilderProgram > ( config : File , sys : System , emitSys : System , createProgram : CreateProgram < T > , createEmitProgram : CreateProgram < U > , optionsToExtend ?: CompilerOptions ) {
163+ const watch = getWatch ( config , /*optionsToExtend*/ optionsToExtend , sys , createProgram ) ;
164+ const emitWatch = getWatch ( config , /*optionsToExtend*/ optionsToExtend , emitSys , createEmitProgram ) ;
165+ verifyOutputs ( sys , emitSys ) ;
166+ watch . close ( ) ;
167+ emitWatch . close ( ) ;
168+ }
169+
170+ it ( "verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files" , ( ) => {
171+ const { sys, watch, mainFile, otherFile } = setup ( createSemanticDiagnosticsBuilderProgram , "{}" ) ;
172+ checkProgramActualFiles ( watch . getProgram ( ) . getProgram ( ) , [ mainFile . path , otherFile . path , libFile . path ] ) ;
173+ sys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
174+ sys . runQueuedTimeoutCallbacks ( ) ;
175+ const program = watch . getProgram ( ) . getProgram ( ) ;
176+ assert . deepEqual ( program . getCachedSemanticDiagnostics ( program . getSourceFile ( mainFile . path ) ) , [ ] ) ;
177+ // Should not retrieve diagnostics for other file thats not changed
178+ assert . deepEqual ( program . getCachedSemanticDiagnostics ( program . getSourceFile ( otherFile . path ) ) , /*expected*/ undefined ) ;
179+ } ) ;
180+
181+ it ( "noEmit with composite writes the tsbuildinfo with pending affected files correctly" , ( ) => {
182+ const configText = JSON . stringify ( { compilerOptions : { composite : true } } ) ;
183+ const { sys, watch, config, mainFile } = setup ( createSemanticDiagnosticsBuilderProgram , configText ) ;
184+ const { sys : emitSys , watch : emitWatch } = setup ( createEmitAndSemanticDiagnosticsBuilderProgram , configText ) ;
185+ verifyOutputs ( sys , emitSys ) ;
186+
187+ watch . close ( ) ;
188+ emitWatch . close ( ) ;
189+
190+ // Emit on both sys should result in same output
191+ verifyBuilder ( config , sys , emitSys , createEmitAndSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram ) ;
192+
193+ // Change file
194+ sys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
195+ emitSys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
196+
197+ // Verify noEmit results in same output
198+ verifyBuilder ( config , sys , emitSys , createSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram , { noEmit : true } ) ;
199+
200+ // Emit on both sys should result in same output
201+ verifyBuilder ( config , sys , emitSys , createEmitAndSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram ) ;
202+
203+ // Change file
204+ sys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
205+ emitSys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
206+
207+ // Emit on both the builders should result in same files
208+ verifyBuilder ( config , sys , emitSys , createSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram ) ;
209+ } ) ;
210+
211+ it ( "noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly" , ( ) => {
212+ const config : File = {
213+ path : `${ projectRoot } /tsconfig.json` ,
214+ content : JSON . stringify ( { compilerOptions : { composite : true } } )
215+ } ;
216+ const mainFile : File = {
217+ path : `${ projectRoot } /main.ts` ,
218+ content : "export const x: string = 10;"
219+ } ;
220+ const otherFile : File = {
221+ path : `${ projectRoot } /other.ts` ,
222+ content : "export const y = 10;"
223+ } ;
224+ const sys = createWatchedSystem ( [ config , mainFile , otherFile , libFile ] ) ;
225+ const emitSys = createWatchedSystem ( [ config , mainFile , otherFile , libFile ] ) ;
226+
227+ // Verify noEmit results in same output
228+ verifyBuilder ( config , sys , emitSys , createSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram , { noEmitOnError : true } ) ;
229+
230+ // Change file
231+ sys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
232+ emitSys . appendFile ( mainFile . path , "\n// SomeComment" ) ;
233+
234+ // Verify noEmit results in same output
235+ verifyBuilder ( config , sys , emitSys , createSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram , { noEmitOnError : true } ) ;
236+
237+ // Fix error
238+ const fixed = "export const x = 10;" ;
239+ sys . appendFile ( mainFile . path , fixed ) ;
240+ emitSys . appendFile ( mainFile . path , fixed ) ;
241+
242+ // Emit on both the builders should result in same files
243+ verifyBuilder ( config , sys , emitSys , createSemanticDiagnosticsBuilderProgram , createEmitAndSemanticDiagnosticsBuilderProgram , { noEmitOnError : true } ) ;
244+ } ) ;
245+ } ) ;
131246}
0 commit comments