Skip to content

Commit 2f726c1

Browse files
committed
Persist resolutions, persists resolutions in program and not watches them
1 parent 46afbaa commit 2f726c1

8 files changed

+193
-228
lines changed

src/compiler/program.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,8 +1191,30 @@ namespace ts {
11911191

11921192
for (let i = 0; i < moduleNames.length; i++) {
11931193
const moduleName = moduleNames[i];
1194+
if (options.persistResolutions) {
1195+
const oldResolvedModule = oldProgram?.getPerFileModuleResolutions().get(file.path)?.get(moduleName);
1196+
if (oldResolvedModule) {
1197+
if (isTraceEnabled(options, host)) {
1198+
trace(
1199+
host,
1200+
oldResolvedModule.resolvedModule?.resolvedFileName ?
1201+
oldResolvedModule.resolvedModule.packageId ?
1202+
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
1203+
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 :
1204+
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved,
1205+
moduleName,
1206+
getNormalizedAbsolutePath(file.originalFileName, currentDirectory),
1207+
oldResolvedModule?.resolvedModule?.resolvedFileName,
1208+
oldResolvedModule?.resolvedModule?.packageId && packageIdToString(oldResolvedModule.resolvedModule.packageId)
1209+
);
1210+
}
1211+
(result || (result = new Array(moduleNames.length)))[i] = oldResolvedModule;
1212+
(reusedNames || (reusedNames = [])).push(moduleName);
1213+
continue;
1214+
}
1215+
}
11941216
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
1195-
if (oldSourceFile && file.version === oldSourceFile.version && !hasInvalidatedResolution(oldSourceFile.path)) {
1217+
else if (oldSourceFile && file.version === oldSourceFile.version && !hasInvalidatedResolution(oldSourceFile.path)) {
11961218
const oldResolvedModule = oldProgram!.getPerFileModuleResolutions().get(file.path)?.get(moduleName);
11971219
if (oldResolvedModule?.resolvedModule) {
11981220
if (isTraceEnabled(options, host)) {
@@ -1345,17 +1367,26 @@ namespace ts {
13451367

13461368
// check properties that can affect structure of the program or module resolution strategy
13471369
// if any of these properties has changed - structure cannot be reused
1348-
const oldOptions = oldProgram.getCompilerOptions();
1349-
if (changesAffectModuleResolution(oldOptions, options)) {
1370+
if (changesAffectModuleResolution(oldProgram.getCompilerOptions(), options)) {
13501371
return StructureIsReused.Not;
13511372
}
13521373

1374+
// With persistResolutions its always to reuse strcture for safe module resolutions
1375+
const result = tryReuseStructureFromOldProgramWithOptionsReusingModuleResolution(oldProgram);
1376+
return options.persistResolutions && result === StructureIsReused.Not ?
1377+
StructureIsReused.SafeModules :
1378+
result;
1379+
1380+
}
1381+
1382+
function tryReuseStructureFromOldProgramWithOptionsReusingModuleResolution(oldProgram: Program | ProgramFromBuildInfo): StructureIsReused {
13531383
// there is an old program, check if we can reuse its structure
13541384
const oldRootNames = oldProgram.getRootFileNames();
13551385
if (!arrayIsEqualTo(oldRootNames, rootNames)) {
13561386
return StructureIsReused.Not;
13571387
}
13581388

1389+
const oldOptions = oldProgram.getCompilerOptions();
13591390
if (!arrayIsEqualTo(options.types, oldOptions.types)) {
13601391
return StructureIsReused.Not;
13611392
}

src/compiler/resolutionCache.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,12 @@ namespace ts {
347347
loader, getResolutionWithResolvedFileName,
348348
shouldRetryResolution, reusedNames, logChanges
349349
}: ResolveNamesWithLocalCacheInput<T, R>): T[] {
350+
const compilerOptions = resolutionHost.getCompilationSettings();
351+
// If resolutions are persisted, we just need to direct to loader and program will do job of storing resolutions,
352+
// We also shouldnt be watching locations since those resolutions are always persisted till user opts not to
353+
if (compilerOptions.persistResolutions) {
354+
return names.map(name => loader(name, containingFile, compilerOptions, resolutionHost.getCompilerHost?.() || resolutionHost, redirectedReference));
355+
}
350356
const path = resolutionHost.toPath(containingFile);
351357
const resolutionsInFile = cache.get(path) || cache.set(path, new Map()).get(path)!;
352358
const dirPath = getDirectoryPath(path);
@@ -357,7 +363,6 @@ namespace ts {
357363
perDirectoryCache.set(dirPath, perDirectoryResolution);
358364
}
359365
const resolvedModules: T[] = [];
360-
const compilerOptions = resolutionHost.getCompilationSettings();
361366
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path);
362367

363368
// All the resolutions in this file are invalidated if this file wasnt resolved using same redirect

tests/baselines/reference/tscWatch/persistResolutions/can-build-after-resolutions-are-cleaned-with-outFile.js

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@ File '/user/username/projects/myproject/src/fileNotFound.d.ts' does not exist.
129129
File '/user/username/projects/myproject/src/fileNotFound.js' does not exist.
130130
File '/user/username/projects/myproject/src/fileNotFound.jsx' does not exist.
131131
======== Module name './fileNotFound' was not resolved. ========
132-
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
133-
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
134132
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file
135133
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots
136134
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots
@@ -168,11 +166,10 @@ WatchedFiles::
168166
FsWatches::
169167

170168
FsWatchesRecursive::
171-
/user/username/projects/myproject/src:
172-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
173-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
174169
/user/username/projects/myproject/node_modules/@types:
175170
{"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
171+
/user/username/projects/myproject/src:
172+
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
176173

177174
exitCode:: ExitStatus.undefined
178175

@@ -294,11 +291,10 @@ WatchedFiles::
294291
FsWatches::
295292

296293
FsWatchesRecursive::
297-
/user/username/projects/myproject/src:
298-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
299-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
300294
/user/username/projects/myproject/node_modules/@types:
301295
{"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
296+
/user/username/projects/myproject/src:
297+
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
302298

303299
exitCode:: ExitStatus.undefined
304300

@@ -394,9 +390,6 @@ export function foo() { return 20; }
394390

395391

396392
Output::
397-
DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/newFile.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
398-
Scheduling invalidateFailedLookup
399-
Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/newFile.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
400393
DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/newFile.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Wild card directory
401394
Scheduling update
402395
Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/newFile.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Wild card directory
@@ -410,12 +403,12 @@ Synchronizing program
410403
CreatingProgramWith::
411404
roots: ["/user/username/projects/myproject/src/filePresent.ts","/user/username/projects/myproject/src/main.ts","/user/username/projects/myproject/src/newFile.ts"]
412405
options: {"module":2,"composite":true,"persistResolutions":true,"traceResolution":true,"outFile":"/user/username/projects/myproject/outFile.js","project":"/user/username/projects/myproject","watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
406+
Reusing resolution of module './filePresent' from '/user/username/projects/myproject/src/main.ts' of old program, it was successfully resolved to '/user/username/projects/myproject/src/filePresent.ts'.
407+
Reusing resolution of module './fileNotFound' from '/user/username/projects/myproject/src/main.ts' of old program, it was not resolved.
413408
======== Resolving module './newFile' from '/user/username/projects/myproject/src/main.ts'. ========
414409
Module resolution kind is not specified, using 'Classic'.
415410
File '/user/username/projects/myproject/src/newFile.ts' exist - use it as a name resolution result.
416411
======== Module name './newFile' was successfully resolved to '/user/username/projects/myproject/src/newFile.ts'. ========
417-
Reusing resolution of module './filePresent' from '/user/username/projects/myproject/src/main.ts' of old program, it was successfully resolved to '/user/username/projects/myproject/src/filePresent.ts'.
418-
Reusing resolution of module './fileNotFound' from '/user/username/projects/myproject/src/main.ts' of old program, it was not resolved.
419412
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/newFile.ts 250 undefined Source file
420413
src/main.ts:2:28 - error TS2792: Cannot find module './fileNotFound'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?
421414

@@ -428,7 +421,7 @@ FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/newFile.t
428421

429422
Program root files: ["/user/username/projects/myproject/src/filePresent.ts","/user/username/projects/myproject/src/main.ts","/user/username/projects/myproject/src/newFile.ts"]
430423
Program options: {"module":2,"composite":true,"persistResolutions":true,"traceResolution":true,"outFile":"/user/username/projects/myproject/outFile.js","project":"/user/username/projects/myproject","watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
431-
Program structureReused: Not
424+
Program structureReused: SafeModules
432425
Program files::
433426
/a/lib/lib.d.ts
434427
/user/username/projects/myproject/src/filePresent.ts
@@ -452,11 +445,10 @@ WatchedFiles::
452445
FsWatches::
453446

454447
FsWatchesRecursive::
455-
/user/username/projects/myproject/src:
456-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
457-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
458448
/user/username/projects/myproject/node_modules/@types:
459449
{"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
450+
/user/username/projects/myproject/src:
451+
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
460452

461453
exitCode:: ExitStatus.undefined
462454

@@ -570,13 +562,9 @@ export function something2() { return 20; }
570562

571563

572564
Output::
573-
DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/fileNotFound.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
574-
Scheduling invalidateFailedLookup
575-
Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/fileNotFound.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
576565
DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/fileNotFound.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Wild card directory
577566
Scheduling update
578567
Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/src/fileNotFound.ts :: WatchInfo: /user/username/projects/myproject/src 1 undefined Wild card directory
579-
Scheduling update
580568
[12:01:15 AM] File change detected. Starting incremental compilation...
581569

582570
Reloading new file names and options
@@ -587,19 +575,19 @@ CreatingProgramWith::
587575
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/fileNotFound.ts 250 undefined Source file
588576
Reusing resolution of module './newFile' from '/user/username/projects/myproject/src/main.ts' of old program, it was successfully resolved to '/user/username/projects/myproject/src/newFile.ts'.
589577
Reusing resolution of module './filePresent' from '/user/username/projects/myproject/src/main.ts' of old program, it was successfully resolved to '/user/username/projects/myproject/src/filePresent.ts'.
590-
======== Resolving module './fileNotFound' from '/user/username/projects/myproject/src/main.ts'. ========
591-
Module resolution kind is not specified, using 'Classic'.
592-
File '/user/username/projects/myproject/src/fileNotFound.ts' exist - use it as a name resolution result.
593-
======== Module name './fileNotFound' was successfully resolved to '/user/username/projects/myproject/src/fileNotFound.ts'. ========
594-
DirectoryWatcher:: Close:: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
595-
Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /user/username/projects/myproject/src 1 undefined Failed Lookup Locations
596-
[[90m12:01:25 AM[0m] Found 0 errors. Watching for file changes.
578+
Reusing resolution of module './fileNotFound' from '/user/username/projects/myproject/src/main.ts' of old program, it was not resolved.
579+
[96msrc/main.ts[0m:[93m2[0m:[93m28[0m - [91merror[0m[90m TS2792: [0mCannot find module './fileNotFound'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?
580+
581+
[7m2[0m import { something2 } from "./fileNotFound";something();
582+
[7m [0m [91m ~~~~~~~~~~~~~~~~[0m
583+
584+
[[90m12:01:25 AM[0m] Found 1 error. Watching for file changes.
597585

598586

599587

600588
Program root files: ["/user/username/projects/myproject/src/fileNotFound.ts","/user/username/projects/myproject/src/filePresent.ts","/user/username/projects/myproject/src/main.ts","/user/username/projects/myproject/src/newFile.ts"]
601589
Program options: {"module":2,"composite":true,"persistResolutions":true,"traceResolution":true,"outFile":"/user/username/projects/myproject/outFile.js","project":"/user/username/projects/myproject","watch":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/tsconfig.json"}
602-
Program structureReused: Not
590+
Program structureReused: SafeModules
603591
Program files::
604592
/a/lib/lib.d.ts
605593
/user/username/projects/myproject/src/fileNotFound.ts
@@ -626,10 +614,10 @@ WatchedFiles::
626614
FsWatches::
627615

628616
FsWatchesRecursive::
629-
/user/username/projects/myproject/src:
630-
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
631617
/user/username/projects/myproject/node_modules/@types:
632618
{"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
619+
/user/username/projects/myproject/src:
620+
{"directoryName":"/user/username/projects/myproject/src","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
633621

634622
exitCode:: ExitStatus.undefined
635623

@@ -740,7 +728,6 @@ declare module "src/main" { }
740728
},
741729
"referencedMap": {
742730
"./src/main.ts": [
743-
"./src/filenotfound.ts",
744731
"./src/filepresent.ts",
745732
"./src/newfile.ts"
746733
]

0 commit comments

Comments
 (0)