Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Picking resolutions of module for sourceFile as method #55818

Merged
merged 3 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions src/compiler/builderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,18 +238,15 @@ export namespace BuilderState {
}

// Handle type reference directives
const resolvedTypeReferenceDirectiveNames = program.resolvedTypeReferenceDirectiveNames?.get(sourceFile.path);
if (resolvedTypeReferenceDirectiveNames) {
resolvedTypeReferenceDirectiveNames.forEach(({ resolvedTypeReferenceDirective }) => {
if (!resolvedTypeReferenceDirective) {
return;
}
program.forEachResolvedTypeReferenceDirective(({ resolvedTypeReferenceDirective }) => {
if (!resolvedTypeReferenceDirective) {
return;
}

const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217
const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(typeFilePath);
});
}
const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217
const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(typeFilePath);
}, sourceFile);

// Add module augmentation as references
if (sourceFile.moduleAugmentations.length) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4959,7 +4959,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
(isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal;
const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat;
const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions);
const resolvedModule = host.resolvedModules?.get(currentSourceFile.path)?.get(moduleReference, mode)?.resolvedModule;
const resolvedModule = host.getResolvedModule(currentSourceFile, moduleReference, mode)?.resolvedModule;
const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile);
const sourceFile = resolvedModule
&& (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set)
Expand Down
84 changes: 63 additions & 21 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ export function getReferencedFileLocation(program: Program, ref: ReferencedFile)
switch (kind) {
case FileIncludeKind.Import:
const importLiteral = getModuleNameStringLiteralAt(file, index);
packageId = program.resolvedModules?.get(file.path)?.get(importLiteral.text, getModeForResolutionAtIndex(file, index))?.resolvedModule?.packageId;
packageId = program.getResolvedModule(file, 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;
Expand All @@ -1187,7 +1187,7 @@ export function getReferencedFileLocation(program: Program, ref: ReferencedFile)
break;
case FileIncludeKind.TypeReferenceDirective:
({ pos, end, resolutionMode } = file.typeReferenceDirectives[index]);
packageId = program.resolvedTypeReferenceDirectiveNames?.get(file.path)?.get(toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.resolvedTypeReferenceDirective?.packageId;
packageId = program.getResolvedTypeReferenceDirective(file, toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.resolvedTypeReferenceDirective?.packageId;
break;
case FileIncludeKind.LibReferenceDirective:
({ pos, end } = file.libReferenceDirectives[index]);
Expand Down Expand Up @@ -1888,6 +1888,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
resolvedModules,
resolvedTypeReferenceDirectiveNames,
resolvedLibReferences,
getResolvedModule,
getResolvedTypeReferenceDirective,
forEachResolvedModule,
forEachResolvedTypeReferenceDirective,
getCurrentPackagesMap: () => packageMap,
typesPackageExists,
packageBundlesTypes,
Expand Down Expand Up @@ -1937,18 +1941,47 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg

return program;

function getResolvedModule(file: SourceFile, moduleName: string, mode: ResolutionMode) {
return resolvedModules?.get(file.path)?.get(moduleName, mode);
}

function getResolvedTypeReferenceDirective(file: SourceFile, typeDirectiveName: string, mode: ResolutionMode) {
return resolvedTypeReferenceDirectiveNames?.get(file.path)?.get(typeDirectiveName, mode);
}

function forEachResolvedModule(
callback: (resolution: ResolvedModuleWithFailedLookupLocations, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
file?: SourceFile,
) {
forEachResolution(resolvedModules, callback, file);
}

function forEachResolvedTypeReferenceDirective(
callback: (resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
file?: SourceFile,
): void {
forEachResolution(resolvedTypeReferenceDirectiveNames, callback, file);
}

function forEachResolution<T>(
resolutionCache: Map<Path, ModeAwareCache<T>> | undefined,
callback: (resolution: T, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
file: SourceFile | undefined,
) {
if (file) resolutionCache?.get(file.path)?.forEach((resolution, name, mode) => callback(resolution, name, mode, file.path));
else resolutionCache?.forEach((resolutions, filePath) => resolutions.forEach((resolution, name, mode) => callback(resolution, name, mode, filePath)));
}

function getPackagesMap() {
if (packageMap) return packageMap;
packageMap = new Map();
// A package name maps to true when we detect it has .d.ts files.
// This is useful as an approximation of whether a package bundles its own types.
// Note: we only look at files already found by module resolution,
// so there may be files we did not consider.
files.forEach(sf =>
resolvedModules?.get(sf.path)?.forEach(({ resolvedModule }) => {
if (resolvedModule?.packageId) packageMap!.set(resolvedModule.packageId.name, resolvedModule.extension === Extension.Dts || !!packageMap!.get(resolvedModule.packageId.name));
})
);
forEachResolvedModule(({ resolvedModule }) => {
if (resolvedModule?.packageId) packageMap!.set(resolvedModule.packageId.name, resolvedModule.extension === Extension.Dts || !!packageMap!.get(resolvedModule.packageId.name));
});
return packageMap;
}

Expand Down Expand Up @@ -2121,7 +2154,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
if (file === oldSourceFile && !hasInvalidatedResolutions(file.path)) {
const mode = getModeForUsageLocation(file, moduleName);
const oldResolution = oldProgram?.resolvedModules?.get(file.path)?.get(moduleName.text, mode);
const oldResolution = oldProgram?.getResolvedModule(file, moduleName.text, mode);
if (oldResolution?.resolvedModule) {
if (isTraceEnabled(options, host)) {
trace(
Expand Down Expand Up @@ -2189,7 +2222,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
// If we change our policy of rechecking failed lookups on each program create,
// we should adjust the value returned here.
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike): boolean {
const resolutionToFile = oldProgram?.resolvedModules?.get(file.path)?.get(moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule;
const resolutionToFile = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule;
const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName);
if (resolutionToFile && resolvedFile) {
// In the old program, we resolved to an ambient module that was in the same
Expand Down Expand Up @@ -2236,7 +2269,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
if (canReuseResolutions) {
const typeDirectiveName = getTypeReferenceResolutionName(entry);
const mode = getModeForFileReference(entry, containingSourceFile?.impliedNodeFormat);
const oldResolution = (!isString(containingFile) ? oldProgram?.resolvedTypeReferenceDirectiveNames?.get(containingFile.path) : oldProgram?.getAutomaticTypeDirectiveResolutions())?.get(typeDirectiveName, mode);
const oldResolution = !isString(containingFile) ?
oldProgram?.getResolvedTypeReferenceDirective(containingFile, typeDirectiveName, mode) :
oldProgram?.getAutomaticTypeDirectiveResolutions()?.get(typeDirectiveName, mode);
if (oldResolution?.resolvedTypeReferenceDirective) {
if (isTraceEnabled(options, host)) {
trace(
Expand Down Expand Up @@ -2478,22 +2513,29 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
const moduleNames = getModuleNames(newSourceFile);
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFile);
(resolvedModulesProcessing ??= new Map()).set(newSourceFile.path, resolutions);
const oldResolutions = oldProgram.resolvedModules?.get(newSourceFile.path);
// ensure that module resolution results are still correct
const resolutionsChanged = hasChangesInResolutions(moduleNames, newSourceFile, resolutions, oldResolutions, moduleResolutionIsEqualTo, moduleResolutionNameAndModeGetter);
const resolutionsChanged = hasChangesInResolutions(
moduleNames,
newSourceFile,
resolutions,
(name, mode) => oldProgram!.getResolvedModule(newSourceFile, name, mode),
moduleResolutionIsEqualTo,
moduleResolutionNameAndModeGetter,
);
if (resolutionsChanged) structureIsReused = StructureIsReused.SafeModules;
const typesReferenceDirectives = newSourceFile.typeReferenceDirectives;
const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState(typesReferenceDirectives, newSourceFile);
(resolvedTypeReferenceDirectiveNamesProcessing ??= new Map()).set(newSourceFile.path, typeReferenceResolutions);
// ensure that types resolutions are still correct
const oldTypeResolutions = oldProgram.resolvedTypeReferenceDirectiveNames?.get(newSourceFile.path);
const typeReferenceResolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, newSourceFile, typeReferenceResolutions, oldTypeResolutions, typeDirectiveIsEqualTo, typeReferenceResolutionNameAndModeGetter);
if (typeReferenceResolutionsChanged) {
structureIsReused = StructureIsReused.SafeModules;
}
else if (oldTypeResolutions) {
(resolvedTypeReferenceDirectiveNamesProcessing ??= new Map()).set(newSourceFile.path, oldTypeResolutions);
}
const typeReferenceResolutionsChanged = hasChangesInResolutions(
typesReferenceDirectives,
newSourceFile,
typeReferenceResolutions,
(name, mode) => oldProgram?.getResolvedTypeReferenceDirective(newSourceFile, name, mode),
typeDirectiveIsEqualTo,
typeReferenceResolutionNameAndModeGetter,
);
if (typeReferenceResolutionsChanged) structureIsReused = StructureIsReused.SafeModules;
}

if (structureIsReused !== StructureIsReused.Completely) {
Expand Down Expand Up @@ -4933,7 +4975,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
symlinks = createSymlinkCache(currentDirectory, getCanonicalFileName);
}
if (files && !symlinks.hasProcessedResolutions()) {
symlinks.setSymlinksFromResolutions(resolvedModules, resolvedTypeReferenceDirectiveNames, automaticTypeDirectiveResolutions);
symlinks.setSymlinksFromResolutions(forEachResolvedModule, forEachResolvedTypeReferenceDirective, automaticTypeDirectiveResolutions);
}
return symlinks;
}
Expand Down
16 changes: 15 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4651,6 +4651,20 @@ export interface Program extends ScriptReferenceHost {
resolvedModules: Map<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
/** @internal */
resolvedTypeReferenceDirectiveNames: Map<Path, ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>> | undefined;
/** @internal */
getResolvedModule(f: SourceFile, moduleName: string, mode: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined;
/** @internal */
getResolvedTypeReferenceDirective(f: SourceFile, typeDirectiveName: string, mode: ResolutionMode): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined;
/** @internal */
forEachResolvedModule(
callback: (resolution: ResolvedModuleWithFailedLookupLocations, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
file?: SourceFile,
): void;
/** @internal */
forEachResolvedTypeReferenceDirective(
callback: (resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
file?: SourceFile,
): void;

/**
* Emits the JavaScript and declaration files. If targetSourceFile is not specified, then
Expand Down Expand Up @@ -4868,7 +4882,7 @@ export interface TypeCheckerHost extends ModuleSpecifierResolutionHost {
getProjectReferenceRedirect(fileName: string): string | undefined;
isSourceOfProjectReferenceRedirect(fileName: string): boolean;

resolvedModules: Map<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
getResolvedModule(f: SourceFile, moduleName: string, mode: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined;

readonly redirectTargetsMap: RedirectTargetsMap;

Expand Down
20 changes: 12 additions & 8 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleWithFaile

/** @internal */
export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeCheckerHost, moduleReference: string, mode: ResolutionMode, packageName: string) {
const node10Result = host.resolvedModules?.get(sourceFile.path)?.get(moduleReference, mode)?.node10Result;
const node10Result = host.getResolvedModule(sourceFile, moduleReference, mode)?.node10Result;
const result = node10Result
? chainDiagnosticMessages(
/*details*/ undefined,
Expand Down Expand Up @@ -828,7 +828,7 @@ export function hasChangesInResolutions<K, V>(
names: readonly K[],
newSourceFile: SourceFile,
newResolutions: readonly V[],
oldResolutions: ModeAwareCache<V> | undefined,
getOldResolution: (name: string, mode: ResolutionMode) => V | undefined,
comparer: (oldResolution: V, newResolution: V) => boolean,
nameAndModeGetter: ResolutionNameAndModeGetter<K, SourceFile>,
): boolean {
Expand All @@ -839,7 +839,7 @@ export function hasChangesInResolutions<K, V>(
const entry = names[i];
const name = nameAndModeGetter.getName(entry);
const mode = nameAndModeGetter.getMode(entry, newSourceFile);
const oldResolution = oldResolutions && oldResolutions.get(name, mode);
const oldResolution = getOldResolution(name, mode);
const changed = oldResolution
? !newResolution || !comparer(oldResolution, newResolution)
: newResolution;
Expand Down Expand Up @@ -8825,8 +8825,12 @@ export interface SymlinkCache {
* `hasProcessedResolutions` returns false (once per cache instance).
*/
setSymlinksFromResolutions(
resolvedModules: Map<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined,
resolvedTypeReferenceDirectiveNames: Map<Path, ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>> | undefined,
forEachResolvedModule: (
callback: (resolution: ResolvedModuleWithFailedLookupLocations, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
) => void,
forEachResolvedTypeReferenceDirective: (
callback: (resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, moduleName: string, mode: ResolutionMode, filePath: Path) => void,
) => void,
typeReferenceDirectives: ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>,
): void;
/**
Expand Down Expand Up @@ -8860,11 +8864,11 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic
(symlinkedDirectories || (symlinkedDirectories = new Map())).set(symlinkPath, real);
}
},
setSymlinksFromResolutions(resolvedModules, resolvedTypeReferenceDirectiveNames, typeReferenceDirectives) {
setSymlinksFromResolutions(forEachResolvedModule, forEachResolvedTypeReferenceDirective, typeReferenceDirectives) {
Debug.assert(!hasProcessedResolutions);
hasProcessedResolutions = true;
resolvedModules?.forEach(cache => cache.forEach(resolution => processResolution(this, resolution.resolvedModule)));
resolvedTypeReferenceDirectiveNames?.forEach(cache => cache.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective)));
forEachResolvedModule(resolution => processResolution(this, resolution.resolvedModule));
forEachResolvedTypeReferenceDirective(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective));
typeReferenceDirectives.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective));
},
hasProcessedResolutions: () => hasProcessedResolutions,
Expand Down
Loading
Loading