Skip to content

Commit 76f2d6a

Browse files
committed
In preparation of sharing resolutions, watch the resolutions right away instead of defering external module reoslutions to watch all failed lookup locations
1 parent 44bb9ae commit 76f2d6a

File tree

131 files changed

+584
-579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+584
-579
lines changed

src/compiler/resolutionCache.ts

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,10 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
115115
countResolutionsResolvedWithGlobalCache(): number;
116116
countResolutionsResolvedWithoutGlobalCache(): number;
117117

118-
watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
119-
name: string,
118+
watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
120119
resolution: T,
121120
filePath: Path,
122121
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
123-
deferWatchingNonRelativeResolution: boolean,
124122
): void;
125123

126124
resolveModuleNameLiterals(
@@ -181,10 +179,13 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
181179
export interface ResolutionWithFailedLookupLocations {
182180
failedLookupLocations?: string[];
183181
affectingLocations?: string[];
182+
alternateResult?: string;
184183
isInvalidated?: boolean;
185184
// Files that have this resolution using
186185
files?: Set<Path>;
187-
alternateResult?: string;
186+
watchedFailed?: number;
187+
watchedAffected?: number;
188+
setAtRoot?: boolean;
188189
globalCacheResolution?: boolean;
189190
}
190191

@@ -599,7 +600,6 @@ export function createResolutionCache(
599600
rootDirForResolution: string,
600601
): ResolutionCache {
601602
let filesWithInvalidatedResolutions: Set<Path> | undefined;
602-
const nonRelativeExternalModuleResolutions = new Set<ResolutionWithFailedLookupLocations>();
603603

604604
const resolutionsWithFailedLookups = new Set<ResolutionWithFailedLookupLocations>();
605605
const resolutionsWithOnlyAffectingLocations = new Set<ResolutionWithFailedLookupLocations>();
@@ -677,7 +677,7 @@ export function createResolutionCache(
677677
dirPathToSymlinkPackageRefCount,
678678
countResolutionsResolvedWithGlobalCache: () => resolutionsResolvedWithGlobalCache,
679679
countResolutionsResolvedWithoutGlobalCache: () => resolutionsResolvedWithoutGlobalCache,
680-
watchFailedLookupLocationsOfExternalModuleResolutions,
680+
watchResolution,
681681
getModuleResolutionCache: () => moduleResolutionCache,
682682
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
683683
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
@@ -710,7 +710,6 @@ export function createResolutionCache(
710710
isSymlinkCache.clear();
711711
packageDirWatchers.clear();
712712
dirPathToSymlinkPackageRefCount.clear();
713-
nonRelativeExternalModuleResolutions.clear();
714713
closeTypeRootsWatch();
715714
resolvedModuleNames.clear();
716715
resolvedTypeReferenceDirectives.clear();
@@ -776,9 +775,6 @@ export function createResolutionCache(
776775
moduleResolutionCache.clearAllExceptPackageJsonInfoCache();
777776
typeReferenceDirectiveResolutionCache.clearAllExceptPackageJsonInfoCache();
778777
libraryResolutionCache.clearAllExceptPackageJsonInfoCache();
779-
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
780-
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
781-
watchFailedLookupLocationOfNonRelativeModuleResolutions();
782778
isSymlinkCache.clear();
783779
}
784780

@@ -800,7 +796,6 @@ export function createResolutionCache(
800796
resolutionsWithGlobalCachePassAreInvalidated = false;
801797
resolutionsWithoutGlobalCachePassAreInvalidated = false;
802798
unresolvedResolutionsWithGlobalCachePassAreInvalidated = false;
803-
watchFailedLookupLocationOfNonRelativeModuleResolutions();
804799
// Update file watches
805800
if (newProgram !== oldProgram) {
806801
cleanupLibResolutionWatching(newProgram);
@@ -875,7 +870,6 @@ export function createResolutionCache(
875870
perFileCache: Map<Path, ModeAwareCache<T>>;
876871
loader: ResolutionLoader<Entry, T, SourceFile>;
877872
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
878-
deferWatchingNonRelativeResolution: boolean;
879873
onNewResolution?: CallbackOnNewResolution<T>;
880874
}
881875
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
@@ -889,7 +883,6 @@ export function createResolutionCache(
889883
ambientEntries,
890884
loader,
891885
getResolutionWithResolvedFileName,
892-
deferWatchingNonRelativeResolution,
893886
onNewResolution,
894887
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
895888
const path = resolutionHost.toPath(containingFile);
@@ -926,7 +919,7 @@ export function createResolutionCache(
926919
}
927920
resolutionsInFile.set(name, mode, resolution);
928921
if (resolution !== existingResolution) {
929-
watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution);
922+
watchResolution(resolution, path, getResolutionWithResolvedFileName);
930923
if (existingResolution) {
931924
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName);
932925
}
@@ -1097,7 +1090,6 @@ export function createResolutionCache(
10971090
typeReferenceDirectiveResolutionCache,
10981091
),
10991092
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirectiveFromResolution,
1100-
deferWatchingNonRelativeResolution: false,
11011093
});
11021094
}
11031095

@@ -1128,7 +1120,6 @@ export function createResolutionCache(
11281120
moduleResolutionCache,
11291121
),
11301122
getResolutionWithResolvedFileName: getResolvedModuleFromResolution,
1131-
deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules
11321123
onNewResolution,
11331124
});
11341125
}
@@ -1145,7 +1136,7 @@ export function createResolutionCache(
11451136
const existingResolution = resolution;
11461137
resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
11471138
const path = resolutionHost.toPath(resolveFrom);
1148-
watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModuleFromResolution, /*deferWatchingNonRelativeResolution*/ false);
1139+
watchResolution(resolution, path, getResolvedModuleFromResolution);
11491140
resolvedLibraries.set(libFileName, resolution);
11501141
if (existingResolution) {
11511142
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModuleFromResolution);
@@ -1194,25 +1185,19 @@ export function createResolutionCache(
11941185
return endsWith(dirPath, "/node_modules/@types");
11951186
}
11961187

