mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #31100 from Microsoft/tsBuildCacheModuleResolution
Cache module resolutions across tsbuild to be able to resolve the modules faster
This commit is contained in:
@@ -421,6 +421,7 @@ namespace ts {
|
||||
*/
|
||||
export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache {
|
||||
getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map<ResolvedModuleWithFailedLookupLocations>;
|
||||
/*@internal*/ directoryToModuleNameMap: CacheWithRedirects<Map<ResolvedModuleWithFailedLookupLocations>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,6 +430,7 @@ namespace ts {
|
||||
*/
|
||||
export interface NonRelativeModuleNameResolutionCache {
|
||||
getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache;
|
||||
/*@internal*/ moduleNameToDirectoryMap: CacheWithRedirects<PerModuleNameCache>;
|
||||
}
|
||||
|
||||
export interface PerModuleNameCache {
|
||||
@@ -436,34 +438,47 @@ namespace ts {
|
||||
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
|
||||
}
|
||||
|
||||
export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache {
|
||||
export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache {
|
||||
return createModuleResolutionCacheWithMaps(
|
||||
createCacheWithRedirects(),
|
||||
createCacheWithRedirects(),
|
||||
createCacheWithRedirects(options),
|
||||
createCacheWithRedirects(options),
|
||||
currentDirectory,
|
||||
getCanonicalFileName
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*@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>(): CacheWithRedirects<T> {
|
||||
const ownMap: Map<T> = createMap();
|
||||
export function createCacheWithRedirects<T>(options?: CompilerOptions): CacheWithRedirects<T> {
|
||||
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;
|
||||
@@ -471,7 +486,8 @@ namespace ts {
|
||||
const path = redirectedReference.sourceFile.path;
|
||||
let redirects = redirectsMap.get(path);
|
||||
if (!redirects) {
|
||||
redirects = createMap();
|
||||
// Reuse map if redirected reference map uses same resolution
|
||||
redirects = !options || optionsHaveModuleResolutionChanges(options, redirectedReference.commandLine.options) ? createMap() : ownMap;
|
||||
redirectsMap.set(path, redirects);
|
||||
}
|
||||
return redirects;
|
||||
@@ -490,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);
|
||||
|
||||
@@ -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 [];
|
||||
}
|
||||
@@ -773,7 +774,7 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
else {
|
||||
moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x));
|
||||
moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x), options);
|
||||
const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache, redirectedReference).resolvedModule!; // TODO: GH#18217
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile, _reusedNames, redirectedReference) => loadWithLocalCache<ResolvedModuleFull>(Debug.assertEachDefined(moduleNames), containingFile, redirectedReference, loader);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean {
|
||||
return oldOptions.configFilePath !== newOptions.configFilePath || moduleResolutionOptionDeclarations.some(o =>
|
||||
return oldOptions.configFilePath !== newOptions.configFilePath ||
|
||||
optionsHaveModuleResolutionChanges(oldOptions, newOptions);
|
||||
}
|
||||
|
||||
export function optionsHaveModuleResolutionChanges(oldOptions: CompilerOptions, newOptions: CompilerOptions) {
|
||||
return moduleResolutionOptionDeclarations.some(o =>
|
||||
!isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o)));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3719,7 +3719,7 @@ declare namespace ts {
|
||||
get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
|
||||
}
|
||||
function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache;
|
||||
function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache;
|
||||
function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
|
||||
function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
|
||||
|
||||
+1
-1
@@ -3719,7 +3719,7 @@ declare namespace ts {
|
||||
get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
|
||||
}
|
||||
function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache;
|
||||
function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache;
|
||||
function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
|
||||
function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
|
||||
|
||||
Reference in New Issue
Block a user