Skip to content

Commit

Permalink
Share module resolution cache among different program
Browse files Browse the repository at this point in the history
  • Loading branch information
sheetalkamat committed Apr 24, 2019
1 parent 3264b64 commit 93b958e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
21 changes: 18 additions & 3 deletions src/compiler/moduleNameResolver.ts
Expand Up @@ -421,6 +421,7 @@ namespace ts {
*/
export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache {
getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map<ResolvedModuleWithFailedLookupLocations>;
/*@internal*/ directoryToModuleNameMap: CacheWithRedirects<Map<ResolvedModuleWithFailedLookupLocations>>;
}

/**
Expand All @@ -429,6 +430,7 @@ namespace ts {
*/
export interface NonRelativeModuleNameResolutionCache {
getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache;
/*@internal*/ moduleNameToDirectoryMap: CacheWithRedirects<PerModuleNameCache>;
}

export interface PerModuleNameCache {
Expand All @@ -445,25 +447,38 @@ namespace ts {
);
}


/*@internal*/
export interface CacheWithRedirects<T> {
ownMap: Map<T>;
redirectsMap: Map<Map<T>>;
getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map<T>;
clear(): void;
setOwnOptions(newOptions: CompilerOptions): void;
setOwnMap(newOwnMap: Map<T>): void;
}

/*@internal*/
export function createCacheWithRedirects<T>(options?: CompilerOptions): CacheWithRedirects<T> {
const ownMap: Map<T> = createMap();
let ownMap: Map<T> = createMap();
const redirectsMap: Map<Map<T>> = createMap();
return {
ownMap,
redirectsMap,
getOrCreateMapOfCacheRedirects,
clear
clear,
setOwnOptions,
setOwnMap
};

function setOwnOptions(newOptions: CompilerOptions) {
options = newOptions;
}

function setOwnMap(newOwnMap: Map<T>) {
ownMap = newOwnMap;
}

function getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined) {
if (!redirectedReference) {
return ownMap;
Expand Down Expand Up @@ -491,7 +506,7 @@ namespace ts {
currentDirectory: string,
getCanonicalFileName: GetCanonicalFileName): ModuleResolutionCache {

return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName };
return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName, directoryToModuleNameMap, moduleNameToDirectoryMap };

function getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference) {
const path = toPath(directoryName, currentDirectory, getCanonicalFileName);
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/program.ts
Expand Up @@ -528,7 +528,8 @@ namespace ts {
}
}

function loadWithLocalCache<T>(names: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] {
/* @internal */
export function loadWithLocalCache<T>(names: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] {
if (names.length === 0) {
return [];
}
Expand Down
37 changes: 37 additions & 0 deletions src/compiler/tsbuild.ts
Expand Up @@ -400,6 +400,10 @@ namespace ts {
const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions);
setGetSourceFileAsHashVersioned(compilerHost, host);

compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames);
compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives);
let moduleResolutionCache = !compilerHost.resolveModuleNames ? createModuleResolutionCache(currentDirectory, getCanonicalFileName) : undefined;

const buildInfoChecked = createFileMap<true>(toPath);

// Watch state
Expand Down Expand Up @@ -1097,6 +1101,30 @@ namespace ts {

// TODO: handle resolve module name to cache result in project reference redirect
projectCompilerOptions = configFile.options;
// Update module resolution cache if needed
if (moduleResolutionCache) {
const projPath = toPath(proj);
if (moduleResolutionCache.directoryToModuleNameMap.redirectsMap.size === 0) {
// The own map will be for projectCompilerOptions
Debug.assert(moduleResolutionCache.moduleNameToDirectoryMap.redirectsMap.size === 0);
moduleResolutionCache.directoryToModuleNameMap.redirectsMap.set(projPath, moduleResolutionCache.directoryToModuleNameMap.ownMap);
moduleResolutionCache.moduleNameToDirectoryMap.redirectsMap.set(projPath, moduleResolutionCache.moduleNameToDirectoryMap.ownMap);
}
else {
// Set correct own map
Debug.assert(moduleResolutionCache.moduleNameToDirectoryMap.redirectsMap.size > 0);

const ref: ResolvedProjectReference = {
sourceFile: projectCompilerOptions.configFile!,
commandLine: configFile
};
moduleResolutionCache.directoryToModuleNameMap.setOwnMap(moduleResolutionCache.directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref));
moduleResolutionCache.moduleNameToDirectoryMap.setOwnMap(moduleResolutionCache.moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref));
}
moduleResolutionCache.directoryToModuleNameMap.setOwnOptions(projectCompilerOptions);
moduleResolutionCache.moduleNameToDirectoryMap.setOwnOptions(projectCompilerOptions);
}

const program = host.createProgram(
configFile.fileNames,
configFile.options,
Expand Down Expand Up @@ -1368,6 +1396,13 @@ namespace ts {
readFileWithCache = newReadFileWithCache;
compilerHost.getSourceFile = getSourceFileWithCache!;

const originalResolveModuleNames = compilerHost.resolveModuleNames;
if (!compilerHost.resolveModuleNames) {
const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, projectCompilerOptions, compilerHost, moduleResolutionCache, redirectedReference).resolvedModule!;
compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference) =>
loadWithLocalCache<ResolvedModuleFull>(Debug.assertEachDefined(moduleNames), containingFile, redirectedReference, loader);
}

const graph = getGlobalDependencyGraph();
reportBuildQueue(graph);
let anyFailed = false;
Expand Down Expand Up @@ -1428,6 +1463,8 @@ namespace ts {
host.writeFile = originalWriteFile;
compilerHost.getSourceFile = savedGetSourceFile;
readFileWithCache = savedReadFileWithCache;
compilerHost.resolveModuleNames = originalResolveModuleNames;
moduleResolutionCache = undefined;
return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
}

Expand Down

0 comments on commit 93b958e

Please sign in to comment.