From 960403ac7e248d8bf18ddcffffba89e6c4c505be Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 19 Apr 2021 13:27:00 -0700 Subject: [PATCH] Cache package.json lookup results from module resolution --- src/compiler/diagnosticMessages.json | 8 +++ src/compiler/moduleNameResolver.ts | 69 +++++++++++++++---- src/compiler/program.ts | 15 +++- src/compiler/resolutionCache.ts | 8 ++- .../unittests/reuseProgramStructure.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 27 +++++--- tests/baselines/reference/api/typescript.d.ts | 27 +++++--- 7 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 270c1b7da3437..a25a5510f9e2e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -5041,6 +5041,14 @@ "code": 6387, "reportsDeprecated": true }, + "Using cached result of 'package.json' at '{0}' that indicates it was found.": { + "category": "Message", + "code": 6388 + }, + "Using cached result of 'package.json' at '{0}' that indicates it was not found.": { + "category": "Message", + "code": 6389 + }, "The expected type comes from property '{0}' which is declared here on type '{1}'": { "category": "Message", diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index fb1651e2f4ad3..4aa23eb1169cc 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -101,9 +101,11 @@ namespace ts { traceEnabled: boolean; failedLookupLocations: Push; resultFromCache?: ResolvedModuleWithFailedLookupLocations; + packageJsonInfoCache: PackageJsonInfoCache | undefined; } /** Just the fields that we use for module resolution. */ + /*@internal*/ interface PackageJsonPathFields { typings?: string; types?: string; @@ -179,6 +181,7 @@ namespace ts { return typesVersions; } + /*@internal*/ interface VersionPaths { version: string; paths: MapLike; @@ -281,13 +284,13 @@ namespace ts { * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ - export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { + export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, packageJsonInfoCache?: PackageJsonInfoCache): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { const traceEnabled = isTraceEnabled(options, host); if (redirectedReference) { options = redirectedReference.commandLine.options; } const failedLookupLocations: string[] = []; - const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled, failedLookupLocations }; + const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled, failedLookupLocations, packageJsonInfoCache }; const typeRoots = getEffectiveTypeRoots(options, host); if (traceEnabled) { @@ -441,7 +444,7 @@ namespace ts { * Cached module resolutions per containing directory. * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ - export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache { + export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map; clear(): void; /** @@ -455,10 +458,16 @@ 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. */ - export interface NonRelativeModuleNameResolutionCache { + export interface NonRelativeModuleNameResolutionCache extends PackageJsonInfoCache { getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; } + export interface PackageJsonInfoCache { + /*@internal*/ getPackageJsonInfo(packageJsonPath: string): PackageJsonInfo | false | undefined; + /*@internal*/ setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | false): void; + clear(): void; + } + export interface PerModuleNameCache { get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; @@ -525,14 +534,29 @@ namespace ts { } } + export function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache { + let cache: ESMap | undefined; + return { getPackageJsonInfo, setPackageJsonInfo, clear }; + function getPackageJsonInfo(packageJsonPath: string) { + return cache?.get(toPath(packageJsonPath, currentDirectory, getCanonicalFileName)); + } + function setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | false) { + (cache ||= new Map()).set(toPath(packageJsonPath, currentDirectory, getCanonicalFileName), info); + } + function clear() { + cache = undefined; + } + } + /*@internal*/ export function createModuleResolutionCacheWithMaps( directoryToModuleNameMap: CacheWithRedirects>, moduleNameToDirectoryMap: CacheWithRedirects, currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): ModuleResolutionCache { - + const packageJsonInfoCache = createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); return { + ...packageJsonInfoCache, getOrCreateCacheForDirectory, getOrCreateCacheForModuleName, clear, @@ -542,6 +566,7 @@ namespace ts { function clear() { directoryToModuleNameMap.clear(); moduleNameToDirectoryMap.clear(); + packageJsonInfoCache.clear(); } function update(options: CompilerOptions) { @@ -969,7 +994,7 @@ namespace ts { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; - const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations }; + const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations, packageJsonInfoCache: cache }; const result = forEach(extensions, ext => tryResolve(ext)); return createResolvedModuleWithFailedLookupLocations(result?.value?.resolved, result?.value?.isExternalLibraryImport, failedLookupLocations, state.resultFromCache); @@ -1175,6 +1200,7 @@ namespace ts { return withPackageId(packageInfo, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths)); } + /*@internal*/ interface PackageJsonInfo { packageDirectory: string; packageJsonContent: PackageJsonPathFields; @@ -1183,21 +1209,40 @@ namespace ts { function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PackageJsonInfo | undefined { const { host, traceEnabled } = state; - const directoryExists = !onlyRecordFailures && directoryProbablyExists(packageDirectory, host); const packageJsonPath = combinePaths(packageDirectory, "package.json"); + if (onlyRecordFailures) { + state.failedLookupLocations.push(packageJsonPath); + return undefined; + } + + const existing = state.packageJsonInfoCache?.getPackageJsonInfo(packageJsonPath); + if (existing !== undefined) { + if (existing) { + if (traceEnabled) trace(host, Diagnostics.Using_cached_result_of_package_json_at_0_that_indicates_it_was_found, packageJsonPath); + return existing; + } + else { + if (traceEnabled) trace(host, Diagnostics.Using_cached_result_of_package_json_at_0_that_indicates_it_was_not_found, packageJsonPath); + state.failedLookupLocations.push(packageJsonPath); + return undefined; + } + } + const directoryExists = directoryProbablyExists(packageDirectory, host); if (directoryExists && host.fileExists(packageJsonPath)) { const packageJsonContent = readJson(packageJsonPath, host) as PackageJson; if (traceEnabled) { trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath); } const versionPaths = readPackageJsonTypesVersionPaths(packageJsonContent, state); - return { packageDirectory, packageJsonContent, versionPaths }; + const result = { packageDirectory, packageJsonContent, versionPaths }; + state.packageJsonInfoCache?.setPackageJsonInfo(packageJsonPath, result); + return result; } else { if (directoryExists && traceEnabled) { trace(host, Diagnostics.File_0_does_not_exist, packageJsonPath); } - + state.packageJsonInfoCache?.setPackageJsonInfo(packageJsonPath, false); // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results state.failedLookupLocations.push(packageJsonPath); } @@ -1486,7 +1531,7 @@ namespace ts { export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; - const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations }; + const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations, packageJsonInfoCache: cache }; const containingDirectory = getDirectoryPath(containingFile); const resolved = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript); @@ -1530,13 +1575,13 @@ namespace ts { * This is the minumum code needed to expose that functionality; the rest is in the host. */ /* @internal */ - export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string): ResolvedModuleWithFailedLookupLocations { + export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string, packageJsonInfoCache: PackageJsonInfoCache): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); if (traceEnabled) { trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache); } const failedLookupLocations: string[] = []; - const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations }; + const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations, packageJsonInfoCache }; const resolved = loadModuleFromImmediateNodeModulesDirectory(Extensions.DtsOnly, moduleName, globalCache, state, /*typesScopeOnly*/ false); return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations, state.resultFromCache); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 29231b7fa5786..6f3fb4eeb1092 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -843,6 +843,7 @@ namespace ts { let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | false | undefined; let moduleResolutionCache: ModuleResolutionCache | undefined; + let packageJsonInfoCache: PackageJsonInfoCache | undefined; let actualResolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference) => ResolvedModuleFull[]; const hasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse; if (host.resolveModuleNames) { @@ -857,7 +858,7 @@ namespace ts { }); } else { - moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x), options); + moduleResolutionCache = createModuleResolutionCache(currentDirectory, getCanonicalFileName, options); const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache, redirectedReference).resolvedModule!; // TODO: GH#18217 actualResolveModuleNamesWorker = (moduleNames, containingFile, _reusedNames, redirectedReference) => loadWithLocalCache(Debug.checkEachDefined(moduleNames), containingFile, redirectedReference, loader); } @@ -867,7 +868,15 @@ namespace ts { actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference) => host.resolveTypeReferenceDirectives!(Debug.checkEachDefined(typeDirectiveNames), containingFile, redirectedReference, options); } else { - const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveTypeReferenceDirective(typesRef, containingFile, options, host, redirectedReference).resolvedTypeReferenceDirective!; // TODO: GH#18217 + packageJsonInfoCache = moduleResolutionCache || createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); + const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveTypeReferenceDirective( + typesRef, + containingFile, + options, + host, + redirectedReference, + packageJsonInfoCache, + ).resolvedTypeReferenceDirective!; // TODO: GH#18217 actualResolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile, redirectedReference) => loadWithLocalCache(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, loader); } @@ -1036,6 +1045,8 @@ namespace ts { ); } + packageJsonInfoCache = undefined; + // unconditionally set oldProgram to undefined to prevent it from being captured in closure oldProgram = undefined; diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 65dde198c286a..28ebf28e52739 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -319,7 +319,9 @@ namespace ts { resolutionHost.projectName, compilerOptions, host, - globalCache); + globalCache, + moduleResolutionCache, + ); if (resolvedModule) { // Modify existing resolution so its saved in the directory cache as well (primaryResult.resolvedModule as any) = resolvedModule; @@ -332,6 +334,10 @@ namespace ts { return primaryResult; } + function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations { + return ts.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host, redirectedReference, moduleResolutionCache); + } + interface ResolveNamesWithLocalCacheInput { names: readonly string[]; containingFile: string; diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index 173113f134dcc..6f185b75312d8 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -474,7 +474,7 @@ namespace ts { "File 'node_modules/@types/a.d.ts' does not exist.", "File 'node_modules/@types/a/index.d.ts' does not exist.", "Loading module 'a' from 'node_modules' folder, target file type 'JavaScript'.", - "File 'node_modules/a/package.json' does not exist.", + "Using cached result of 'package.json' at 'node_modules/a/package.json' that indicates it was not found.", "File 'node_modules/a.js' does not exist.", "File 'node_modules/a.jsx' does not exist.", "File 'node_modules/a/index.js' does not exist.", diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b52222142dcc8..f5edd8edc5330 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4707,13 +4707,13 @@ declare namespace ts { export {}; } declare namespace ts { - function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; + export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; /** * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, packageJsonInfoCache?: PackageJsonInfoCache): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; /** * Given a set of options, returns the set of type directive names * that should be included for this program automatically. @@ -4722,12 +4722,12 @@ declare namespace ts { * More type directives might appear in the program later as a result of loading actual source files; * this list is only the set of defaults that are implicitly included. */ - function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; + export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; /** * Cached module resolutions per containing directory. * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ - interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache { + export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map; clear(): void; /** @@ -4740,18 +4740,23 @@ 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 { + export interface NonRelativeModuleNameResolutionCache extends PackageJsonInfoCache { getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; } - interface PerModuleNameCache { + export interface PackageJsonInfoCache { + clear(): void; + } + export interface PerModuleNameCache { get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } - 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; - function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache; + export function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache; + export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined; + export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export {}; } declare namespace ts { /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index efacca17e7cc4..f409cccf55149 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4707,13 +4707,13 @@ declare namespace ts { export {}; } declare namespace ts { - function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; + export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; /** * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, packageJsonInfoCache?: PackageJsonInfoCache): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; /** * Given a set of options, returns the set of type directive names * that should be included for this program automatically. @@ -4722,12 +4722,12 @@ declare namespace ts { * More type directives might appear in the program later as a result of loading actual source files; * this list is only the set of defaults that are implicitly included. */ - function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; + export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; /** * Cached module resolutions per containing directory. * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ - interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache { + export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map; clear(): void; /** @@ -4740,18 +4740,23 @@ 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 { + export interface NonRelativeModuleNameResolutionCache extends PackageJsonInfoCache { getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; } - interface PerModuleNameCache { + export interface PackageJsonInfoCache { + clear(): void; + } + export interface PerModuleNameCache { get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } - 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; - function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache; + export function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache; + export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined; + export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; + export {}; } declare namespace ts { /**