diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index ee02f47f17a..c1d361379a6 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -447,8 +447,11 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string } const containingDirectory = containingFile ? getDirectoryPath(containingFile) : undefined; - const perFolderCache = containingDirectory ? cache && cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference) : undefined; - let result = perFolderCache && perFolderCache.get(typeReferenceDirectiveName, /*mode*/ resolutionMode); + let result = containingDirectory ? cache?.getFromDirectoryCache(typeReferenceDirectiveName, resolutionMode, containingDirectory, redirectedReference) : undefined; + if (!result && containingDirectory && !isExternalModuleNameRelative(typeReferenceDirectiveName)) { + result = cache?.getFromNonRelativeNameCache(typeReferenceDirectiveName, resolutionMode, containingDirectory, redirectedReference); + } + if (result) { if (traceEnabled) { trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1, typeReferenceDirectiveName, containingFile); @@ -459,6 +462,7 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string return result; } + const typeRoots = getEffectiveTypeRoots(options, host); if (traceEnabled) { if (containingFile === undefined) { @@ -537,7 +541,12 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string affectingLocations: initializeResolutionField(affectingLocations), resolutionDiagnostics: initializeResolutionField(diagnostics), }; - perFolderCache?.set(typeReferenceDirectiveName, /*mode*/ resolutionMode, result); + if (containingDirectory) { + cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(typeReferenceDirectiveName, /*mode*/ resolutionMode, result); + if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) { + cache?.getOrCreateCacheForNonRelativeName(typeReferenceDirectiveName, resolutionMode, redirectedReference).set(containingDirectory, result); + } + } if (traceEnabled) traceResult(result); return result; @@ -678,7 +687,7 @@ export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: M return result; } -export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { +export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { /** @internal */ clearAllExceptPackageJsonInfoCache(): void; } @@ -696,6 +705,7 @@ export interface ModeAwareCache { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ export interface PerDirectoryResolutionCache { + getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; clear(): void; /** @@ -705,6 +715,22 @@ export interface PerDirectoryResolutionCache { update(options: CompilerOptions): void; } +export interface NonRelativeNameResolutionCache { + getFromNonRelativeNameCache(nonRelativeName: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; + getOrCreateCacheForNonRelativeName(nonRelativeName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache; + clear(): void; + /** + * Updates with the current compilerOptions the cache will operate with. + * This updates the redirects map as well if needed so module resolutions are cached if they can across the projects + */ + update(options: CompilerOptions): void; +} + +export interface PerNonRelativeNameCache { + get(directory: string): T | undefined; + set(directory: string, result: T): void; +} + export interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getPackageJsonInfoCache(): PackageJsonInfoCache; /** @internal */ clearAllExceptPackageJsonInfoCache(): void; @@ -714,7 +740,8 @@ export interface ModuleResolutionCache extends PerDirectoryResolutionCache result of module lookup in this directory * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. */ -export interface NonRelativeModuleNameResolutionCache extends PackageJsonInfoCache { +export interface NonRelativeModuleNameResolutionCache extends NonRelativeNameResolutionCache, PackageJsonInfoCache { + /** @deprecated Use getOrCreateCacheForNonRelativeName */ getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; } @@ -726,10 +753,7 @@ export interface PackageJsonInfoCache { clear(): void; } -export interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; - set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; -} +export type PerModuleNameCache = PerNonRelativeNameCache; function compilerOptionValueToString(value: unknown): string { if (value === null || typeof value !== "object") { // eslint-disable-line no-null/no-null @@ -754,6 +778,7 @@ export function getKeyForCompilerOptions(options: CompilerOptions, affectingOpti /** @internal */ export interface CacheWithRedirects { + getMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map | undefined; getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map; update(newOptions: CompilerOptions): void; clear(): void; @@ -768,26 +793,35 @@ export function createCacheWithRedirects(ownOptions: CompilerOptions | und let ownMap = new Map(); if (ownOptions) redirectsMap.set(ownOptions, ownMap); return { + getMapOfCacheRedirects, getOrCreateMapOfCacheRedirects, update, clear, }; + function getMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map | undefined { + return redirectedReference ? + getOrCreateMap(redirectedReference.commandLine.options, /*create*/ false) : + ownMap; + } + function getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map { return redirectedReference ? - getOrCreateMap(redirectedReference.commandLine.options) : + getOrCreateMap(redirectedReference.commandLine.options, /*create*/ true) : ownMap; } function update(newOptions: CompilerOptions) { if (ownOptions !== newOptions) { - if (ownOptions) ownMap = getOrCreateMap(newOptions); // set new map for new options as ownMap + if (ownOptions) ownMap = getOrCreateMap(newOptions, /*create*/ true); // set new map for new options as ownMap else redirectsMap.set(newOptions, ownMap); // Use existing map if oldOptions = undefined ownOptions = newOptions; } } - function getOrCreateMap(redirectOptions: CompilerOptions): Map { + function getOrCreateMap(redirectOptions: CompilerOptions, create: true): Map; + function getOrCreateMap(redirectOptions: CompilerOptions, create: false): Map | undefined; + function getOrCreateMap(redirectOptions: CompilerOptions, create: boolean): Map | undefined { let result = redirectsMap.get(redirectOptions); if (result) return result; const key = getRedirectsCacheKey(redirectOptions); @@ -798,9 +832,10 @@ export function createCacheWithRedirects(ownOptions: CompilerOptions | und if (ownKey === key) result = ownMap; else if (!redirectsKeyToMap.has(ownKey)) redirectsKeyToMap.set(ownKey, ownMap); } - redirectsKeyToMap.set(key, result ??= new Map()); + if (create) result ??= new Map(); + if (result) redirectsKeyToMap.set(key, result); } - redirectsMap.set(redirectOptions, result); + if (result) redirectsMap.set(redirectOptions, result); return result; } @@ -856,8 +891,10 @@ function getOrCreateCache(cacheWithRedirects: CacheWithRedirects, re return result; } -function createPerDirectoryResolutionCache(currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, directoryToModuleNameMap: CacheWithRedirects>): PerDirectoryResolutionCache { +function createPerDirectoryResolutionCache(currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, options: CompilerOptions | undefined): PerDirectoryResolutionCache { + const directoryToModuleNameMap = createCacheWithRedirects>(options); return { + getFromDirectoryCache, getOrCreateCacheForDirectory, clear, update, @@ -875,6 +912,11 @@ function createPerDirectoryResolutionCache(currentDirectory: string, getCanon const path = toPath(directoryName, currentDirectory, getCanonicalFileName); return getOrCreateCache(directoryToModuleNameMap, redirectedReference, path, () => createModeAwareCache()); } + + function getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined) { + const path = toPath(directoryName, currentDirectory, getCanonicalFileName); + return directoryToModuleNameMap.getMapOfCacheRedirects(redirectedReference)?.get(path)?.get(name, mode); + } } /** @internal */ @@ -938,52 +980,53 @@ export function zipToModeAwareCache( return map; } -export function createModuleResolutionCache( +function getOriginalOrResolvedModuleFileName(result: ResolvedModuleWithFailedLookupLocations) { + return result.resolvedModule && (result.resolvedModule.originalPath || result.resolvedModule.resolvedFileName); +} + +function getOriginalOrResolvedTypeReferenceFileName(result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { + return result.resolvedTypeReferenceDirective && + (result.resolvedTypeReferenceDirective.originalPath || result.resolvedTypeReferenceDirective.resolvedFileName); +} + +function createNonRelativeNameResolutionCache( currentDirectory: string, getCanonicalFileName: (s: string) => string, - options?: CompilerOptions -): ModuleResolutionCache { - const directoryToModuleNameMap = createCacheWithRedirects>(options); - const perDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap); - const moduleNameToDirectoryMap = createCacheWithRedirects(options); - const packageJsonInfoCache = createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); - + options: CompilerOptions | undefined, + getResolvedFileName: (result: T) => string | undefined, +): NonRelativeNameResolutionCache { + const moduleNameToDirectoryMap = createCacheWithRedirects>(options); return { - ...packageJsonInfoCache, - ...perDirectoryResolutionCache, - getOrCreateCacheForModuleName, + getFromNonRelativeNameCache, + getOrCreateCacheForNonRelativeName, clear, update, - getPackageJsonInfoCache: () => packageJsonInfoCache, - clearAllExceptPackageJsonInfoCache, }; function clear() { - clearAllExceptPackageJsonInfoCache(); - packageJsonInfoCache.clear(); - } - - function clearAllExceptPackageJsonInfoCache() { - perDirectoryResolutionCache.clear(); moduleNameToDirectoryMap.clear(); } function update(options: CompilerOptions) { - directoryToModuleNameMap.update(options); moduleNameToDirectoryMap.update(options); } - function getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache { + function getFromNonRelativeNameCache(nonRelativeModuleName: string, mode: ResolutionMode, directoryName: string, redirectedReference?: ResolvedProjectReference): T | undefined { + Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName)); + return moduleNameToDirectoryMap.getMapOfCacheRedirects(redirectedReference)?.get(createModeAwareCacheKey(nonRelativeModuleName, mode))?.get(directoryName); + } + + function getOrCreateCacheForNonRelativeName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache { Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName)); return getOrCreateCache(moduleNameToDirectoryMap, redirectedReference, createModeAwareCacheKey(nonRelativeModuleName, mode), createPerModuleNameCache); } - function createPerModuleNameCache(): PerModuleNameCache { - const directoryPathMap = new Map(); + function createPerModuleNameCache(): PerNonRelativeNameCache { + const directoryPathMap = new Map(); return { get, set }; - function get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined { + function get(directory: string): T | undefined { return directoryPathMap.get(toPath(directory, currentDirectory, getCanonicalFileName)); } @@ -998,7 +1041,7 @@ export function createModuleResolutionCache( * ] * this means that request for module resolution from file in any of these folder will be immediately found in cache. */ - function set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void { + function set(directory: string, result: T): void { const path = toPath(directory, currentDirectory, getCanonicalFileName); // if entry is already in cache do nothing if (directoryPathMap.has(path)) { @@ -1006,8 +1049,7 @@ export function createModuleResolutionCache( } directoryPathMap.set(path, result); - const resolvedFileName = result.resolvedModule && - (result.resolvedModule.originalPath || result.resolvedModule.resolvedFileName); + const resolvedFileName = getResolvedFileName(result); // find common prefix between directory and resolved file name // this common prefix should be the shortest path that has the same resolution // directory: /a/b/c/d/e @@ -1051,20 +1093,33 @@ export function createModuleResolutionCache( } } -export function createTypeReferenceDirectiveResolutionCache( +interface ModuleOrTypeReferenceResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { + getPackageJsonInfoCache(): PackageJsonInfoCache; + clearAllExceptPackageJsonInfoCache(): void; +} +function createModuleOrTypeReferenceResolutionCache( currentDirectory: string, getCanonicalFileName: (s: string) => string, - options?: CompilerOptions, - packageJsonInfoCache?: PackageJsonInfoCache, -): TypeReferenceDirectiveResolutionCache { - const directoryToModuleNameMap = createCacheWithRedirects>(options); - const perDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap); - packageJsonInfoCache ||= createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); + options: CompilerOptions | undefined, + packageJsonInfoCache: PackageJsonInfoCache | undefined, + getResolvedFileName: (result: T) => string | undefined, +): ModuleOrTypeReferenceResolutionCache { + const perDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, options); + const nonRelativeNameResolutionCache = createNonRelativeNameResolutionCache( + currentDirectory, + getCanonicalFileName, + options, + getResolvedFileName, + ); + packageJsonInfoCache ??= createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); return { ...packageJsonInfoCache, ...perDirectoryResolutionCache, + ...nonRelativeNameResolutionCache, clear, + update, + getPackageJsonInfoCache: () => packageJsonInfoCache!, clearAllExceptPackageJsonInfoCache, }; @@ -1075,14 +1130,49 @@ export function createTypeReferenceDirectiveResolutionCache( function clearAllExceptPackageJsonInfoCache() { perDirectoryResolutionCache.clear(); + nonRelativeNameResolutionCache.clear(); } + + function update(options: CompilerOptions) { + perDirectoryResolutionCache.update(options); + nonRelativeNameResolutionCache.update(options); + } +} + +export function createModuleResolutionCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, + options?: CompilerOptions +): ModuleResolutionCache { + const result = createModuleOrTypeReferenceResolutionCache( + currentDirectory, + getCanonicalFileName, + options, + /*packageJsonInfoCache*/ undefined, + getOriginalOrResolvedModuleFileName, + ) as ModuleResolutionCache; + result.getOrCreateCacheForModuleName = (nonRelativeName, mode, redirectedReference) => result.getOrCreateCacheForNonRelativeName(nonRelativeName, mode, redirectedReference); + return result; +} + +export function createTypeReferenceDirectiveResolutionCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, + options?: CompilerOptions, + packageJsonInfoCache?: PackageJsonInfoCache, +): TypeReferenceDirectiveResolutionCache { + return createModuleOrTypeReferenceResolutionCache( + currentDirectory, + getCanonicalFileName, + options, + packageJsonInfoCache, + getOriginalOrResolvedTypeReferenceFileName + ); } export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache, mode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined { const containingDirectory = getDirectoryPath(containingFile); - const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory); - if (!perFolderCache) return undefined; - return perFolderCache.get(moduleName, mode); + return cache.getFromDirectoryCache(moduleName, mode, containingDirectory, /*redirectedReference*/ undefined); } export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations { @@ -1097,8 +1187,7 @@ export function resolveModuleName(moduleName: string, containingFile: string, co } } const containingDirectory = getDirectoryPath(containingFile); - const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference); - let result = perFolderCache && perFolderCache.get(moduleName, resolutionMode); + let result = cache?.getFromDirectoryCache(moduleName, resolutionMode, containingDirectory, redirectedReference); if (result) { if (traceEnabled) { @@ -1152,12 +1241,10 @@ export function resolveModuleName(moduleName: string, containingFile: string, co if (result && result.resolvedModule) perfLogger.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`); perfLogger.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null"); - if (perFolderCache) { - perFolderCache.set(moduleName, resolutionMode, result); - if (!isExternalModuleNameRelative(moduleName)) { - // put result in per-module name cache - cache.getOrCreateCacheForModuleName(moduleName, resolutionMode, redirectedReference).set(containingDirectory, result); - } + cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(moduleName, resolutionMode, result); + if (!isExternalModuleNameRelative(moduleName)) { + // put result in per-module name cache + cache?.getOrCreateCacheForNonRelativeName(moduleName, resolutionMode, redirectedReference).set(containingDirectory, result); } } @@ -2512,7 +2599,7 @@ function loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName: string, } function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { - const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, state.features === 0 ? undefined : state.features & NodeResolutionFeatures.EsmMode ? ModuleKind.ESNext : ModuleKind.CommonJS, redirectedReference); + const mode = state.features === 0 ? undefined : state.features & NodeResolutionFeatures.EsmMode ? ModuleKind.ESNext : ModuleKind.CommonJS; // Do (up to) two passes through node_modules: // 1. For each ancestor node_modules directory, try to find: // i. TS/DTS files in the implementation package @@ -2534,7 +2621,7 @@ function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, function lookup(extensions: Extensions) { return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => { if (getBaseFileName(ancestorDirectory) !== "node_modules") { - const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, ancestorDirectory, state); + const resolutionFromCache = tryFindNonRelativeModuleNameInCache(cache, moduleName, mode, ancestorDirectory, redirectedReference, state); if (resolutionFromCache) { return resolutionFromCache; } @@ -2719,8 +2806,8 @@ export function unmangleScopedPackageName(typesPackageName: string): string { typesPackageName; } -function tryFindNonRelativeModuleNameInCache(cache: PerModuleNameCache | undefined, moduleName: string, containingDirectory: string, state: ModuleResolutionState): SearchResult { - const result = cache && cache.get(containingDirectory); +function tryFindNonRelativeModuleNameInCache(cache: NonRelativeModuleNameResolutionCache | undefined, moduleName: string, mode: ResolutionMode, containingDirectory: string, redirectedReference: ResolvedProjectReference | undefined, state: ModuleResolutionState): SearchResult { + const result = cache && cache.getFromNonRelativeNameCache(moduleName, mode, containingDirectory, redirectedReference); if (result) { if (state.traceEnabled) { trace(state.host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); @@ -2769,10 +2856,9 @@ export function classicNameResolver(moduleName: string, containingFile: string, } if (!isExternalModuleNameRelative(moduleName)) { - const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, /*mode*/ undefined, redirectedReference); // Climb up parent directories looking for a module. const resolved = forEachAncestorDirectory(containingDirectory, directory => { - const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, state); + const resolutionFromCache = tryFindNonRelativeModuleNameInCache(cache, moduleName, /*mode*/ undefined, directory, redirectedReference, state); if (resolutionFromCache) { return resolutionFromCache; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ea600b28df7..45e6c8df8dd 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1855,7 +1855,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // This may totally change if/when the issue of output paths not mapping to input files is fixed in a broader context // When it is, how we extract diagnostics from the module name resolver will have the be refined - the current cache // APIs wrapping the underlying resolver make it almost impossible to smuggle the diagnostics out in a generalized way - const fromCache = moduleResolutionCache.getOrCreateCacheForModuleName(name, mode, redirectedReference).get(containingDir); + const fromCache = moduleResolutionCache.getFromNonRelativeNameCache(name, mode, containingDir, redirectedReference); if (fromCache) addResolutionDiagnostics(fromCache); } diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts index 5ae7ebee71e..869a86894dc 100644 --- a/src/testRunner/unittests/moduleResolution.ts +++ b/src/testRunner/unittests/moduleResolution.ts @@ -162,7 +162,7 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths describe("unittests:: moduleResolution:: Node module resolution - non-relative paths", () => { it("computes correct commonPrefix for moduleName cache", () => { const resolutionCache = ts.createModuleResolutionCache("/", (f) => f); - let cache = resolutionCache.getOrCreateCacheForModuleName("a", /*mode*/ undefined); + let cache = resolutionCache.getOrCreateCacheForNonRelativeName("a", /*mode*/ undefined); cache.set("/sub", { resolvedModule: { originalPath: undefined, @@ -177,7 +177,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p assert.isDefined(cache.get("/sub")); assert.isUndefined(cache.get("/")); - cache = resolutionCache.getOrCreateCacheForModuleName("b", /*mode*/ undefined); + cache = resolutionCache.getOrCreateCacheForNonRelativeName("b", /*mode*/ undefined); cache.set("/sub/dir/foo", { resolvedModule: { originalPath: undefined, @@ -194,7 +194,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p assert.isDefined(cache.get("/sub")); assert.isUndefined(cache.get("/")); - cache = resolutionCache.getOrCreateCacheForModuleName("c", /*mode*/ undefined); + cache = resolutionCache.getOrCreateCacheForNonRelativeName("c", /*mode*/ undefined); cache.set("/foo/bar", { resolvedModule: { originalPath: undefined, @@ -210,7 +210,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p assert.isDefined(cache.get("/foo")); assert.isDefined(cache.get("/")); - cache = resolutionCache.getOrCreateCacheForModuleName("d", /*mode*/ undefined); + cache = resolutionCache.getOrCreateCacheForNonRelativeName("d", /*mode*/ undefined); cache.set("/foo", { resolvedModule: { originalPath: undefined, @@ -225,7 +225,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p assert.isDefined(cache.get("/foo")); assert.isUndefined(cache.get("/")); - cache = resolutionCache.getOrCreateCacheForModuleName("e", /*mode*/ undefined); + cache = resolutionCache.getOrCreateCacheForNonRelativeName("e", /*mode*/ undefined); cache.set("c:/foo", { resolvedModule: { originalPath: undefined, @@ -241,7 +241,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p assert.isDefined(cache.get("c:/")); assert.isUndefined(cache.get("d:/")); - cache = resolutionCache.getOrCreateCacheForModuleName("f", /*mode*/ undefined); + cache = resolutionCache.getOrCreateCacheForNonRelativeName("f", /*mode*/ undefined); cache.set("/foo/bar/baz", { resolvedModule: undefined, failedLookupLocations: [], diff --git a/src/testRunner/unittests/tsserver/getEditsForFileRename.ts b/src/testRunner/unittests/tsserver/getEditsForFileRename.ts index 38ae46689f8..ec177e79192 100644 --- a/src/testRunner/unittests/tsserver/getEditsForFileRename.ts +++ b/src/testRunner/unittests/tsserver/getEditsForFileRename.ts @@ -42,7 +42,7 @@ describe("unittests:: tsserver:: getEditsForFileRename", () => { readFile: path => host.readFile(path), fileExists: path => host.fileExists(path), resolveModuleNames: (moduleNames, containingFile) => moduleNames.map(name => ts.resolveModuleName(name, containingFile, options, lsHost, moduleResolutionCache).resolvedModule), - getResolvedModuleWithFailedLookupLocationsFromCache: (moduleName, containingFile, mode) => moduleResolutionCache.getOrCreateCacheForDirectory(ts.getDirectoryPath(containingFile)).get(moduleName, mode), + getResolvedModuleWithFailedLookupLocationsFromCache: (moduleName, containingFile, mode) => moduleResolutionCache.getFromDirectoryCache(moduleName, mode, ts.getDirectoryPath(containingFile), /*redirectedReference*/ undefined), }; const service = ts.createLanguageService(lsHost); const edits = service.getEditsForFileRename("/old.ts", "/new.ts", ts.testFormatSettings, ts.emptyOptions); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index d9c8599b1a2..28d224c431f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -9187,7 +9187,7 @@ declare namespace ts { function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations; function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { + interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { } interface ModeAwareCache { get(key: string, mode: ResolutionMode): T | undefined; @@ -9202,6 +9202,7 @@ declare namespace ts { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ interface PerDirectoryResolutionCache { + getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; clear(): void; /** @@ -9210,6 +9211,20 @@ declare namespace ts { */ update(options: CompilerOptions): void; } + interface NonRelativeNameResolutionCache { + getFromNonRelativeNameCache(nonRelativeName: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; + getOrCreateCacheForNonRelativeName(nonRelativeName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache; + clear(): void; + /** + * Updates with the current compilerOptions the cache will operate with. + * This updates the redirects map as well if needed so module resolutions are cached if they can across the projects + */ + update(options: CompilerOptions): void; + } + interface PerNonRelativeNameCache { + get(directory: string): T | undefined; + set(directory: string, result: T): void; + } interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getPackageJsonInfoCache(): PackageJsonInfoCache; } @@ -9217,16 +9232,14 @@ declare namespace ts { * Stored map from non-relative module name to a table: directory -> result of module lookup in this directory * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. */ - interface NonRelativeModuleNameResolutionCache extends PackageJsonInfoCache { + interface NonRelativeModuleNameResolutionCache extends NonRelativeNameResolutionCache, PackageJsonInfoCache { + /** @deprecated Use getOrCreateCacheForNonRelativeName */ getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; } interface PackageJsonInfoCache { clear(): void; } - interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; - set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; - } + type PerModuleNameCache = PerNonRelativeNameCache; /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index a097a08654d..048500f17af 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5254,7 +5254,7 @@ declare namespace ts { function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations; function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { + interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { } interface ModeAwareCache { get(key: string, mode: ResolutionMode): T | undefined; @@ -5269,6 +5269,7 @@ declare namespace ts { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ interface PerDirectoryResolutionCache { + getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; clear(): void; /** @@ -5277,6 +5278,20 @@ declare namespace ts { */ update(options: CompilerOptions): void; } + interface NonRelativeNameResolutionCache { + getFromNonRelativeNameCache(nonRelativeName: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; + getOrCreateCacheForNonRelativeName(nonRelativeName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache; + clear(): void; + /** + * Updates with the current compilerOptions the cache will operate with. + * This updates the redirects map as well if needed so module resolutions are cached if they can across the projects + */ + update(options: CompilerOptions): void; + } + interface PerNonRelativeNameCache { + get(directory: string): T | undefined; + set(directory: string, result: T): void; + } interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getPackageJsonInfoCache(): PackageJsonInfoCache; } @@ -5284,16 +5299,14 @@ declare namespace ts { * Stored map from non-relative module name to a table: directory -> result of module lookup in this directory * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. */ - interface NonRelativeModuleNameResolutionCache extends PackageJsonInfoCache { + interface NonRelativeModuleNameResolutionCache extends NonRelativeNameResolutionCache, PackageJsonInfoCache { + /** @deprecated Use getOrCreateCacheForNonRelativeName */ getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; } interface PackageJsonInfoCache { clear(): void; } - interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; - set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; - } + type PerModuleNameCache = PerNonRelativeNameCache; /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * diff --git a/tests/baselines/reference/library-reference-6.trace.json b/tests/baselines/reference/library-reference-6.trace.json index da7f6712612..33c7d2c28bc 100644 --- a/tests/baselines/reference/library-reference-6.trace.json +++ b/tests/baselines/reference/library-reference-6.trace.json @@ -5,10 +5,7 @@ "File '/node_modules/@types/alpha/index.d.ts' exist - use it as a name resolution result.", "Resolving real path for '/node_modules/@types/alpha/index.d.ts', result '/node_modules/@types/alpha/index.d.ts'.", "======== Type reference directive 'alpha' was successfully resolved to '/node_modules/@types/alpha/index.d.ts', primary: true. ========", - "======== Resolving type reference directive 'alpha', containing file '/__inferred type names__.ts', root directory '/node_modules/@types'. ========", - "Resolving with primary search path '/node_modules/@types'.", - "File '/node_modules/@types/alpha/package.json' does not exist according to earlier cached lookups.", - "File '/node_modules/@types/alpha/index.d.ts' exist - use it as a name resolution result.", - "Resolving real path for '/node_modules/@types/alpha/index.d.ts', result '/node_modules/@types/alpha/index.d.ts'.", + "======== Resolving type reference directive 'alpha', containing file '/__inferred type names__.ts'. ========", + "Resolution for type reference directive 'alpha' was found in cache from location '/'.", "======== Type reference directive 'alpha' was successfully resolved to '/node_modules/@types/alpha/index.d.ts', primary: true. ========" ] \ No newline at end of file