Skip to content

Commit ec47859

Browse files
committed
Make watch use sourceFileHash so it can be used with --incremental as well
1 parent 97fbc87 commit ec47859

File tree

2 files changed

+39
-40
lines changed

2 files changed

+39
-40
lines changed

src/compiler/tsbuild.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -451,15 +451,7 @@ namespace ts {
451451
let readFileWithCache = (f: string) => host.readFile(f);
452452
let projectCompilerOptions = baseCompilerOptions;
453453
const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions);
454-
const originalGetSourceFile = compilerHost.getSourceFile;
455-
const computeHash = host.createHash || generateDjb2Hash;
456-
compilerHost.getSourceFile = (...args) => {
457-
const result = originalGetSourceFile.call(compilerHost, ...args);
458-
if (result) {
459-
result.version = computeHash.call(host, result.text);
460-
}
461-
return result;
462-
};
454+
setCreateSourceFileAsHashVersioned(compilerHost, host);
463455

464456
const buildInfoChecked = createFileMap<true>(toPath);
465457

src/compiler/watch.ts

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,18 @@ namespace ts {
280280
}
281281
}
282282

283+
export function setCreateSourceFileAsHashVersioned(compilerHost: CompilerHost, host: ProgramHost<any>) {
284+
const originalGetSourceFile = compilerHost.getSourceFile;
285+
const computeHash = host.createHash || generateDjb2Hash;
286+
compilerHost.getSourceFile = (...args) => {
287+
const result = originalGetSourceFile.call(compilerHost, ...args);
288+
if (result) {
289+
result.version = computeHash.call(host, result.text);
290+
}
291+
return result;
292+
};
293+
}
294+
283295
/**
284296
* Creates the watch compiler host that can be extended with config file or root file names and options host
285297
*/
@@ -524,8 +536,6 @@ namespace ts {
524536
}
525537
}
526538

527-
const initialVersion = 1;
528-
529539
/**
530540
* Creates the watch from the host for root files and compiler options
531541
*/
@@ -536,13 +546,14 @@ namespace ts {
536546
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
537547
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T> & WatchCompilerHostOfConfigFile<T>): WatchOfFilesAndCompilerOptions<T> | WatchOfConfigFile<T> {
538548
interface FilePresentOnHost {
539-
version: number;
549+
version: string;
540550
sourceFile: SourceFile;
541551
fileWatcher: FileWatcher;
542552
}
543-
type FileMissingOnHost = number;
553+
type FileMissingOnHost = false;
544554
interface FilePresenceUnknownOnHost {
545-
version: number;
555+
version: false;
556+
fileWatcher?: FileWatcher;
546557
}
547558
type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost;
548559
type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost;
@@ -597,6 +608,7 @@ namespace ts {
597608
}
598609

599610
const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost;
611+
setCreateSourceFileAsHashVersioned(compilerHost, host);
600612
// Members for CompilerHost
601613
const getNewSourceFile = compilerHost.getSourceFile;
602614
compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args);
@@ -731,64 +743,59 @@ namespace ts {
731743
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
732744
}
733745

