Skip to content

Commit 6c9662b

Browse files
committed
Use globalCacheResolution to invalidate resolutions on typings update
1 parent 01bf971 commit 6c9662b

3 files changed

Lines changed: 43 additions & 53 deletions

File tree

src/compiler/resolutionCache.ts

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
emptyArray,
1616
endsWith,
1717
Extension,
18-
extensionIsTS,
1918
fileExtensionIs,
2019
FileReference,
2120
FileWatcher,
@@ -142,16 +141,15 @@ export interface ResolutionCache {
142141
invalidateResolutionsOfFailedLookupLocations(): boolean;
143142
invalidateResolutionsWithGlobalCachePass(): void;
144143
invalidateResolutionsWithoutGlobalCachePass(): void;
144+
invalidateUnresolvedResolutionsWithGlobalCachePass(): void;
145145
invalidateResolutionOfFile(filePath: Path): void;
146146
removeResolutionsOfFile(filePath: Path): void;
147147
removeResolutionsFromProjectReferenceRedirects(filePath: Path): void;
148-
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<Path, readonly string[]>): void;
149148
createHasInvalidatedResolutions(
150149
customHasInvalidatedResolutions: HasInvalidatedResolutions,
151150
customHasInvalidatedLibResolutions: HasInvalidatedLibResolutions,
152151
): HasInvalidatedFromResolutionCache;
153152
hasChangedAutomaticTypeDirectiveNames(): boolean;
154-
isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean;
155153

156154
startCachingPerDirectoryResolution(): void;
157155
finishCachingPerDirectoryResolution(newProgram: Program | undefined, oldProgram: Program | undefined): void;
@@ -530,6 +528,15 @@ export function createModuleResolutionLoaderUsingGlobalCache(
530528
};
531529
}
532530

