1+ import {
2+ verifyProgramStructure ,
3+ verifyResolutionCache ,
4+ } from "../../../harness/incrementalUtils" ;
15import {
26 patchHostForBuildInfoReadWrite ,
37} from "../../_namespaces/fakes" ;
@@ -38,6 +42,9 @@ export interface TscWatchCompileChange<T extends ts.BuilderProgram = ts.EmitAndS
3842 programs : readonly CommandLineProgram [ ] ,
3943 watchOrSolution : WatchOrSolution < T > ,
4044 ) => void ;
45+ // TODO:: sheetal: Needing these fields are technically issues that need to be fixed later
46+ symlinksNotReflected ?: readonly string [ ] ;
47+ skipStructureCheck ?: true ;
4148}
4249export interface TscWatchCheckOptions {
4350 baselineSourceMap ?: boolean ;
@@ -214,6 +221,7 @@ export interface RunWatchBaseline<T extends ts.BuilderProgram> extends BaselineB
214221 sys : TscWatchSystem ;
215222 getPrograms : ( ) => readonly CommandLineProgram [ ] ;
216223 watchOrSolution : WatchOrSolution < T > ;
224+ useSourceOfProjectReferenceRedirect ?: ( ) => boolean ;
217225}
218226export function runWatchBaseline < T extends ts . BuilderProgram = ts . EmitAndSemanticDiagnosticsBuilderProgram > ( {
219227 scenario,
@@ -227,6 +235,7 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
227235 baselineDependencies,
228236 edits,
229237 watchOrSolution,
238+ useSourceOfProjectReferenceRedirect,
230239} : RunWatchBaseline < T > ) {
231240 baseline . push ( `${ sys . getExecutingFilePath ( ) } ${ commandLineArgs . join ( " " ) } ` ) ;
232241 let programs = watchBaseline ( {
@@ -240,7 +249,7 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
240249 } ) ;
241250
242251 if ( edits ) {
243- for ( const { caption, edit, timeouts } of edits ) {
252+ for ( const { caption, edit, timeouts, symlinksNotReflected , skipStructureCheck } of edits ) {
244253 oldSnap = applyEdit ( sys , baseline , edit , caption ) ;
245254 timeouts ( sys , programs , watchOrSolution ) ;
246255 programs = watchBaseline ( {
@@ -251,6 +260,10 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
251260 oldSnap,
252261 baselineSourceMap,
253262 baselineDependencies,
263+ caption,
264+ resolutionCache : ! skipStructureCheck ? ( watchOrSolution as ts . WatchOfConfigFile < T > | undefined ) ?. getResolutionCache ?.( ) : undefined ,
265+ useSourceOfProjectReferenceRedirect,
266+ symlinksNotReflected,
254267 } ) ;
255268 }
256269 }
@@ -268,20 +281,94 @@ export function isWatch(commandLineArgs: readonly string[]) {
268281export interface WatchBaseline extends BaselineBase , TscWatchCheckOptions {
269282 oldPrograms : readonly ( CommandLineProgram | undefined ) [ ] ;
270283 getPrograms : ( ) => readonly CommandLineProgram [ ] ;
284+ caption ?: string ;
285+ resolutionCache ?: ts . ResolutionCache ;
286+ useSourceOfProjectReferenceRedirect ?: ( ) => boolean ;
287+ symlinksNotReflected ?: readonly string [ ] ;
271288}
272- export function watchBaseline ( { baseline, getPrograms, oldPrograms, sys, oldSnap, baselineSourceMap, baselineDependencies } : WatchBaseline ) {
289+ export function watchBaseline ( {
290+ baseline,
291+ getPrograms,
292+ oldPrograms,
293+ sys,
294+ oldSnap,
295+ baselineSourceMap,
296+ baselineDependencies,
297+ caption,
298+ resolutionCache,
299+ useSourceOfProjectReferenceRedirect,
300+ symlinksNotReflected,
301+ } : WatchBaseline ) {
273302 if ( baselineSourceMap ) generateSourceMapBaselineFiles ( sys ) ;
274303 sys . serializeOutput ( baseline ) ;
275- const programs = baselinePrograms ( baseline , getPrograms , oldPrograms , baselineDependencies ) ;
304+ const programs = getPrograms ( ) ;
305+ baselinePrograms ( baseline , programs , oldPrograms , baselineDependencies ) ;
276306 sys . serializeWatches ( baseline ) ;
277307 baseline . push ( `exitCode:: ExitStatus.${ ts . ExitStatus [ sys . exitCode as ts . ExitStatus ] } ` , "" ) ;
278308 sys . diff ( baseline , oldSnap ) ;
279309 sys . writtenFiles . forEach ( ( value , key ) => {
280310 assert . equal ( value , 1 , `Expected to write file ${ key } only once` ) ;
281311 } ) ;
312+ // Verify program structure and resolution cache when incremental edit with tsc --watch (without build mode)
313+ if ( resolutionCache && programs . length ) {
314+ ts . Debug . assert ( programs . length === 1 ) ;
315+ verifyProgramStructureAndResolutionCache ( caption ! , sys , programs [ 0 ] [ 0 ] , resolutionCache , useSourceOfProjectReferenceRedirect , symlinksNotReflected ) ;
316+ }
282317 sys . writtenFiles . clear ( ) ;
283318 return programs ;
284319}
320+ function verifyProgramStructureAndResolutionCache (
321+ caption : string ,
322+ sys : TscWatchSystem ,
323+ program : ts . Program ,
324+ resolutionCache : ts . ResolutionCache ,
325+ useSourceOfProjectReferenceRedirect ?: ( ) => boolean ,
326+ symlinksNotReflected ?: readonly string [ ] ,
327+ ) {
328+ const options = program . getCompilerOptions ( ) ;
329+ const compilerHost = ts . createCompilerHostWorker ( options , /*setParentNodes*/ undefined , sys ) ;
330+ compilerHost . trace = ts . noop ;
331+ compilerHost . writeFile = ts . notImplemented ;
332+ compilerHost . useSourceOfProjectReferenceRedirect = useSourceOfProjectReferenceRedirect ;
333+ const readFile = compilerHost . readFile ;
334+ compilerHost . readFile = fileName => {
335+ const text = readFile . call ( compilerHost , fileName ) ;
336+ if ( ! ts . contains ( symlinksNotReflected , fileName ) ) return text ;
337+ // Handle symlinks that dont reflect the watch change
338+ ts . Debug . assert ( sys . toPath ( sys . realpath ( fileName ) ) !== sys . toPath ( fileName ) ) ;
339+ const file = program . getSourceFile ( fileName ) ! ;
340+ ts . Debug . assert ( file . text !== text ) ;
341+ return file . text ;
342+ } ;
343+ verifyProgramStructure (
344+ ts . createProgram ( {
345+ rootNames : program . getRootFileNames ( ) ,
346+ options,
347+ projectReferences : program . getProjectReferences ( ) ,
348+ host : compilerHost ,
349+ } ) ,
350+ program ,
351+ caption ,
352+ ) ;
353+ verifyResolutionCache ( resolutionCache , program , {
354+ ...compilerHost ,
355+
356+ getCompilerHost : ( ) => compilerHost ,
357+ toPath : fileName => sys . toPath ( fileName ) ,
358+ getCompilationSettings : ( ) => options ,
359+ fileIsOpen : ts . returnFalse ,
360+ getCurrentProgram : ( ) => program ,
361+
362+ watchDirectoryOfFailedLookupLocation : ts . returnNoopFileWatcher ,
363+ watchAffectingFileLocation : ts . returnNoopFileWatcher ,
364+ onInvalidatedResolution : ts . noop ,
365+ watchTypeRootsDirectory : ts . returnNoopFileWatcher ,
366+ onChangedAutomaticTypeDirectiveNames : ts . noop ,
367+ scheduleInvalidateResolutionsOfFailedLookupLocations : ts . noop ,
368+ getCachedDirectoryStructureHost : ts . returnUndefined ,
369+ writeLog : ts . noop ,
370+ } , caption ) ;
371+ }
285372export interface VerifyTscWatch extends TscWatchCompile {
286373 baselineIncremental ?: boolean ;
287374}
0 commit comments