mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-17 00:34:47 -05:00
Api cleanup for Module and Type Reference directive resolution (#51546)
* Refactoring so CacheWithRedirects has Key and Value type parameters * ModuleResolutionCache or TypeRefDirectiveCache will look in directory before solving, so ResolutionCache doesnt need this check * Test showing module resolution is not shared because resolution cache doesnt update own options * Enable traceResolution on some of the project reference tests * Simplify CacheWithRedirects and ensure the options are set in all common scenarios so cache can be shared between redirects * Make failedlookup etc optional in ResolvedModule/TypeRefefWithFailedLookupLocations Also make accidental public failed lookup internal * Add new API for module and type ref resolution * Store auto type reference resolutions * Modify test to show how using program partially doesnt report resolution diagnostics * Ensure that resolution diagnostics are reported in filePreocessingDiagnostics so they can be reused when program is reused * Some cleanup * Remove the newly added ReoslutionInfo in favor of new APIs * update
This commit is contained in:
@@ -233,7 +233,7 @@ export namespace BuilderState {
|
||||
|
||||
// Handle type reference directives
|
||||
if (sourceFile.resolvedTypeReferenceDirectiveNames) {
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames.forEach((resolvedTypeReferenceDirective) => {
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames.forEach(({ resolvedTypeReferenceDirective }) => {
|
||||
if (!resolvedTypeReferenceDirective) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1333,8 +1333,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
host.getSourceFiles().forEach(sf => {
|
||||
if (!sf.resolvedModules) return;
|
||||
|
||||
sf.resolvedModules.forEach(r => {
|
||||
if (r && r.packageId) map.set(r.packageId.name, r.extension === Extension.Dts || !!map.get(r.packageId.name));
|
||||
sf.resolvedModules.forEach(({ resolvedModule }) => {
|
||||
if (resolvedModule?.packageId) map.set(resolvedModule.packageId.name, resolvedModule.extension === Extension.Dts || !!map.get(resolvedModule.packageId.name));
|
||||
});
|
||||
});
|
||||
return map;
|
||||
@@ -44897,15 +44897,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// this variable and functions that use it are deliberately moved here from the outer scope
|
||||
// to avoid scope pollution
|
||||
const resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives();
|
||||
let fileToDirective: Map<string, [specifier: string, mode: ResolutionMode | undefined]>;
|
||||
let fileToDirective: Map<string, [specifier: string, mode: ResolutionMode]>;
|
||||
if (resolvedTypeReferenceDirectives) {
|
||||
// populate reverse mapping: file path -> type reference directive that was resolved to this file
|
||||
fileToDirective = new Map<string, [specifier: string, mode: ResolutionMode | undefined]>();
|
||||
resolvedTypeReferenceDirectives.forEach((resolvedDirective, key, mode) => {
|
||||
if (!resolvedDirective || !resolvedDirective.resolvedFileName) {
|
||||
fileToDirective = new Map<string, [specifier: string, mode: ResolutionMode]>();
|
||||
resolvedTypeReferenceDirectives.forEach(({ resolvedTypeReferenceDirective }, key, mode) => {
|
||||
if (!resolvedTypeReferenceDirective?.resolvedFileName) {
|
||||
return;
|
||||
}
|
||||
const file = host.getSourceFile(resolvedDirective.resolvedFileName);
|
||||
const file = host.getSourceFile(resolvedTypeReferenceDirective.resolvedFileName);
|
||||
if (file) {
|
||||
// Add the transitive closure of path references loaded by this file (as long as they are not)
|
||||
// part of an existing type reference.
|
||||
@@ -45032,7 +45032,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
// defined here to avoid outer scope pollution
|
||||
function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode | undefined][] | undefined {
|
||||
function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode][] | undefined {
|
||||
// program does not have any files with type reference directives - bail out
|
||||
if (!fileToDirective) {
|
||||
return undefined;
|
||||
@@ -45057,13 +45057,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
// defined here to avoid outer scope pollution
|
||||
function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode | undefined][] | undefined {
|
||||
function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode][] | undefined {
|
||||
// program does not have any files with type reference directives - bail out
|
||||
if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) {
|
||||
return undefined;
|
||||
}
|
||||
// check what declarations in the symbol can contribute to the target meaning
|
||||
let typeReferenceDirectives: [specifier: string, mode: ResolutionMode | undefined][] | undefined;
|
||||
let typeReferenceDirectives: [specifier: string, mode: ResolutionMode][] | undefined;
|
||||
for (const decl of symbol.declarations!) {
|
||||
// check meaning of the local symbol to see if declaration needs to be analyzed further
|
||||
if (decl.symbol && decl.symbol.flags & meaning!) {
|
||||
@@ -45114,7 +45114,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: ResolutionMode | undefined) {
|
||||
function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: ResolutionMode) {
|
||||
if (fileToDirective.has(file.path)) return;
|
||||
fileToDirective.set(file.path, [key, mode]);
|
||||
for (const { fileName, resolutionMode } of file.referencedFiles) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
extensionIsTS,
|
||||
fileExtensionIs,
|
||||
fileExtensionIsOneOf,
|
||||
FileReference,
|
||||
filter,
|
||||
firstDefined,
|
||||
forEach,
|
||||
@@ -41,7 +40,6 @@ import {
|
||||
GetEffectiveTypeRootsHost,
|
||||
getEmitModuleKind,
|
||||
getEmitModuleResolutionKind,
|
||||
getModeForUsageLocation,
|
||||
getNormalizedAbsolutePath,
|
||||
getOwnKeys,
|
||||
getPathComponents,
|
||||
@@ -58,7 +56,6 @@ import {
|
||||
isExternalModuleNameRelative,
|
||||
isRootedDiskPath,
|
||||
isString,
|
||||
isStringLiteralLike,
|
||||
lastOrUndefined,
|
||||
length,
|
||||
MapLike,
|
||||
@@ -86,6 +83,7 @@ import {
|
||||
removeFileExtension,
|
||||
removePrefix,
|
||||
ResolutionMode,
|
||||
ResolutionNameAndModeGetter,
|
||||
ResolvedModuleWithFailedLookupLocations,
|
||||
ResolvedProjectReference,
|
||||
ResolvedTypeReferenceDirective,
|
||||
@@ -95,10 +93,8 @@ import {
|
||||
SourceFile,
|
||||
startsWith,
|
||||
stringContains,
|
||||
StringLiteralLike,
|
||||
supportedDeclarationExtensions,
|
||||
supportedTSImplementationExtensions,
|
||||
toFileNameLowerCase,
|
||||
toPath,
|
||||
tryExtractTSExtension,
|
||||
tryGetExtensionFromPath,
|
||||
@@ -213,17 +209,28 @@ function createResolvedModuleWithFailedLookupLocations(
|
||||
resultFromCache: ResolvedModuleWithFailedLookupLocations | undefined
|
||||
): ResolvedModuleWithFailedLookupLocations {
|
||||
if (resultFromCache) {
|
||||
resultFromCache.failedLookupLocations.push(...failedLookupLocations);
|
||||
resultFromCache.affectingLocations.push(...affectingLocations);
|
||||
resultFromCache.failedLookupLocations = updateResolutionField(resultFromCache.failedLookupLocations, failedLookupLocations);
|
||||
resultFromCache.affectingLocations = updateResolutionField(resultFromCache.affectingLocations, affectingLocations);
|
||||
resultFromCache.resolutionDiagnostics = updateResolutionField(resultFromCache.resolutionDiagnostics, diagnostics);
|
||||
return resultFromCache;
|
||||
}
|
||||
return {
|
||||
resolvedModule: resolved && { resolvedFileName: resolved.path, originalPath: resolved.originalPath === true ? undefined : resolved.originalPath, extension: resolved.extension, isExternalLibraryImport, packageId: resolved.packageId },
|
||||
failedLookupLocations,
|
||||
affectingLocations,
|
||||
resolutionDiagnostics: diagnostics,
|
||||
failedLookupLocations: initializeResolutionField(failedLookupLocations),
|
||||
affectingLocations: initializeResolutionField(affectingLocations),
|
||||
resolutionDiagnostics: initializeResolutionField(diagnostics),
|
||||
};
|
||||
}
|
||||
function initializeResolutionField<T>(value: T[]): T[] | undefined {
|
||||
return value.length ? value : undefined;
|
||||
}
|
||||
/** @internal */
|
||||
export function updateResolutionField<T>(to: T[] | undefined, value: T[] | undefined) {
|
||||
if (!value?.length) return to;
|
||||
if (!to?.length) return value;
|
||||
to.push(...value);
|
||||
return to;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ModuleResolutionState {
|
||||
@@ -524,7 +531,12 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string
|
||||
isExternalLibraryImport: pathContainsNodeModules(fileName),
|
||||
};
|
||||
}
|
||||
result = { resolvedTypeReferenceDirective, failedLookupLocations, affectingLocations, resolutionDiagnostics: diagnostics };
|
||||
result = {
|
||||
resolvedTypeReferenceDirective,
|
||||
failedLookupLocations: initializeResolutionField(failedLookupLocations),
|
||||
affectingLocations: initializeResolutionField(affectingLocations),
|
||||
resolutionDiagnostics: initializeResolutionField(diagnostics),
|
||||
};
|
||||
perFolderCache?.set(typeReferenceDirectiveName, /*mode*/ resolutionMode, result);
|
||||
if (traceEnabled) traceResult(result);
|
||||
return result;
|
||||
@@ -911,23 +923,17 @@ export function createModeAwareCache<T>(): ModeAwareCache<T> {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getResolutionName(entry: string | FileReference | StringLiteralLike) {
|
||||
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
|
||||
return !isString(entry) ? isStringLiteralLike(entry) ? entry.text : toFileNameLowerCase(entry.fileName) : entry;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getResolutionMode(entry: FileReference | StringLiteralLike, file: SourceFile) {
|
||||
return isStringLiteralLike(entry) ? getModeForUsageLocation(file, entry) : entry.resolutionMode || file.impliedNodeFormat;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function zipToModeAwareCache<V>(file: SourceFile, keys: readonly StringLiteralLike[] | readonly FileReference[], values: readonly V[]): ModeAwareCache<V> {
|
||||
export function zipToModeAwareCache<K, V>(
|
||||
file: SourceFile,
|
||||
keys: readonly K[],
|
||||
values: readonly V[],
|
||||
nameAndModeGetter: ResolutionNameAndModeGetter<K, SourceFile>,
|
||||
): ModeAwareCache<V> {
|
||||
Debug.assert(keys.length === values.length);
|
||||
const map = createModeAwareCache<V>();
|
||||
for (let i = 0; i < keys.length; ++i) {
|
||||
const entry = keys[i];
|
||||
map.set(getResolutionName(entry), getResolutionMode(entry, file), values[i]);
|
||||
map.set(nameAndModeGetter.getName(entry), nameAndModeGetter.getMode(entry, file), values[i]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@@ -1373,7 +1379,7 @@ function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, l
|
||||
export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string {
|
||||
const { resolvedModule, failedLookupLocations } = tryResolveJSModuleWorker(moduleName, initialDir, host);
|
||||
if (!resolvedModule) {
|
||||
throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`);
|
||||
throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations?.join(", ")}`);
|
||||
}
|
||||
return resolvedModule.resolvedFileName;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
changeExtension,
|
||||
changesAffectingProgramStructure,
|
||||
changesAffectModuleResolution,
|
||||
clone,
|
||||
combinePaths,
|
||||
CommentDirective,
|
||||
CommentDirectivesMap,
|
||||
@@ -42,6 +41,7 @@ import {
|
||||
createGetCanonicalFileName,
|
||||
createInputFilesWithFilePaths,
|
||||
createModeAwareCache,
|
||||
createModeAwareCacheKey,
|
||||
createModuleResolutionCache,
|
||||
createMultiMap,
|
||||
CreateProgramOptions,
|
||||
@@ -131,10 +131,7 @@ import {
|
||||
getPositionOfLineAndCharacter,
|
||||
getPropertyArrayElementValue,
|
||||
getPropertyAssignment,
|
||||
getResolutionMode,
|
||||
getResolutionName,
|
||||
getResolvedModule,
|
||||
getResolvedTypeReferenceDirective,
|
||||
getRootLength,
|
||||
getSetExternalModuleIndicator,
|
||||
getSpellingSuggestion,
|
||||
@@ -207,6 +204,8 @@ import {
|
||||
maybeBind,
|
||||
memoize,
|
||||
MethodDeclaration,
|
||||
ModeAwareCache,
|
||||
ModeAwareCacheKey,
|
||||
ModifierFlags,
|
||||
ModifierLike,
|
||||
ModuleBlock,
|
||||
@@ -214,7 +213,6 @@ import {
|
||||
ModuleKind,
|
||||
ModuleResolutionCache,
|
||||
ModuleResolutionHost,
|
||||
ModuleResolutionInfo,
|
||||
moduleResolutionIsEqualTo,
|
||||
ModuleResolutionKind,
|
||||
Mutable,
|
||||
@@ -261,9 +259,8 @@ import {
|
||||
ResolvedModuleFull,
|
||||
ResolvedModuleWithFailedLookupLocations,
|
||||
ResolvedProjectReference,
|
||||
ResolvedTypeReferenceDirective,
|
||||
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
resolveModuleName,
|
||||
resolveModuleNameFromCache,
|
||||
resolveTypeReferenceDirective,
|
||||
returnFalse,
|
||||
returnUndefined,
|
||||
@@ -304,7 +301,6 @@ import {
|
||||
TypeChecker,
|
||||
typeDirectiveIsEqualTo,
|
||||
TypeReferenceDirectiveResolutionCache,
|
||||
TypeReferenceDirectiveResolutionInfo,
|
||||
UnparsedSource,
|
||||
VariableDeclaration,
|
||||
VariableStatement,
|
||||
@@ -808,28 +804,6 @@ export function flattenDiagnosticMessageText(diag: string | DiagnosticMessageCha
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function loadWithTypeDirectiveCache<T>(names: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, containingFileMode: ResolutionMode, loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined, resolutionMode: ResolutionMode) => T): T[] {
|
||||
if (names.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const resolutions: T[] = [];
|
||||
const cache = createModeAwareCache<T>();
|
||||
for (const name of names) {
|
||||
let result: T;
|
||||
const mode = getModeForFileReference(name, containingFileMode);
|
||||
const strName = getResolutionName(name);
|
||||
if (cache.has(strName, mode)) {
|
||||
result = cache.get(strName, mode)!;
|
||||
}
|
||||
else {
|
||||
cache.set(strName, mode, result = loader(strName, containingFile, redirectedReference, mode));
|
||||
}
|
||||
resolutions.push(result);
|
||||
}
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subset of a SourceFile used to calculate index-based resolutions
|
||||
* This includes some internal fields, so unless you have very good reason,
|
||||
@@ -937,26 +911,117 @@ export function getResolutionModeOverrideForClause(clause: AssertClause | undefi
|
||||
return elem.value.text === "import" ? ModuleKind.ESNext : ModuleKind.CommonJS;
|
||||
}
|
||||
|
||||
const emptyResolution: ResolvedModuleWithFailedLookupLocations & ResolvedTypeReferenceDirectiveWithFailedLookupLocations = {
|
||||
resolvedModule: undefined,
|
||||
resolvedTypeReferenceDirective: undefined,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export function loadWithModeAwareCache<T>(names: readonly StringLiteralLike[] | readonly string[], containingFile: SourceFile, containingFileName: string, redirectedReference: ResolvedProjectReference | undefined, resolutionInfo: ModuleResolutionInfo | undefined, loader: (name: string, resolverMode: ResolutionMode, containingFileName: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] {
|
||||
if (names.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const resolutions: T[] = [];
|
||||
const cache = createModeAwareCache<T>();
|
||||
let i = 0;
|
||||
for (const entry of resolutionInfo ? resolutionInfo.names : names) {
|
||||
let result: T;
|
||||
const mode = !isString(entry) ?
|
||||
getModeForUsageLocation(containingFile, entry) :
|
||||
getModeForResolutionAtIndex(containingFile, i);
|
||||
i++;
|
||||
const name = isString(entry) ? entry : entry.text;
|
||||
if (cache.has(name, mode)) {
|
||||
result = cache.get(name, mode)!;
|
||||
}
|
||||
else {
|
||||
cache.set(name, mode, result = loader(name, mode, containingFileName, redirectedReference));
|
||||
export interface ResolutionNameAndModeGetter<Entry, SourceFile> {
|
||||
getName(entry: Entry): string;
|
||||
getMode(entry: Entry, file: SourceFile): ResolutionMode;
|
||||
}
|
||||
|
||||
|
||||
/** @internal */
|
||||
export interface ResolutionLoader<Entry, Resolution, SourceFile> {
|
||||
nameAndMode: ResolutionNameAndModeGetter<Entry, SourceFile>;
|
||||
resolve(name: string, mode: ResolutionMode): Resolution;
|
||||
}
|
||||
|
||||
function getModuleResolutionName(literal: StringLiteralLike) {
|
||||
return literal.text;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const moduleResolutionNameAndModeGetter: ResolutionNameAndModeGetter<StringLiteralLike, SourceFile> = {
|
||||
getName: getModuleResolutionName,
|
||||
getMode: (entry, file) => getModeForUsageLocation(file, entry),
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export function createModuleResolutionLoader(
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
host: ModuleResolutionHost,
|
||||
cache: ModuleResolutionCache | undefined,
|
||||
): ResolutionLoader<StringLiteralLike, ResolvedModuleWithFailedLookupLocations, SourceFile> {
|
||||
return {
|
||||
nameAndMode: moduleResolutionNameAndModeGetter,
|
||||
resolve: (moduleName, resoluionMode) => resolveModuleName(
|
||||
moduleName,
|
||||
containingFile,
|
||||
options,
|
||||
host,
|
||||
cache,
|
||||
redirectedReference,
|
||||
resoluionMode,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function getTypeReferenceResolutionName<T extends FileReference | string>(entry: T) {
|
||||
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
|
||||
return !isString(entry) ? toFileNameLowerCase(entry.fileName) : entry;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const typeReferenceResolutionNameAndModeGetter: ResolutionNameAndModeGetter<FileReference | string, SourceFile | undefined> = {
|
||||
getName: getTypeReferenceResolutionName,
|
||||
getMode: (entry, file) => getModeForFileReference(entry, file?.impliedNodeFormat),
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export function createTypeReferenceResolutionLoader<T extends FileReference | string>(
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
host: ModuleResolutionHost,
|
||||
cache: TypeReferenceDirectiveResolutionCache | undefined,
|
||||
): ResolutionLoader<T, ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFile | undefined> {
|
||||
return {
|
||||
nameAndMode: typeReferenceResolutionNameAndModeGetter,
|
||||
resolve: (typeRef, resoluionMode) => resolveTypeReferenceDirective(
|
||||
typeRef,
|
||||
containingFile,
|
||||
options,
|
||||
host,
|
||||
redirectedReference,
|
||||
cache,
|
||||
resoluionMode,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function loadWithModeAwareCache<Entry, SourceFile, ResolutionCache, Resolution>(
|
||||
entries: readonly Entry[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile,
|
||||
host: ModuleResolutionHost,
|
||||
resolutionCache: ResolutionCache | undefined,
|
||||
createLoader: (
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
host: ModuleResolutionHost,
|
||||
resolutionCache: ResolutionCache | undefined,
|
||||
) => ResolutionLoader<Entry, Resolution, SourceFile>,
|
||||
): readonly Resolution[] {
|
||||
if (entries.length === 0) return emptyArray;
|
||||
const resolutions: Resolution[] = [];
|
||||
const cache = new Map<ModeAwareCacheKey, Resolution>();
|
||||
const loader = createLoader(containingFile, redirectedReference, options, host, resolutionCache);
|
||||
for (const entry of entries) {
|
||||
const name = loader.nameAndMode.getName(entry);
|
||||
const mode = loader.nameAndMode.getMode(entry, containingSourceFile);
|
||||
const key = createModeAwareCacheKey(name, mode);
|
||||
let result = cache.get(key);
|
||||
if (!result) {
|
||||
cache.set(key, result = loader.resolve(name, mode));
|
||||
}
|
||||
resolutions.push(result);
|
||||
}
|
||||
@@ -1057,7 +1122,7 @@ export function getReferencedFileLocation(getSourceFileByPath: (path: Path) => S
|
||||
switch (kind) {
|
||||
case FileIncludeKind.Import:
|
||||
const importLiteral = getModuleNameStringLiteralAt(file, index);
|
||||
packageId = file.resolvedModules?.get(importLiteral.text, getModeForResolutionAtIndex(file, index))?.packageId;
|
||||
packageId = file.resolvedModules?.get(importLiteral.text, getModeForResolutionAtIndex(file, index))?.resolvedModule?.packageId;
|
||||
if (importLiteral.pos === -1) return { file, packageId, text: importLiteral.text };
|
||||
pos = skipTrivia(file.text, importLiteral.pos);
|
||||
end = importLiteral.end;
|
||||
@@ -1067,7 +1132,7 @@ export function getReferencedFileLocation(getSourceFileByPath: (path: Path) => S
|
||||
break;
|
||||
case FileIncludeKind.TypeReferenceDirective:
|
||||
({ pos, end, resolutionMode } = file.typeReferenceDirectives[index]);
|
||||
packageId = file.resolvedTypeReferenceDirectiveNames?.get(toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.packageId;
|
||||
packageId = file.resolvedTypeReferenceDirectiveNames?.get(toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.resolvedTypeReferenceDirective?.packageId;
|
||||
break;
|
||||
case FileIncludeKind.LibReferenceDirective:
|
||||
({ pos, end } = file.libReferenceDirectives[index]);
|
||||
@@ -1376,8 +1441,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
const cachedBindAndCheckDiagnosticsForFile: DiagnosticCache<Diagnostic> = {};
|
||||
const cachedDeclarationDiagnosticsForFile: DiagnosticCache<DiagnosticWithLocation> = {};
|
||||
|
||||
let resolvedTypeReferenceDirectives = createModeAwareCache<ResolvedTypeReferenceDirective | undefined>();
|
||||
let resolvedTypeReferenceDirectives = createModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>();
|
||||
let fileProcessingDiagnostics: FilePreprocessingDiagnostics[] | undefined;
|
||||
let automaticTypeDirectiveNames: string[] | undefined;
|
||||
let automaticTypeDirectiveResolutions: ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>;
|
||||
|
||||
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
|
||||
// This works as imported modules are discovered recursively in a depth first manner, specifically:
|
||||
@@ -1405,6 +1472,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
let skipDefaultLib = options.noLib;
|
||||
const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options));
|
||||
const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : getDirectoryPath(getDefaultLibraryFileName());
|
||||
/**
|
||||
* Diagnostics for the program
|
||||
* Only add diagnostics directly if it always would be done irrespective of program structure reuse.
|
||||
* Otherwise fileProcessingDiagnostics is correct locations so that the diagnostics can be reported in all structure use scenarios
|
||||
*/
|
||||
const programDiagnostics = createDiagnosticCollection();
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
@@ -1415,67 +1487,86 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | false | undefined;
|
||||
|
||||
let moduleResolutionCache: ModuleResolutionCache | undefined;
|
||||
let typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined;
|
||||
let actualResolveModuleNamesWorker: (
|
||||
moduleNames: readonly StringLiteralLike[],
|
||||
containingFile: SourceFile,
|
||||
containingFileName: string,
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
resolutionInfo: ModuleResolutionInfo | undefined,
|
||||
) => (ResolvedModuleFull | undefined)[];
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile,
|
||||
reusedNames: readonly StringLiteralLike[] | undefined,
|
||||
) => readonly ResolvedModuleWithFailedLookupLocations[];
|
||||
const hasInvalidatedResolutions = host.hasInvalidatedResolutions || returnFalse;
|
||||
if (host.resolveModuleNames) {
|
||||
actualResolveModuleNamesWorker = (moduleNames, containingFile, containingFileName, redirectedReference, resolutionInfo) =>
|
||||
if (host.resolveModuleNameLiterals) {
|
||||
actualResolveModuleNamesWorker = host.resolveModuleNameLiterals.bind(host);
|
||||
moduleResolutionCache = host.getModuleResolutionCache?.();
|
||||
}
|
||||
else if (host.resolveModuleNames) {
|
||||
actualResolveModuleNamesWorker = (moduleNames, containingFile, redirectedReference, options, containingSourceFile, reusedNames) =>
|
||||
host.resolveModuleNames!(
|
||||
moduleNames.map(literal => literal.text),
|
||||
containingFileName,
|
||||
resolutionInfo?.reusedNames?.map(literal => literal.text),
|
||||
moduleNames.map(getModuleResolutionName),
|
||||
containingFile,
|
||||
reusedNames?.map(getModuleResolutionName),
|
||||
redirectedReference,
|
||||
options,
|
||||
containingFile,
|
||||
resolutionInfo,
|
||||
).map(resolved => {
|
||||
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
|
||||
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
|
||||
return resolved as ResolvedModuleFull;
|
||||
}
|
||||
const withExtension = clone(resolved) as ResolvedModuleFull;
|
||||
withExtension.extension = extensionFromPath(resolved.resolvedFileName);
|
||||
return withExtension;
|
||||
});
|
||||
containingSourceFile,
|
||||
).map(resolved => resolved ?
|
||||
((resolved as ResolvedModuleFull).extension !== undefined) ?
|
||||
{ resolvedModule: resolved as ResolvedModuleFull } :
|
||||
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
|
||||
{ resolvedModule: { ...resolved, extension: extensionFromPath(resolved.resolvedFileName) } } :
|
||||
emptyResolution
|
||||
);
|
||||
moduleResolutionCache = host.getModuleResolutionCache?.();
|
||||
}
|
||||
else {
|
||||
moduleResolutionCache = createModuleResolutionCache(currentDirectory, getCanonicalFileName, options);
|
||||
const loader = (moduleName: string, resolverMode: ResolutionMode, containingFileName: string, redirectedReference: ResolvedProjectReference | undefined) =>
|
||||
resolveModuleName(moduleName, containingFileName, options, host, moduleResolutionCache, redirectedReference, resolverMode).resolvedModule;
|
||||
actualResolveModuleNamesWorker = (moduleNames, containingFile, containingFileName, redirectedReference, resolutionInfo) =>
|
||||
loadWithModeAwareCache(moduleNames, containingFile, containingFileName, redirectedReference, resolutionInfo, loader);
|
||||
actualResolveModuleNamesWorker = (moduleNames, containingFile, redirectedReference, options, containingSourceFile) =>
|
||||
loadWithModeAwareCache(
|
||||
moduleNames,
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingSourceFile,
|
||||
host,
|
||||
moduleResolutionCache,
|
||||
createModuleResolutionLoader,
|
||||
);
|
||||
}
|
||||
|
||||
let actualResolveTypeReferenceDirectiveNamesWorker: (
|
||||
typeDirectiveNames: string[] | readonly FileReference[],
|
||||
let actualResolveTypeReferenceDirectiveNamesWorker: <T extends FileReference | string>(
|
||||
typeDirectiveNames: T[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
containingFileMode: ResolutionMode | undefined,
|
||||
resolutionInfo: TypeReferenceDirectiveResolutionInfo | undefined,
|
||||
) => (ResolvedTypeReferenceDirective | undefined)[];
|
||||
if (host.resolveTypeReferenceDirectives) {
|
||||
actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, containingFileMode, resolutionInfo) =>
|
||||
host.resolveTypeReferenceDirectives!(Debug.checkEachDefined(typeDirectiveNames), containingFile, redirectedReference, options, containingFileMode, resolutionInfo);
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile | undefined,
|
||||
reusedNames: readonly T[] | undefined,
|
||||
) => readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
if (host.resolveTypeReferenceDirectiveReferences) {
|
||||
actualResolveTypeReferenceDirectiveNamesWorker = host.resolveTypeReferenceDirectiveReferences.bind(host);
|
||||
}
|
||||
else if (host.resolveTypeReferenceDirectives) {
|
||||
actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, options, containingSourceFile) =>
|
||||
host.resolveTypeReferenceDirectives!(
|
||||
typeDirectiveNames.map(getTypeReferenceResolutionName),
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingSourceFile?.impliedNodeFormat,
|
||||
).map(resolvedTypeReferenceDirective => ({ resolvedTypeReferenceDirective }));
|
||||
}
|
||||
else {
|
||||
typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache());
|
||||
const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined, resolutionMode: ResolutionMode | undefined) => resolveTypeReferenceDirective(
|
||||
typesRef,
|
||||
containingFile,
|
||||
options,
|
||||
host,
|
||||
redirectedReference,
|
||||
typeReferenceDirectiveResolutionCache,
|
||||
resolutionMode,
|
||||
).resolvedTypeReferenceDirective!; // TODO: GH#18217
|
||||
actualResolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile, redirectedReference, containingFileMode) => loadWithTypeDirectiveCache<ResolvedTypeReferenceDirective>(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, containingFileMode, loader);
|
||||
const typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache());
|
||||
actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, options, containingSourceFile) =>
|
||||
loadWithModeAwareCache(
|
||||
typeDirectiveNames,
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingSourceFile,
|
||||
host,
|
||||
typeReferenceDirectiveResolutionCache,
|
||||
createTypeReferenceResolutionLoader,
|
||||
);
|
||||
}
|
||||
|
||||
// Map from a stringified PackageId to the source file with that id.
|
||||
@@ -1569,17 +1660,27 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
tracing?.pop();
|
||||
|
||||
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
|
||||
const typeReferences: string[] = rootNames.length ? getAutomaticTypeDirectiveNames(options, host) : emptyArray;
|
||||
|
||||
if (typeReferences.length) {
|
||||
tracing?.push(tracing.Phase.Program, "processTypeReferences", { count: typeReferences.length });
|
||||
automaticTypeDirectiveNames ??= rootNames.length ? getAutomaticTypeDirectiveNames(options, host) : emptyArray;
|
||||
automaticTypeDirectiveResolutions = createModeAwareCache();
|
||||
if (automaticTypeDirectiveNames.length) {
|
||||
tracing?.push(tracing.Phase.Program, "processTypeReferences", { count: automaticTypeDirectiveNames.length });
|
||||
// This containingFilename needs to match with the one used in managed-side
|
||||
const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) : host.getCurrentDirectory();
|
||||
const containingFilename = combinePaths(containingDirectory, inferredTypesContainingFile);
|
||||
const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState(typeReferences, containingFilename);
|
||||
for (let i = 0; i < typeReferences.length; i++) {
|
||||
const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState(automaticTypeDirectiveNames, containingFilename);
|
||||
for (let i = 0; i < automaticTypeDirectiveNames.length; i++) {
|
||||
// under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode
|
||||
processTypeReferenceDirective(typeReferences[i], /*mode*/ undefined, resolutions[i], { kind: FileIncludeKind.AutomaticTypeDirectiveFile, typeReference: typeReferences[i], packageId: resolutions[i]?.packageId });
|
||||
automaticTypeDirectiveResolutions.set(automaticTypeDirectiveNames[i], /*mode*/ undefined, resolutions[i]);
|
||||
processTypeReferenceDirective(
|
||||
automaticTypeDirectiveNames[i],
|
||||
/*mode*/ undefined,
|
||||
resolutions[i],
|
||||
{
|
||||
kind: FileIncludeKind.AutomaticTypeDirectiveFile,
|
||||
typeReference: automaticTypeDirectiveNames[i],
|
||||
packageId: resolutions[i]?.resolvedTypeReferenceDirective?.packageId,
|
||||
},
|
||||
);
|
||||
}
|
||||
tracing?.pop();
|
||||
}
|
||||
@@ -1646,8 +1747,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
);
|
||||
}
|
||||
|
||||
typeReferenceDirectiveResolutionCache = undefined;
|
||||
|
||||
// unconditionally set oldProgram to undefined to prevent it from being captured in closure
|
||||
oldProgram = undefined;
|
||||
|
||||
@@ -1682,6 +1781,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
getRelationCacheSizes: () => getTypeChecker().getRelationCacheSizes(),
|
||||
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
|
||||
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
|
||||
getAutomaticTypeDirectiveNames: () => automaticTypeDirectiveNames!,
|
||||
getAutomaticTypeDirectiveResolutions: () => automaticTypeDirectiveResolutions,
|
||||
isSourceFileFromExternalLibrary,
|
||||
isSourceFileDefaultLibrary,
|
||||
getSourceFileFromReference,
|
||||
@@ -1691,7 +1792,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
usesUriStyleNodeCoreModules,
|
||||
isEmittedFile,
|
||||
getConfigFileParsingDiagnostics,
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache,
|
||||
getProjectReferences,
|
||||
getResolvedProjectReferences,
|
||||
getProjectReferenceRedirect,
|
||||
@@ -1721,6 +1821,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
case FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic:
|
||||
const { file, pos, end } = getReferencedFileLocation(getSourceFileByPath, diagnostic.reason) as ReferenceFileLocation;
|
||||
return programDiagnostics.add(createFileDiagnostic(file, Debug.checkDefined(pos), Debug.checkDefined(end) - pos, diagnostic.diagnostic, ...diagnostic.args || emptyArray));
|
||||
case FilePreprocessingDiagnosticsKind.ResolutionDiagnostics:
|
||||
return diagnostic.diagnostics.forEach(d => programDiagnostics.add(d));
|
||||
default:
|
||||
Debug.assertNever(diagnostic);
|
||||
}
|
||||
@@ -1733,55 +1835,51 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
return program;
|
||||
|
||||
function addResolutionDiagnostics(list: Diagnostic[] | undefined) {
|
||||
if (!list) return;
|
||||
for (const elem of list) {
|
||||
programDiagnostics.add(elem);
|
||||
}
|
||||
function addResolutionDiagnostics(resolution: ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations) {
|
||||
if (!resolution.resolutionDiagnostics?.length) return;
|
||||
(fileProcessingDiagnostics ??= []).push({
|
||||
kind: FilePreprocessingDiagnosticsKind.ResolutionDiagnostics,
|
||||
diagnostics: resolution.resolutionDiagnostics
|
||||
});
|
||||
}
|
||||
|
||||
function pullDiagnosticsFromCache(names: readonly StringLiteralLike[] | readonly FileReference[], containingFile: SourceFile) {
|
||||
if (!moduleResolutionCache) return;
|
||||
function addResolutionDiagnosticsFromResolutionOrCache(containingFile: SourceFile, name: string, resolution: ResolvedModuleWithFailedLookupLocations, mode: ResolutionMode) {
|
||||
// diagnostics directly from the resolution
|
||||
if (host.resolveModuleNameLiterals || !host.resolveModuleNames) return addResolutionDiagnostics(resolution);
|
||||
if (!moduleResolutionCache || isExternalModuleNameRelative(name)) return;
|
||||
const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory);
|
||||
const containingDir = getDirectoryPath(containingFileName);
|
||||
const redirectedReference = getRedirectReferenceForResolution(containingFile);
|
||||
for (const n of names) {
|
||||
// mimics logic done in the resolution cache, should be resilient to upgrading it to use `FileReference`s for non-type-reference modal lookups to make it rely on the index in the list less
|
||||
const mode = getResolutionMode(n, containingFile);
|
||||
const name = getResolutionName(n);
|
||||
// only nonrelative names hit the cache, and, at least as of right now, only nonrelative names can issue diagnostics
|
||||
// (Since diagnostics are only issued via import or export map lookup)
|
||||
// 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
|
||||
if (isExternalModuleNameRelative(name)) continue;
|
||||
const diags = moduleResolutionCache.getOrCreateCacheForModuleName(name, mode, redirectedReference).get(containingDir)?.resolutionDiagnostics;
|
||||
addResolutionDiagnostics(diags);
|
||||
}
|
||||
// only nonrelative names hit the cache, and, at least as of right now, only nonrelative names can issue diagnostics
|
||||
// (Since diagnostics are only issued via import or export map lookup)
|
||||
// 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);
|
||||
if (fromCache) addResolutionDiagnostics(fromCache);
|
||||
}
|
||||
|
||||
function resolveModuleNamesWorker(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile, resolutionInfo: ModuleResolutionInfo | undefined): readonly (ResolvedModuleFull | undefined)[] {
|
||||
function resolveModuleNamesWorker(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
if (!moduleNames.length) return emptyArray;
|
||||
const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory);
|
||||
const redirectedReference = getRedirectReferenceForResolution(containingFile);
|
||||
tracing?.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName });
|
||||
performance.mark("beforeResolveModule");
|
||||
const result = actualResolveModuleNamesWorker(moduleNames, containingFile, containingFileName, redirectedReference, resolutionInfo);
|
||||
const result = actualResolveModuleNamesWorker(moduleNames, containingFileName, redirectedReference, options, containingFile, reusedNames);
|
||||
performance.mark("afterResolveModule");
|
||||
performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule");
|
||||
tracing?.pop();
|
||||
pullDiagnosticsFromCache(moduleNames, containingFile);
|
||||
return result;
|
||||
}
|
||||
|
||||
function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: string[] | readonly FileReference[], containingFile: string | SourceFile, resolutionInfo: TypeReferenceDirectiveResolutionInfo | undefined): readonly (ResolvedTypeReferenceDirective | undefined)[] {
|
||||
function resolveTypeReferenceDirectiveNamesWorker<T extends FileReference | string>(typeDirectiveNames: T[], containingFile: string | SourceFile, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
|
||||
if (!typeDirectiveNames.length) return [];
|
||||
const containingSourceFile = !isString(containingFile) ? containingFile : undefined;
|
||||
const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile;
|
||||
const redirectedReference = !isString(containingFile) ? getRedirectReferenceForResolution(containingFile) : undefined;
|
||||
const containingFileMode = !isString(containingFile) ? containingFile.impliedNodeFormat : undefined;
|
||||
const redirectedReference = containingSourceFile && getRedirectReferenceForResolution(containingSourceFile);
|
||||
tracing?.push(tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName });
|
||||
performance.mark("beforeResolveTypeReference");
|
||||
const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, containingFileMode, resolutionInfo);
|
||||
const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, options, containingSourceFile, reusedNames);
|
||||
performance.mark("afterResolveTypeReference");
|
||||
performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference");
|
||||
tracing?.pop();
|
||||
@@ -1833,10 +1931,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
return libs.length + 2;
|
||||
}
|
||||
|
||||
function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, mode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined {
|
||||
return moduleResolutionCache && resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache, mode);
|
||||
}
|
||||
|
||||
function toPath(fileName: string): Path {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
@@ -1869,11 +1963,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
return classifiableNames;
|
||||
}
|
||||
|
||||
function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], file: SourceFile): readonly (ResolvedModuleFull | undefined)[] {
|
||||
function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], file: SourceFile): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
if (structureIsReused === StructureIsReused.Not && !file.ambientModuleNames.length) {
|
||||
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
|
||||
// the best we can do is fallback to the default logic.
|
||||
return resolveModuleNamesWorker(moduleNames, file, /*resolutionInfo*/ undefined);
|
||||
return resolveModuleNamesWorker(moduleNames, file, /*reusedNames*/ undefined);
|
||||
}
|
||||
|
||||
const oldSourceFile = oldProgram && oldProgram.getSourceFile(file.fileName);
|
||||
@@ -1886,9 +1980,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
// which per above occurred during the current program creation.
|
||||
// Since we assume the filesystem does not change during program creation,
|
||||
// it is safe to reuse resolutions from the earlier call.
|
||||
const result: (ResolvedModuleFull | undefined)[] = [];
|
||||
const result: ResolvedModuleWithFailedLookupLocations[] = [];
|
||||
for (const moduleName of moduleNames) {
|
||||
const resolvedModule = file.resolvedModules.get(moduleName.text, getModeForUsageLocation(file, moduleName));
|
||||
const resolvedModule = file.resolvedModules.get(moduleName.text, getModeForUsageLocation(file, moduleName))!;
|
||||
result.push(resolvedModule);
|
||||
}
|
||||
return result;
|
||||
@@ -1909,30 +2003,30 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
* Needs to be reset to undefined before returning,
|
||||
* * ResolvedModuleFull instance: can be reused.
|
||||
*/
|
||||
let result: (ResolvedModuleFull | undefined)[] | undefined;
|
||||
let result: ResolvedModuleWithFailedLookupLocations[] | undefined;
|
||||
let reusedNames: StringLiteralLike[] | undefined;
|
||||
/** A transient placeholder used to mark predicted resolution in the result list. */
|
||||
const predictedToResolveToAmbientModuleMarker: ResolvedModuleFull = {} as any;
|
||||
const predictedToResolveToAmbientModuleMarker: ResolvedModuleWithFailedLookupLocations = emptyResolution;
|
||||
|
||||
for (let i = 0; i < moduleNames.length; i++) {
|
||||
const moduleName = moduleNames[i];
|
||||
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
|
||||
if (file === oldSourceFile && !hasInvalidatedResolutions(oldSourceFile.path)) {
|
||||
const mode = getModeForUsageLocation(file, moduleName);
|
||||
const oldResolvedModule = getResolvedModule(oldSourceFile, moduleName.text, mode);
|
||||
if (oldResolvedModule) {
|
||||
const oldResolution = oldSourceFile.resolvedModules?.get(moduleName.text, mode);
|
||||
if (oldResolution?.resolvedModule) {
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(host,
|
||||
oldResolvedModule.packageId ?
|
||||
oldResolution.resolvedModule.packageId ?
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2,
|
||||
moduleName.text,
|
||||
getNormalizedAbsolutePath(file.originalFileName, currentDirectory),
|
||||
oldResolvedModule.resolvedFileName,
|
||||
oldResolvedModule.packageId && packageIdToString(oldResolvedModule.packageId)
|
||||
oldResolution.resolvedModule.resolvedFileName,
|
||||
oldResolution.resolvedModule.packageId && packageIdToString(oldResolution.resolvedModule.packageId)
|
||||
);
|
||||
}
|
||||
(result ??= new Array(moduleNames.length))[i] = oldResolvedModule;
|
||||
(result ??= new Array(moduleNames.length))[i] = oldResolution;
|
||||
(reusedNames ??= []).push(moduleName);
|
||||
continue;
|
||||
}
|
||||
@@ -1962,7 +2056,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
|
||||
const resolutions = unknownModuleNames && unknownModuleNames.length
|
||||
? resolveModuleNamesWorker(unknownModuleNames, file, { names: unknownModuleNames, reusedNames })
|
||||
? resolveModuleNamesWorker(unknownModuleNames, file, reusedNames)
|
||||
: emptyArray;
|
||||
|
||||
// Combine results of resolutions and predicted results
|
||||
@@ -1974,14 +2068,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
let j = 0;
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (result[i]) {
|
||||
// `result[i]` is either a `ResolvedModuleFull` or a marker.
|
||||
// If it is the former, we can leave it as is.
|
||||
if (result[i] === predictedToResolveToAmbientModuleMarker) {
|
||||
result[i] = undefined;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!result[i]) {
|
||||
result[i] = resolutions[j];
|
||||
j++;
|
||||
}
|
||||
@@ -2017,13 +2104,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
}
|
||||
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly (ResolvedTypeReferenceDirective | undefined)[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: string[], containingFile: string): readonly (ResolvedTypeReferenceDirective | undefined)[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: string[] | readonly FileReference[], containingFile: string | SourceFile): readonly (ResolvedTypeReferenceDirective | undefined)[] {
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState<T extends string | FileReference>(typeDirectiveNames: T[], containingFile: string | SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
|
||||
if (structureIsReused === StructureIsReused.Not) {
|
||||
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
|
||||
// the best we can do is fallback to the default logic.
|
||||
return resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, /*resolutionInfo*/ undefined);
|
||||
return resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, /*resuedNames*/ undefined);
|
||||
}
|
||||
|
||||
const oldSourceFile = !isString(containingFile) ? oldProgram && oldProgram.getSourceFile(containingFile.fileName) : undefined;
|
||||
@@ -2037,10 +2124,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
// which per above occurred during the current program creation.
|
||||
// Since we assume the filesystem does not change during program creation,
|
||||
// it is safe to reuse resolutions from the earlier call.
|
||||
const result: (ResolvedTypeReferenceDirective | undefined)[] = [];
|
||||
const result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] = [];
|
||||
for (const typeDirectiveName of typeDirectiveNames as readonly FileReference[]) {
|
||||
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
|
||||
const resolvedTypeReferenceDirective = containingFile.resolvedTypeReferenceDirectiveNames.get(getResolutionName(typeDirectiveName), typeDirectiveName.resolutionMode || containingFile.impliedNodeFormat);
|
||||
const resolvedTypeReferenceDirective = containingFile.resolvedTypeReferenceDirectiveNames.get(getTypeReferenceResolutionName(typeDirectiveName), getModeForFileReference(typeDirectiveName, containingFile.impliedNodeFormat))!;
|
||||
result.push(resolvedTypeReferenceDirective);
|
||||
}
|
||||
return result;
|
||||
@@ -2048,9 +2135,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
|
||||
/** An ordered list of module names for which we cannot recover the resolution. */
|
||||
let unknownTypeReferenceDirectiveNames: string[] | FileReference[] | undefined;
|
||||
let result: (ResolvedTypeReferenceDirective | undefined)[] | undefined;
|
||||
let reusedNames: (string | FileReference)[] | undefined;
|
||||
let unknownTypeReferenceDirectiveNames: T[] | undefined;
|
||||
let result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] | undefined;
|
||||
let reusedNames: T[] | undefined;
|
||||
const containingSourceFile = !isString(containingFile) ? containingFile : undefined;
|
||||
const canReuseResolutions = !isString(containingFile) ?
|
||||
containingFile === oldSourceFile && !hasInvalidatedResolutions(oldSourceFile.path) :
|
||||
@@ -2058,35 +2145,35 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
for (let i = 0; i < typeDirectiveNames.length; i++) {
|
||||
const entry = typeDirectiveNames[i];
|
||||
if (canReuseResolutions) {
|
||||
const typeDirectiveName = getResolutionName(entry);
|
||||
const typeDirectiveName = getTypeReferenceResolutionName(entry);
|
||||
const mode = getModeForFileReference(entry, containingSourceFile?.impliedNodeFormat);
|
||||
const oldResolvedTypeReferenceDirective = getResolvedTypeReferenceDirective(oldSourceFile, typeDirectiveName, mode);
|
||||
if (oldResolvedTypeReferenceDirective) {
|
||||
const oldResolution = (!isString(containingFile) ? oldSourceFile?.resolvedTypeReferenceDirectiveNames : oldProgram?.getAutomaticTypeDirectiveResolutions())?.get(typeDirectiveName, mode);
|
||||
if (oldResolution?.resolvedTypeReferenceDirective) {
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(host,
|
||||
oldResolvedTypeReferenceDirective.packageId ?
|
||||
oldResolution.resolvedTypeReferenceDirective.packageId ?
|
||||
Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
|
||||
Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2,
|
||||
typeDirectiveName,
|
||||
!isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile,
|
||||
oldResolvedTypeReferenceDirective.resolvedFileName,
|
||||
oldResolvedTypeReferenceDirective.packageId && packageIdToString(oldResolvedTypeReferenceDirective.packageId)
|
||||
oldResolution.resolvedTypeReferenceDirective.resolvedFileName,
|
||||
oldResolution.resolvedTypeReferenceDirective.packageId && packageIdToString(oldResolution.resolvedTypeReferenceDirective.packageId)
|
||||
);
|
||||
}
|
||||
(result ??= new Array(typeDirectiveNames.length))[i] = oldResolvedTypeReferenceDirective;
|
||||
(result ??= new Array(typeDirectiveNames.length))[i] = oldResolution;
|
||||
(reusedNames ??= []).push(entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result.
|
||||
(unknownTypeReferenceDirectiveNames ??= []).push(entry as FileReference & string);
|
||||
(unknownTypeReferenceDirectiveNames ??= []).push(entry);
|
||||
}
|
||||
|
||||
if (!unknownTypeReferenceDirectiveNames) return result || emptyArray;
|
||||
const resolutions = resolveTypeReferenceDirectiveNamesWorker(
|
||||
unknownTypeReferenceDirectiveNames,
|
||||
containingFile,
|
||||
{ names: unknownTypeReferenceDirectiveNames, reusedNames }
|
||||
reusedNames,
|
||||
);
|
||||
|
||||
// Combine results of resolutions
|
||||
@@ -2301,10 +2388,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
const moduleNames = getModuleNames(newSourceFile);
|
||||
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFile);
|
||||
// ensure that module resolution results are still correct
|
||||
const resolutionsChanged = hasChangesInResolutions(moduleNames, newSourceFile, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo);
|
||||
const resolutionsChanged = hasChangesInResolutions(moduleNames, newSourceFile, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo, moduleResolutionNameAndModeGetter);
|
||||
if (resolutionsChanged) {
|
||||
structureIsReused = StructureIsReused.SafeModules;
|
||||
newSourceFile.resolvedModules = zipToModeAwareCache(newSourceFile, moduleNames, resolutions);
|
||||
newSourceFile.resolvedModules = zipToModeAwareCache(newSourceFile, moduleNames, resolutions, moduleResolutionNameAndModeGetter);
|
||||
}
|
||||
else {
|
||||
newSourceFile.resolvedModules = oldSourceFile.resolvedModules;
|
||||
@@ -2312,10 +2399,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
const typesReferenceDirectives = newSourceFile.typeReferenceDirectives;
|
||||
const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState(typesReferenceDirectives, newSourceFile);
|
||||
// ensure that types resolutions are still correct
|
||||
const typeReferenceResolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, newSourceFile, typeReferenceResolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, typeDirectiveIsEqualTo);
|
||||
const typeReferenceResolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, newSourceFile, typeReferenceResolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, typeDirectiveIsEqualTo, typeReferenceResolutionNameAndModeGetter);
|
||||
if (typeReferenceResolutionsChanged) {
|
||||
structureIsReused = StructureIsReused.SafeModules;
|
||||
newSourceFile.resolvedTypeReferenceDirectiveNames = zipToModeAwareCache(newSourceFile, typesReferenceDirectives, typeReferenceResolutions);
|
||||
newSourceFile.resolvedTypeReferenceDirectiveNames = zipToModeAwareCache(newSourceFile, typesReferenceDirectives, typeReferenceResolutions, typeReferenceResolutionNameAndModeGetter);
|
||||
}
|
||||
else {
|
||||
newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames;
|
||||
@@ -2326,10 +2413,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
return structureIsReused;
|
||||
}
|
||||
|
||||
if (changesAffectingProgramStructure(oldOptions, options) || host.hasChangedAutomaticTypeDirectiveNames?.()) {
|
||||
if (changesAffectingProgramStructure(oldOptions, options)) {
|
||||
return StructureIsReused.SafeModules;
|
||||
}
|
||||
|
||||
if (host.hasChangedAutomaticTypeDirectiveNames) {
|
||||
if (host.hasChangedAutomaticTypeDirectiveNames()) return StructureIsReused.SafeModules;
|
||||
}
|
||||
else {
|
||||
automaticTypeDirectiveNames = getAutomaticTypeDirectiveNames(options, host);
|
||||
if (!arrayIsEqualTo(oldProgram.getAutomaticTypeDirectiveNames(), automaticTypeDirectiveNames)) return StructureIsReused.SafeModules;
|
||||
}
|
||||
missingFilePaths = oldProgram.getMissingFilePaths();
|
||||
|
||||
// update fileName -> file mapping
|
||||
@@ -2357,6 +2451,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
fileReasons = oldProgram.getFileIncludeReasons();
|
||||
fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics();
|
||||
resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives();
|
||||
automaticTypeDirectiveNames = oldProgram.getAutomaticTypeDirectiveNames();
|
||||
automaticTypeDirectiveResolutions = oldProgram.getAutomaticTypeDirectiveResolutions();
|
||||
|
||||
sourceFileToPackageName = oldProgram.sourceFileToPackageName;
|
||||
redirectTargetsMap = oldProgram.redirectTargetsMap;
|
||||
@@ -3573,7 +3669,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
function processTypeReferenceDirectives(file: SourceFile) {
|
||||
const typeDirectives = file.typeReferenceDirectives;
|
||||
if (!typeDirectives) {
|
||||
if (!typeDirectives.length) {
|
||||
file.resolvedTypeReferenceDirectiveNames = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3586,7 +3683,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective, getModeForFileReference(ref, file.impliedNodeFormat));
|
||||
const mode = ref.resolutionMode || file.impliedNodeFormat;
|
||||
if (mode && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) {
|
||||
programDiagnostics.add(createDiagnosticForRange(file, ref, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext));
|
||||
(fileProcessingDiagnostics ??= []).push({
|
||||
kind: FilePreprocessingDiagnosticsKind.ResolutionDiagnostics,
|
||||
diagnostics: [
|
||||
createDiagnosticForRange(file, ref, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext)
|
||||
]
|
||||
});
|
||||
}
|
||||
processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: FileIncludeKind.TypeReferenceDirective, file: file.path, index, });
|
||||
}
|
||||
@@ -3594,28 +3696,29 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
function processTypeReferenceDirective(
|
||||
typeReferenceDirective: string,
|
||||
mode: ResolutionMode | undefined,
|
||||
resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined,
|
||||
mode: ResolutionMode,
|
||||
resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
reason: FileIncludeReason
|
||||
): void {
|
||||
tracing?.push(tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolvedTypeReferenceDirective, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : undefined });
|
||||
processTypeReferenceDirectiveWorker(typeReferenceDirective, mode, resolvedTypeReferenceDirective, reason);
|
||||
tracing?.push(tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolution.resolvedTypeReferenceDirective, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : undefined });
|
||||
processTypeReferenceDirectiveWorker(typeReferenceDirective, mode, resolution, reason);
|
||||
tracing?.pop();
|
||||
}
|
||||
|
||||
function processTypeReferenceDirectiveWorker(
|
||||
typeReferenceDirective: string,
|
||||
mode: ResolutionMode | undefined,
|
||||
resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined,
|
||||
mode: ResolutionMode,
|
||||
resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
reason: FileIncludeReason
|
||||
): void {
|
||||
|
||||
addResolutionDiagnostics(resolution);
|
||||
// If we already found this library as a primary reference - nothing to do
|
||||
const previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective, mode);
|
||||
const previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective, mode)?.resolvedTypeReferenceDirective;
|
||||
if (previousResolution && previousResolution.primary) {
|
||||
return;
|
||||
}
|
||||
let saveResolution = true;
|
||||
const { resolvedTypeReferenceDirective } = resolution;
|
||||
if (resolvedTypeReferenceDirective) {
|
||||
if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth++;
|
||||
|
||||
@@ -3656,7 +3759,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
|
||||
if (saveResolution) {
|
||||
resolvedTypeReferenceDirectives.set(typeReferenceDirective, mode, resolvedTypeReferenceDirective);
|
||||
resolvedTypeReferenceDirectives.set(typeReferenceDirective, mode, resolution);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3714,8 +3817,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
Debug.assert(resolutions.length === moduleNames.length);
|
||||
const optionsForFile = (useSourceOfProjectReferenceRedirect ? getRedirectReferenceForResolution(file)?.commandLine.options : undefined) || options;
|
||||
for (let index = 0; index < moduleNames.length; index++) {
|
||||
const resolution = resolutions[index];
|
||||
setResolvedModule(file, moduleNames[index].text, resolution, getModeForUsageLocation(file, moduleNames[index]));
|
||||
const resolution = resolutions[index].resolvedModule;
|
||||
const moduleName = moduleNames[index].text;
|
||||
const mode = getModeForUsageLocation(file, moduleNames[index]);
|
||||
setResolvedModule(file, moduleName, resolutions[index], mode);
|
||||
addResolutionDiagnosticsFromResolutionOrCache(file, moduleName, resolutions[index], mode);
|
||||
|
||||
if (!resolution) {
|
||||
continue;
|
||||
@@ -4479,8 +4585,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
if (!symlinks) {
|
||||
symlinks = createSymlinkCache(currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
if (files && resolvedTypeReferenceDirectives && !symlinks.hasProcessedResolutions()) {
|
||||
symlinks.setSymlinksFromResolutions(files, resolvedTypeReferenceDirectives);
|
||||
if (files && automaticTypeDirectiveResolutions && !symlinks.hasProcessedResolutions()) {
|
||||
symlinks.setSymlinksFromResolutions(files, automaticTypeDirectiveResolutions);
|
||||
}
|
||||
return symlinks;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
closeFileWatcher,
|
||||
closeFileWatcherOf,
|
||||
CompilerOptions,
|
||||
contains,
|
||||
createModeAwareCache,
|
||||
createModuleResolutionCache,
|
||||
createMultiMap,
|
||||
createTypeReferenceDirectiveResolutionCache,
|
||||
createTypeReferenceResolutionLoader,
|
||||
Debug,
|
||||
Diagnostics,
|
||||
directorySeparator,
|
||||
@@ -30,11 +30,7 @@ import {
|
||||
GetCanonicalFileName,
|
||||
getDirectoryPath,
|
||||
getEffectiveTypeRoots,
|
||||
getModeForFileReference,
|
||||
getModeForResolutionAtIndex,
|
||||
getModeForUsageLocation,
|
||||
getNormalizedAbsolutePath,
|
||||
getResolutionName,
|
||||
getRootLength,
|
||||
HasInvalidatedResolutions,
|
||||
ignoredPaths,
|
||||
@@ -44,8 +40,6 @@ import {
|
||||
isExternalOrCommonJsModule,
|
||||
isNodeModulesDirectory,
|
||||
isRootedDiskPath,
|
||||
isString,
|
||||
isStringLiteralLike,
|
||||
isTraceEnabled,
|
||||
length,
|
||||
loadModuleFromGlobalCache,
|
||||
@@ -53,8 +47,7 @@ import {
|
||||
MinimalResolutionCacheHost,
|
||||
ModeAwareCache,
|
||||
ModuleResolutionCache,
|
||||
ModuleResolutionHost,
|
||||
ModuleResolutionInfo,
|
||||
moduleResolutionNameAndModeGetter,
|
||||
mutateMap,
|
||||
noopFileWatcher,
|
||||
normalizePath,
|
||||
@@ -67,20 +60,20 @@ import {
|
||||
removeSuffix,
|
||||
removeTrailingDirectorySeparator,
|
||||
resolutionExtensionIsTSOrJson,
|
||||
ResolutionLoader,
|
||||
ResolutionMode,
|
||||
ResolvedModuleFull,
|
||||
ResolvedModuleWithFailedLookupLocations,
|
||||
ResolvedProjectReference,
|
||||
ResolvedTypeReferenceDirective,
|
||||
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
returnTrue,
|
||||
some,
|
||||
SourceFile,
|
||||
startsWith,
|
||||
stringContains,
|
||||
StringLiteralLike,
|
||||
trace,
|
||||
TypeReferenceDirectiveResolutionInfo,
|
||||
unorderedRemoveItem,
|
||||
updateResolutionField,
|
||||
WatchDirectoryFlags,
|
||||
} from "./_namespaces/ts";
|
||||
|
||||
@@ -93,22 +86,27 @@ export interface ResolutionCache {
|
||||
startRecordingFilesWithChangedResolutions(): void;
|
||||
finishRecordingFilesWithChangedResolutions(): Path[] | undefined;
|
||||
|
||||
resolveModuleNames(
|
||||
moduleNames: string[],
|
||||
resolveModuleNameLiterals(
|
||||
moduleLiterals: readonly StringLiteralLike[],
|
||||
containingFile: string,
|
||||
reusedNames: string[] | undefined,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile,
|
||||
reusedNames: readonly StringLiteralLike[] | undefined,
|
||||
): readonly ResolvedModuleWithFailedLookupLocations[];
|
||||
resolveTypeReferenceDirectiveReferences<T extends FileReference | string>(
|
||||
typeDirectiveReferences: readonly T[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile | undefined,
|
||||
resolutionInfo: ModuleResolutionInfo | undefined
|
||||
): (ResolvedModuleFull | undefined)[];
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ResolutionMode): CachedResolvedModuleWithFailedLookupLocations | undefined;
|
||||
resolveTypeReferenceDirectives(
|
||||
typeDirectiveNames: string[] | readonly FileReference[],
|
||||
reusedNames: readonly T[] | undefined
|
||||
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
|
||||
resolveSingleModuleNameWithoutWatching(
|
||||
moduleName: string,
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
containingFileMode: ResolutionMode,
|
||||
resolutionInfo: TypeReferenceDirectiveResolutionInfo | undefined,
|
||||
): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
): ResolvedModuleWithFailedLookupLocations;
|
||||
|
||||
invalidateResolutionsOfFailedLookupLocations(): boolean;
|
||||
invalidateResolutionOfFile(filePath: Path): void;
|
||||
@@ -133,8 +131,8 @@ export interface ResolutionCache {
|
||||
|
||||
/** @internal */
|
||||
export interface ResolutionWithFailedLookupLocations {
|
||||
readonly failedLookupLocations: string[];
|
||||
readonly affectingLocations: string[];
|
||||
failedLookupLocations?: string[];
|
||||
affectingLocations?: string[];
|
||||
isInvalidated?: boolean;
|
||||
refCount?: number;
|
||||
// Files that have this resolution using
|
||||
@@ -329,9 +327,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
|
||||
startCachingPerDirectoryResolution,
|
||||
finishCachingPerDirectoryResolution,
|
||||
resolveModuleNames,
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache,
|
||||
resolveTypeReferenceDirectives,
|
||||
resolveModuleNameLiterals,
|
||||
resolveTypeReferenceDirectiveReferences,
|
||||
resolveSingleModuleNameWithoutWatching,
|
||||
removeResolutionsFromProjectReferenceRedirects,
|
||||
removeResolutionsOfFile,
|
||||
hasChangedAutomaticTypeDirectiveNames: () => hasChangedAutomaticTypeDirectiveNames,
|
||||
@@ -466,7 +464,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
hasChangedAutomaticTypeDirectiveNames = false;
|
||||
}
|
||||
|
||||
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, _containingSourceFile?: never, mode?: ResolutionMode): CachedResolvedModuleWithFailedLookupLocations {
|
||||
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, redirectedReference?: ResolvedProjectReference, mode?: ResolutionMode): CachedResolvedModuleWithFailedLookupLocations {
|
||||
const host = resolutionHost.getCompilerHost?.() || resolutionHost;
|
||||
const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache, redirectedReference, mode);
|
||||
// return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts
|
||||
if (!resolutionHost.getGlobalCache) {
|
||||
@@ -478,7 +477,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
if (globalCache !== undefined && !isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension))) {
|
||||
// create different collection of failed lookup locations for second pass
|
||||
// if it will fail and we've already found something during the first pass - we don't want to pollute its results
|
||||
const { resolvedModule, failedLookupLocations, affectingLocations } = loadModuleFromGlobalCache(
|
||||
const { resolvedModule, failedLookupLocations, affectingLocations, resolutionDiagnostics } = loadModuleFromGlobalCache(
|
||||
Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName),
|
||||
resolutionHost.projectName,
|
||||
compilerOptions,
|
||||
@@ -489,8 +488,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
if (resolvedModule) {
|
||||
// Modify existing resolution so its saved in the directory cache as well
|
||||
(primaryResult.resolvedModule as any) = resolvedModule;
|
||||
primaryResult.failedLookupLocations.push(...failedLookupLocations);
|
||||
primaryResult.affectingLocations.push(...affectingLocations);
|
||||
primaryResult.failedLookupLocations = updateResolutionField(primaryResult.failedLookupLocations, failedLookupLocations);
|
||||
primaryResult.affectingLocations = updateResolutionField(primaryResult.affectingLocations, affectingLocations);
|
||||
primaryResult.resolutionDiagnostics = updateResolutionField(primaryResult.resolutionDiagnostics, resolutionDiagnostics);
|
||||
return primaryResult;
|
||||
}
|
||||
}
|
||||
@@ -499,34 +499,45 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
return primaryResult;
|
||||
}
|
||||
|
||||
function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, _containingSourceFile?: SourceFile, resolutionMode?: ResolutionMode): CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations {
|
||||
return ts.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host, redirectedReference, typeReferenceDirectiveResolutionCache, resolutionMode);
|
||||
function createModuleResolutionLoader(
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
): ResolutionLoader<StringLiteralLike, ResolvedModuleWithFailedLookupLocations, SourceFile> {
|
||||
return {
|
||||
nameAndMode: moduleResolutionNameAndModeGetter,
|
||||
resolve: (moduleName, resoluionMode) => resolveModuleName(
|
||||
moduleName,
|
||||
containingFile,
|
||||
options,
|
||||
redirectedReference,
|
||||
resoluionMode,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
interface ResolveNamesWithLocalCacheInput<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName> {
|
||||
names: readonly string[] | readonly FileReference[];
|
||||
interface ResolveNamesWithLocalCacheInput<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName> {
|
||||
entries: readonly Entry[];
|
||||
containingFile: string;
|
||||
containingSourceFile: SourceFile;
|
||||
redirectedReference: ResolvedProjectReference | undefined;
|
||||
options: CompilerOptions;
|
||||
reusedNames?: readonly Entry[];
|
||||
perFileCache: Map<Path, ModeAwareCache<T>>;
|
||||
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, containingSourceFile?: SourceFile, resolutionMode?: ResolutionMode) => T;
|
||||
loader: ResolutionLoader<Entry, T, SourceFile>;
|
||||
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
|
||||
shouldRetryResolution: (t: T) => boolean;
|
||||
reusedNames?: readonly string[];
|
||||
resolutionInfo?: ModuleResolutionInfo | TypeReferenceDirectiveResolutionInfo;
|
||||
logChanges?: boolean;
|
||||
containingSourceFile?: SourceFile;
|
||||
containingSourceFileMode?: ResolutionMode;
|
||||
}
|
||||
function resolveNamesWithLocalCache<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
|
||||
names, containingFile, redirectedReference,
|
||||
perFileCache,
|
||||
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
|
||||
entries, containingFile, containingSourceFile, redirectedReference, options,
|
||||
perFileCache, reusedNames,
|
||||
loader, getResolutionWithResolvedFileName,
|
||||
shouldRetryResolution, reusedNames, resolutionInfo, logChanges, containingSourceFile, containingSourceFileMode
|
||||
}: ResolveNamesWithLocalCacheInput<T, R>): (R | undefined)[] {
|
||||
shouldRetryResolution, logChanges,
|
||||
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
|
||||
const path = resolutionHost.toPath(containingFile);
|
||||
const resolutionsInFile = perFileCache.get(path) || perFileCache.set(path, createModeAwareCache()).get(path)!;
|
||||
const resolvedModules: (R | undefined)[] = [];
|
||||
const compilerOptions = resolutionHost.getCompilationSettings();
|
||||
const resolvedModules: T[] = [];
|
||||
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path);
|
||||
|
||||
// All the resolutions in this file are invalidated if this file wasn't resolved using same redirect
|
||||
@@ -537,22 +548,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
!!redirectedReference;
|
||||
|
||||
const seenNamesInFile = createModeAwareCache<true>();
|
||||
let i = 0;
|
||||
for (const entry of containingSourceFile && resolutionInfo ? resolutionInfo.names : names) {
|
||||
const name = getResolutionName(entry);
|
||||
// Imports supply a `containingSourceFile` but no `containingSourceFileMode` - it would be redundant
|
||||
// they require calculating the mode for a given import from it's position in the resolution table, since a given
|
||||
// import's syntax may override the file's default mode.
|
||||
// Type references instead supply a `containingSourceFileMode` and a non-string entry which contains
|
||||
// a default file mode override if applicable.
|
||||
const mode = !isString(entry) ?
|
||||
isStringLiteralLike(entry) ?
|
||||
getModeForUsageLocation(containingSourceFile!, entry) :
|
||||
getModeForFileReference(entry, containingSourceFileMode) :
|
||||
containingSourceFile ?
|
||||
getModeForResolutionAtIndex(containingSourceFile, i) :
|
||||
undefined;
|
||||
i++;
|
||||
for (const entry of entries) {
|
||||
const name = loader.nameAndMode.getName(entry);
|
||||
const mode = loader.nameAndMode.getMode(entry, containingSourceFile);
|
||||
let resolution = resolutionsInFile.get(name, mode);
|
||||
// Resolution is valid if it is present and not invalidated
|
||||
if (!seenNamesInFile.has(name, mode) &&
|
||||
@@ -560,7 +558,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
// If the name is unresolved import that was invalidated, recalculate
|
||||
(hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && shouldRetryResolution(resolution))) {
|
||||
const existingResolution = resolution;
|
||||
resolution = loader(name, containingFile, compilerOptions, resolutionHost.getCompilerHost?.() || resolutionHost, redirectedReference, containingSourceFile, mode);
|
||||
resolution = loader.resolve(name, mode);
|
||||
if (resolutionHost.onDiscoveredSymlink && resolutionIsSymlink(resolution)) {
|
||||
resolutionHost.onDiscoveredSymlink();
|
||||
}
|
||||
@@ -578,11 +576,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
else {
|
||||
const host = resolutionHost.getCompilerHost?.() || resolutionHost;
|
||||
if (isTraceEnabled(compilerOptions, host) && !seenNamesInFile.has(name, mode)) {
|
||||
if (isTraceEnabled(options, host) && !seenNamesInFile.has(name, mode)) {
|
||||
const resolved = getResolutionWithResolvedFileName(resolution);
|
||||
trace(
|
||||
host,
|
||||
loader === resolveModuleName as unknown ?
|
||||
perFileCache === resolvedModuleNames as unknown ?
|
||||
resolved?.resolvedFileName ?
|
||||
resolved.packageId ?
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
|
||||
@@ -602,30 +600,22 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
Debug.assert(resolution !== undefined && !resolution.isInvalidated);
|
||||
seenNamesInFile.set(name, mode, true);
|
||||
resolvedModules.push(getResolutionWithResolvedFileName(resolution));
|
||||
}
|
||||
|
||||
// If resolving type reference directive we dont need containingSourceFile to determine if we can use resolutionInfo
|
||||
if (resolutionInfo && (loader === resolveTypeReferenceDirective as unknown || containingSourceFile)) {
|
||||
resolutionInfo.reusedNames?.forEach(entry => seenNamesInFile.set(
|
||||
getResolutionName(entry),
|
||||
!isString(entry) && isStringLiteralLike(entry) ?
|
||||
getModeForUsageLocation(containingSourceFile!, entry) :
|
||||
getModeForFileReference(entry, containingSourceFileMode),
|
||||
true,
|
||||
));
|
||||
reusedNames = undefined;
|
||||
resolvedModules.push(resolution);
|
||||
}
|
||||
reusedNames?.forEach(entry => seenNamesInFile.set(
|
||||
loader.nameAndMode.getName(entry),
|
||||
loader.nameAndMode.getMode(entry, containingSourceFile),
|
||||
true,
|
||||
));
|
||||
if (resolutionsInFile.size() !== seenNamesInFile.size()) {
|
||||
// Stop watching and remove the unused name
|
||||
resolutionsInFile.forEach((resolution, name, mode) => {
|
||||
if (!seenNamesInFile.has(name, mode) && !contains(reusedNames, name)) {
|
||||
if (!seenNamesInFile.has(name, mode)) {
|
||||
stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName);
|
||||
resolutionsInFile.delete(name, mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return resolvedModules;
|
||||
|
||||
function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean {
|
||||
@@ -647,53 +637,67 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
}
|
||||
|
||||
function resolveTypeReferenceDirectives(
|
||||
typeDirectiveNames: string[] | readonly FileReference[],
|
||||
function resolveTypeReferenceDirectiveReferences<T extends FileReference | string>(
|
||||
typeDirectiveReferences: readonly T[],
|
||||
containingFile: string,
|
||||
redirectedReference?: ResolvedProjectReference,
|
||||
containingFileMode?: ResolutionMode,
|
||||
resolutionInfo?: TypeReferenceDirectiveResolutionInfo,
|
||||
): (ResolvedTypeReferenceDirective | undefined)[] {
|
||||
return resolveNamesWithLocalCache<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolvedTypeReferenceDirective>({
|
||||
names: typeDirectiveNames,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile | undefined,
|
||||
reusedNames: readonly T[] | undefined
|
||||
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]{
|
||||
return resolveNamesWithLocalCache({
|
||||
entries: typeDirectiveReferences,
|
||||
containingFile,
|
||||
containingSourceFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
reusedNames,
|
||||
perFileCache: resolvedTypeReferenceDirectives,
|
||||
loader: resolveTypeReferenceDirective,
|
||||
loader: createTypeReferenceResolutionLoader(
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
resolutionHost.getCompilerHost?.() || resolutionHost,
|
||||
typeReferenceDirectiveResolutionCache
|
||||
),
|
||||
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective,
|
||||
shouldRetryResolution: resolution => resolution.resolvedTypeReferenceDirective === undefined,
|
||||
containingSourceFileMode: containingFileMode,
|
||||
resolutionInfo,
|
||||
});
|
||||
}
|
||||
|
||||
function resolveModuleNames(
|
||||
moduleNames: string[],
|
||||
function resolveModuleNameLiterals(
|
||||
moduleLiterals: readonly StringLiteralLike[],
|
||||
containingFile: string,
|
||||
reusedNames: string[] | undefined,
|
||||
redirectedReference?: ResolvedProjectReference,
|
||||
containingSourceFile?: SourceFile,
|
||||
resolutionInfo?: ModuleResolutionInfo
|
||||
): (ResolvedModuleFull | undefined)[] {
|
||||
return resolveNamesWithLocalCache<CachedResolvedModuleWithFailedLookupLocations, ResolvedModuleFull>({
|
||||
names: moduleNames,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile,
|
||||
reusedNames: readonly StringLiteralLike[] | undefined,
|
||||
): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
return resolveNamesWithLocalCache({
|
||||
entries: moduleLiterals,
|
||||
containingFile,
|
||||
containingSourceFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
reusedNames,
|
||||
perFileCache: resolvedModuleNames,
|
||||
loader: resolveModuleName,
|
||||
loader: createModuleResolutionLoader(
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
),
|
||||
getResolutionWithResolvedFileName: getResolvedModule,
|
||||
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
|
||||
reusedNames,
|
||||
resolutionInfo,
|
||||
logChanges: logChangesWhenResolvingModule,
|
||||
containingSourceFile,
|
||||
});
|
||||
}
|
||||
|
||||
function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ResolutionMode): CachedResolvedModuleWithFailedLookupLocations | undefined {
|
||||
const cache = resolvedModuleNames.get(resolutionHost.toPath(containingFile));
|
||||
if (!cache) return undefined;
|
||||
return cache.get(moduleName, resolutionMode);
|
||||
function resolveSingleModuleNameWithoutWatching(moduleName: string, containingFile: string) {
|
||||
const path = resolutionHost.toPath(containingFile);
|
||||
const resolutionsInFile = resolvedModuleNames.get(path);
|
||||
const resolution = resolutionsInFile?.get(moduleName, /*mode*/ undefined);
|
||||
if (resolution && !resolution.isInvalidated) return resolution;
|
||||
return resolveModuleName(moduleName, containingFile, resolutionHost.getCompilationSettings());
|
||||
}
|
||||
|
||||
function isNodeModulesAtTypesDirectory(dirPath: Path) {
|
||||
@@ -797,42 +801,44 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
Debug.assert(!!resolution.refCount);
|
||||
|
||||
const { failedLookupLocations, affectingLocations } = resolution;
|
||||
if (!failedLookupLocations.length && !affectingLocations.length) return;
|
||||
if (failedLookupLocations.length) resolutionsWithFailedLookups.push(resolution);
|
||||
if (!failedLookupLocations?.length && !affectingLocations?.length) return;
|
||||
if (failedLookupLocations?.length) resolutionsWithFailedLookups.push(resolution);
|
||||
|
||||
let setAtRoot = false;
|
||||
for (const failedLookupLocation of failedLookupLocations) {
|
||||
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
|
||||
const toWatch = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (toWatch) {
|
||||
const { dir, dirPath, nonRecursive } = toWatch;
|
||||
// If the failed lookup location path is not one of the supported extensions,
|
||||
// store it in the custom path
|
||||
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
|
||||
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
|
||||
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
|
||||
}
|
||||
if (dirPath === rootPath) {
|
||||
Debug.assert(!nonRecursive);
|
||||
setAtRoot = true;
|
||||
}
|
||||
else {
|
||||
setDirectoryWatcher(dir, dirPath, nonRecursive);
|
||||
if (failedLookupLocations) {
|
||||
for (const failedLookupLocation of failedLookupLocations) {
|
||||
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
|
||||
const toWatch = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (toWatch) {
|
||||
const { dir, dirPath, nonRecursive } = toWatch;
|
||||
// If the failed lookup location path is not one of the supported extensions,
|
||||
// store it in the custom path
|
||||
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
|
||||
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
|
||||
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
|
||||
}
|
||||
if (dirPath === rootPath) {
|
||||
Debug.assert(!nonRecursive);
|
||||
setAtRoot = true;
|
||||
}
|
||||
else {
|
||||
setDirectoryWatcher(dir, dirPath, nonRecursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setAtRoot) {
|
||||
// This is always non recursive
|
||||
setDirectoryWatcher(rootDir!, rootPath, /*nonRecursive*/ true); // TODO: GH#18217
|
||||
if (setAtRoot) {
|
||||
// This is always non recursive
|
||||
setDirectoryWatcher(rootDir!, rootPath, /*nonRecursive*/ true); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
watchAffectingLocationsOfResolution(resolution, !failedLookupLocations.length);
|
||||
watchAffectingLocationsOfResolution(resolution, !failedLookupLocations?.length);
|
||||
}
|
||||
|
||||
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) {
|
||||
Debug.assert(!!resolution.refCount);
|
||||
const { affectingLocations } = resolution;
|
||||
if (!affectingLocations.length) return;
|
||||
if (!affectingLocations?.length) return;
|
||||
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.push(resolution);
|
||||
// Watch package json
|
||||
for (const affectingLocation of affectingLocations) {
|
||||
@@ -932,7 +938,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
const { failedLookupLocations, affectingLocations } = resolution;
|
||||
if (unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) {
|
||||
let removeAtRoot = false;
|
||||
for (const failedLookupLocation of failedLookupLocations) {
|
||||
for (const failedLookupLocation of failedLookupLocations!) {
|
||||
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
|
||||
const toWatch = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (toWatch) {
|
||||
@@ -960,13 +966,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
removeDirectoryWatcher(rootPath);
|
||||
}
|
||||
}
|
||||
else if (affectingLocations.length) {
|
||||
else if (affectingLocations?.length) {
|
||||
unorderedRemoveItem(resolutionsWithOnlyAffectingLocations, resolution);
|
||||
}
|
||||
|
||||
for (const affectingLocation of affectingLocations) {
|
||||
const watcher = fileWatchesOfAffectingLocations.get(affectingLocation)!;
|
||||
watcher.resolutions--;
|
||||
if (affectingLocations) {
|
||||
for (const affectingLocation of affectingLocations) {
|
||||
const watcher = fileWatchesOfAffectingLocations.get(affectingLocation)!;
|
||||
watcher.resolutions--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,7 +1028,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective);
|
||||
}
|
||||
|
||||
function invalidateResolutions(resolutions: ResolutionWithFailedLookupLocations[] | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean) {
|
||||
function invalidateResolutions(resolutions: ResolutionWithFailedLookupLocations[] | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) {
|
||||
if (!resolutions) return false;
|
||||
let invalidated = false;
|
||||
for (const resolution of resolutions) {
|
||||
@@ -1130,7 +1138,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
function canInvalidateFailedLookupResolution(resolution: ResolutionWithFailedLookupLocations) {
|
||||
if (canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution)) return true;
|
||||
if (!failedLookupChecks && !startsWithPathChecks && !isInDirectoryChecks) return false;
|
||||
return resolution.failedLookupLocations.some(location => isInvalidatedFailedLookup(resolutionHost.toPath(location)));
|
||||
return resolution.failedLookupLocations?.some(location => isInvalidatedFailedLookup(resolutionHost.toPath(location)));
|
||||
}
|
||||
|
||||
function isInvalidatedFailedLookup(locationPath: Path) {
|
||||
@@ -1140,7 +1148,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
|
||||
function canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution: ResolutionWithFailedLookupLocations) {
|
||||
return !!affectingPathChecks && resolution.affectingLocations.some(location => affectingPathChecks!.has(location));
|
||||
return !!affectingPathChecks && resolution.affectingLocations?.some(location => affectingPathChecks!.has(location));
|
||||
}
|
||||
|
||||
function closeTypeRootsWatch() {
|
||||
|
||||
@@ -24,9 +24,11 @@ import {
|
||||
createDiagnosticReporter,
|
||||
createGetCanonicalFileName,
|
||||
createModuleResolutionCache,
|
||||
createModuleResolutionLoader,
|
||||
CreateProgram,
|
||||
createProgramHost,
|
||||
createTypeReferenceDirectiveResolutionCache,
|
||||
createTypeReferenceResolutionLoader,
|
||||
createWatchFactory,
|
||||
createWatchHost,
|
||||
CustomTransformers,
|
||||
@@ -75,7 +77,6 @@ import {
|
||||
isString,
|
||||
listFiles,
|
||||
loadWithModeAwareCache,
|
||||
loadWithTypeDirectiveCache,
|
||||
map,
|
||||
maybeBind,
|
||||
missingFileModifiedTime,
|
||||
@@ -97,15 +98,10 @@ import {
|
||||
ProgramMultiFileEmitBuildInfo,
|
||||
readBuilderProgram,
|
||||
ReadBuildProgramHost,
|
||||
ResolutionMode,
|
||||
resolveConfigFileProjectName,
|
||||
ResolvedConfigFileName,
|
||||
ResolvedProjectReference,
|
||||
ResolvedTypeReferenceDirective,
|
||||
resolveModuleName,
|
||||
resolvePath,
|
||||
resolveProjectReferencePath,
|
||||
resolveTypeReferenceDirective,
|
||||
returnUndefined,
|
||||
SemanticDiagnosticsBuilderProgram,
|
||||
setGetSourceFileAsHashVersioned,
|
||||
@@ -438,22 +434,40 @@ function createSolutionBuilderState<T extends BuilderProgram>(watch: boolean, ho
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => state.projectCompilerOptions) as CompilerHost & ReadBuildProgramHost;
|
||||
setGetSourceFileAsHashVersioned(compilerHost);
|
||||
compilerHost.getParsedCommandLine = fileName => parseConfigFile(state, fileName as ResolvedConfigFileName, toResolvedConfigFilePath(state, fileName as ResolvedConfigFileName));
|
||||
compilerHost.resolveModuleNameLiterals = maybeBind(host, host.resolveModuleNameLiterals);
|
||||
compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind(host, host.resolveTypeReferenceDirectiveReferences);
|
||||
compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames);
|
||||
compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives);
|
||||
compilerHost.getModuleResolutionCache = maybeBind(host, host.getModuleResolutionCache);
|
||||
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, resolverMode: ResolutionMode, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) =>
|
||||
resolveModuleName(moduleName, containingFile, state.projectCompilerOptions, compilerHost, moduleResolutionCache, redirectedReference, resolverMode).resolvedModule;
|
||||
compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, _options, containingSourceFile, resolutionInfo) =>
|
||||
loadWithModeAwareCache(Debug.checkEachDefined(moduleNames), Debug.checkDefined(containingSourceFile), containingFile, redirectedReference, resolutionInfo, loader);
|
||||
let moduleResolutionCache: ModuleResolutionCache | undefined, typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined;
|
||||
if (!compilerHost.resolveModuleNameLiterals && !compilerHost.resolveModuleNames) {
|
||||
moduleResolutionCache = createModuleResolutionCache(currentDirectory, getCanonicalFileName);
|
||||
compilerHost.resolveModuleNameLiterals = (moduleNames, containingFile, redirectedReference, options, containingSourceFile) =>
|
||||
loadWithModeAwareCache(
|
||||
moduleNames,
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingSourceFile,
|
||||
host,
|
||||
moduleResolutionCache,
|
||||
createModuleResolutionLoader,
|
||||
);
|
||||
compilerHost.getModuleResolutionCache = () => moduleResolutionCache;
|
||||
}
|
||||
if (!compilerHost.resolveTypeReferenceDirectives) {
|
||||
const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined, containingFileMode: ResolutionMode) => resolveTypeReferenceDirective(moduleName, containingFile, state.projectCompilerOptions, compilerHost, redirectedReference, state.typeReferenceDirectiveResolutionCache, containingFileMode).resolvedTypeReferenceDirective!;
|
||||
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile, redirectedReference, _options, containingFileMode) =>
|
||||
loadWithTypeDirectiveCache<ResolvedTypeReferenceDirective>(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, containingFileMode, loader);
|
||||
if (!compilerHost.resolveTypeReferenceDirectiveReferences && !compilerHost.resolveTypeReferenceDirectives) {
|
||||
typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache());
|
||||
compilerHost.resolveTypeReferenceDirectiveReferences = (typeDirectiveNames, containingFile, redirectedReference, options, containingSourceFile) =>
|
||||
loadWithModeAwareCache(
|
||||
typeDirectiveNames,
|
||||
containingFile,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingSourceFile,
|
||||
host,
|
||||
typeReferenceDirectiveResolutionCache,
|
||||
createTypeReferenceResolutionLoader,
|
||||
);
|
||||
}
|
||||
compilerHost.getBuildInfo = (fileName, configFilePath) => getBuildInfo(state, fileName, toResolvedConfigFilePath(state, configFilePath as ResolvedConfigFileName), /*modifiedTime*/ undefined);
|
||||
|
||||
|
||||
@@ -4114,8 +4114,8 @@ export interface SourceFile extends Declaration {
|
||||
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined
|
||||
// It is used to resolve module names in the checker.
|
||||
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
|
||||
/** @internal */ resolvedModules?: ModeAwareCache<ResolvedModuleFull | undefined>;
|
||||
/** @internal */ resolvedTypeReferenceDirectiveNames: ModeAwareCache<ResolvedTypeReferenceDirective | undefined>;
|
||||
/** @internal */ resolvedModules?: ModeAwareCache<ResolvedModuleWithFailedLookupLocations>;
|
||||
/** @internal */ resolvedTypeReferenceDirectiveNames?: ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>;
|
||||
/** @internal */ imports: readonly StringLiteralLike[];
|
||||
// Identifier only if `declare global`
|
||||
/** @internal */ moduleAugmentations: readonly (StringLiteral | Identifier)[];
|
||||
@@ -4386,7 +4386,8 @@ export type FileIncludeReason =
|
||||
/** @internal */
|
||||
export const enum FilePreprocessingDiagnosticsKind {
|
||||
FilePreprocessingReferencedDiagnostic,
|
||||
FilePreprocessingFileExplainingDiagnostic
|
||||
FilePreprocessingFileExplainingDiagnostic,
|
||||
ResolutionDiagnostics,
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -4407,7 +4408,13 @@ export interface FilePreprocessingFileExplainingDiagnostic {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type FilePreprocessingDiagnostics = FilePreprocessingReferencedDiagnostic | FilePreprocessingFileExplainingDiagnostic;
|
||||
export interface ResolutionDiagnostics {
|
||||
kind: FilePreprocessingDiagnosticsKind.ResolutionDiagnostics;
|
||||
diagnostics: readonly Diagnostic[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type FilePreprocessingDiagnostics = FilePreprocessingReferencedDiagnostic | FilePreprocessingFileExplainingDiagnostic | ResolutionDiagnostics;
|
||||
|
||||
/** @internal */
|
||||
export const enum EmitOnly{
|
||||
@@ -4483,7 +4490,9 @@ export interface Program extends ScriptReferenceHost {
|
||||
getRelationCacheSizes(): { assignable: number, identity: number, subtype: number, strictSubtype: number };
|
||||
|
||||
/** @internal */ getFileProcessingDiagnostics(): FilePreprocessingDiagnostics[] | undefined;
|
||||
/** @internal */ getResolvedTypeReferenceDirectives(): ModeAwareCache<ResolvedTypeReferenceDirective | undefined>;
|
||||
/** @internal */ getResolvedTypeReferenceDirectives(): ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>;
|
||||
/** @internal */ getAutomaticTypeDirectiveNames(): string[];
|
||||
/** @internal */ getAutomaticTypeDirectiveResolutions(): ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>;
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
isSourceFileDefaultLibrary(file: SourceFile): boolean;
|
||||
|
||||
@@ -4521,8 +4530,6 @@ export interface Program extends ScriptReferenceHost {
|
||||
/** @internal */ getFileIncludeReasons(): MultiMap<Path, FileIncludeReason>;
|
||||
/** @internal */ useCaseSensitiveFileNames(): boolean;
|
||||
|
||||
/** @internal */ getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, mode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
|
||||
getProjectReferences(): readonly ProjectReference[] | undefined;
|
||||
getResolvedProjectReferences(): readonly (ResolvedProjectReference | undefined)[] | undefined;
|
||||
/** @internal */ getProjectReferenceRedirect(fileName: string): string | undefined;
|
||||
@@ -4646,7 +4653,7 @@ export interface TypeCheckerHost extends ModuleSpecifierResolutionHost {
|
||||
|
||||
getSourceFiles(): readonly SourceFile[];
|
||||
getSourceFile(fileName: string): SourceFile | undefined;
|
||||
getResolvedTypeReferenceDirectives(): ModeAwareCache<ResolvedTypeReferenceDirective | undefined>;
|
||||
getResolvedTypeReferenceDirectives(): ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>;
|
||||
getProjectReferenceRedirect(fileName: string): string | undefined;
|
||||
isSourceOfProjectReferenceRedirect(fileName: string): boolean;
|
||||
|
||||
@@ -5343,8 +5350,8 @@ export interface EmitResolver {
|
||||
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
|
||||
isArgumentsLocalBinding(node: Identifier): boolean;
|
||||
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined;
|
||||
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode | undefined][] | undefined;
|
||||
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode | undefined][] | undefined;
|
||||
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode][] | undefined;
|
||||
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode][] | undefined;
|
||||
isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean;
|
||||
getJsxFactoryEntity(location?: Node): EntityName | undefined;
|
||||
getJsxFragmentFactoryEntity(location?: Node): EntityName | undefined;
|
||||
@@ -7275,11 +7282,11 @@ export const enum Extension {
|
||||
export interface ResolvedModuleWithFailedLookupLocations {
|
||||
readonly resolvedModule: ResolvedModuleFull | undefined;
|
||||
/** @internal */
|
||||
readonly failedLookupLocations: string[];
|
||||
failedLookupLocations?: string[];
|
||||
/** @internal */
|
||||
readonly affectingLocations: string[];
|
||||
affectingLocations?: string[];
|
||||
/** @internal */
|
||||
readonly resolutionDiagnostics: Diagnostic[]
|
||||
resolutionDiagnostics?: Diagnostic[]
|
||||
}
|
||||
|
||||
export interface ResolvedTypeReferenceDirective {
|
||||
@@ -7300,9 +7307,9 @@ export interface ResolvedTypeReferenceDirective {
|
||||
|
||||
export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
|
||||
readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
|
||||
readonly failedLookupLocations: string[];
|
||||
/** @internal */ readonly affectingLocations: string[];
|
||||
/** @internal */ resolutionDiagnostics: Diagnostic[];
|
||||
/** @internal */ failedLookupLocations?: string[];
|
||||
/** @internal */ affectingLocations?: string[];
|
||||
/** @internal */ resolutionDiagnostics?: Diagnostic[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -7310,13 +7317,6 @@ export type HasInvalidatedResolutions = (sourceFile: Path) => boolean;
|
||||
/** @internal */
|
||||
export type HasChangedAutomaticTypeDirectiveNames = () => boolean;
|
||||
|
||||
export interface ResolutionInfo<T> {
|
||||
names: readonly T[];
|
||||
reusedNames: readonly T[] | undefined;
|
||||
}
|
||||
export type ModuleResolutionInfo = ResolutionInfo<StringLiteralLike>;
|
||||
export type TypeReferenceDirectiveResolutionInfo = ResolutionInfo<string | FileReference>;
|
||||
|
||||
export interface CompilerHost extends ModuleResolutionHost {
|
||||
getSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined;
|
||||
getSourceFileByPath?(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined;
|
||||
@@ -7337,15 +7337,34 @@ export interface CompilerHost extends ModuleResolutionHost {
|
||||
* If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just
|
||||
* 'throw new Error("NotImplemented")'
|
||||
*/
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile, resolutionInfo?: ModuleResolutionInfo): (ResolvedModule | undefined)[];
|
||||
/** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[];
|
||||
/**
|
||||
* Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it
|
||||
*/
|
||||
getModuleResolutionCache?(): ModuleResolutionCache | undefined;
|
||||
/**
|
||||
* @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext
|
||||
*
|
||||
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
|
||||
*/
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode | undefined, resolutionInfo?: TypeReferenceDirectiveResolutionInfo): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
resolveModuleNameLiterals?(
|
||||
moduleLiterals: readonly StringLiteralLike[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile,
|
||||
reusedNames: readonly StringLiteralLike[] | undefined,
|
||||
): readonly ResolvedModuleWithFailedLookupLocations[];
|
||||
resolveTypeReferenceDirectiveReferences?<T extends FileReference | string>(
|
||||
typeDirectiveReferences: readonly T[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile | undefined,
|
||||
reusedNames: readonly T[] | undefined
|
||||
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void;
|
||||
/** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void;
|
||||
|
||||
@@ -124,7 +124,6 @@ import {
|
||||
FileExtensionInfo,
|
||||
fileExtensionIs,
|
||||
fileExtensionIsOneOf,
|
||||
FileReference,
|
||||
FileWatcher,
|
||||
filter,
|
||||
find,
|
||||
@@ -184,8 +183,6 @@ import {
|
||||
getPathComponents,
|
||||
getPathFromPathComponents,
|
||||
getRelativePathToDirectoryOrUrl,
|
||||
getResolutionMode,
|
||||
getResolutionName,
|
||||
getRootLength,
|
||||
getSnippetElement,
|
||||
getStringComparer,
|
||||
@@ -425,8 +422,11 @@ import {
|
||||
RequireOrImportCall,
|
||||
RequireVariableStatement,
|
||||
ResolutionMode,
|
||||
ResolutionNameAndModeGetter,
|
||||
ResolvedModuleFull,
|
||||
ResolvedModuleWithFailedLookupLocations,
|
||||
ResolvedTypeReferenceDirective,
|
||||
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
ReturnStatement,
|
||||
SatisfiesExpression,
|
||||
ScriptKind,
|
||||
@@ -705,11 +705,11 @@ export function getFullWidth(node: Node) {
|
||||
|
||||
/** @internal */
|
||||
export function getResolvedModule(sourceFile: SourceFile | undefined, moduleNameText: string, mode: ResolutionMode): ResolvedModuleFull | undefined {
|
||||
return sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules.get(moduleNameText, mode);
|
||||
return sourceFile?.resolvedModules?.get(moduleNameText, mode)?.resolvedModule;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleFull | undefined, mode: ResolutionMode): void {
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleWithFailedLookupLocations, mode: ResolutionMode): void {
|
||||
if (!sourceFile.resolvedModules) {
|
||||
sourceFile.resolvedModules = createModeAwareCache();
|
||||
}
|
||||
@@ -718,7 +718,7 @@ export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined, mode: ResolutionMode): void {
|
||||
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, mode: ResolutionMode): void {
|
||||
if (!sourceFile.resolvedTypeReferenceDirectiveNames) {
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames = createModeAwareCache();
|
||||
}
|
||||
@@ -728,7 +728,7 @@ export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeRe
|
||||
|
||||
/** @internal */
|
||||
export function getResolvedTypeReferenceDirective(sourceFile: SourceFile | undefined, typeReferenceDirectiveName: string, mode: ResolutionMode): ResolvedTypeReferenceDirective | undefined {
|
||||
return sourceFile?.resolvedTypeReferenceDirectiveNames?.get(typeReferenceDirectiveName, mode);
|
||||
return sourceFile?.resolvedTypeReferenceDirectiveNames?.get(typeReferenceDirectiveName, mode)?.resolvedTypeReferenceDirective;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -739,12 +739,16 @@ export function projectReferenceIsEqualTo(oldRef: ProjectReference, newRef: Proj
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleFull, newResolution: ResolvedModuleFull): boolean {
|
||||
return oldResolution.isExternalLibraryImport === newResolution.isExternalLibraryImport &&
|
||||
oldResolution.extension === newResolution.extension &&
|
||||
oldResolution.resolvedFileName === newResolution.resolvedFileName &&
|
||||
oldResolution.originalPath === newResolution.originalPath &&
|
||||
packageIdIsEqual(oldResolution.packageId, newResolution.packageId);
|
||||
export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleWithFailedLookupLocations, newResolution: ResolvedModuleWithFailedLookupLocations): boolean {
|
||||
return oldResolution === newResolution ||
|
||||
oldResolution.resolvedModule === newResolution.resolvedModule ||
|
||||
!!oldResolution.resolvedModule &&
|
||||
!!newResolution.resolvedModule &&
|
||||
oldResolution.resolvedModule.isExternalLibraryImport === newResolution.resolvedModule.isExternalLibraryImport &&
|
||||
oldResolution.resolvedModule.extension === newResolution.resolvedModule.extension &&
|
||||
oldResolution.resolvedModule.resolvedFileName === newResolution.resolvedModule.resolvedFileName &&
|
||||
oldResolution.resolvedModule.originalPath === newResolution.resolvedModule.originalPath &&
|
||||
packageIdIsEqual(oldResolution.resolvedModule.packageId, newResolution.resolvedModule.packageId);
|
||||
}
|
||||
|
||||
function packageIdIsEqual(a: PackageId | undefined, b: PackageId | undefined): boolean {
|
||||
@@ -762,26 +766,32 @@ export function packageIdToString(packageId: PackageId): string {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function typeDirectiveIsEqualTo(oldResolution: ResolvedTypeReferenceDirective, newResolution: ResolvedTypeReferenceDirective): boolean {
|
||||
return oldResolution.resolvedFileName === newResolution.resolvedFileName
|
||||
&& oldResolution.primary === newResolution.primary
|
||||
&& oldResolution.originalPath === newResolution.originalPath;
|
||||
export function typeDirectiveIsEqualTo(oldResolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, newResolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations): boolean {
|
||||
return oldResolution === newResolution ||
|
||||
oldResolution.resolvedTypeReferenceDirective === newResolution.resolvedTypeReferenceDirective ||
|
||||
!!oldResolution.resolvedTypeReferenceDirective &&
|
||||
!!newResolution.resolvedTypeReferenceDirective &&
|
||||
oldResolution.resolvedTypeReferenceDirective.resolvedFileName === newResolution.resolvedTypeReferenceDirective.resolvedFileName &&
|
||||
!!oldResolution.resolvedTypeReferenceDirective.primary === !!newResolution.resolvedTypeReferenceDirective.primary &&
|
||||
oldResolution.resolvedTypeReferenceDirective.originalPath === newResolution.resolvedTypeReferenceDirective.originalPath;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function hasChangesInResolutions<T>(
|
||||
names: readonly StringLiteralLike[] | readonly FileReference[],
|
||||
export function hasChangesInResolutions<K, V>(
|
||||
names: readonly K[],
|
||||
newSourceFile: SourceFile,
|
||||
newResolutions: readonly T[],
|
||||
oldResolutions: ModeAwareCache<T> | undefined,
|
||||
comparer: (oldResolution: T, newResolution: T) => boolean): boolean {
|
||||
newResolutions: readonly V[],
|
||||
oldResolutions: ModeAwareCache<V> | undefined,
|
||||
comparer: (oldResolution: V, newResolution: V) => boolean,
|
||||
nameAndModeGetter: ResolutionNameAndModeGetter<K, SourceFile>,
|
||||
): boolean {
|
||||
Debug.assert(names.length === newResolutions.length);
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const newResolution = newResolutions[i];
|
||||
const entry = names[i];
|
||||
const name = getResolutionName(entry);
|
||||
const mode = getResolutionMode(entry, newSourceFile);
|
||||
const name = nameAndModeGetter.getName(entry);
|
||||
const mode = nameAndModeGetter.getMode(entry, newSourceFile);
|
||||
const oldResolution = oldResolutions && oldResolutions.get(name, mode);
|
||||
const changed =
|
||||
oldResolution
|
||||
@@ -7726,7 +7736,7 @@ export interface SymlinkCache {
|
||||
* don't include automatic type reference directives. Must be called only when
|
||||
* `hasProcessedResolutions` returns false (once per cache instance).
|
||||
*/
|
||||
setSymlinksFromResolutions(files: readonly SourceFile[], typeReferenceDirectives: ModeAwareCache<ResolvedTypeReferenceDirective | undefined> | undefined): void;
|
||||
setSymlinksFromResolutions(files: readonly SourceFile[], typeReferenceDirectives: ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>): void;
|
||||
/**
|
||||
* @internal
|
||||
* Whether `setSymlinksFromResolutions` has already been called.
|
||||
@@ -7762,9 +7772,10 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic
|
||||
Debug.assert(!hasProcessedResolutions);
|
||||
hasProcessedResolutions = true;
|
||||
for (const file of files) {
|
||||
file.resolvedModules?.forEach(resolution => processResolution(this, resolution));
|
||||
file.resolvedModules?.forEach(resolution => processResolution(this, resolution.resolvedModule));
|
||||
file.resolvedTypeReferenceDirectiveNames?.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective));
|
||||
}
|
||||
typeReferenceDirectives?.forEach(resolution => processResolution(this, resolution));
|
||||
typeReferenceDirectives.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective));
|
||||
},
|
||||
hasProcessedResolutions: () => hasProcessedResolutions,
|
||||
};
|
||||
|
||||
@@ -57,7 +57,6 @@ import {
|
||||
MapLike,
|
||||
maybeBind,
|
||||
ModuleResolutionCache,
|
||||
ModuleResolutionInfo,
|
||||
noop,
|
||||
noopFileWatcher,
|
||||
parseConfigHostFromCompilerHostLike,
|
||||
@@ -69,18 +68,20 @@ import {
|
||||
ResolutionCacheHost,
|
||||
ResolutionMode,
|
||||
ResolvedModule,
|
||||
ResolvedModuleWithFailedLookupLocations,
|
||||
ResolvedProjectReference,
|
||||
ResolvedTypeReferenceDirective,
|
||||
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
returnFalse,
|
||||
returnTrue,
|
||||
ScriptTarget,
|
||||
setGetSourceFileAsHashVersioned,
|
||||
SharedExtendedConfigFileWatcher,
|
||||
SourceFile,
|
||||
StringLiteralLike,
|
||||
sys,
|
||||
System,
|
||||
toPath,
|
||||
TypeReferenceDirectiveResolutionInfo,
|
||||
updateErrorForNoInputFiles,
|
||||
updateMissingFilePathsWatch,
|
||||
updateSharedExtendedConfigFileWatcher,
|
||||
@@ -202,10 +203,34 @@ export interface ProgramHost<T extends BuilderProgram> {
|
||||
/** If provided is used to get the environment variable */
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
|
||||
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile, resolutionInfo?: ModuleResolutionInfo): (ResolvedModule | undefined)[];
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode, resolutionInfo?: TypeReferenceDirectiveResolutionInfo): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
/**
|
||||
* @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext
|
||||
*
|
||||
* If provided, used to resolve the module names, otherwise typescript's default module resolution
|
||||
*/
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[];
|
||||
/**
|
||||
* @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext
|
||||
*
|
||||
* If provided, used to resolve type reference directives, otherwise typescript's default resolution
|
||||
*/
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
resolveModuleNameLiterals?(
|
||||
moduleLiterals: readonly StringLiteralLike[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile,
|
||||
reusedNames: readonly StringLiteralLike[] | undefined,
|
||||
): readonly ResolvedModuleWithFailedLookupLocations[];
|
||||
resolveTypeReferenceDirectiveReferences?<T extends FileReference | string>(
|
||||
typeDirectiveReferences: readonly T[],
|
||||
containingFile: string,
|
||||
redirectedReference: ResolvedProjectReference | undefined,
|
||||
options: CompilerOptions,
|
||||
containingSourceFile: SourceFile | undefined,
|
||||
reusedNames: readonly T[] | undefined
|
||||
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
/** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */
|
||||
hasInvalidatedResolutions?(filePath: Path): boolean;
|
||||
/**
|
||||
@@ -463,16 +488,21 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
/*logChangesWhenResolvingModule*/ false
|
||||
);
|
||||
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
|
||||
compilerHost.resolveModuleNames = host.resolveModuleNames ?
|
||||
((...args) => host.resolveModuleNames!(...args)) :
|
||||
((moduleNames, containingFile, reusedNames, redirectedReference, _options, sourceFile, resolutionInfo) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, sourceFile, resolutionInfo));
|
||||
compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ?
|
||||
((...args) => host.resolveTypeReferenceDirectives!(...args)) :
|
||||
((typeDirectiveNames, containingFile, redirectedReference, _options, containingFileMode, resolutionInfo) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference, containingFileMode, resolutionInfo));
|
||||
compilerHost.getModuleResolutionCache = host.resolveModuleNames ?
|
||||
compilerHost.resolveModuleNameLiterals = maybeBind(host, host.resolveModuleNameLiterals);
|
||||
compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames);
|
||||
if (!compilerHost.resolveModuleNameLiterals && !compilerHost.resolveModuleNames) {
|
||||
compilerHost.resolveModuleNameLiterals = resolutionCache.resolveModuleNameLiterals.bind(resolutionCache);
|
||||
}
|
||||
compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind(host, host.resolveTypeReferenceDirectiveReferences);
|
||||
compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives);
|
||||
if (!compilerHost.resolveTypeReferenceDirectiveReferences && !compilerHost.resolveTypeReferenceDirectives) {
|
||||
compilerHost.resolveTypeReferenceDirectiveReferences = resolutionCache.resolveTypeReferenceDirectiveReferences.bind(resolutionCache);
|
||||
}
|
||||
compilerHost.getModuleResolutionCache = host.resolveModuleNameLiterals || host.resolveModuleNames ?
|
||||
maybeBind(host, host.getModuleResolutionCache) :
|
||||
(() => resolutionCache.getModuleResolutionCache());
|
||||
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
|
||||
const userProvidedResolution = !!host.resolveModuleNameLiterals || !!host.resolveTypeReferenceDirectiveReferences ||
|
||||
!!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
|
||||
// All resolutions are invalid if user provided resolutions and didnt supply hasInvalidatedResolutions
|
||||
const customHasInvalidatedResolutions = userProvidedResolution ?
|
||||
maybeBind(host, host.hasInvalidatedResolutions) || returnTrue :
|
||||
|
||||
Reference in New Issue
Block a user