Multifaceted approach to performantly enabling fileExists outside of the synchronize step in the emit host (#25107)

* Multifaceted approach to performantly enabling fileExists outside of the synchronize step in the emit host

* make cache undefinable and handle correctly

* Remove unneeded cast

* Readd assert

* More useful failure messager
This commit is contained in:
Wesley Wigham 2018-06-22 14:05:36 -07:00 committed by GitHub
parent c441451f83
commit bd97e12f76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 8 deletions

View File

@ -1239,7 +1239,14 @@ namespace ts {
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
isEmitBlocked,
readFile: f => host.readFile(f),
fileExists: f => host.fileExists(f),
fileExists: f => {
// Use local caches
const path = toPath(f);
if (getSourceFileByPath(path)) return true;
if (contains(missingFilePaths, path)) return false;
// Before falling back to the host
return host.fileExists(f);
},
...(host.directoryExists ? { directoryExists: f => host.directoryExists!(f) } : {}),
};
}

View File

@ -1171,13 +1171,13 @@ namespace ts {
}
// Get a fresh cache of the host information
let hostCache = new HostCache(host, getCanonicalFileName);
let hostCache: HostCache | undefined = new HostCache(host, getCanonicalFileName);
const rootFileNames = hostCache.getRootFileNames();
const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse;
// If the program is already up-to-date, we can reuse it
if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) {
if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache!.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) {
return;
}
@ -1204,7 +1204,7 @@ namespace ts {
readFile(fileName) {
// stub missing host functionality
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const entry = hostCache.getEntryByPath(path);
const entry = hostCache && hostCache.getEntryByPath(path);
if (entry) {
return isString(entry) ? undefined : getSnapshotText(entry.scriptSnapshot);
}
@ -1246,7 +1246,7 @@ namespace ts {
// hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point.
// It needs to be cleared to allow all collected snapshots to be released
hostCache = undefined!;
hostCache = undefined;
// We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above,
// Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during
@ -1260,7 +1260,7 @@ namespace ts {
function fileExists(fileName: string): boolean {
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const entry = hostCache.getEntryByPath(path);
const entry = hostCache && hostCache.getEntryByPath(path);
return entry ?
!isString(entry) :
(!!host.fileExists && host.fileExists(fileName));
@ -1278,11 +1278,11 @@ namespace ts {
}
function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
Debug.assert(hostCache !== undefined);
Debug.assert(hostCache !== undefined, "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host.");
// The program is asking for this file, check first if the host can locate it.
// If the host can not locate the file, then it does not exist. return undefined
// to the program to allow reporting of errors for missing files.
const hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path);
const hostFileInformation = hostCache && hostCache.getOrCreateEntryByPath(fileName, path);
if (!hostFileInformation) {
return undefined;
}

View File

@ -0,0 +1,14 @@
/// <reference path="fourslash.ts" />
// @declaration: true
// @Filename: node_modules/foo/index.d.ts
////export function f(): I;
////export interface I {
//// x: number;
////}
// @Filename: a.ts
////import { f } from "foo";
////export const x = f();
goTo.file(1);
verify.getSemanticDiagnostics([]);