From e133b0876c3873a3da5eec695eb9d11f3444b96b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 23 Mar 2023 11:55:32 -0700 Subject: [PATCH 1/2] Add failing test --- src/testRunner/unittests/tscWatch/watchApi.ts | 104 +++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index c7c80c1daf280..8e6c86af257cf 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -1,6 +1,7 @@ import * as Harness from "../../_namespaces/Harness"; import * as ts from "../../_namespaces/ts"; -import { commandLineCallbacks } from "../tsc/helpers"; +import { dedent } from "../../_namespaces/Utils"; +import { commandLineCallbacks, libContent } from "../tsc/helpers"; import { createWatchedSystem, File, @@ -11,6 +12,7 @@ import { applyEdit, createBaseline, createWatchCompilerHostOfConfigFileForBaseline, + createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline, runWatchBaseline, watchBaseline, } from "./helpers"; @@ -718,3 +720,103 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO verify("when emitting with emitOnlyDtsFiles"); verify("when emitting with emitOnlyDtsFiles with outFile", "outFile.js"); }); + +describe("unittests:: tsc-watch:: watchAPI:: when creating program with project references but not config file", () => { + function setup(libExtends: boolean) { + const system = createWatchedSystem({ + "/user/username/projects/project/tsconfig.json": JSON.stringify({ + compilerOptions: { types: [] }, + files: ["app.ts"], + references: [{ path: "./lib" }] + }), + "/user/username/projects/project/app.ts": dedent` + import { one } from './lib'; + console.log(one); + `, + "/user/username/projects/project/lib/tsconfig.json": JSON.stringify({ + extends: libExtends ? "./tsconfig.base.json" : undefined, + compilerOptions: libExtends ? undefined : { composite: true, types: [] }, + files: ["index.ts"], + }), + "/user/username/projects/project/lib/tsconfig.base.json": JSON.stringify({ + compilerOptions: { composite: true, types: [] }, + }), + "/user/username/projects/project/lib/index.ts": "export const one = 1;", + "/user/username/projects/project/lib/index.d.ts": "export const one = 1;", + [libFile.path]: libContent, + }); + const baseline = createBaseline(system); + const commandLine = ts.getParsedCommandLineOfConfigFile( + "/user/username/projects/project/tsconfig.json", + { extendedDiagnostics: true }, + { + useCaseSensitiveFileNames: true, + fileExists: path => system.fileExists(path), + readFile: path => system.readFile(path), + getCurrentDirectory: () => system.getCurrentDirectory(), + readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + onUnRecoverableConfigFileDiagnostic: ts.noop, + } + )!; + const compilerHost = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + cb: baseline.cb, + system, + rootFiles: commandLine.fileNames, + options: commandLine.options, + projectReferences: commandLine.projectReferences, + watchOptions: commandLine.watchOptions, + }); + const watch = ts.createWatchProgram(compilerHost); + return { watch, baseline }; + } + + it("when watching referenced project when there is no config file name", () => { + const { watch, baseline } = setup(/*libExtends*/ false); + runWatchBaseline({ + scenario: "watchApi", + subScenario: "when watching referenced project when there is no config file name", + commandLineArgs: ["--w", "-p", ".", "--extendedDiagnostics"], + ...baseline, + edits: [ + { + caption: "Modify lib tsconfig", + edit: sys => sys.writeFile(`/user/username/projects/project/lib/tsconfig.json`, JSON.stringify({ + compilerOptions: { composite: true }, + files: ["index.ts"], + })), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + ], + watchOrSolution: watch + }); + }); + + it("when watching referenced project with extends when there is no config file name", () => { + const { watch, baseline } = setup(/*libExtends*/ true); + runWatchBaseline({ + scenario: "watchApi", + subScenario: "when watching referenced project with extends when there is no config file name", + commandLineArgs: ["--w", "-p", ".", "--extendedDiagnostics"], + ...baseline, + edits: [ + { + caption: "Modify lib tsconfig", + edit: sys => sys.writeFile(`/user/username/projects/project/lib/tsconfig.json`, JSON.stringify({ + extends: "./tsconfig.base.json", + compilerOptions: { typeRoots: [] }, + files: ["index.ts"], + })), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + { + caption: "Modify lib extends", + edit: sys => sys.writeFile(`/user/username/projects/project/lib/tsconfig.base.json`, JSON.stringify({ + compilerOptions: { composite: true }, + })), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + ], + watchOrSolution: watch + }); + }); +}); From fadd86263a19a4dcb65ca0a458241bc9e3b8f00f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 23 Mar 2023 12:15:38 -0700 Subject: [PATCH 2/2] Fix incorrect assert --- src/compiler/watchPublic.ts | 3 +- ...oject-when-there-is-no-config-file-name.js | 139 ++++++++++++++ ...tends-when-there-is-no-config-file-name.js | 180 ++++++++++++++++++ 3 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-when-there-is-no-config-file-name.js create mode 100644 tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-with-extends-when-there-is-no-config-file-name.js diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index 5227073fe8d29..de98d499b7db6 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -1088,7 +1088,6 @@ export function createWatchProgram(host: WatchCompiler } function updateExtendedConfigFilesWatches(forProjectPath: Path, options: CompilerOptions | undefined, watchOptions: WatchOptions | undefined, watchType: WatchTypeRegistry["ExtendedConfigFile"] | WatchTypeRegistry["ExtendedConfigOfReferencedProject"]) { - Debug.assert(configFileName); updateSharedExtendedConfigFileWatcher( forProjectPath, options, @@ -1104,7 +1103,7 @@ export function createWatchProgram(host: WatchCompiler // If there are no referenced projects this extended config file watcher depend on ignore if (!projects?.size) return; projects.forEach(projectPath => { - if (toPath(configFileName) === projectPath) { + if (configFileName && toPath(configFileName) === projectPath) { // If this is the config file of the project, reload completely reloadLevel = ConfigFileProgramReloadLevel.Full; } diff --git a/tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-when-there-is-no-config-file-name.js b/tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-when-there-is-no-config-file-name.js new file mode 100644 index 0000000000000..86908451f4445 --- /dev/null +++ b/tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-when-there-is-no-config-file-name.js @@ -0,0 +1,139 @@ +Input:: +//// [/user/username/projects/project/tsconfig.json] +{"compilerOptions":{"types":[]},"files":["app.ts"],"references":[{"path":"./lib"}]} + +//// [/user/username/projects/project/app.ts] +import { one } from './lib'; +console.log(one); + + +//// [/user/username/projects/project/lib/tsconfig.json] +{"compilerOptions":{"composite":true,"types":[]},"files":["index.ts"]} + +//// [/user/username/projects/project/lib/tsconfig.base.json] +{"compilerOptions":{"composite":true,"types":[]}} + +//// [/user/username/projects/project/lib/index.ts] +export const one = 1; + +//// [/user/username/projects/project/lib/index.d.ts] +export const one = 1; + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + + +/a/lib/tsc.js --w -p . --extendedDiagnostics +Output:: +[12:00:31 AM] Starting compilation in watch mode... + +Current directory: / CaseSensitiveFileNames: false +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/project/app.ts"] + options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/project/lib","originalPath":"./lib"}] +Loading config file: /user/username/projects/project/lib/tsconfig.json +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/lib/tsconfig.json 2000 undefined Config file of referened project +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/app.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user 1 undefined Failed Lookup Locations +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user 1 undefined Failed Lookup Locations +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/lib/index.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Triggered with /user/username/projects/project/app.js :: WatchInfo: /user 1 undefined Failed Lookup Locations +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/project/app.js :: WatchInfo: /user 1 undefined Failed Lookup Locations +[12:00:34 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/project/app.ts"] +Program options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Shape signatures in builder refreshed for:: +/a/lib/lib.d.ts (used version) +/user/username/projects/project/lib/index.d.ts (used version) +/user/username/projects/project/app.ts (used version) + +FsWatches:: +/user/username/projects/project/lib/tsconfig.json: *new* + {} +/user/username/projects/project/app.ts: *new* + {} +/user/username/projects/project/lib/index.d.ts: *new* + {} +/a/lib/lib.d.ts: *new* + {} + +FsWatchesRecursive:: +/user: *new* + {} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/project/app.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var lib_1 = require("./lib"); +console.log(lib_1.one); + + + +Change:: Modify lib tsconfig + +Input:: +//// [/user/username/projects/project/lib/tsconfig.json] +{"compilerOptions":{"composite":true},"files":["index.ts"]} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/project/lib/tsconfig.json 1:: WatchInfo: /user/username/projects/project/lib/tsconfig.json 2000 undefined Config file of referened project +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/project/lib/tsconfig.json 1:: WatchInfo: /user/username/projects/project/lib/tsconfig.json 2000 undefined Config file of referened project +Synchronizing program +Loading config file: /user/username/projects/project/lib/tsconfig.json +[12:00:38 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/project/app.ts"] + options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/project/lib","originalPath":"./lib"}] +[12:00:39 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/project/app.ts"] +Program options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Semantic diagnostics in builder refreshed for:: + +No shapes updated in the builder:: + +exitCode:: ExitStatus.undefined + diff --git a/tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-with-extends-when-there-is-no-config-file-name.js b/tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-with-extends-when-there-is-no-config-file-name.js new file mode 100644 index 0000000000000..5922ff6df2970 --- /dev/null +++ b/tests/baselines/reference/tscWatch/watchApi/when-watching-referenced-project-with-extends-when-there-is-no-config-file-name.js @@ -0,0 +1,180 @@ +Input:: +//// [/user/username/projects/project/tsconfig.json] +{"compilerOptions":{"types":[]},"files":["app.ts"],"references":[{"path":"./lib"}]} + +//// [/user/username/projects/project/app.ts] +import { one } from './lib'; +console.log(one); + + +//// [/user/username/projects/project/lib/tsconfig.json] +{"extends":"./tsconfig.base.json","files":["index.ts"]} + +//// [/user/username/projects/project/lib/tsconfig.base.json] +{"compilerOptions":{"composite":true,"types":[]}} + +//// [/user/username/projects/project/lib/index.ts] +export const one = 1; + +//// [/user/username/projects/project/lib/index.d.ts] +export const one = 1; + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + + +/a/lib/tsc.js --w -p . --extendedDiagnostics +Output:: +[12:00:31 AM] Starting compilation in watch mode... + +Current directory: / CaseSensitiveFileNames: false +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/project/app.ts"] + options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/project/lib","originalPath":"./lib"}] +Loading config file: /user/username/projects/project/lib/tsconfig.json +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/lib/tsconfig.json 2000 undefined Config file of referened project +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/lib/tsconfig.base.json 2000 undefined Extended config file of referenced project +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/app.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user 1 undefined Failed Lookup Locations +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user 1 undefined Failed Lookup Locations +FileWatcher:: Added:: WatchInfo: /user/username/projects/project/lib/index.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Triggered with /user/username/projects/project/app.js :: WatchInfo: /user 1 undefined Failed Lookup Locations +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/project/app.js :: WatchInfo: /user 1 undefined Failed Lookup Locations +[12:00:34 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/project/app.ts"] +Program options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Shape signatures in builder refreshed for:: +/a/lib/lib.d.ts (used version) +/user/username/projects/project/lib/index.d.ts (used version) +/user/username/projects/project/app.ts (used version) + +FsWatches:: +/user/username/projects/project/lib/tsconfig.json: *new* + {} +/user/username/projects/project/lib/tsconfig.base.json: *new* + {} +/user/username/projects/project/app.ts: *new* + {} +/user/username/projects/project/lib/index.d.ts: *new* + {} +/a/lib/lib.d.ts: *new* + {} + +FsWatchesRecursive:: +/user: *new* + {} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/project/app.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var lib_1 = require("./lib"); +console.log(lib_1.one); + + + +Change:: Modify lib tsconfig + +Input:: +//// [/user/username/projects/project/lib/tsconfig.json] +{"extends":"./tsconfig.base.json","compilerOptions":{"typeRoots":[]},"files":["index.ts"]} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/project/lib/tsconfig.json 1:: WatchInfo: /user/username/projects/project/lib/tsconfig.json 2000 undefined Config file of referened project +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/project/lib/tsconfig.json 1:: WatchInfo: /user/username/projects/project/lib/tsconfig.json 2000 undefined Config file of referened project +Synchronizing program +Loading config file: /user/username/projects/project/lib/tsconfig.json +[12:00:38 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/project/app.ts"] + options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/project/lib","originalPath":"./lib"}] +[12:00:39 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/project/app.ts"] +Program options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Semantic diagnostics in builder refreshed for:: + +No shapes updated in the builder:: + +exitCode:: ExitStatus.undefined + + +Change:: Modify lib extends + +Input:: +//// [/user/username/projects/project/lib/tsconfig.base.json] +{"compilerOptions":{"composite":true}} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/project/lib/tsconfig.base.json 1:: WatchInfo: /user/username/projects/project/lib/tsconfig.base.json 2000 undefined Extended config file of referenced project +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/project/lib/tsconfig.base.json 1:: WatchInfo: /user/username/projects/project/lib/tsconfig.base.json 2000 undefined Extended config file of referenced project +Synchronizing program +Loading config file: /user/username/projects/project/lib/tsconfig.json +[12:00:43 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/project/app.ts"] + options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/project/lib","originalPath":"./lib"}] +[12:00:44 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/project/app.ts"] +Program options: {"types":[],"extendedDiagnostics":true,"configFilePath":"/user/username/projects/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/project/lib/index.d.ts +/user/username/projects/project/app.ts + +Semantic diagnostics in builder refreshed for:: + +No shapes updated in the builder:: + +exitCode:: ExitStatus.undefined +