734-
function isFileMissingOnHost(hostSourceFile: HostFileInfo): hostSourceFile is FileMissingOnHost {
735-
return typeof hostSourceFile === "number";
746+
function isFileMissingOnHost(hostSourceFile: HostFileInfo | undefined): hostSourceFile is FileMissingOnHost {
747+
return typeof hostSourceFile === "boolean";
736748
}
737749

738-
function isFilePresentOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresentOnHost {
739-
return !!(hostSourceFile as FilePresentOnHost).sourceFile;
750+
function isFilePresenceUnknownOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresenceUnknownOnHost {
751+
return typeof (hostSourceFile as FilePresenceUnknownOnHost).version === "boolean";
740752
}
741753

742754
function fileExists(fileName: string) {
743755
const path = toPath(fileName);
744756
// If file is missing on host from cache, we can definitely say file doesnt exist
745757
// otherwise we need to ensure from the disk
746-
if (isFileMissingOnHost(sourceFilesCache.get(path)!)) {
758+
if (isFileMissingOnHost(sourceFilesCache.get(path))) {
747759
return true;
748760
}
749761

750762
return directoryStructureHost.fileExists(fileName);
751763
}
752764

753765
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
754-
const hostSourceFile = sourceFilesCache.get(path)!;
766+
const hostSourceFile = sourceFilesCache.get(path);
755767
// No source file on the host
756768
if (isFileMissingOnHost(hostSourceFile)) {
757769
return undefined;
758770
}
759771

760772
// Create new source file if requested or the versions dont match
761-
if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) {
773+
if (hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile)) {
762774
const sourceFile = getNewSourceFile(fileName, languageVersion, onError);
763775
if (hostSourceFile) {
764-
if (shouldCreateNewSourceFile) {
765-
hostSourceFile.version++;
766-
}
767-
768776
if (sourceFile) {
769777
// Set the source file and create file watcher now that file was present on the disk
770778
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
771-
sourceFile.version = hostSourceFile.version.toString();
772-
if (!(hostSourceFile as FilePresentOnHost).fileWatcher) {
773-
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
779+
hostSourceFile.version = sourceFile.version;
780+
if (!hostSourceFile.fileWatcher) {
781+
hostSourceFile.fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
774782
}
775783
}
776784
else {
777785
// There is no source file on host any more, close the watch, missing file paths will track it
778-
if (isFilePresentOnHost(hostSourceFile)) {
786+
if (hostSourceFile.fileWatcher) {
779787
hostSourceFile.fileWatcher.close();
780788
}
781-
sourceFilesCache.set(path, hostSourceFile.version);
789+
sourceFilesCache.set(path, false);
782790
}
783791
}
784792
else {
785793
if (sourceFile) {
786-
sourceFile.version = initialVersion.toString();
787794
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
788-
sourceFilesCache.set(path, { sourceFile, version: initialVersion, fileWatcher });
795+
sourceFilesCache.set(path, { sourceFile, version: sourceFile.version, fileWatcher });
789796
}
790797
else {
791-
sourceFilesCache.set(path, initialVersion);
798+
sourceFilesCache.set(path, false);
792799
}
793800
}
794801
return sourceFile;
@@ -801,17 +808,17 @@ namespace ts {
801808
if (hostSourceFile !== undefined) {
802809
if (isFileMissingOnHost(hostSourceFile)) {
803810
// The next version, lets set it as presence unknown file
804-
sourceFilesCache.set(path, { version: Number(hostSourceFile) + 1 });
811+
sourceFilesCache.set(path, { version: false });
805812
}
806813
else {
807-
hostSourceFile.version++;
814+
(hostSourceFile as FilePresenceUnknownOnHost).version = false;
808815
}
809816
}
810817
}
811818

812819
function getSourceVersion(path: Path): string | undefined {
813820
const hostSourceFile = sourceFilesCache.get(path);
814-
return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString();
821+
return !hostSourceFile || !hostSourceFile.version ? undefined : hostSourceFile.version;
815822
}
816823

817824
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) {
@@ -820,14 +827,14 @@ namespace ts {
820827
// remove the cached entry.
821828
// Note we arent deleting entry if file became missing in new program or
822829
// there was version update and new source file was created.
823-
if (hostSourceFileInfo) {
830+
if (hostSourceFileInfo !== undefined) {
824831
// record the missing file paths so they can be removed later if watchers arent tracking them
825832
if (isFileMissingOnHost(hostSourceFileInfo)) {
826833
(missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path);
827834
}
828835
else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) {
829-
if ((hostSourceFileInfo as FilePresentOnHost).fileWatcher) {
830-
(hostSourceFileInfo as FilePresentOnHost).fileWatcher.close();
836+
if (hostSourceFileInfo.fileWatcher) {
837+
hostSourceFileInfo.fileWatcher.close();
831838
}
832839
sourceFilesCache.delete(oldSourceFile.resolvedPath);
833840
if (!hasSourceFileByPath) {
@@ -924,7 +931,7 @@ namespace ts {
924931
updateCachedSystemWithFile(fileName, path, eventKind);
925932

926933
// Update the source file cache
927-
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) {
934+
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.has(path)) {
928935
resolutionCache.invalidateResolutionOfFile(path);
929936
}
930937
resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);

0 commit comments

Comments
 (0)