• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts.tscWatch {
2    describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolution", () => {
3        it("verify that module resolution with json extension works when returned without extension", () => {
4            const configFileJson: any = {
5                compilerOptions: { module: "commonjs", resolveJsonModule: true },
6                files: ["index.ts"]
7            };
8            const mainFile: File = {
9                path: `${projectRoot}/index.ts`,
10                content: "import settings from './settings.json';"
11            };
12            const config: File = {
13                path: `${projectRoot}/tsconfig.json`,
14                content: JSON.stringify(configFileJson)
15            };
16            const settingsJson: File = {
17                path: `${projectRoot}/settings.json`,
18                content: JSON.stringify({ content: "Print this" })
19            };
20            const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(
21                [libFile, mainFile, config, settingsJson],
22                { currentDirectory: projectRoot }),
23            );
24            const host = createWatchCompilerHostOfConfigFileForBaseline({
25                configFileName: config.path,
26                system: sys,
27                cb,
28            });
29            const parsedCommandResult = parseJsonConfigFileContent(configFileJson, sys, config.path);
30            host.resolveModuleNames = (moduleNames, containingFile) => moduleNames.map(m => {
31                const result = resolveModuleName(m, containingFile, parsedCommandResult.options, host);
32                const resolvedModule = result.resolvedModule!;
33                return {
34                    resolvedFileName: resolvedModule.resolvedFileName,
35                    isExternalLibraryImport: resolvedModule.isExternalLibraryImport,
36                    originalFileName: resolvedModule.originalPath,
37                };
38            });
39            const watch = createWatchProgram(host);
40            runWatchBaseline({
41                scenario: "watchApi",
42                subScenario: "verify that module resolution with json extension works when returned without extension",
43                commandLineArgs: ["--w", "--p", config.path],
44                sys,
45                baseline,
46                oldSnap,
47                getPrograms,
48                changes: emptyArray,
49                watchOrSolution: watch
50            });
51        });
52
53        describe("hasInvalidatedResolutions", () => {
54            function verifyWatch(subScenario: string, implementHasInvalidatedResolution: boolean) {
55                it(subScenario, () => {
56                    const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem({
57                        [`${projectRoot}/tsconfig.json`]: JSON.stringify({
58                            compilerOptions: { traceResolution: true, extendedDiagnostics: true },
59                            files: ["main.ts"]
60                        }),
61                        [`${projectRoot}/main.ts`]: `import { foo } from "./other";`,
62                        [`${projectRoot}/other.d.ts`]: "export function foo(): void;",
63                        [libFile.path]: libFile.content,
64                    }, { currentDirectory: projectRoot }));
65                    const host = createWatchCompilerHostOfConfigFileForBaseline({
66                        configFileName: `${projectRoot}/tsconfig.json`,
67                        system: sys,
68                        cb,
69                    });
70                    host.resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference, options) =>
71                        moduleNames.map(m => resolveModuleName(m, containingFile, options, host).resolvedModule);
72                    // Invalidate resolutions only when ts file is created
73                    if (implementHasInvalidatedResolution) host.hasInvalidatedResolutions = () => sys.fileExists(`${projectRoot}/other.ts`);
74                    const watch = createWatchProgram(host);
75                    runWatchBaseline({
76                        scenario: "watchApi",
77                        subScenario,
78                        commandLineArgs: ["--w"],
79                        sys,
80                        baseline,
81                        oldSnap,
82                        getPrograms,
83                        changes: [
84                            {
85                                caption: "write other with same contents",
86                                change: sys => sys.appendFile(`${projectRoot}/other.d.ts`, ""),
87                                timeouts: sys => sys.runQueuedTimeoutCallbacks(),
88                            },
89                            {
90                                caption: "change other file",
91                                change: sys => sys.appendFile(`${projectRoot}/other.d.ts`, "export function bar(): void;"),
92                                timeouts: sys => sys.runQueuedTimeoutCallbacks(),
93                            },
94                            {
95                                caption: "write other with same contents but write ts file",
96                                change: sys => {
97                                    sys.appendFile(`${projectRoot}/other.d.ts`, "");
98                                    sys.writeFile(`${projectRoot}/other.ts`, "export function foo() {}");
99                                },
100                                timeouts: sys => sys.runQueuedTimeoutCallbacks(),
101                            },
102                        ],
103                        watchOrSolution: watch
104                    });
105                });
106            }
107            verifyWatch("host implements does not implement hasInvalidatedResolutions", /*implementHasInvalidatedResolution*/ false);
108            verifyWatch("host implements hasInvalidatedResolutions", /*implementHasInvalidatedResolution*/ true);
109        });
110    });
111
112    describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to watch status reporter", () => {
113        it("verify that the error count is correctly passed down to the watch status reporter", () => {
114            const config: File = {
115                path: `${projectRoot}/tsconfig.json`,
116                content: JSON.stringify({
117                    compilerOptions: { module: "commonjs" },
118                    files: ["index.ts"]
119                })
120            };
121            const mainFile: File = {
122                path: `${projectRoot}/index.ts`,
123                content: "let compiler = new Compiler(); for (let i = 0; j < 5; i++) {}"
124            };
125            const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(
126                [libFile, mainFile, config],
127                { currentDirectory: projectRoot }),
128            );
129            const host = createWatchCompilerHostOfConfigFileForBaseline({
130                configFileName: config.path,
131                system: sys,
132                cb,
133            });
134            const existing = host.onWatchStatusChange!;
135            let watchedErrorCount;
136            host.onWatchStatusChange = (diagnostic, newLine, options, errorCount) => {
137                existing.call(host, diagnostic, newLine, options, errorCount);
138                watchedErrorCount = errorCount;
139            };
140            const watch = createWatchProgram(host);
141            assert.equal(watchedErrorCount, 2, "The error count was expected to be 2 for the file change");
142            runWatchBaseline({
143                scenario: "watchApi",
144                subScenario: "verify that the error count is correctly passed down to the watch status reporter",
145                commandLineArgs: ["--w", "--p", config.path],
146                sys,
147                baseline,
148                oldSnap,
149                getPrograms,
150                changes: emptyArray,
151                watchOrSolution: watch
152            });
153        });
154    });
155
156    describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement setTimeout or clearTimeout", () => {
157        it("verifies that getProgram gets updated program if new file is added to the program", () => {
158            const config: File = {
159                path: `${projectRoot}/tsconfig.json`,
160                content: "{}"
161            };
162            const mainFile: File = {
163                path: `${projectRoot}/main.ts`,
164                content: "const x = 10;"
165            };
166            const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([config, mainFile, libFile]));
167            const host = createWatchCompilerHostOfConfigFileForBaseline({
168                configFileName: config.path,
169                system: sys,
170                cb,
171            });
172            host.setTimeout = undefined;
173            host.clearTimeout = undefined;
174            const watch = createWatchProgram(host);
175            runWatchBaseline({
176                scenario: "watchApi",
177                subScenario: "without timesouts on host program gets updated",
178                commandLineArgs: ["--w", "--p", config.path],
179                sys,
180                baseline,
181                oldSnap,
182                getPrograms,
183                changes: [{
184                    caption: "Write a file",
185                    change: sys => sys.writeFile(`${projectRoot}/bar.ts`, "const y =10;"),
186                    timeouts: sys => {
187                        sys.checkTimeoutQueueLength(0);
188                        watch.getProgram();
189                    }
190                }],
191                watchOrSolution: watch
192            });
193        });
194    });
195
196    describe("unittests:: tsc-watch:: watchAPI:: when watchHost can add extraFileExtensions to process", () => {
197        it("verifies that extraFileExtensions are supported to get the program with other extensions", () => {
198            const config: File = {
199                path: `${projectRoot}/tsconfig.json`,
200                content: "{}"
201            };
202            const mainFile: File = {
203                path: `${projectRoot}/main.ts`,
204                content: "const x = 10;"
205            };
206            const otherFile: File = {
207                path: `${projectRoot}/other.vue`,
208                content: ""
209            };
210            const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(
211                createWatchedSystem([config, mainFile, otherFile, libFile])
212            );
213            const host = createWatchCompilerHostOfConfigFileForBaseline({
214                configFileName: config.path,
215                optionsToExtend: { allowNonTsExtensions: true },
216                extraFileExtensions: [{ extension: ".vue", isMixedContent: true, scriptKind: ScriptKind.Deferred }],
217                system: sys,
218                cb,
219            });
220            const watch = createWatchProgram(host);
221            runWatchBaseline({
222                scenario: "watchApi",
223                subScenario: "extraFileExtensions are supported",
224                commandLineArgs: ["--w", "--p", config.path],
225                sys,
226                baseline,
227                oldSnap,
228                getPrograms,
229                changes: [{
230                    caption: "Write a file",
231                    change: sys => sys.writeFile(`${projectRoot}/other2.vue`, otherFile.content),
232                    timeouts: checkSingleTimeoutQueueLengthAndRun,
233                }],
234                watchOrSolution: watch
235            });
236        });
237    });
238
239    describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticDiagnosticsBuilderProgram", () => {
240        function createSystem(configText: string, mainText: string) {
241            const config: File = {
242                path: `${projectRoot}/tsconfig.json`,
243                content: configText
244            };
245            const mainFile: File = {
246                path: `${projectRoot}/main.ts`,
247                content: mainText
248            };
249            const otherFile: File = {
250                path: `${projectRoot}/other.ts`,
251                content: "export const y = 10;"
252            };
253            return {
254                ...createBaseline(createWatchedSystem([config, mainFile, otherFile, libFile])),
255                config,
256                mainFile,
257                otherFile,
258            };
259        }
260
261        function createWatch<T extends BuilderProgram>(
262            baseline: string[],
263            config: File,
264            sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
265            createProgram: CreateProgram<T>,
266            optionsToExtend?: CompilerOptions,
267        ) {
268            const { cb, getPrograms } = commandLineCallbacks(sys);
269            baseline.push(`tsc --w${optionsToExtend?.noEmit ? " --noEmit" : ""}`);
270            const oldSnap = sys.snap();
271            const host = createWatchCompilerHostOfConfigFileForBaseline<T>({
272                configFileName: config.path,
273                optionsToExtend,
274                createProgram,
275                system: sys,
276                cb,
277            });
278            const watch = createWatchProgram(host);
279            watchBaseline({
280                baseline,
281                getPrograms,
282                oldPrograms: emptyArray,
283                sys,
284                oldSnap,
285            });
286            watch.close();
287        }
288
289        function verifyOutputs(baseline: string[], sys: System, emitSys: System) {
290            baseline.push("Checking if output is same as EmitAndSemanticDiagnosticsBuilderProgram::");
291            for (const output of [`${projectRoot}/main.js`, `${projectRoot}/main.d.ts`, `${projectRoot}/other.js`, `${projectRoot}/other.d.ts`, `${projectRoot}/tsconfig.tsbuildinfo`]) {
292                baseline.push(`Output file text for ${output} is same:: ${sys.readFile(output) === emitSys.readFile(output)}`);
293            }
294            baseline.push("");
295        }
296
297        function createSystemForBuilderTest(configText: string, mainText: string) {
298            const result = createSystem(configText, mainText);
299            const { sys: emitSys, baseline: emitBaseline } = createSystem(configText, mainText);
300            return { ...result, emitSys, emitBaseline };
301        }
302
303        function applyChangeForBuilderTest(
304            baseline: string[],
305            emitBaseline: string[],
306            sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
307            emitSys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
308            change: (sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles) => void,
309            caption: string
310        ) {
311            // Change file
312            applyChange(sys, baseline, change, caption);
313            applyChange(emitSys, emitBaseline, change, caption);
314        }
315
316        function verifyBuilder<T extends BuilderProgram>(
317            baseline: string[],
318            emitBaseline: string[],
319            config: File,
320            sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
321            emitSys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
322            createProgram: CreateProgram<T>,
323            optionsToExtend?: CompilerOptions) {
324            createWatch(baseline, config, sys, createProgram, optionsToExtend);
325            createWatch(emitBaseline, config, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, optionsToExtend);
326            verifyOutputs(baseline, sys, emitSys);
327        }
328
329        it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => {
330            const { sys, baseline, oldSnap, cb, getPrograms, config, mainFile } = createSystem("{}", "export const x = 10;");
331            const host = createWatchCompilerHostOfConfigFileForBaseline({
332                configFileName: config.path,
333                optionsToExtend: { noEmit: true },
334                createProgram: createSemanticDiagnosticsBuilderProgram,
335                system: sys,
336                cb,
337            });
338            const watch = createWatchProgram(host);
339            runWatchBaseline({
340                scenario: "watchApi",
341                subScenario: "verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram",
342                commandLineArgs: ["--w", "--p", config.path],
343                sys,
344                baseline,
345                oldSnap,
346                getPrograms,
347                changes: [{
348                    caption: "Modify a file",
349                    change: sys => sys.appendFile(mainFile.path, "\n// SomeComment"),
350                    timeouts: runQueuedTimeoutCallbacks,
351                }],
352                watchOrSolution: watch
353            });
354        });
355
356        describe("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
357            let baseline: string[];
358            let emitBaseline: string[];
359            before(() => {
360                const configText = JSON.stringify({ compilerOptions: { composite: true } });
361                const mainText = "export const x = 10;";
362                const result = createSystemForBuilderTest(configText, mainText);
363                baseline = result.baseline;
364                emitBaseline = result.emitBaseline;
365                const { sys, config, mainFile, emitSys } = result;
366
367                // No Emit
368                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true });
369
370                // Emit on both sys should result in same output
371                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram);
372
373                // Change file
374                applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment");
375
376                // Verify noEmit results in same output
377                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, { noEmit: true });
378
379                // Emit on both sys should result in same output
380                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram);
381
382                // Change file
383                applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment");
384
385                // Emit on both the builders should result in same files
386                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
387            });
388            after(() => {
389                baseline = undefined!;
390                emitBaseline = undefined!;
391            });
392            it("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
393                Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-semantic-builder.js`, baseline.join("\r\n"));
394            });
395            it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
396                Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n"));
397            });
398        });
399
400        describe("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
401            let baseline: string[];
402            let emitBaseline: string[];
403            before(() => {
404                const configText = JSON.stringify({ compilerOptions: { composite: true, noEmitOnError: true } });
405                const mainText = "export const x: string = 10;";
406                const result = createSystemForBuilderTest(configText, mainText);
407                baseline = result.baseline;
408                emitBaseline = result.emitBaseline;
409                const { sys, config, mainFile, emitSys } = result;
410
411                // Verify noEmit results in same output
412                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
413
414                // Change file
415                applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment");
416
417                // Verify noEmit results in same output
418                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
419
420                // Fix error
421                const fixed = "export const x = 10;";
422                applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.writeFile(mainFile.path, fixed), "Fix error");
423
424                // Emit on both the builders should result in same files
425                verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
426            });
427
428            it("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
429                Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-semantic-builder.js`, baseline.join("\r\n"));
430            });
431            it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
432                Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n"));
433            });
434        });
435
436        it("SemanticDiagnosticsBuilderProgram emitDtsOnly does not update affected files pending emit", () => {
437            // Initial
438            const { sys, baseline, config, mainFile } = createSystem(JSON.stringify({ compilerOptions: { composite: true, noEmitOnError: true } }), "export const x: string = 10;");
439            createWatch(baseline, config, sys, createSemanticDiagnosticsBuilderProgram);
440
441            // Fix error and emit
442            applyChange(sys, baseline, sys => sys.writeFile(mainFile.path, "export const x = 10;"), "Fix error");
443
444            const { cb, getPrograms } = commandLineCallbacks(sys);
445            const oldSnap = sys.snap();
446            const reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true);
447            const reportWatchStatus = createWatchStatusReporter(sys, /*pretty*/ true);
448            const host = createWatchCompilerHostOfConfigFile({
449                configFileName: config.path,
450                createProgram: createSemanticDiagnosticsBuilderProgram,
451                system: sys,
452                reportDiagnostic,
453                reportWatchStatus,
454            });
455            host.afterProgramCreate = program => {
456                const diagnostics = sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics());
457                diagnostics.forEach(reportDiagnostic);
458                // Buildinfo should still have affectedFilesPendingEmit since we are only emitting dts files
459                program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDts*/ true);
460                reportWatchStatus(
461                    createCompilerDiagnostic(getWatchErrorSummaryDiagnosticMessage(diagnostics.length), diagnostics.length),
462                    sys.newLine,
463                    program.getCompilerOptions(),
464                    diagnostics.length
465                );
466                cb(program);
467            };
468            createWatchProgram(host);
469            watchBaseline({
470                baseline,
471                getPrograms,
472                oldPrograms: emptyArray,
473                sys,
474                oldSnap,
475            });
476            Harness.Baseline.runBaseline(`tscWatch/watchApi/semantic-builder-emitOnlyDts.js`, baseline.join("\r\n"));
477        });
478    });
479
480    describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implemented", () => {
481        function setup(useSourceOfProjectReferenceRedirect?: () => boolean) {
482            const config1: File = {
483                path: `${projectRoot}/projects/project1/tsconfig.json`,
484                content: JSON.stringify({
485                    compilerOptions: {
486                        module: "none",
487                        composite: true
488                    },
489                    exclude: ["temp"]
490                })
491            };
492            const class1: File = {
493                path: `${projectRoot}/projects/project1/class1.ts`,
494                content: `class class1 {}`
495            };
496            const class1Dts: File = {
497                path: `${projectRoot}/projects/project1/class1.d.ts`,
498                content: `declare class class1 {}`
499            };
500            const config2: File = {
501                path: `${projectRoot}/projects/project2/tsconfig.json`,
502                content: JSON.stringify({
503                    compilerOptions: {
504                        module: "none",
505                        composite: true
506                    },
507                    references: [
508                        { path: "../project1" }
509                    ]
510                })
511            };
512            const class2: File = {
513                path: `${projectRoot}/projects/project2/class2.ts`,
514                content: `class class2 {}`
515            };
516            const system = createWatchedSystem([config1, class1, class1Dts, config2, class2, libFile]);
517            const baseline = createBaseline(system);
518            const compilerHost = createWatchCompilerHostOfConfigFileForBaseline({
519                cb: baseline.cb,
520                system,
521                configFileName: config2.path,
522                optionsToExtend: { extendedDiagnostics: true }
523            });
524            compilerHost.useSourceOfProjectReferenceRedirect = useSourceOfProjectReferenceRedirect;
525            const calledGetParsedCommandLine = new Set<string>();
526            compilerHost.getParsedCommandLine = fileName => {
527                assert.isFalse(calledGetParsedCommandLine.has(fileName), `Already called on ${fileName}`);
528                calledGetParsedCommandLine.add(fileName);
529                return getParsedCommandLineOfConfigFile(fileName, /*optionsToExtend*/ undefined, {
530                    useCaseSensitiveFileNames: true,
531                    fileExists: path => system.fileExists(path),
532                    readFile: path => system.readFile(path),
533                    getCurrentDirectory: () => system.getCurrentDirectory(),
534                    readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth),
535                    onUnRecoverableConfigFileDiagnostic: noop,
536                });
537            };
538            const watch = createWatchProgram(compilerHost);
539            return { watch, baseline, config2, calledGetParsedCommandLine };
540        }
541
542        it("when new file is added to the referenced project with host implementing getParsedCommandLine", () => {
543            const { watch, baseline, config2, calledGetParsedCommandLine } = setup(returnTrue);
544            runWatchBaseline({
545                scenario: "watchApi",
546                subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine",
547                commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"],
548                ...baseline,
549                changes: [
550                    {
551                        caption: "Add class3 to project1",
552                        change: sys => {
553                            calledGetParsedCommandLine.clear();
554                            sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`);
555                        },
556                        timeouts: checkSingleTimeoutQueueLengthAndRun,
557                    },
558                    {
559                        caption: "Add excluded file to project1",
560                        change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }),
561                        timeouts: sys => sys.checkTimeoutQueueLength(0),
562                    },
563                    {
564                        caption: "Add output of class3",
565                        change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`),
566                        timeouts: sys => sys.checkTimeoutQueueLength(0),
567                    },
568                ],
569                watchOrSolution: watch
570            });
571        });
572
573        it("when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", () => {
574            const { watch, baseline, config2, calledGetParsedCommandLine } = setup();
575            runWatchBaseline({
576                scenario: "watchApi",
577                subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect",
578                commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"],
579                ...baseline,
580                changes: [
581                    {
582                        caption: "Add class3 to project1",
583                        change: sys => {
584                            calledGetParsedCommandLine.clear();
585                            sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`);
586                        },
587                        timeouts: checkSingleTimeoutQueueLengthAndRun,
588                    },
589                    {
590                        caption: "Add class3 output to project1",
591                        change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`),
592                        timeouts: checkSingleTimeoutQueueLengthAndRun,
593                    },
594                    {
595                        caption: "Add excluded file to project1",
596                        change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }),
597                        timeouts: sys => sys.checkTimeoutQueueLength(0),
598                    },
599                    {
600                        caption: "Delete output of class3",
601                        change: sys => sys.deleteFile(`${projectRoot}/projects/project1/class3.d.ts`),
602                        timeouts: checkSingleTimeoutQueueLengthAndRun,
603                    },
604                    {
605                        caption: "Add output of class3",
606                        change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`),
607                        timeouts: checkSingleTimeoutQueueLengthAndRun,
608                    },
609                ],
610                watchOrSolution: watch
611            });
612        });
613    });
614}
615