Skip to content

Commit ba00137

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 f9fbc58 commit ba00137

File tree

153 files changed

+2094
-2093
lines changed

Some content is hidden

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

153 files changed

+2094
-2093
lines changed

src/compiler/resolutionCache.ts

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

117-
watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
118-
name: string,
117+
watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
119118
resolution: T,
120119
filePath: Path,
121120
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
122-
deferWatchingNonRelativeResolution: boolean,
123121
): void;
124122

125123
resolveModuleNameLiterals(
@@ -180,10 +178,13 @@ export interface ResolutionCache extends Required<CompilerHostSupportingResoluti
180178
export interface ResolutionWithFailedLookupLocations {
181179
failedLookupLocations?: string[];
182180
affectingLocations?: string[];
181+
alternateResult?: string;
183182
isInvalidated?: boolean;
184183
// Files that have this resolution using
185184
files?: Set<Path>;
186-
alternateResult?: string;
185+
watchedFailed?: number;
186+
watchedAffected?: number;
187+
setAtRoot?: boolean;
187188
globalCacheResolution?: boolean;
188189
}
189190

@@ -602,7 +603,6 @@ export function createResolutionCache(
602603
rootDirForResolution: string,
603604
): ResolutionCache {
604605
let filesWithInvalidatedResolutions: Set<Path> | undefined;
605-
const nonRelativeExternalModuleResolutions = new Set<ResolutionWithFailedLookupLocations>();
606606

607607
const resolutionsWithFailedLookups = new Set<ResolutionWithFailedLookupLocations>();
608608
const resolutionsWithOnlyAffectingLocations = new Set<ResolutionWithFailedLookupLocations>();
@@ -680,7 +680,7 @@ export function createResolutionCache(
680680
dirPathToSymlinkPackageRefCount,
681681
countResolutionsResolvedWithGlobalCache: () => resolutionsResolvedWithGlobalCache,
682682
countResolutionsResolvedWithoutGlobalCache: () => resolutionsResolvedWithoutGlobalCache,
683-
watchFailedLookupLocationsOfExternalModuleResolutions,
683+
watchResolution,
684684
getModuleResolutionCache: () => moduleResolutionCache,
685685
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
686686
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
@@ -713,7 +713,6 @@ export function createResolutionCache(
713713
isSymlinkCache.clear();
714714
packageDirWatchers.clear();
715715
dirPathToSymlinkPackageRefCount.clear();
716-
nonRelativeExternalModuleResolutions.clear();
717716
closeTypeRootsWatch();
718717
resolvedModuleNames.clear();
719718
resolvedTypeReferenceDirectives.clear();
@@ -779,9 +778,6 @@ export function createResolutionCache(
779778
moduleResolutionCache.clearAllExceptPackageJsonInfoCache();
780779
typeReferenceDirectiveResolutionCache.clearAllExceptPackageJsonInfoCache();
781780
libraryResolutionCache.clearAllExceptPackageJsonInfoCache();
782-
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
783-
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
784-
watchFailedLookupLocationOfNonRelativeModuleResolutions();
785781
isSymlinkCache.clear();
786782
}
787783

@@ -803,7 +799,6 @@ export function createResolutionCache(
803799
resolutionsWithGlobalCachePassAreInvalidated = false;
804800
resolutionsWithoutGlobalCachePassAreInvalidated = false;
805801
unresolvedResolutionsWithGlobalCachePassAreInvalidated = false;
806-
watchFailedLookupLocationOfNonRelativeModuleResolutions();
807802
// Update file watches
808803
if (newProgram !== oldProgram) {
809804
cleanupLibResolutionWatching(newProgram);
@@ -878,7 +873,6 @@ export function createResolutionCache(
878873
perFileCache: Map<Path, ModeAwareCache<T>>;
879874
loader: ResolutionLoader<Entry, T, SourceFile>;
880875
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>;
881-
deferWatchingNonRelativeResolution: boolean;
882876
onNewResolution?: CallbackOnNewResolution<T>;
883877
}
884878
function resolveNamesWithLocalCache<Entry, SourceFile, T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>({
@@ -892,7 +886,6 @@ export function createResolutionCache(
892886
ambientEntries,
893887
loader,
894888
getResolutionWithResolvedFileName,
895-
deferWatchingNonRelativeResolution,
896889
onNewResolution,
897890
}: ResolveNamesWithLocalCacheInput<Entry, SourceFile, T, R>): readonly T[] {
898891
const path = resolutionHost.toPath(containingFile);
@@ -929,7 +922,7 @@ export function createResolutionCache(
929922
}
930923
resolutionsInFile.set(name, mode, resolution);
931924
if (resolution !== existingResolution) {
932-
watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution);
925+
watchResolution(resolution, path, getResolutionWithResolvedFileName);
933926
if (existingResolution) {
934927
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName);
935928
}
@@ -1100,7 +1093,6 @@ export function createResolutionCache(
11001093
typeReferenceDirectiveResolutionCache,
11011094
),
11021095
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirectiveFromResolution,
1103-
deferWatchingNonRelativeResolution: false,
11041096
});
11051097
}
11061098

@@ -1131,7 +1123,6 @@ export function createResolutionCache(
11311123
moduleResolutionCache,
11321124
),
11331125
getResolutionWithResolvedFileName: getResolvedModuleFromResolution,
1134-
deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules
11351126
onNewResolution,
11361127
});
11371128
}
@@ -1148,7 +1139,7 @@ export function createResolutionCache(
11481139
const existingResolution = resolution;
11491140
resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
11501141
const path = resolutionHost.toPath(resolveFrom);
1151-
watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModuleFromResolution, /*deferWatchingNonRelativeResolution*/ false);
1142+
watchResolution(resolution, path, getResolvedModuleFromResolution);
11521143
resolvedLibraries.set(libFileName, resolution);
11531144
if (existingResolution) {
11541145
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModuleFromResolution);
@@ -1197,23 +1188,17 @@ export function createResolutionCache(
11971188
return endsWith(dirPath, "/node_modules/@types");
11981189
}
11991190

1200-
function watchFailedLookupLocationsOfExternalModuleResolutions<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
1201-
name: string,
1191+
function watchResolution<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
12021192
resolution: T,
12031193
filePath: Path,
12041194
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
1205-
deferWatchingNonRelativeResolution: boolean,
12061195
) {
12071196
(resolution.files ??= new Set()).add(filePath);
1197+
watchFailedLookupLocationOfResolution(resolution);
1198+
watchAffectingLocationsOfResolution(resolution);
12081199
if (resolution.files.size !== 1) return;
12091200
if (resolution.globalCacheResolution) resolutionsResolvedWithGlobalCache++;
12101201
else if (resolution.globalCacheResolution === false) resolutionsResolvedWithoutGlobalCache++;
1211-
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
1212-
watchFailedLookupLocationOfResolution(resolution);
1213-
}
1214-
else {
1215-
nonRelativeExternalModuleResolutions.add(resolution);
1216-
}
12171202
const resolved = getResolutionWithResolvedFileName(resolution);
12181203
if (resolved && resolved.resolvedFileName) {
12191204
const key = resolutionHost.toPath(resolved.resolvedFileName);
@@ -1251,33 +1236,38 @@ export function createResolutionCache(
12511236
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
12521237
Debug.assert(!!resolution.files?.size);
12531238

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

1258-
let setAtRoot = false;
1259-
if (failedLookupLocations) {
1260-
for (const failedLookupLocation of failedLookupLocations) {
1261-
setAtRoot = watchFailedLookupLocation(failedLookupLocation, setAtRoot);
1262-
}
1248+
let setAtRoot = !!resolution.setAtRoot;
1249+
for (let i = watchedFailed || 0; i < failedLookupLocations!.length; i++) {
1250+
setAtRoot = watchFailedLookupLocation(failedLookupLocations![i], setAtRoot);
12631251
}
1264-
if (alternateResult) setAtRoot = watchFailedLookupLocation(alternateResult, setAtRoot);
1265-
if (setAtRoot) {
1252+
if (!watchedFailed && alternateResult) setAtRoot = watchFailedLookupLocation(alternateResult, setAtRoot);
1253+
if (!resolution.setAtRoot && setAtRoot) {
12661254
// This is always non recursive
12671255
setDirectoryWatcher(rootDir, rootPath, /*packageDir*/ undefined, /*packageDirPath*/ undefined, /*nonRecursive*/ true);
12681256
}
1269-
watchAffectingLocationsOfResolution(resolution, !failedLookupLocations?.length && !alternateResult);
1257+
resolution.watchedFailed = failedLookupLocations?.length;
1258+
resolution.setAtRoot = setAtRoot;
12701259
}
12711260

1272-
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) {
1261+
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations) {
12731262
Debug.assert(!!resolution.files?.size);
1274-
const { affectingLocations } = resolution;
1275-
if (!affectingLocations?.length) return;
1276-
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution);
1263+
const { affectingLocations, watchedAffected } = resolution;
1264+
if (affectingLocations?.length === watchedAffected) return;
1265+
if (!watchedAffected && !resolution.watchedFailed) resolutionsWithOnlyAffectingLocations.add(resolution);
12771266
// Watch package json
1278-
for (const affectingLocation of affectingLocations) {
1279-
createFileWatcherOfAffectingLocation(affectingLocation, /*forResolution*/ true);
1267+
for (let i = watchedAffected || 0; i < affectingLocations!.length; i++) {
1268+
createFileWatcherOfAffectingLocation(affectingLocations![i], /*forResolution*/ true);
12801269
}
1270+
resolution.watchedAffected = affectingLocations?.length;
12811271
}
12821272

12831273
function createFileWatcherOfAffectingLocation(affectingLocation: string, forResolution: boolean) {
@@ -1345,11 +1335,6 @@ export function createResolutionCache(
13451335
packageJsonMap?.delete(resolutionHost.toPath(path));
13461336
}
13471337

1348-
function watchFailedLookupLocationOfNonRelativeModuleResolutions() {
1349-
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfResolution);
1350-
nonRelativeExternalModuleResolutions.clear();
1351-
}
1352-
13531338
function createDirectoryWatcherForPackageDir(
13541339
dir: string,
13551340
dirPath: Path,

src/harness/incrementalUtils.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ export function verifyResolutionCache(
227227
path,
228228
resolutions,
229229
getResolvedModuleFileName,
230-
/*deferWatchingNonRelativeResolution*/ true,
231230
expected.resolvedModuleNames,
232231
(name, mode) => actualProgram.getResolvedModule(actualProgram.getSourceFileByPath(path)!, name, mode),
233232
)
@@ -238,7 +237,6 @@ export function verifyResolutionCache(
238237
path,
239238
resolutions,
240239
getResolvedTypeRefFileName,
241-
/*deferWatchingNonRelativeResolution*/ false,
242240
expected.resolvedTypeReferenceDirectives,
243241
(name, mode) =>
244242
path !== inferredTypesPath ?
@@ -256,7 +254,6 @@ export function verifyResolutionCache(
256254
getResolvedModuleFileName(resolved),
257255
ts.getLibraryNameFromLibFileName(libFileName),
258256
/*mode*/ undefined,
259-
/*deferWatchingNonRelativeResolution*/ false,
260257
);
261258
expected.resolvedLibraries.set(libFileName, expectedResolution);
262259
});
@@ -309,7 +306,20 @@ export function verifyResolutionCache(
309306
!resolution.isInvalidated,
310307
`${projectName}:: Resolution should not be invalidated`,
311308
);
312-
verifySet(resolutionToExpected.get(resolution)!.files, resolution.files, `${projectName}:: Resolution files`);
309+
const expected = resolutionToExpected.get(resolution)!;
310+
verifySet(expected.files, resolution.files, `${projectName}:: Resolution files`);
311+
ts.Debug.assert(
312+
expected.watchedFailed === resolution.watchedFailed,
313+
`${projectName}:: Expected watchedFailed of Resolution ${expected.watchedFailed} but got ${resolution.watchedFailed}`,
314+
);
315+
ts.Debug.assert(
316+
expected.watchedAffected === resolution.watchedAffected,
317+
`${projectName}:: Expected watchedAffected of Resolution ${expected.watchedAffected} but got ${resolution.watchedAffected}`,
318+
);
319+
ts.Debug.assert(
320+
expected.setAtRoot === resolution.setAtRoot,
321+
`${projectName}:: Expected setAtRoot of Resolution ${expected.setAtRoot} but got ${resolution.setAtRoot}`,
322+
);
313323
});
314324
verifyMapOfResolutionSet(expected.resolvedFileToResolution, actual.resolvedFileToResolution, `resolvedFileToResolution`);
315325
verifyResolutionSet(expected.resolutionsWithFailedLookups, actual.resolutionsWithFailedLookups, `resolutionsWithFailedLookups`);
@@ -373,7 +383,6 @@ export function verifyResolutionCache(
373383
fileName: ts.Path,
374384
cache: ts.ModeAwareCache<T> | undefined,
375385
getResolvedFileName: (resolution: T) => string | undefined,
376-
deferWatchingNonRelativeResolution: boolean,
377386
storeExpected: Map<ts.Path, ts.ModeAwareCache<ts.ResolutionWithFailedLookupLocations>>,
378387
getProgramResolutions: (name: string, mode: ts.ResolutionMode) => T | undefined,
379388
) {
@@ -384,7 +393,7 @@ export function verifyResolutionCache(
384393
let expectedCache: ts.ModeAwareCache<ts.ResolutionWithFailedLookupLocations> | undefined;
385394
cache?.forEach((resolved, name, mode) => {
386395
const resolvedFileName = getResolvedFileName(resolved);
387-
const expected = collectResolution(cacheType, fileName, resolved, resolvedFileName, name, mode, deferWatchingNonRelativeResolution);
396+
const expected = collectResolution(cacheType, fileName, resolved, resolvedFileName, name, mode);
388397
if (!expectedCache) storeExpected.set(fileName, expectedCache = ts.createModeAwareCache());
389398
expectedCache.set(name, mode, expected);
390399
// Resolution in cache should be same as that is in program
@@ -402,7 +411,6 @@ export function verifyResolutionCache(
402411
resolvedFileName: string | undefined,
403412
name: string,
404413
mode: ts.ResolutionMode,
405-
deferWatchingNonRelativeResolution: boolean,
406414
): ExpectedResolution {
407415
const existing = resolutionToRefs.get(resolved);
408416
let expectedResolution: ExpectedResolution;
@@ -423,7 +431,7 @@ export function verifyResolutionCache(
423431
expectedToResolution.set(expectedResolution, resolved);
424432
resolutionToExpected.set(resolved, expectedResolution);
425433
}
426-
expected.watchFailedLookupLocationsOfExternalModuleResolutions(name, expectedResolution, fileName, () => ({ resolvedFileName }), deferWatchingNonRelativeResolution);
434+
expected.watchResolution(expectedResolution, fileName, () => ({ resolvedFileName }));
427435
return expectedResolution;
428436
}
429437

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)