531+
/** @internal */
532+
export function needsResolutionFromGlobalCache(moduleName: string, resolution: ResolvedModuleWithFailedLookupLocations): boolean {
533+
return !isExternalModuleNameRelative(moduleName) && isUnresolvedOrResolvedToJs(resolution);
534+
}
535+
536+
function isUnresolvedOrResolvedToJs(resolution: ResolvedModuleWithFailedLookupLocations) {
537+
return !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension);
538+
}
539+
533540
function resolveModuleNameUsingGlobalCache(
534541
resolutionHost: ResolutionCacheHost,
535542
moduleResolutionCache: ModuleResolutionCache,
@@ -548,7 +555,7 @@ function resolveModuleNameUsingGlobalCache(
548555

549556
// otherwise try to load typings from @types
550557
const globalCache = resolutionHost.getGlobalTypingsCacheLocation();
551-
if (!isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension))) {
558+
if (needsResolutionFromGlobalCache(moduleName, primaryResult)) {
552559
if (globalCache === undefined) {
553560
primaryResult.globalCacheResolution = false;
554561
return primaryResult;
@@ -587,7 +594,6 @@ export function createResolutionCache(
587594
): ResolutionCache {
588595
let filesWithChangedSetOfUnresolvedImports: Path[] | undefined;
589596
let filesWithInvalidatedResolutions: Set<Path> | undefined;
590-
let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyMap<Path, readonly string[]> | undefined;
591597
const nonRelativeExternalModuleResolutions = new Set<ResolutionWithFailedLookupLocations>();
592598

593599
const resolutionsWithFailedLookups = new Set<ResolutionWithFailedLookupLocations>();
@@ -604,6 +610,7 @@ export function createResolutionCache(
604610
let allModuleAndTypeResolutionsAreInvalidated = false;
605611
let resolutionsWithGlobalCachePassAreInvalidated = false;
606612
let resolutionsWithoutGlobalCachePassAreInvalidated = false;
613+
let unresolvedResolutionsWithGlobalCachePassAreInvalidated = false;
607614

608615
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!());
609616
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
@@ -685,9 +692,8 @@ export function createResolutionCache(
685692
invalidateResolutionsOfFailedLookupLocations,
686693
invalidateResolutionsWithGlobalCachePass,
687694
invalidateResolutionsWithoutGlobalCachePass,
688-
setFilesWithInvalidatedNonRelativeUnresolvedImports,
695+
invalidateUnresolvedResolutionsWithGlobalCachePass,
689696
createHasInvalidatedResolutions,
690-
isFileWithInvalidatedNonRelativeUnresolvedImports,
691697
updateTypeRootsWatch,
692698
closeTypeRootsWatch,
693699
clear,
@@ -717,6 +723,7 @@ export function createResolutionCache(
717723
allModuleAndTypeResolutionsAreInvalidated = false;
718724
resolutionsWithGlobalCachePassAreInvalidated = false;
719725
resolutionsWithoutGlobalCachePassAreInvalidated = false;
726+
unresolvedResolutionsWithGlobalCachePassAreInvalidated = false;
720727
moduleResolutionCache.clear();
721728
typeReferenceDirectiveResolutionCache.clear();
722729
moduleResolutionCache.update(resolutionHost.getCompilationSettings());
@@ -745,16 +752,6 @@ export function createResolutionCache(
745752
return collected;
746753
}
747754

748-
function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean {
749-
if (!filesWithInvalidatedNonRelativeUnresolvedImports) {
750-
return false;
751-
}
752-
753-
// Invalidated if file has unresolved imports
754-
const value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path);
755-
return !!value && !!value.length;
756-
}
757-
758755
function createHasInvalidatedResolutions(
759756
customHasInvalidatedResolutions: HasInvalidatedResolutions,
760757
customHasInvalidatedLibResolutions: HasInvalidatedLibResolutions,
@@ -767,8 +764,10 @@ export function createResolutionCache(
767764
hasInvalidatedResolutions: path =>
768765
customHasInvalidatedResolutions(path) ||
769766
allModuleAndTypeResolutionsAreInvalidated ||
770-
!!collected?.has(path) ||
771-
isFileWithInvalidatedNonRelativeUnresolvedImports(path),
767+
resolutionsWithGlobalCachePassAreInvalidated ||
768+
resolutionsWithoutGlobalCachePassAreInvalidated ||
769+
unresolvedResolutionsWithGlobalCachePassAreInvalidated ||
770+
!!collected?.has(path),
772771
hasInvalidatedLibResolutions: libFileName =>
773772
customHasInvalidatedLibResolutions(libFileName) ||
774773
!!resolvedLibraries?.get(libFileName)?.isInvalidated,
@@ -803,8 +802,10 @@ export function createResolutionCache(
803802
}
804803

805804
function finishCachingPerDirectoryResolution(newProgram: Program | undefined, oldProgram: Program | undefined) {
806-
filesWithInvalidatedNonRelativeUnresolvedImports = undefined;
807805
allModuleAndTypeResolutionsAreInvalidated = false;
806+
resolutionsWithGlobalCachePassAreInvalidated = false;
807+
resolutionsWithoutGlobalCachePassAreInvalidated = false;
808+
unresolvedResolutionsWithGlobalCachePassAreInvalidated = false;
808809
watchFailedLookupLocationOfNonRelativeModuleResolutions();
809810
// Update file watches
810811
if (newProgram !== oldProgram) {
@@ -862,6 +863,13 @@ export function createResolutionCache(
862863
}
863864
}
864865

866+
function isResolutionInvalidatedPerGlobalCacheOptions(resolution: ResolutionWithFailedLookupLocations) {
867+
if (resolutionsWithGlobalCachePassAreInvalidated && resolution.globalCacheResolution) return true;
868+
if (resolutionsWithoutGlobalCachePassAreInvalidated && resolution.globalCacheResolution === false) return true;
869+
if (unresolvedResolutionsWithGlobalCachePassAreInvalidated && resolution.globalCacheResolution && isUnresolvedOrResolvedToJs(resolution as ResolvedModuleWithFailedLookupLocations)) return true;
870+
return false;
871+
}
872+
865873
interface ResolveNamesWithLocalCacheInput<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName> {
866874
entries: readonly Entry[];
867875
containingFile: string;
@@ -872,7 +880,6 @@ export function createResolutionCache(
872880
perFileCache: Map<Path, ModeAwareCache<T>>;
873881
loader: ResolutionLoader<Entry, T, SourceFile>;
874882
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
875-
shouldRetryResolution: (t: T) => boolean;
876883
logChanges?: boolean;
877884
deferWatchingNonRelativeResolution: boolean;
878885
}
@@ -887,13 +894,11 @@ export function createResolutionCache(
887894
loader,
888895
getResolutionWithResolvedFileName,
889896
deferWatchingNonRelativeResolution,
890-
shouldRetryResolution,
891897
logChanges,
892898
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
893899
const path = resolutionHost.toPath(containingFile);
894900
const resolutionsInFile = perFileCache.get(path) || perFileCache.set(path, createModeAwareCache()).get(path)!;
895901
const resolvedModules: T[] = [];
896-
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path);
897902

898903
// All the resolutions in this file are invalidated if this file wasn't resolved using same redirect
899904
const program = resolutionHost.getCurrentProgram();
@@ -910,9 +915,13 @@ export function createResolutionCache(
910915
// Resolution is valid if it is present and not invalidated
911916
if (
912917
!seenNamesInFile.has(name, mode) &&
913-
(allModuleAndTypeResolutionsAreInvalidated || unmatchedRedirects || !resolution || resolution.isInvalidated ||
914-
// If the name is unresolved import that was invalidated, recalculate
915-
(hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && shouldRetryResolution(resolution)))
918+
(
919+
allModuleAndTypeResolutionsAreInvalidated ||
920+
unmatchedRedirects ||
921+
!resolution ||
922+
resolution.isInvalidated ||
923+
isResolutionInvalidatedPerGlobalCacheOptions(resolution)
924+
)
916925
) {
917926
const existingResolution = resolution;
918927
resolution = loader.resolve(name, mode);
@@ -1022,7 +1031,6 @@ export function createResolutionCache(
10221031
typeReferenceDirectiveResolutionCache,
10231032
),
10241033
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirectiveFromResolution,
1025-
shouldRetryResolution: resolution => resolution.resolvedTypeReferenceDirective === undefined,
10261034
deferWatchingNonRelativeResolution: false,
10271035
});
10281036
}
@@ -1051,7 +1059,6 @@ export function createResolutionCache(
10511059
moduleResolutionCache,
10521060
),
10531061
getResolutionWithResolvedFileName: getResolvedModuleFromResolution,
1054-
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
10551062
logChanges: !!resolutionHost.getGlobalTypingsCacheLocation,
10561063
deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules
10571064
});
@@ -1521,11 +1528,6 @@ export function createResolutionCache(
15211528
}
15221529
}
15231530

1524-
function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: ReadonlyMap<Path, readonly string[]>) {
1525-
Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined);
1526-
filesWithInvalidatedNonRelativeUnresolvedImports = filesMap;
1527-
}
1528-
15291531
function scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath: Path, isCreatingWatchedDirectory: boolean) {
15301532
if (isCreatingWatchedDirectory) {
15311533
// Watching directory is created
@@ -1593,6 +1595,9 @@ export function createResolutionCache(
15931595
function invalidateResolutionsWithoutGlobalCachePass() {
15941596
if (resolutionsResolvedWithoutGlobalCache) resolutionsWithoutGlobalCachePassAreInvalidated = true;
15951597
}
1598+
function invalidateUnresolvedResolutionsWithGlobalCachePass() {
1599+
if (resolutionsResolvedWithGlobalCache) unresolvedResolutionsWithGlobalCachePassAreInvalidated = true;
1600+
}
15961601

15971602
function invalidateResolutionsOfFailedLookupLocations() {
15981603
if (allModuleAndTypeResolutionsAreInvalidated) {
@@ -1605,8 +1610,6 @@ export function createResolutionCache(
16051610
startsWithPathChecks = undefined;
16061611
isInDirectoryChecks = undefined;
16071612
affectingPathChecks = undefined;
1608-
resolutionsWithGlobalCachePassAreInvalidated = false;
1609-
resolutionsWithoutGlobalCachePassAreInvalidated = false;
16101613
return true;
16111614
}
16121615
let invalidated = false;
@@ -1620,10 +1623,7 @@ export function createResolutionCache(
16201623
affectingPathChecksForFile = undefined;
16211624
}
16221625

1623-
if (
1624-
!failedLookupChecks && !startsWithPathChecks && !isInDirectoryChecks && !affectingPathChecks &&
1625-
!resolutionsWithGlobalCachePassAreInvalidated && !resolutionsWithoutGlobalCachePassAreInvalidated
1626-
) {
1626+
if (!failedLookupChecks && !startsWithPathChecks && !isInDirectoryChecks && !affectingPathChecks) {
16271627
return invalidated;
16281628
}
16291629

@@ -1634,8 +1634,6 @@ export function createResolutionCache(
16341634
isInDirectoryChecks = undefined;
16351635
invalidated = invalidateResolutions(resolutionsWithOnlyAffectingLocations, canInvalidatedFailedLookupResolutionWithAffectingLocation) || invalidated;
16361636
affectingPathChecks = undefined;
1637-
resolutionsWithGlobalCachePassAreInvalidated = false;
1638-
resolutionsWithoutGlobalCachePassAreInvalidated = false;
16391637
return invalidated;
16401638
}
16411639

@@ -1655,8 +1653,6 @@ export function createResolutionCache(
16551653
}
16561654

16571655
function canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution: ResolutionWithFailedLookupLocations) {
1658-
if (resolutionsWithGlobalCachePassAreInvalidated && resolution.globalCacheResolution) return true;
1659-
if (resolutionsWithoutGlobalCachePassAreInvalidated && resolution.globalCacheResolution === false) return true;
16601656
return !!affectingPathChecks && resolution.affectingLocations?.some(location => affectingPathChecks!.has(location));
16611657
}
16621658

src/server/project.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ import {
7676
InstallPackageOptions,
7777
IScriptSnapshot,
7878
isDeclarationFileName,
79-
isExternalModuleNameRelative,
8079
isInsideNodeModules,
8180
JSDocParsingMode,
8281
JsTyping,
@@ -90,6 +89,7 @@ import {
9089
ModuleResolutionCache,
9190
ModuleResolutionHost,
9291
ModuleSpecifierCache,
92+
needsResolutionFromGlobalCache,
9393
noopFileWatcher,
9494
normalizePath,
9595
normalizeSlashes,
@@ -107,7 +107,6 @@ import {
107107
ProjectReference,
108108
removeFileExtension,
109109
ResolutionCache,
110-
resolutionExtensionIsTSOrJson,
111110
ResolvedModuleWithFailedLookupLocations,
112111
ResolvedProjectReference,
113112
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
@@ -1557,7 +1556,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
15571556
// If typing files changed, then only schedule project update
15581557
this.typingFiles = typingFiles;
15591558
// Invalidate files with unresolved imports
1560-
this.resolutionCache.setFilesWithInvalidatedNonRelativeUnresolvedImports(this.cachedUnresolvedImportsPerFile);
1559+
if (this.typingFiles.length) this.resolutionCache.invalidateUnresolvedResolutionsWithGlobalCachePass();
15611560
this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this);
15621561
}
15631562
}
@@ -2444,11 +2443,10 @@ function extractUnresolvedImportsFromSourceFile(
24442443
): readonly string[] {
24452444
return getOrUpdate(cachedUnresolvedImportsPerFile, file.path, () => {
24462445
let unresolvedImports: string[] | undefined;
2447-
program.forEachResolvedModule(({ resolvedModule }, name) => {
2446+
program.forEachResolvedModule((resolution, name) => {
24482447
// pick unresolved non-relative names
24492448
if (
2450-
(!resolvedModule || !resolutionExtensionIsTSOrJson(resolvedModule.extension)) &&
2451-
!isExternalModuleNameRelative(name) &&
2449+
needsResolutionFromGlobalCache(name, resolution) &&
24522450
!ambientModules.some(m => m === name)
24532451
) {
24542452
unresolvedImports = append(unresolvedImports, parsePackageName(name).packageName);

src/testRunner/unittests/tsserver/typingsInstaller.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,8 +2410,6 @@ describe("unittests:: tsserver:: typingsInstaller:: recomputing resolutions of u
24102410
},
24112411
});
24122412
host.runQueuedTimeoutCallbacks(); // Update the graph
2413-
// Update the typing
2414-
assert.isFalse(proj.resolutionCache.isFileWithInvalidatedNonRelativeUnresolvedImports(app.path as ts.Path));
24152413
baselineTsserverLogs("typingsInstaller", scenario, session);
24162414
}
24172415

@@ -2515,9 +2513,7 @@ declare module "stream" {
25152513
},
25162514
});
25172515
proj.updateGraph(); // Update the graph
2518-
// Update the typing
25192516
session.host.baselineHost("After program update");
2520-
assert.isFalse(proj.resolutionCache.isFileWithInvalidatedNonRelativeUnresolvedImports(file.path as ts.Path));
25212517
baselineTsserverLogs("typingsInstaller", "should handle node core modules", session);
25222518
});
25232519
});

0 commit comments

Comments
 (0)