From a455955aac85ecc5b2182fe50b83670188955feb Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 22 Sep 2022 16:51:53 -0700 Subject: [PATCH] Make hasInvalidatedResolution non internal for program and add it watchApi (#50776) * Make stub for hasInvalidatedResolution * Wire through hasInvalidatedResolutions Fixes #48057 * Update comment * Feedback --- src/compiler/resolutionCache.ts | 12 +- src/compiler/types.ts | 3 +- src/compiler/watchPublic.ts | 9 +- src/server/project.ts | 2 +- src/testRunner/unittests/tscWatch/watchApi.ts | 91 ++++-- .../reference/api/tsserverlibrary.d.ts | 4 + tests/baselines/reference/api/typescript.d.ts | 4 + ...-not-implement-hasInvalidatedResolution.js | 287 ++++++++++++++++++ ...ost-implements-hasInvalidatedResolution.js | 273 +++++++++++++++++ 9 files changed, 656 insertions(+), 29 deletions(-) create mode 100644 tests/baselines/reference/tscWatch/watchApi/host-implements-does-not-implement-hasInvalidatedResolution.js create mode 100644 tests/baselines/reference/tscWatch/watchApi/host-implements-hasInvalidatedResolution.js diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 46130e35659f9..27b863a3abf3c 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -14,7 +14,7 @@ namespace ts { removeResolutionsOfFile(filePath: Path): void; removeResolutionsFromProjectReferenceRedirects(filePath: Path): void; setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: ESMap): void; - createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution; + createHasInvalidatedResolution(customHasInvalidatedResolution: HasInvalidatedResolution): HasInvalidatedResolution; hasChangedAutomaticTypeDirectiveNames(): boolean; isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean; @@ -300,17 +300,13 @@ namespace ts { return !!value && !!value.length; } - function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution { + function createHasInvalidatedResolution(customHasInvalidatedResolution: HasInvalidatedResolution): HasInvalidatedResolution { // Ensure pending resolutions are applied invalidateResolutionsOfFailedLookupLocations(); - if (forceAllFilesAsInvalidated) { - // Any file asked would have invalidated resolution - filesWithInvalidatedResolutions = undefined; - return returnTrue; - } const collected = filesWithInvalidatedResolutions; filesWithInvalidatedResolutions = undefined; - return path => (!!collected && collected.has(path)) || + return path => customHasInvalidatedResolution(path) || + !!collected?.has(path) || isFileWithInvalidatedNonRelativeUnresolvedImports(path); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1753770f44ce4..f63c1f21078bc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7215,7 +7215,8 @@ namespace ts { getEnvironmentVariable?(name: string): string | undefined; /* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void; /* @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void; - /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; + /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ + hasInvalidatedResolution?(filePath: Path): boolean; /* @internal */ hasChangedAutomaticTypeDirectiveNames?: HasChangedAutomaticTypeDirectiveNames; createHash?(data: string): string; getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index 51f58d396c59c..788a8856f3a58 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -112,6 +112,8 @@ namespace ts { resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined): (ResolvedTypeReferenceDirective | undefined)[]; + /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ + hasInvalidatedResolution?(filePath: Path): boolean; /** * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ @@ -371,6 +373,10 @@ namespace ts { maybeBind(host, host.getModuleResolutionCache) : (() => resolutionCache.getModuleResolutionCache()); const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives; + // All resolutions are invalid if user provided resolutions and didnt supply hasInvalidatedResolution + const customHasInvalidatedResolution = userProvidedResolution ? + maybeBind(host, host.hasInvalidatedResolution) || returnTrue : + returnFalse; builderProgram = readBuilderProgram(compilerOptions, compilerHost) as any as T; synchronizeProgram(); @@ -443,8 +449,7 @@ namespace ts { } } - // All resolutions are invalid if user provided resolutions - const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution); + const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(customHasInvalidatedResolution); const { originalReadFile, originalFileExists, originalDirectoryExists, originalCreateDirectory, originalWriteFile, diff --git a/src/server/project.ts b/src/server/project.ts index 43b1c7128e005..8a45bab06057f 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1176,7 +1176,7 @@ namespace ts.server { Debug.assert(!this.isClosed(), "Called update graph worker of closed project"); this.writeLog(`Starting updateGraphWorker: Project: ${this.getProjectName()}`); const start = timestamp(); - this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution(); + this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution(returnFalse); this.resolutionCache.startCachingPerDirectoryResolution(); this.program = this.languageService.getProgram(); // TODO: GH#18217 this.dirty = false; diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index 477a982eafde2..cfcbc115a69f4 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -1,23 +1,22 @@ namespace ts.tscWatch { describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolution", () => { - const configFileJson: any = { - compilerOptions: { module: "commonjs", resolveJsonModule: true }, - files: ["index.ts"] - }; - const mainFile: File = { - path: `${projectRoot}/index.ts`, - content: "import settings from './settings.json';" - }; - const config: File = { - path: `${projectRoot}/tsconfig.json`, - content: JSON.stringify(configFileJson) - }; - const settingsJson: File = { - path: `${projectRoot}/settings.json`, - content: JSON.stringify({ content: "Print this" }) - }; - it("verify that module resolution with json extension works when returned without extension", () => { + const configFileJson: any = { + compilerOptions: { module: "commonjs", resolveJsonModule: true }, + files: ["index.ts"] + }; + const mainFile: File = { + path: `${projectRoot}/index.ts`, + content: "import settings from './settings.json';" + }; + const config: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify(configFileJson) + }; + const settingsJson: File = { + path: `${projectRoot}/settings.json`, + content: JSON.stringify({ content: "Print this" }) + }; const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem( [libFile, mainFile, config, settingsJson], { currentDirectory: projectRoot }), @@ -50,6 +49,64 @@ namespace ts.tscWatch { watchOrSolution: watch }); }); + + describe("hasInvalidatedResolution", () => { + function verifyWatch(subScenario: string, implementHasInvalidatedResolution: boolean) { + it(subScenario, () => { + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem({ + [`${projectRoot}/tsconfig.json`]: JSON.stringify({ + compilerOptions: { traceResolution: true, extendedDiagnostics: true }, + files: ["main.ts"] + }), + [`${projectRoot}/main.ts`]: `import { foo } from "./other";`, + [`${projectRoot}/other.d.ts`]: "export function foo(): void;", + [libFile.path]: libFile.content, + }, { currentDirectory: projectRoot })); + const host = createWatchCompilerHostOfConfigFileForBaseline({ + configFileName: `${projectRoot}/tsconfig.json`, + system: sys, + cb, + }); + host.resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference, options) => + moduleNames.map(m => resolveModuleName(m, containingFile, options, host).resolvedModule); + // Invalidate resolutions only when ts file is created + if (implementHasInvalidatedResolution) host.hasInvalidatedResolution = () => sys.fileExists(`${projectRoot}/other.ts`); + const watch = createWatchProgram(host); + runWatchBaseline({ + scenario: "watchApi", + subScenario, + commandLineArgs: ["--w"], + sys, + baseline, + oldSnap, + getPrograms, + changes: [ + { + caption: "write other with same contents", + change: sys => sys.appendFile(`${projectRoot}/other.d.ts`, ""), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + { + caption: "change other file", + change: sys => sys.appendFile(`${projectRoot}/other.d.ts`, "export function bar(): void;"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + { + caption: "write other with same contents but write ts file", + change: sys => { + sys.appendFile(`${projectRoot}/other.d.ts`, ""); + sys.writeFile(`${projectRoot}/other.ts`, "export function foo() {}"); + }, + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + ], + watchOrSolution: watch + }); + }); + } + verifyWatch("host implements does not implement hasInvalidatedResolution", /*implementHasInvalidatedResolution*/ false); + verifyWatch("host implements hasInvalidatedResolution", /*implementHasInvalidatedResolution*/ true); + }); }); describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to watch status reporter", () => { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 50fbd1d4dea72..7b3d74e82987d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3320,6 +3320,8 @@ declare namespace ts { */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined): (ResolvedTypeReferenceDirective | undefined)[]; getEnvironmentVariable?(name: string): string | undefined; + /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ + hasInvalidatedResolution?(filePath: Path): boolean; createHash?(data: string): string; getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; } @@ -5442,6 +5444,8 @@ declare namespace ts { resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined): (ResolvedTypeReferenceDirective | undefined)[]; + /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ + hasInvalidatedResolution?(filePath: Path): boolean; /** * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index d323d77c229dd..d65d6e1054086 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3320,6 +3320,8 @@ declare namespace ts { */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined): (ResolvedTypeReferenceDirective | undefined)[]; getEnvironmentVariable?(name: string): string | undefined; + /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ + hasInvalidatedResolution?(filePath: Path): boolean; createHash?(data: string): string; getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; } @@ -5442,6 +5444,8 @@ declare namespace ts { resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined): (ResolvedTypeReferenceDirective | undefined)[]; + /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ + hasInvalidatedResolution?(filePath: Path): boolean; /** * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ diff --git a/tests/baselines/reference/tscWatch/watchApi/host-implements-does-not-implement-hasInvalidatedResolution.js b/tests/baselines/reference/tscWatch/watchApi/host-implements-does-not-implement-hasInvalidatedResolution.js new file mode 100644 index 0000000000000..b18d7b8972d77 --- /dev/null +++ b/tests/baselines/reference/tscWatch/watchApi/host-implements-does-not-implement-hasInvalidatedResolution.js @@ -0,0 +1,287 @@ +Input:: +//// [/user/username/projects/myproject/tsconfig.json] +{"compilerOptions":{"traceResolution":true,"extendedDiagnostics":true},"files":["main.ts"]} + +//// [/user/username/projects/myproject/main.ts] +import { foo } from "./other"; + +//// [/user/username/projects/myproject/other.d.ts] +export function foo(): void; + +//// [/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; } + + +/a/lib/tsc.js --w +Output:: +>> Screen clear +[12:00:23 AM] Starting compilation in watch mode... + +Current directory: /user/username/projects/myproject CaseSensitiveFileNames: false +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/main.ts 250 undefined Source file +======== Resolving module './other' from '/user/username/projects/myproject/main.ts'. ======== +Module resolution kind is not specified, using 'NodeJs'. +Loading module as file / folder, candidate module location '/user/username/projects/myproject/other', target file type 'TypeScript'. +File '/user/username/projects/myproject/other.ts' does not exist. +File '/user/username/projects/myproject/other.tsx' does not exist. +File '/user/username/projects/myproject/other.d.ts' exist - use it as a name resolution result. +======== Module name './other' was successfully resolved to '/user/username/projects/myproject/other.d.ts'. ======== +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +[12:00:26 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/a/lib/lib.d.ts (used version) +/user/username/projects/myproject/other.d.ts (used version) +/user/username/projects/myproject/main.ts (used version) + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/main.js] +"use strict"; +exports.__esModule = true; + + + +Change:: write other with same contents + +Input:: +//// [/user/username/projects/myproject/other.d.ts] file changed its modified time + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Synchronizing program +[12:00:29 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +======== Resolving module './other' from '/user/username/projects/myproject/main.ts'. ======== +Module resolution kind is not specified, using 'NodeJs'. +Loading module as file / folder, candidate module location '/user/username/projects/myproject/other', target file type 'TypeScript'. +File '/user/username/projects/myproject/other.ts' does not exist. +File '/user/username/projects/myproject/other.tsx' does not exist. +File '/user/username/projects/myproject/other.d.ts' exist - use it as a name resolution result. +======== Module name './other' was successfully resolved to '/user/username/projects/myproject/other.d.ts'. ======== +[12:00:30 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: SafeModules +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: + +No shapes updated in the builder:: + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + + +Change:: change other file + +Input:: +//// [/user/username/projects/myproject/other.d.ts] +export function foo(): void;export function bar(): void; + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Synchronizing program +[12:00:33 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +======== Resolving module './other' from '/user/username/projects/myproject/main.ts'. ======== +Module resolution kind is not specified, using 'NodeJs'. +Loading module as file / folder, candidate module location '/user/username/projects/myproject/other', target file type 'TypeScript'. +File '/user/username/projects/myproject/other.ts' does not exist. +File '/user/username/projects/myproject/other.tsx' does not exist. +File '/user/username/projects/myproject/other.d.ts' exist - use it as a name resolution result. +======== Module name './other' was successfully resolved to '/user/username/projects/myproject/other.d.ts'. ======== +[12:00:37 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: SafeModules +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/user/username/projects/myproject/other.d.ts (used version) +/user/username/projects/myproject/main.ts (computed .d.ts) + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/main.js] file written with same contents + +Change:: write other with same contents but write ts file + +Input:: +//// [/user/username/projects/myproject/other.d.ts] file changed its modified time +//// [/user/username/projects/myproject/other.ts] +export function foo() {} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Synchronizing program +[12:00:42 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +======== Resolving module './other' from '/user/username/projects/myproject/main.ts'. ======== +Module resolution kind is not specified, using 'NodeJs'. +Loading module as file / folder, candidate module location '/user/username/projects/myproject/other', target file type 'TypeScript'. +File '/user/username/projects/myproject/other.ts' exist - use it as a name resolution result. +======== Module name './other' was successfully resolved to '/user/username/projects/myproject/other.ts'. ======== +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/other.ts 250 undefined Source file +[12:00:48 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: SafeModules +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/other.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/user/username/projects/myproject/other.ts (computed .d.ts) +/user/username/projects/myproject/main.ts (computed .d.ts) + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} +/user/username/projects/myproject/other.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/main.js] file written with same contents +//// [/user/username/projects/myproject/other.js] +"use strict"; +exports.__esModule = true; +exports.foo = void 0; +function foo() { } +exports.foo = foo; + + diff --git a/tests/baselines/reference/tscWatch/watchApi/host-implements-hasInvalidatedResolution.js b/tests/baselines/reference/tscWatch/watchApi/host-implements-hasInvalidatedResolution.js new file mode 100644 index 0000000000000..71dac5e657e1b --- /dev/null +++ b/tests/baselines/reference/tscWatch/watchApi/host-implements-hasInvalidatedResolution.js @@ -0,0 +1,273 @@ +Input:: +//// [/user/username/projects/myproject/tsconfig.json] +{"compilerOptions":{"traceResolution":true,"extendedDiagnostics":true},"files":["main.ts"]} + +//// [/user/username/projects/myproject/main.ts] +import { foo } from "./other"; + +//// [/user/username/projects/myproject/other.d.ts] +export function foo(): void; + +//// [/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; } + + +/a/lib/tsc.js --w +Output:: +>> Screen clear +[12:00:23 AM] Starting compilation in watch mode... + +Current directory: /user/username/projects/myproject CaseSensitiveFileNames: false +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Config file +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/main.ts 250 undefined Source file +======== Resolving module './other' from '/user/username/projects/myproject/main.ts'. ======== +Module resolution kind is not specified, using 'NodeJs'. +Loading module as file / folder, candidate module location '/user/username/projects/myproject/other', target file type 'TypeScript'. +File '/user/username/projects/myproject/other.ts' does not exist. +File '/user/username/projects/myproject/other.tsx' does not exist. +File '/user/username/projects/myproject/other.d.ts' exist - use it as a name resolution result. +======== Module name './other' was successfully resolved to '/user/username/projects/myproject/other.d.ts'. ======== +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +[12:00:26 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/a/lib/lib.d.ts (used version) +/user/username/projects/myproject/other.d.ts (used version) +/user/username/projects/myproject/main.ts (used version) + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/main.js] +"use strict"; +exports.__esModule = true; + + + +Change:: write other with same contents + +Input:: +//// [/user/username/projects/myproject/other.d.ts] file changed its modified time + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Synchronizing program +[12:00:29 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +[12:00:30 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: Completely +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: + +No shapes updated in the builder:: + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + + +Change:: change other file + +Input:: +//// [/user/username/projects/myproject/other.d.ts] +export function foo(): void;export function bar(): void; + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Synchronizing program +[12:00:33 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +[12:00:37 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: Completely +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/other.d.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/user/username/projects/myproject/other.d.ts (used version) +/user/username/projects/myproject/main.ts (computed .d.ts) + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/main.js] file written with same contents + +Change:: write other with same contents but write ts file + +Input:: +//// [/user/username/projects/myproject/other.d.ts] file changed its modified time +//// [/user/username/projects/myproject/other.ts] +export function foo() {} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/other.d.ts 1:: WatchInfo: /user/username/projects/myproject/other.d.ts 250 undefined Source file +Synchronizing program +[12:00:42 AM] File change detected. Starting incremental compilation... + +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/main.ts"] + options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +======== Resolving module './other' from '/user/username/projects/myproject/main.ts'. ======== +Module resolution kind is not specified, using 'NodeJs'. +Loading module as file / folder, candidate module location '/user/username/projects/myproject/other', target file type 'TypeScript'. +File '/user/username/projects/myproject/other.ts' exist - use it as a name resolution result. +======== Module name './other' was successfully resolved to '/user/username/projects/myproject/other.ts'. ======== +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/other.ts 250 undefined Source file +[12:00:48 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/main.ts"] +Program options: {"traceResolution":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"} +Program structureReused: SafeModules +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/other.ts +/user/username/projects/myproject/main.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/other.ts +/user/username/projects/myproject/main.ts + +Shape signatures in builder refreshed for:: +/user/username/projects/myproject/other.ts (computed .d.ts) +/user/username/projects/myproject/main.ts (computed .d.ts) + +PolledWatches:: +/user/username/projects/myproject/node_modules/@types: + {"pollingInterval":500} + +FsWatches:: +/user/username/projects/myproject/tsconfig.json: + {} +/user/username/projects/myproject/main.ts: + {} +/user/username/projects/myproject/other.d.ts: + {} +/a/lib/lib.d.ts: + {} +/user/username/projects/myproject/other.ts: + {} + +FsWatchesRecursive:: + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/main.js] file written with same contents +//// [/user/username/projects/myproject/other.js] +"use strict"; +exports.__esModule = true; +exports.foo = void 0; +function foo() { } +exports.foo = foo; + +