In project, instead of iterating over program files to determine if file needs to be detached, do it through existing mechanism of releasing oldSourceFile (#59181)

This commit is contained in:
Sheetal Nandi
2024-07-08 13:37:44 -07:00
committed by GitHub
parent eb23677656
commit 247a98335d
8 changed files with 47 additions and 45 deletions
+2 -2
View File
@@ -1860,13 +1860,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
// old file wasn't redirect but new file is
(oldSourceFile.resolvedPath === oldSourceFile.path && newFile.resolvedPath !== oldSourceFile.path)
) {
host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path));
host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path), newFile);
}
}
if (!host.getParsedCommandLine) {
oldProgram.forEachResolvedProjectReference(resolvedProjectReference => {
if (!getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) {
host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false);
host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false, /*newSourceFileByResolvedPath*/ undefined);
}
});
}
+12 -18
View File
@@ -141,7 +141,7 @@ export interface ResolutionCache {
invalidateResolutionsOfFailedLookupLocations(): boolean;
invalidateResolutionOfFile(filePath: Path): void;
removeResolutionsOfFile(filePath: Path, syncDirWatcherRemove?: boolean): void;
removeResolutionsOfFile(filePath: Path): void;
removeResolutionsFromProjectReferenceRedirects(filePath: Path): void;
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<Path, readonly string[]>): void;
createHasInvalidatedResolutions(
@@ -1273,7 +1273,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
else if (packageDirWatcher.isSymlink !== isSymlink) {
// Handle the change
packageDirWatcher.dirPathToWatcher.forEach(watcher => {
removeDirectoryWatcher(packageDirWatcher!.isSymlink ? packageDirPath : dirPath, /*syncDirWatcherRemove*/ false);
removeDirectoryWatcher(packageDirWatcher!.isSymlink ? packageDirPath : dirPath);
watcher.watcher = createDirPathToWatcher();
});
packageDirWatcher.isSymlink = isSymlink;
@@ -1329,7 +1329,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
return dirWatcher;
}
function stopWatchFailedLookupLocation(failedLookupLocation: string, removeAtRoot: boolean, syncDirWatcherRemove: boolean | undefined) {
function stopWatchFailedLookupLocation(failedLookupLocation: string, removeAtRoot: boolean) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const toWatch = getDirectoryToWatchFailedLookupLocation(
failedLookupLocation,
@@ -1350,7 +1350,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
const forDirPath = packageDirWatcher.dirPathToWatcher.get(dirPath)!;
forDirPath.refCount--;
if (forDirPath.refCount === 0) {
removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath, syncDirWatcherRemove);
removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath);
packageDirWatcher.dirPathToWatcher.delete(dirPath);
if (packageDirWatcher.isSymlink) {
const refCount = dirPathToSymlinkPackageRefCount.get(dirPath)! - 1;
@@ -1361,11 +1361,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
dirPathToSymlinkPackageRefCount.set(dirPath, refCount);
}
}
if (syncDirWatcherRemove) closePackageDirWatcher(packageDirWatcher, packageDirPath);
}
}
else {
removeDirectoryWatcher(dirPath, syncDirWatcherRemove);
removeDirectoryWatcher(dirPath);
}
}
return removeAtRoot;
@@ -1375,7 +1374,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
resolution: T,
filePath: Path,
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
syncDirWatcherRemove?: boolean,
) {
Debug.checkDefined(resolution.files).delete(filePath);
if (resolution.files!.size) return;
@@ -1392,11 +1390,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
let removeAtRoot = false;
if (failedLookupLocations) {
for (const failedLookupLocation of failedLookupLocations) {
removeAtRoot = stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot, syncDirWatcherRemove);
removeAtRoot = stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot);
}
}
if (alternateResult) removeAtRoot = stopWatchFailedLookupLocation(alternateResult, removeAtRoot, syncDirWatcherRemove);
if (removeAtRoot) removeDirectoryWatcher(rootPath, syncDirWatcherRemove);
if (alternateResult) removeAtRoot = stopWatchFailedLookupLocation(alternateResult, removeAtRoot);
if (removeAtRoot) removeDirectoryWatcher(rootPath);
}
else if (affectingLocations?.length) {
resolutionsWithOnlyAffectingLocations.delete(resolution);
@@ -1406,16 +1404,14 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
for (const affectingLocation of affectingLocations) {
const watcher = fileWatchesOfAffectingLocations.get(affectingLocation)!;
watcher.resolutions--;
if (syncDirWatcherRemove) closeFileWatcherOfAffectingLocation(watcher, affectingLocation);
}
}
}
function removeDirectoryWatcher(dirPath: Path, syncDirWatcherRemove: boolean | undefined) {
function removeDirectoryWatcher(dirPath: Path) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath)!;
// Do not close the watcher yet since it might be needed by other failed lookup locations.
dirWatcher.refCount--;
if (syncDirWatcherRemove) closeDirectoryWatchesOfFailedLookup(dirWatcher, dirPath);
}
function createDirectoryWatcher(directory: string, dirPath: Path, nonRecursive: boolean | undefined) {
@@ -1434,7 +1430,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
cache: Map<string, ModeAwareCache<T>>,
filePath: Path,
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
syncDirWatcherRemove: boolean | undefined,
) {
// Deleted file, stop watching failed lookups for all the resolutions in the file
const resolutions = cache.get(filePath);
@@ -1444,7 +1439,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
resolution,
filePath,
getResolutionWithResolvedFileName,
syncDirWatcherRemove,
)
);
cache.delete(filePath);
@@ -1465,9 +1459,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
resolvedProjectReference.commandLine.fileNames.forEach(f => removeResolutionsOfFile(resolutionHost.toPath(f)));
}
function removeResolutionsOfFile(filePath: Path, syncDirWatcherRemove?: boolean) {
removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModuleFromResolution, syncDirWatcherRemove);
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirectiveFromResolution, syncDirWatcherRemove);
function removeResolutionsOfFile(filePath: Path) {
removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModuleFromResolution);
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirectiveFromResolution);
}
function invalidateResolutions(resolutions: Set<ResolutionWithFailedLookupLocations> | Map<string, ResolutionWithFailedLookupLocations> | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) {
+1 -1
View File
@@ -7963,7 +7963,7 @@ export interface CompilerHost extends ModuleResolutionHost {
*/
hasInvalidatedLibResolutions?(libFileName: string): boolean;
getEnvironmentVariable?(name: string): string | undefined;
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void;
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined): void;
/** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void;
/** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */
hasInvalidatedResolutions?(filePath: Path): boolean;
+20 -18
View File
@@ -1393,6 +1393,24 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
this.hasAddedOrRemovedSymlinks = true;
}
/** @internal */
onReleaseOldSourceFile(
oldSourceFile: SourceFile,
_oldOptions: CompilerOptions,
hasSourceFileByPath: boolean,
newSourceFileByResolvedPath: SourceFile | undefined,
) {
if (
!newSourceFileByResolvedPath ||
(oldSourceFile.resolvedPath === oldSourceFile.path && newSourceFileByResolvedPath.resolvedPath !== oldSourceFile.path)
) {
// new program does not contain this file - detach it from the project
// - remove resolutions only if the new program doesnt contain source file by the path
// (not resolvedPath since path is used for resolution)
this.detachScriptInfoFromProject(oldSourceFile.fileName, hasSourceFileByPath);
}
}
/** @internal */
updateFromProjectInProgress = false;
@@ -1639,22 +1657,6 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
let hasNewProgram = false;
if (this.program && (!oldProgram || (this.program !== oldProgram && this.program.structureIsReused !== StructureIsReused.Completely))) {
hasNewProgram = true;
if (oldProgram) {
for (const f of oldProgram.getSourceFiles()) {
const newFile = this.program.getSourceFileByPath(f.resolvedPath);
if (!newFile || (f.resolvedPath === f.path && newFile.resolvedPath !== f.path)) {
// new program does not contain this file - detach it from the project
// - remove resolutions only if the new program doesnt contain source file by the path (not resolvedPath since path is used for resolution)
this.detachScriptInfoFromProject(f.fileName, !!this.program.getSourceFileByPath(f.path), /*syncDirWatcherRemove*/ true);
}
}
oldProgram.forEachResolvedProjectReference(resolvedProjectReference => {
if (!this.program!.getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) {
this.detachScriptInfoFromProject(resolvedProjectReference.sourceFile.fileName, /*noRemoveResolution*/ undefined, /*syncDirWatcherRemove*/ true);
}
});
}
// Update roots
this.rootFilesMap.forEach((value, path) => {
@@ -1791,12 +1793,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
this.projectService.sendPerformanceEvent(kind, durationMs);
}
private detachScriptInfoFromProject(uncheckedFileName: string, noRemoveResolution?: boolean, syncDirWatcherRemove?: boolean) {
private detachScriptInfoFromProject(uncheckedFileName: string, noRemoveResolution?: boolean) {
const scriptInfoToDetach = this.projectService.getScriptInfo(uncheckedFileName);
if (scriptInfoToDetach) {
scriptInfoToDetach.detachFromProject(this);
if (!noRemoveResolution) {
this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path, syncDirWatcherRemove);
this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path);
}
}
}
+7 -2
View File
@@ -1866,17 +1866,22 @@ export function createLanguageService(
host.onReleaseParsedCommandLine?.(configFileName, oldResolvedRef, oldOptions);
}
else if (oldResolvedRef) {
onReleaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions);
releaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions);
}
}
// Release any files we have acquired in the old program but are
// not part of the new program.
function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) {
function releaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) {
const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions);
documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey, oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat);
}
function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined) {
releaseOldSourceFile(oldSourceFile, oldOptions);
host.onReleaseOldSourceFile?.(oldSourceFile, oldOptions, hasSourceFileByPath, newSourceFileByResolvedPath);
}
function getOrCreateSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersionOrOptions, onError, shouldCreateNewSourceFile);
}
+1
View File
@@ -430,6 +430,7 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR
/** @internal */ sendPerformanceEvent?(kind: PerformanceEvent["kind"], durationMs: number): void;
getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
/** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void;
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined): void;
/** @internal */ getIncompleteCompletionsCache?(): IncompleteCompletionsCache;
/** @internal */ runWithTemporaryFileUpdate?(rootFile: string, updatedText: string, cb: (updatedProgram: Program, originalProgram: Program | undefined, updatedPastedText: SourceFile) => void): void;
jsDocParsingMode?: JSDocParsingMode | undefined;
@@ -879,13 +879,13 @@ Info seq [hh:mm:ss:mss] ======== Module name 'package-aX' was not resolved. ===
Info seq [hh:mm:ss:mss] Reusing resolution of module '@typescript/lib-es2021' from '/home/src/projects/project/packages/package-b/__lib_node_modules_lookup_lib.es2021.d.ts__.ts' of old program, it was not resolved.
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/packages/package-b/package-aX 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/packages/package-b/package-aX 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-b/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-b/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/node_modules/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/node_modules/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a/package.json 2000 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /home/src/projects/project/packages/package-b/tsconfig.json projectStateVersion: 2 projectProgramVersion: 1 structureChanged: true structureIsReused:: SafeModules Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/home/src/projects/project/packages/package-b/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (2)
@@ -696,13 +696,13 @@ Info seq [hh:mm:ss:mss] ======== Module name 'package-aX' was not resolved. ===
Info seq [hh:mm:ss:mss] Reusing resolution of module '@typescript/lib-es2021' from '/home/src/projects/project/packages/package-b/__lib_node_modules_lookup_lib.es2021.d.ts__.ts' of old program, it was not resolved.
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/packages/package-b/package-aX 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/packages/package-b/package-aX 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-b/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-b/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/node_modules/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/node_modules/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a/package.json 2000 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Close:: WatchInfo: /home/src/projects/project/packages/package-a 1 undefined Project: /home/src/projects/project/packages/package-b/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /home/src/projects/project/packages/package-b/tsconfig.json projectStateVersion: 2 projectProgramVersion: 1 structureChanged: true structureIsReused:: SafeModules Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/home/src/projects/project/packages/package-b/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (2)