From ec4785962422d309b613b46e29bbc4eda094b3b3 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 1 Mar 2019 15:47:17 -0800 Subject: [PATCH] Make watch use sourceFileHash so it can be used with --incremental as well --- src/compiler/tsbuild.ts | 10 +----- src/compiler/watch.ts | 69 +++++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 1ab990355b8..59edd85d716 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -451,15 +451,7 @@ namespace ts { let readFileWithCache = (f: string) => host.readFile(f); let projectCompilerOptions = baseCompilerOptions; const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions); - const originalGetSourceFile = compilerHost.getSourceFile; - const computeHash = host.createHash || generateDjb2Hash; - compilerHost.getSourceFile = (...args) => { - const result = originalGetSourceFile.call(compilerHost, ...args); - if (result) { - result.version = computeHash.call(host, result.text); - } - return result; - }; + setCreateSourceFileAsHashVersioned(compilerHost, host); const buildInfoChecked = createFileMap(toPath); diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 41ef7876d76..02b40720783 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -280,6 +280,18 @@ namespace ts { } } + export function setCreateSourceFileAsHashVersioned(compilerHost: CompilerHost, host: ProgramHost) { + const originalGetSourceFile = compilerHost.getSourceFile; + const computeHash = host.createHash || generateDjb2Hash; + compilerHost.getSourceFile = (...args) => { + const result = originalGetSourceFile.call(compilerHost, ...args); + if (result) { + result.version = computeHash.call(host, result.text); + } + return result; + }; + } + /** * Creates the watch compiler host that can be extended with config file or root file names and options host */ @@ -524,8 +536,6 @@ namespace ts { } } - const initialVersion = 1; - /** * Creates the watch from the host for root files and compiler options */ @@ -536,13 +546,14 @@ namespace ts { export function createWatchProgram(host: WatchCompilerHostOfConfigFile): WatchOfConfigFile; export function createWatchProgram(host: WatchCompilerHostOfFilesAndCompilerOptions & WatchCompilerHostOfConfigFile): WatchOfFilesAndCompilerOptions | WatchOfConfigFile { interface FilePresentOnHost { - version: number; + version: string; sourceFile: SourceFile; fileWatcher: FileWatcher; } - type FileMissingOnHost = number; + type FileMissingOnHost = false; interface FilePresenceUnknownOnHost { - version: number; + version: false; + fileWatcher?: FileWatcher; } type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost; type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost; @@ -597,6 +608,7 @@ namespace ts { } const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost; + setCreateSourceFileAsHashVersioned(compilerHost, host); // Members for CompilerHost const getNewSourceFile = compilerHost.getSourceFile; compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args); @@ -731,19 +743,19 @@ namespace ts { return ts.toPath(fileName, currentDirectory, getCanonicalFileName); } - function isFileMissingOnHost(hostSourceFile: HostFileInfo): hostSourceFile is FileMissingOnHost { - return typeof hostSourceFile === "number"; + function isFileMissingOnHost(hostSourceFile: HostFileInfo | undefined): hostSourceFile is FileMissingOnHost { + return typeof hostSourceFile === "boolean"; } - function isFilePresentOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresentOnHost { - return !!(hostSourceFile as FilePresentOnHost).sourceFile; + function isFilePresenceUnknownOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresenceUnknownOnHost { + return typeof (hostSourceFile as FilePresenceUnknownOnHost).version === "boolean"; } function fileExists(fileName: string) { const path = toPath(fileName); // If file is missing on host from cache, we can definitely say file doesnt exist // otherwise we need to ensure from the disk - if (isFileMissingOnHost(sourceFilesCache.get(path)!)) { + if (isFileMissingOnHost(sourceFilesCache.get(path))) { return true; } @@ -751,44 +763,39 @@ namespace ts { } function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { - const hostSourceFile = sourceFilesCache.get(path)!; + const hostSourceFile = sourceFilesCache.get(path); // No source file on the host if (isFileMissingOnHost(hostSourceFile)) { return undefined; } // Create new source file if requested or the versions dont match - if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) { + if (hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile)) { const sourceFile = getNewSourceFile(fileName, languageVersion, onError); if (hostSourceFile) { - if (shouldCreateNewSourceFile) { - hostSourceFile.version++; - } - if (sourceFile) { // Set the source file and create file watcher now that file was present on the disk (hostSourceFile as FilePresentOnHost).sourceFile = sourceFile; - sourceFile.version = hostSourceFile.version.toString(); - if (!(hostSourceFile as FilePresentOnHost).fileWatcher) { - (hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile); + hostSourceFile.version = sourceFile.version; + if (!hostSourceFile.fileWatcher) { + hostSourceFile.fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile); } } else { // There is no source file on host any more, close the watch, missing file paths will track it - if (isFilePresentOnHost(hostSourceFile)) { + if (hostSourceFile.fileWatcher) { hostSourceFile.fileWatcher.close(); } - sourceFilesCache.set(path, hostSourceFile.version); + sourceFilesCache.set(path, false); } } else { if (sourceFile) { - sourceFile.version = initialVersion.toString(); const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile); - sourceFilesCache.set(path, { sourceFile, version: initialVersion, fileWatcher }); + sourceFilesCache.set(path, { sourceFile, version: sourceFile.version, fileWatcher }); } else { - sourceFilesCache.set(path, initialVersion); + sourceFilesCache.set(path, false); } } return sourceFile; @@ -801,17 +808,17 @@ namespace ts { if (hostSourceFile !== undefined) { if (isFileMissingOnHost(hostSourceFile)) { // The next version, lets set it as presence unknown file - sourceFilesCache.set(path, { version: Number(hostSourceFile) + 1 }); + sourceFilesCache.set(path, { version: false }); } else { - hostSourceFile.version++; + (hostSourceFile as FilePresenceUnknownOnHost).version = false; } } } function getSourceVersion(path: Path): string | undefined { const hostSourceFile = sourceFilesCache.get(path); - return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString(); + return !hostSourceFile || !hostSourceFile.version ? undefined : hostSourceFile.version; } function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) { @@ -820,14 +827,14 @@ namespace ts { // remove the cached entry. // Note we arent deleting entry if file became missing in new program or // there was version update and new source file was created. - if (hostSourceFileInfo) { + if (hostSourceFileInfo !== undefined) { // record the missing file paths so they can be removed later if watchers arent tracking them if (isFileMissingOnHost(hostSourceFileInfo)) { (missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path); } else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) { - if ((hostSourceFileInfo as FilePresentOnHost).fileWatcher) { - (hostSourceFileInfo as FilePresentOnHost).fileWatcher.close(); + if (hostSourceFileInfo.fileWatcher) { + hostSourceFileInfo.fileWatcher.close(); } sourceFilesCache.delete(oldSourceFile.resolvedPath); if (!hasSourceFileByPath) { @@ -924,7 +931,7 @@ namespace ts { updateCachedSystemWithFile(fileName, path, eventKind); // Update the source file cache - if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) { + if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.has(path)) { resolutionCache.invalidateResolutionOfFile(path); } resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);