1197-
function watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
1198-
name: string,
1188+
function watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
11991189
resolution: T,
12001190
filePath: Path,
12011191
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
1202-
deferWatchingNonRelativeResolution: boolean,
12031192
) {
12041193
(resolution.files ??= new Set()).add(filePath);
1194+
watchFailedLookupLocationOfResolution(resolution);
1195+
watchAffectingLocationsOfResolution(resolution);
12051196
if (resolution.files.size !== 1) return;
12061197

12071198
if (resolution.globalCacheResolution) resolutionsResolvedWithGlobalCache++;
12081199
else if (resolution.globalCacheResolution === false) resolutionsResolvedWithoutGlobalCache++;
12091200

1210-
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
1211-
watchFailedLookupLocationOfResolution(resolution);
1212-
}
1213-
else {
1214-
nonRelativeExternalModuleResolutions.add(resolution);
1215-
}
12161201
const resolved = getResolutionWithResolvedFileName(resolution);
12171202
if (resolved && resolved.resolvedFileName) {
12181203
const key = resolutionHost.toPath(resolved.resolvedFileName);
@@ -1249,33 +1234,38 @@ export function createResolutionCache(
12491234
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
12501235
Debug.assert(!!resolution.files?.size);
12511236

1252-
const { failedLookupLocations, affectingLocations, alternateResult } = resolution;
1253-
if (!failedLookupLocations?.length && !affectingLocations?.length && !alternateResult) return;
1254-
if (failedLookupLocations?.length || alternateResult) resolutionsWithFailedLookups.add(resolution);
1237+
const { failedLookupLocations, alternateResult, watchedFailed } = resolution;
1238+
// There have to be failed lookup locations if there is alternateResult so storing failedLookupLocation length is good enough,
1239+
// alternateResult doesnt change later only failed lookup locations get added on
1240+
if (watchedFailed === failedLookupLocations?.length) return;
1241+
if (!watchedFailed) {
1242+
resolutionsWithFailedLookups.add(resolution);
1243+
if (resolution.watchedAffected) resolutionsWithOnlyAffectingLocations.delete(resolution);
1244+
}
12551245

1256-
let setAtRoot = false;
1257-
if (failedLookupLocations) {
1258-
for (const failedLookupLocation of failedLookupLocations) {
1259-
setAtRoot = watchFailedLookupLocation(failedLookupLocation, setAtRoot);
1260-
}
1246+
let setAtRoot = !!resolution.setAtRoot;
1247+
for (let i = watchedFailed || 0; i < failedLookupLocations!.length; i++) {
1248+
setAtRoot = watchFailedLookupLocation(failedLookupLocations![i], setAtRoot);
12611249
}
1262-
if (alternateResult) setAtRoot = watchFailedLookupLocation(alternateResult, setAtRoot);
1263-
if (setAtRoot) {
1250+
if (!watchedFailed && alternateResult) setAtRoot = watchFailedLookupLocation(alternateResult, setAtRoot);
1251+
if (!resolution.setAtRoot && setAtRoot) {
12641252
// This is always non recursive
12651253
setDirectoryWatcher(rootDir, rootPath, /*packageDir*/ undefined, /*packageDirPath*/ undefined, /*nonRecursive*/ true);
12661254
}
1267-
watchAffectingLocationsOfResolution(resolution, !failedLookupLocations?.length && !alternateResult);
1255+
resolution.watchedFailed = failedLookupLocations?.length;
1256+
resolution.setAtRoot = setAtRoot;
12681257
}
12691258

1270-
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) {
1259+
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations) {
12711260
Debug.assert(!!resolution.files?.size);
1272-
const { affectingLocations } = resolution;
1273-
if (!affectingLocations?.length) return;
1274-
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution);
1261+
const { affectingLocations, watchedAffected } = resolution;
1262+
if (affectingLocations?.length === watchedAffected) return;
1263+
if (!watchedAffected && !resolution.watchedFailed) resolutionsWithOnlyAffectingLocations.add(resolution);
12751264
// Watch package json
1276-
for (const affectingLocation of affectingLocations) {
1277-
createFileWatcherOfAffectingLocation(affectingLocation, /*forResolution*/ true);
1265+
for (let i = watchedAffected || 0; i < affectingLocations!.length; i++) {
1266+
createFileWatcherOfAffectingLocation(affectingLocations![i], /*forResolution*/ true);
12781267
}
1268+
resolution.watchedAffected = affectingLocations?.length;
12791269
}
12801270

12811271
function createFileWatcherOfAffectingLocation(affectingLocation: string, forResolution: boolean) {
@@ -1343,11 +1333,6 @@ export function createResolutionCache(
13431333
packageJsonMap?.delete(resolutionHost.toPath(path));
13441334
}
13451335

1346-
function watchFailedLookupLocationOfNonRelativeModuleResolutions() {
1347-
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfResolution);
1348-
nonRelativeExternalModuleResolutions.clear();
1349-
}
1350-
13511336
function createDirectoryWatcherForPackageDir(
13521337
dir: string,
13531338
dirPath: Path,

src/harness/incrementalUtils.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ export function verifyResolutionCache(
222222
path,
223223
resolutions,
224224
getResolvedModuleFileName,
225-
/*deferWatchingNonRelativeResolution*/ true,
226225
expected.resolvedModuleNames,
227226
(name, mode) => actualProgram.getResolvedModule(actualProgram.getSourceFileByPath(path)!, name, mode),
228227
)
@@ -233,7 +232,6 @@ export function verifyResolutionCache(
233232
path,
234233
resolutions,
235234
getResolvedTypeRefFileName,
236-
/*deferWatchingNonRelativeResolution*/ false,
237235
expected.resolvedTypeReferenceDirectives,
238236
(name, mode) =>
239237
path !== inferredTypesPath ?
@@ -251,7 +249,6 @@ export function verifyResolutionCache(
251249
getResolvedModuleFileName(resolved),
252250
ts.getLibraryNameFromLibFileName(libFileName),
253251
/*mode*/ undefined,
254-
/*deferWatchingNonRelativeResolution*/ false,
255252
);
256253
expected.resolvedLibraries.set(libFileName, expectedResolution);
257254
});
@@ -304,7 +301,20 @@ export function verifyResolutionCache(
304301
!resolution.isInvalidated,
305302
`${projectName}:: Resolution should not be invalidated`,
306303
);
307-
verifySet(resolutionToExpected.get(resolution)!.files, resolution.files, `${projectName}:: Resolution files`);
304+
const expected = resolutionToExpected.get(resolution)!;
305+
verifySet(expected.files, resolution.files, `${projectName}:: Resolution files`);
306+
ts.Debug.assert(
307+
expected.watchedFailed === resolution.watchedFailed,
308+
`${projectName}:: Expected watchedFailed of Resolution ${expected.watchedFailed} but got ${resolution.watchedFailed}`,
309+
);
310+
ts.Debug.assert(
311+
expected.watchedAffected === resolution.watchedAffected,
312+
`${projectName}:: Expected watchedAffected of Resolution ${expected.watchedAffected} but got ${resolution.watchedAffected}`,
313+
);
314+
ts.Debug.assert(
315+
expected.setAtRoot === resolution.setAtRoot,
316+
`${projectName}:: Expected setAtRoot of Resolution ${expected.setAtRoot} but got ${resolution.setAtRoot}`,
317+
);
308318
});
309319
verifyMapOfResolutionSet(expected.resolvedFileToResolution, actual.resolvedFileToResolution, `resolvedFileToResolution`);
310320
verifyResolutionSet(expected.resolutionsWithFailedLookups, actual.resolutionsWithFailedLookups, `resolutionsWithFailedLookups`);
@@ -366,7 +376,6 @@ export function verifyResolutionCache(
366376
fileName: ts.Path,
367377
cache: ts.ModeAwareCache<T> | undefined,
368378
getResolvedFileName: (resolution: T) => string | undefined,
369-
deferWatchingNonRelativeResolution: boolean,
370379
storeExpected: Map<ts.Path, ts.ModeAwareCache<ts.ResolutionWithFailedLookupLocations>>,
371380
getProgramResolutions: (name: string, mode: ts.ResolutionMode) => T | undefined,
372381
) {
@@ -377,7 +386,7 @@ export function verifyResolutionCache(
377386
let expectedCache: ts.ModeAwareCache<ts.ResolutionWithFailedLookupLocations> | undefined;
378387
cache?.forEach((resolved, name, mode) => {
379388
const resolvedFileName = getResolvedFileName(resolved);
380-
const expected = collectResolution(cacheType, fileName, resolved, resolvedFileName, name, mode, deferWatchingNonRelativeResolution);
389+
const expected = collectResolution(cacheType, fileName, resolved, resolvedFileName, name, mode);
381390
if (!expectedCache) storeExpected.set(fileName, expectedCache = ts.createModeAwareCache());
382391
expectedCache.set(name, mode, expected);
383392
// Resolution in cache should be same as that is in program
@@ -395,7 +404,6 @@ export function verifyResolutionCache(
395404
resolvedFileName: string | undefined,
396405
name: string,
397406
mode: ts.ResolutionMode,
398-
deferWatchingNonRelativeResolution: boolean,
399407
): ExpectedResolution {
400408
const existing = resolutionToRefs.get(resolved);
401409
let expectedResolution: ExpectedResolution;
@@ -416,7 +424,7 @@ export function verifyResolutionCache(
416424
expectedToResolution.set(expectedResolution, resolved);
417425
resolutionToExpected.set(resolved, expectedResolution);
418426
}
419-
expected.watchFailedLookupLocationsOfExternalModuleResolutions(name, expectedResolution, fileName, () => ({ resolvedFileName }), deferWatchingNonRelativeResolution);
427+
expected.watchResolution(expectedResolution, fileName, () => ({ resolvedFileName }));
420428
return expectedResolution;
421429
}
422430

tests/baselines/reference/tscWatch/extends/configDir-template.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ File '/home/src/projects/myproject/root2/other/sometype2/package.json' does not
127127
File '/home/src/projects/myproject/root2/other/sometype2/index.d.ts' exists - use it as a name resolution result.
128128
Resolving real path for '/home/src/projects/myproject/root2/other/sometype2/index.d.ts', result '/home/src/projects/myproject/root2/other/sometype2/index.d.ts'.
129129
======== Module name 'other/sometype2' was successfully resolved to '/home/src/projects/myproject/root2/other/sometype2/index.d.ts'. ========
130-
FileWatcher:: Added:: WatchInfo: /home/src/projects/myproject/root2/other/sometype2/index.d.ts 250 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Source file
131-
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Source file
132130
DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/myproject/other 1 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Failed Lookup Locations
133131
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/myproject/other 1 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Failed Lookup Locations
134132
DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/myproject/src 1 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Failed Lookup Locations
@@ -141,6 +139,8 @@ DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/configs 1 {"excludeFile
141139
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/configs 1 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Failed Lookup Locations
142140
DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/myproject/root2 1 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Failed Lookup Locations
143141
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/myproject/root2 1 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Failed Lookup Locations
142+
FileWatcher:: Added:: WatchInfo: /home/src/projects/myproject/root2/other/sometype2/index.d.ts 250 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Source file
143+
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 {"excludeFiles":["/home/src/projects/myproject/main.ts"]} Source file
144144
../../../../a/lib/lib.d.ts
145145
Default library for target 'es5'
146146
types/sometype.ts

0 commit comments

Comments
 (0)