mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Module Resolution and Type Reference directive cache updates and its API changes (#43700)
* Make the module resolution cache apis for updating compiler options or clearing it * Cache package.json lookup results from module resolution * Use per directory cache for type reference directive resolution as well * Update Baselines and/or Applied Lint Fixes * Change trace according to feedback * Update Baselines and/or Applied Lint Fixes Co-authored-by: TypeScript Bot <typescriptbot@microsoft.com>
This commit is contained in:
@@ -4849,6 +4849,22 @@
|
||||
"category": "Error",
|
||||
"code": 6238
|
||||
},
|
||||
"File '{0}' exists according to earlier cached lookups.": {
|
||||
"category": "Message",
|
||||
"code": 6239
|
||||
},
|
||||
"File '{0}' does not exist according to earlier cached lookups.": {
|
||||
"category": "Message",
|
||||
"code": 6240
|
||||
},
|
||||
"Resolution for type reference directive '{0}' was found in cache from location '{1}'.": {
|
||||
"category": "Message",
|
||||
"code": 6241
|
||||
},
|
||||
"======== Resolving type reference directive '{0}', containing file '{1}'. ========": {
|
||||
"category": "Message",
|
||||
"code": 6242
|
||||
},
|
||||
|
||||
"Projects to reference": {
|
||||
"category": "Message",
|
||||
|
||||
@@ -101,9 +101,11 @@ namespace ts {
|
||||
traceEnabled: boolean;
|
||||
failedLookupLocations: Push<string>;
|
||||
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<string[]>;
|
||||
@@ -281,13 +284,24 @@ 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, cache?: TypeReferenceDirectiveResolutionCache): ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
|
||||
const traceEnabled = isTraceEnabled(options, host);
|
||||
if (redirectedReference) {
|
||||
options = redirectedReference.commandLine.options;
|
||||
}
|
||||
const failedLookupLocations: string[] = [];
|
||||
const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled, failedLookupLocations };
|
||||
|
||||
const containingDirectory = containingFile ? getDirectoryPath(containingFile) : undefined;
|
||||
const perFolderCache = containingDirectory ? cache && cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference) : undefined;
|
||||
let result = perFolderCache && perFolderCache.get(typeReferenceDirectiveName);
|
||||
if (result) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1, typeReferenceDirectiveName, containingFile);
|
||||
if (redirectedReference) trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName);
|
||||
trace(host, Diagnostics.Resolution_for_type_reference_directive_0_was_found_in_cache_from_location_1, typeReferenceDirectiveName, containingDirectory);
|
||||
traceResult(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const typeRoots = getEffectiveTypeRoots(options, host);
|
||||
if (traceEnabled) {
|
||||
@@ -312,6 +326,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled, failedLookupLocations, packageJsonInfoCache: cache };
|
||||
let resolved = primaryLookup();
|
||||
let primary = true;
|
||||
if (!resolved) {
|
||||
@@ -323,18 +339,24 @@ namespace ts {
|
||||
if (resolved) {
|
||||
const { fileName, packageId } = resolved;
|
||||
const resolvedFileName = options.preserveSymlinks ? fileName : realPath(fileName, host, traceEnabled);
|
||||
if (traceEnabled) {
|
||||
if (packageId) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_with_Package_ID_2_primary_Colon_3, typeReferenceDirectiveName, resolvedFileName, packageIdToString(packageId), primary);
|
||||
}
|
||||
else {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFileName, primary);
|
||||
}
|
||||
}
|
||||
resolvedTypeReferenceDirective = { primary, resolvedFileName, packageId, isExternalLibraryImport: pathContainsNodeModules(fileName) };
|
||||
}
|
||||
result = { resolvedTypeReferenceDirective, failedLookupLocations };
|
||||
perFolderCache?.set(typeReferenceDirectiveName, result);
|
||||
if (traceEnabled) traceResult(result);
|
||||
return result;
|
||||
|
||||
return { resolvedTypeReferenceDirective, failedLookupLocations };
|
||||
function traceResult(result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) {
|
||||
if (!result.resolvedTypeReferenceDirective?.resolvedFileName) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
|
||||
}
|
||||
else if (result.resolvedTypeReferenceDirective.packageId) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_with_Package_ID_2_primary_Colon_3, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, packageIdToString(result.resolvedTypeReferenceDirective.packageId), result.resolvedTypeReferenceDirective.primary);
|
||||
}
|
||||
else {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, result.resolvedTypeReferenceDirective.primary);
|
||||
}
|
||||
}
|
||||
|
||||
function primaryLookup(): PathAndPackageId | undefined {
|
||||
// Check primary library paths
|
||||
@@ -378,11 +400,7 @@ namespace ts {
|
||||
const { path: candidate } = normalizePathAndParts(combinePaths(initialLocationForSecondaryLookup, typeReferenceDirectiveName));
|
||||
result = nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true);
|
||||
}
|
||||
const resolvedFile = resolvedTypeScriptOnly(result);
|
||||
if (!resolvedFile && traceEnabled) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
|
||||
}
|
||||
return resolvedFile;
|
||||
return resolvedTypeScriptOnly(result);
|
||||
}
|
||||
else {
|
||||
if (traceEnabled) {
|
||||
@@ -437,22 +455,39 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>, PackageJsonInfoCache {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached module resolutions per containing directory.
|
||||
* Cached 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 {
|
||||
getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map<ResolvedModuleWithFailedLookupLocations>;
|
||||
/*@internal*/ directoryToModuleNameMap: CacheWithRedirects<ESMap<string, ResolvedModuleWithFailedLookupLocations>>;
|
||||
export interface PerDirectoryResolutionCache<T> {
|
||||
getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map<T>;
|
||||
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 ModuleResolutionCache extends PerDirectoryResolutionCache<ResolvedModuleWithFailedLookupLocations>, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache {
|
||||
getPackageJsonInfoCache(): PackageJsonInfoCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
/*@internal*/ moduleNameToDirectoryMap: CacheWithRedirects<PerModuleNameCache>;
|
||||
}
|
||||
|
||||
export interface PackageJsonInfoCache {
|
||||
/*@internal*/ getPackageJsonInfo(packageJsonPath: string): PackageJsonInfo | boolean | undefined;
|
||||
/*@internal*/ setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | boolean): void;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
export interface PerModuleNameCache {
|
||||
@@ -460,16 +495,6 @@ namespace ts {
|
||||
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
|
||||
}
|
||||
|
||||
export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache {
|
||||
return createModuleResolutionCacheWithMaps(
|
||||
createCacheWithRedirects(options),
|
||||
createCacheWithRedirects(options),
|
||||
currentDirectory,
|
||||
getCanonicalFileName
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*@internal*/
|
||||
export interface CacheWithRedirects<T> {
|
||||
ownMap: ESMap<string, T>;
|
||||
@@ -521,33 +546,125 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function createModuleResolutionCacheWithMaps(
|
||||
directoryToModuleNameMap: CacheWithRedirects<ESMap<string, ResolvedModuleWithFailedLookupLocations>>,
|
||||
moduleNameToDirectoryMap: CacheWithRedirects<PerModuleNameCache>,
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: GetCanonicalFileName): ModuleResolutionCache {
|
||||
function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache {
|
||||
let cache: ESMap<Path, PackageJsonInfo | boolean> | undefined;
|
||||
return { getPackageJsonInfo, setPackageJsonInfo, clear };
|
||||
function getPackageJsonInfo(packageJsonPath: string) {
|
||||
return cache?.get(toPath(packageJsonPath, currentDirectory, getCanonicalFileName));
|
||||
}
|
||||
function setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | boolean) {
|
||||
(cache ||= new Map()).set(toPath(packageJsonPath, currentDirectory, getCanonicalFileName), info);
|
||||
}
|
||||
function clear() {
|
||||
cache = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName, directoryToModuleNameMap, moduleNameToDirectoryMap };
|
||||
function getOrCreateCache<T>(cacheWithRedirects: CacheWithRedirects<T>, redirectedReference: ResolvedProjectReference | undefined, key: string, create: () => T): T {
|
||||
const cache = cacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference);
|
||||
let result = cache.get(key);
|
||||
if (!result) {
|
||||
result = create();
|
||||
cache.set(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function updateRedirectsMap<T>(
|
||||
options: CompilerOptions,
|
||||
directoryToModuleNameMap: CacheWithRedirects<ESMap<string, T>>,
|
||||
moduleNameToDirectoryMap?: CacheWithRedirects<PerModuleNameCache>
|
||||
) {
|
||||
if (!options.configFile) return;
|
||||
if (directoryToModuleNameMap.redirectsMap.size === 0) {
|
||||
// The own map will be for projectCompilerOptions
|
||||
Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.redirectsMap.size === 0);
|
||||
Debug.assert(directoryToModuleNameMap.ownMap.size === 0);
|
||||
Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.ownMap.size === 0);
|
||||
directoryToModuleNameMap.redirectsMap.set(options.configFile.path, directoryToModuleNameMap.ownMap);
|
||||
moduleNameToDirectoryMap?.redirectsMap.set(options.configFile.path, moduleNameToDirectoryMap.ownMap);
|
||||
}
|
||||
else {
|
||||
// Set correct own map
|
||||
Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.redirectsMap.size > 0);
|
||||
const ref: ResolvedProjectReference = {
|
||||
sourceFile: options.configFile,
|
||||
commandLine: { options } as ParsedCommandLine
|
||||
};
|
||||
directoryToModuleNameMap.setOwnMap(directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref));
|
||||
moduleNameToDirectoryMap?.setOwnMap(moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref));
|
||||
}
|
||||
directoryToModuleNameMap.setOwnOptions(options);
|
||||
moduleNameToDirectoryMap?.setOwnOptions(options);
|
||||
}
|
||||
|
||||
function createPerDirectoryResolutionCache<T>(currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, directoryToModuleNameMap: CacheWithRedirects<ESMap<string, T>>): PerDirectoryResolutionCache<T> {
|
||||
return {
|
||||
getOrCreateCacheForDirectory,
|
||||
clear,
|
||||
update,
|
||||
};
|
||||
|
||||
function clear() {
|
||||
directoryToModuleNameMap.clear();
|
||||
}
|
||||
|
||||
function update(options: CompilerOptions) {
|
||||
updateRedirectsMap(options, directoryToModuleNameMap);
|
||||
}
|
||||
|
||||
function getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference) {
|
||||
const path = toPath(directoryName, currentDirectory, getCanonicalFileName);
|
||||
return getOrCreateCache<ESMap<string, ResolvedModuleWithFailedLookupLocations>>(directoryToModuleNameMap, redirectedReference, path, () => new Map());
|
||||
return getOrCreateCache<ESMap<string, T>>(directoryToModuleNameMap, redirectedReference, path, () => new Map());
|
||||
}
|
||||
}
|
||||
|
||||
export function createModuleResolutionCache(
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: (s: string) => string,
|
||||
options?: CompilerOptions
|
||||
): ModuleResolutionCache;
|
||||
/*@internal*/
|
||||
export function createModuleResolutionCache(
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
options: undefined,
|
||||
directoryToModuleNameMap: CacheWithRedirects<ESMap<string, ResolvedModuleWithFailedLookupLocations>>,
|
||||
moduleNameToDirectoryMap: CacheWithRedirects<PerModuleNameCache>,
|
||||
): ModuleResolutionCache;
|
||||
export function createModuleResolutionCache(
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
options?: CompilerOptions,
|
||||
directoryToModuleNameMap?: CacheWithRedirects<ESMap<string, ResolvedModuleWithFailedLookupLocations>>,
|
||||
moduleNameToDirectoryMap?: CacheWithRedirects<PerModuleNameCache>,
|
||||
): ModuleResolutionCache {
|
||||
const preDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap ||= createCacheWithRedirects(options));
|
||||
moduleNameToDirectoryMap ||= createCacheWithRedirects(options);
|
||||
const packageJsonInfoCache = createPackageJsonInfoCache(currentDirectory, getCanonicalFileName);
|
||||
|
||||
return {
|
||||
...packageJsonInfoCache,
|
||||
...preDirectoryResolutionCache,
|
||||
getOrCreateCacheForModuleName,
|
||||
clear,
|
||||
update,
|
||||
getPackageJsonInfoCache: () => packageJsonInfoCache,
|
||||
};
|
||||
|
||||
function clear() {
|
||||
preDirectoryResolutionCache.clear();
|
||||
moduleNameToDirectoryMap!.clear();
|
||||
packageJsonInfoCache.clear();
|
||||
}
|
||||
|
||||
function update(options: CompilerOptions) {
|
||||
updateRedirectsMap(options, directoryToModuleNameMap!, moduleNameToDirectoryMap);
|
||||
}
|
||||
|
||||
function getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache {
|
||||
Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName));
|
||||
return getOrCreateCache(moduleNameToDirectoryMap, redirectedReference, nonRelativeModuleName, createPerModuleNameCache);
|
||||
}
|
||||
|
||||
function getOrCreateCache<T>(cacheWithRedirects: CacheWithRedirects<T>, redirectedReference: ResolvedProjectReference | undefined, key: string, create: () => T): T {
|
||||
const cache = cacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference);
|
||||
let result = cache.get(key);
|
||||
if (!result) {
|
||||
result = create();
|
||||
cache.set(key, result);
|
||||
}
|
||||
return result;
|
||||
return getOrCreateCache(moduleNameToDirectoryMap!, redirectedReference, nonRelativeModuleName, createPerModuleNameCache);
|
||||
}
|
||||
|
||||
function createPerModuleNameCache(): PerModuleNameCache {
|
||||
@@ -623,6 +740,42 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function createTypeReferenceDirectiveResolutionCache(
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: (s: string) => string,
|
||||
options?: CompilerOptions,
|
||||
packageJsonInfoCache?: PackageJsonInfoCache,
|
||||
): TypeReferenceDirectiveResolutionCache;
|
||||
/*@internal*/
|
||||
export function createTypeReferenceDirectiveResolutionCache(
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
options: undefined,
|
||||
packageJsonInfoCache: PackageJsonInfoCache | undefined,
|
||||
directoryToModuleNameMap: CacheWithRedirects<ESMap<string, ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>,
|
||||
): TypeReferenceDirectiveResolutionCache;
|
||||
export function createTypeReferenceDirectiveResolutionCache(
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
options?: CompilerOptions,
|
||||
packageJsonInfoCache?: PackageJsonInfoCache | undefined,
|
||||
directoryToModuleNameMap?: CacheWithRedirects<ESMap<string, ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>,
|
||||
): TypeReferenceDirectiveResolutionCache {
|
||||
const preDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap ||= createCacheWithRedirects(options));
|
||||
packageJsonInfoCache ||= createPackageJsonInfoCache(currentDirectory, getCanonicalFileName);
|
||||
|
||||
return {
|
||||
...packageJsonInfoCache,
|
||||
...preDirectoryResolutionCache,
|
||||
clear,
|
||||
};
|
||||
|
||||
function clear() {
|
||||
preDirectoryResolutionCache.clear();
|
||||
packageJsonInfoCache!.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined {
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory);
|
||||
@@ -931,7 +1084,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);
|
||||
@@ -1137,6 +1290,7 @@ namespace ts {
|
||||
return withPackageId(packageInfo, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths));
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
interface PackageJsonInfo {
|
||||
packageDirectory: string;
|
||||
packageJsonContent: PackageJsonPathFields;
|
||||
@@ -1145,21 +1299,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 (typeof existing !== "boolean") {
|
||||
if (traceEnabled) trace(host, Diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath);
|
||||
return existing;
|
||||
}
|
||||
else {
|
||||
if (existing && traceEnabled) trace(host, Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, 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, directoryExists);
|
||||
// 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);
|
||||
}
|
||||
@@ -1448,7 +1621,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);
|
||||
@@ -1492,13 +1665,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);
|
||||
}
|
||||
|
||||
@@ -843,6 +843,7 @@ namespace ts {
|
||||
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | false | undefined;
|
||||
|
||||
let moduleResolutionCache: ModuleResolutionCache | undefined;
|
||||
let typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | 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<ResolvedModuleFull>(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
|
||||
typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache());
|
||||
const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveTypeReferenceDirective(
|
||||
typesRef,
|
||||
containingFile,
|
||||
options,
|
||||
host,
|
||||
redirectedReference,
|
||||
typeReferenceDirectiveResolutionCache,
|
||||
).resolvedTypeReferenceDirective!; // TODO: GH#18217
|
||||
actualResolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile, redirectedReference) => loadWithLocalCache<ResolvedTypeReferenceDirective>(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, loader);
|
||||
}
|
||||
|
||||
@@ -1036,6 +1045,8 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
typeReferenceDirectiveResolutionCache = undefined;
|
||||
|
||||
// unconditionally set oldProgram to undefined to prevent it from being captured in closure
|
||||
oldProgram = undefined;
|
||||
|
||||
|
||||
@@ -166,15 +166,23 @@ namespace ts {
|
||||
const resolvedModuleNames = new Map<Path, ESMap<string, CachedResolvedModuleWithFailedLookupLocations>>();
|
||||
const perDirectoryResolvedModuleNames: CacheWithRedirects<ESMap<string, CachedResolvedModuleWithFailedLookupLocations>> = createCacheWithRedirects();
|
||||
const nonRelativeModuleNameCache: CacheWithRedirects<PerModuleNameCache> = createCacheWithRedirects();
|
||||
const moduleResolutionCache = createModuleResolutionCacheWithMaps(
|
||||
const moduleResolutionCache = createModuleResolutionCache(
|
||||
getCurrentDirectory(),
|
||||
resolutionHost.getCanonicalFileName,
|
||||
/*options*/ undefined,
|
||||
perDirectoryResolvedModuleNames,
|
||||
nonRelativeModuleNameCache,
|
||||
getCurrentDirectory(),
|
||||
resolutionHost.getCanonicalFileName
|
||||
);
|
||||
|
||||
const resolvedTypeReferenceDirectives = new Map<Path, ESMap<string, CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
|
||||
const perDirectoryResolvedTypeReferenceDirectives: CacheWithRedirects<ESMap<string, CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations>> = createCacheWithRedirects();
|
||||
const typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(
|
||||
getCurrentDirectory(),
|
||||
resolutionHost.getCanonicalFileName,
|
||||
/*options*/ undefined,
|
||||
moduleResolutionCache.getPackageJsonInfoCache(),
|
||||
perDirectoryResolvedTypeReferenceDirectives
|
||||
);
|
||||
|
||||
/**
|
||||
* These are the extensions that failed lookup files will have by default,
|
||||
@@ -284,9 +292,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function clearPerDirectoryResolutions() {
|
||||
perDirectoryResolvedModuleNames.clear();
|
||||
nonRelativeModuleNameCache.clear();
|
||||
perDirectoryResolvedTypeReferenceDirectives.clear();
|
||||
moduleResolutionCache.clear();
|
||||
typeReferenceDirectiveResolutionCache.clear();
|
||||
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions);
|
||||
nonRelativeExternalModuleResolutions.clear();
|
||||
}
|
||||
@@ -320,7 +327,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;
|
||||
@@ -333,6 +342,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, typeReferenceDirectiveResolutionCache);
|
||||
}
|
||||
|
||||
interface ResolveNamesWithLocalCacheInput<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName> {
|
||||
names: readonly string[];
|
||||
containingFile: string;
|
||||
|
||||
@@ -238,6 +238,7 @@ namespace ts {
|
||||
|
||||
readonly compilerHost: CompilerHost;
|
||||
readonly moduleResolutionCache: ModuleResolutionCache | undefined;
|
||||
readonly typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined;
|
||||
|
||||
// Mutable state
|
||||
buildOrder: AnyBuildOrder | undefined;
|
||||
@@ -275,11 +276,17 @@ namespace ts {
|
||||
compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames);
|
||||
compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives);
|
||||
const moduleResolutionCache = !compilerHost.resolveModuleNames ? createModuleResolutionCache(currentDirectory, getCanonicalFileName) : undefined;
|
||||
const typeReferenceDirectiveResolutionCache = !compilerHost.resolveTypeReferenceDirectives ? createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache()) : undefined;
|
||||
if (!compilerHost.resolveModuleNames) {
|
||||
const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, state.projectCompilerOptions, compilerHost, moduleResolutionCache, redirectedReference).resolvedModule!;
|
||||
compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference) =>
|
||||
loadWithLocalCache<ResolvedModuleFull>(Debug.checkEachDefined(moduleNames), containingFile, redirectedReference, loader);
|
||||
}
|
||||
if (!compilerHost.resolveTypeReferenceDirectives) {
|
||||
const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveTypeReferenceDirective(moduleName, containingFile, state.projectCompilerOptions, compilerHost, redirectedReference, state.typeReferenceDirectiveResolutionCache).resolvedTypeReferenceDirective!;
|
||||
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile, redirectedReference) =>
|
||||
loadWithLocalCache<ResolvedTypeReferenceDirective>(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, loader);
|
||||
}
|
||||
|
||||
const { watchFile, watchDirectory, writeLog } = createWatchFactory<ResolvedConfigFileName>(hostWithWatch, options);
|
||||
|
||||
@@ -310,6 +317,7 @@ namespace ts {
|
||||
|
||||
compilerHost,
|
||||
moduleResolutionCache,
|
||||
typeReferenceDirectiveResolutionCache,
|
||||
|
||||
// Mutable state
|
||||
buildOrder: undefined,
|
||||
@@ -548,7 +556,7 @@ namespace ts {
|
||||
function disableCache(state: SolutionBuilderState) {
|
||||
if (!state.cache) return;
|
||||
|
||||
const { cache, host, compilerHost, extendedConfigCache, moduleResolutionCache } = state;
|
||||
const { cache, host, compilerHost, extendedConfigCache, moduleResolutionCache, typeReferenceDirectiveResolutionCache } = state;
|
||||
|
||||
host.readFile = cache.originalReadFile;
|
||||
host.fileExists = cache.originalFileExists;
|
||||
@@ -558,10 +566,8 @@ namespace ts {
|
||||
compilerHost.getSourceFile = cache.originalGetSourceFile;
|
||||
state.readFileWithCache = cache.originalReadFileWithCache;
|
||||
extendedConfigCache.clear();
|
||||
if (moduleResolutionCache) {
|
||||
moduleResolutionCache.directoryToModuleNameMap.clear();
|
||||
moduleResolutionCache.moduleNameToDirectoryMap.clear();
|
||||
}
|
||||
moduleResolutionCache?.clear();
|
||||
typeReferenceDirectiveResolutionCache?.clear();
|
||||
state.cache = undefined;
|
||||
}
|
||||
|
||||
@@ -842,7 +848,7 @@ namespace ts {
|
||||
const { host, compilerHost } = state;
|
||||
state.projectCompilerOptions = config.options;
|
||||
// Update module resolution cache if needed
|
||||
updateModuleResolutionCache(state, project, config);
|
||||
state.moduleResolutionCache?.update(config.options);
|
||||
|
||||
// Create program
|
||||
program = host.createProgram(
|
||||
@@ -1306,37 +1312,6 @@ namespace ts {
|
||||
return { buildResult, step: BuildStep.QueueReferencingProjects };
|
||||
}
|
||||
|
||||
function updateModuleResolutionCache(
|
||||
state: SolutionBuilderState,
|
||||
proj: ResolvedConfigFileName,
|
||||
config: ParsedCommandLine
|
||||
) {
|
||||
if (!state.moduleResolutionCache) return;
|
||||
|
||||
// Update module resolution cache if needed
|
||||
const { moduleResolutionCache } = state;
|
||||
const projPath = toPath(state, 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: config.options.configFile!,
|
||||
commandLine: config
|
||||
};
|
||||
moduleResolutionCache.directoryToModuleNameMap.setOwnMap(moduleResolutionCache.directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref));
|
||||
moduleResolutionCache.moduleNameToDirectoryMap.setOwnMap(moduleResolutionCache.moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref));
|
||||
}
|
||||
moduleResolutionCache.directoryToModuleNameMap.setOwnOptions(config.options);
|
||||
moduleResolutionCache.moduleNameToDirectoryMap.setOwnOptions(config.options);
|
||||
}
|
||||
|
||||
function checkConfigFileUpToDateStatus(state: SolutionBuilderState, configFile: string, oldestOutputFileTime: Date, oldestOutputFileName: string): Status.OutOfDateWithSelf | undefined {
|
||||
// Check tsconfig time
|
||||
const tsconfigTime = getModifiedTime(state.host, configFile);
|
||||
|
||||
@@ -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.",
|
||||
"File 'node_modules/a/package.json' does not exist according to earlier cached lookups.",
|
||||
"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.",
|
||||
|
||||
Reference in New Issue
Block a user