From 9ff9476b4aed078d44cb5446dd2fd59c1ab1341b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 10 Jul 2017 14:32:36 -0700 Subject: [PATCH] Handle the deleted file in update graph better, so that in next update it is possible to schedule the update graph of project --- src/compiler/types.ts | 4 ++++ src/server/editorServices.ts | 4 ---- src/server/lsHost.ts | 40 +++++++++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 14b80325aa3..b1610c76088 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3975,6 +3975,8 @@ namespace ts { resolvedModule: ResolvedModuleFull | undefined; /* @internal */ failedLookupLocations: string[]; + /*@internal*/ + isInvalidated?: boolean; } export interface ResolvedTypeReferenceDirective { @@ -3987,6 +3989,8 @@ namespace ts { export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; failedLookupLocations: string[]; + /*@internal*/ + isInvalidated?: boolean; } export interface CompilerHost extends ModuleResolutionHost { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e4e62e7dd68..e5fb2006379 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -361,8 +361,6 @@ namespace ts.server { readonly toCanonicalFileName: (f: string) => string; - public lastDeletedFile: ScriptInfo; - public readonly host: ServerHost; public readonly logger: Logger; public readonly cancellationToken: HostCancellationToken; @@ -571,7 +569,6 @@ namespace ts.server { if (!info.isScriptOpen()) { this.filenameToScriptInfo.delete(info.path); - this.lastDeletedFile = info; // capture list of projects since detachAllProjects will wipe out original list const containingProjects = info.containingProjects.slice(); @@ -580,7 +577,6 @@ namespace ts.server { // update projects to make sure that set of referenced files is correct this.updateProjectGraphs(containingProjects); - this.lastDeletedFile = undefined; if (!this.eventHandler) { return; diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index 55513f1a285..c8ab7d3c0f3 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -3,6 +3,7 @@ /// namespace ts.server { + type NameResolutionWithFailedLookupLocations = { failedLookupLocations: string[], isInvalidated?: boolean }; export class LSHost implements ts.LanguageServiceHost, ModuleResolutionHost { private compilationSettings: ts.CompilerOptions; private readonly resolvedModuleNames = createMap>(); @@ -62,7 +63,7 @@ namespace ts.server { return collected; } - private resolveNamesWithLocalCache( + private resolveNamesWithLocalCache( names: string[], containingFile: string, cache: Map>, @@ -77,7 +78,6 @@ namespace ts.server { const newResolutions: Map = createMap(); const resolvedModules: R[] = []; const compilerOptions = this.getCompilationSettings(); - const lastDeletedFileName = this.project.projectService.lastDeletedFile && this.project.projectService.lastDeletedFile.fileName; for (const name of names) { // check if this is a duplicate entry in the list @@ -112,7 +112,7 @@ namespace ts.server { if (oldResolution === newResolution) { return true; } - if (!oldResolution || !newResolution) { + if (!oldResolution || !newResolution || oldResolution.isInvalidated) { return false; } const oldResult = getResult(oldResolution); @@ -127,13 +127,13 @@ namespace ts.server { } function moduleResolutionIsValid(resolution: T): boolean { - if (!resolution) { + if (!resolution || resolution.isInvalidated) { return false; } const result = getResult(resolution); if (result) { - return getResultFileName(result) !== lastDeletedFileName; + return true; } // consider situation if we have no candidate locations as valid resolution. @@ -234,8 +234,34 @@ namespace ts.server { } notifyFileRemoved(info: ScriptInfo) { - this.resolvedModuleNames.delete(info.path); - this.resolvedTypeReferenceDirectives.delete(info.path); + this.invalidateResolutionOfDeletedFile(info, this.resolvedModuleNames, + m => m.resolvedModule, r => r.resolvedFileName); + this.invalidateResolutionOfDeletedFile(info, this.resolvedTypeReferenceDirectives, + m => m.resolvedTypeReferenceDirective, r => r.resolvedFileName); + } + + private invalidateResolutionOfDeletedFile( + deletedInfo: ScriptInfo, + cache: Map>, + getResult: (s: T) => R, + getResultFileName: (result: R) => string | undefined) { + cache.forEach((value, path) => { + if (path === deletedInfo.path) { + cache.delete(path); + } + else if (value) { + value.forEach((resolution) => { + if (resolution && !resolution.isInvalidated) { + const result = getResult(resolution); + if (result) { + if (getResultFileName(result) === deletedInfo.path) { + resolution.isInvalidated = true; + } + } + } + }); + } + }); } setCompilationSettings(opt: ts.CompilerOptions) {