From cc9419d1cababe1bbf366f982517c6290e7aeff8 Mon Sep 17 00:00:00 2001 From: Keen Yee Liau Date: Fri, 5 Jan 2018 12:33:26 -0800 Subject: [PATCH] fix(language-service): Clear caches when program changes (#21337) This commit fixes a bug whereby the caches are not cleared when the program changes. This subsequently produces the incorrect error of 'Component ... is not included in a module ...'. PR Close #19405 PR Close #21337 --- packages/language-service/src/typescript_host.ts | 14 +++++++++----- .../language-service/test/diagnostics_spec.ts | 2 +- .../test/typescript_host_spec.ts | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/language-service/src/typescript_host.ts b/packages/language-service/src/typescript_host.ts index 79b06efa31..8a076f6f69 100644 --- a/packages/language-service/src/typescript_host.ts +++ b/packages/language-service/src/typescript_host.ts @@ -140,7 +140,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost { } getAnalyzedModules(): NgAnalyzedModules { - this.validate(); + this.updateAnalyzedModules(); return this.ensureAnalyzedModules(); } @@ -240,7 +240,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost { private validate() { const program = this.program; - if (this._staticSymbolResolver && this.lastProgram != program) { + if (this.lastProgram !== program) { // Invalidate file that have changed in the static symbol resolver const invalidateFile = (fileName: string) => this._staticSymbolResolver.invalidateFile(fileName); @@ -253,14 +253,18 @@ export class TypeScriptServiceHost implements LanguageServiceHost { const lastVersion = this.fileVersions.get(fileName); if (version != lastVersion) { this.fileVersions.set(fileName, version); - invalidateFile(fileName); + if (this._staticSymbolResolver) { + invalidateFile(fileName); + } } } // Remove file versions that are no longer in the file and invalidate them. const missing = Array.from(this.fileVersions.keys()).filter(f => !seen.has(f)); missing.forEach(f => this.fileVersions.delete(f)); - missing.forEach(invalidateFile); + if (this._staticSymbolResolver) { + missing.forEach(invalidateFile); + } this.lastProgram = program; } @@ -634,4 +638,4 @@ function convertChain(chain: FormattedMessageChain): DiagnosticMessageChain { function errorToDiagnosticWithChain(error: FormattedError, span: Span): DeclarationError { return {message: error.chain ? convertChain(error.chain) : error.message, span}; -} \ No newline at end of file +} diff --git a/packages/language-service/test/diagnostics_spec.ts b/packages/language-service/test/diagnostics_spec.ts index 07a77c2872..00c1dd1fa0 100644 --- a/packages/language-service/test/diagnostics_spec.ts +++ b/packages/language-service/test/diagnostics_spec.ts @@ -248,7 +248,7 @@ describe('diagnostics', () => { template: \`
- Loading comps... + Loading comps... \` }) export class MyComponent {} diff --git a/packages/language-service/test/typescript_host_spec.ts b/packages/language-service/test/typescript_host_spec.ts index 5bea1caf50..8f492234ee 100644 --- a/packages/language-service/test/typescript_host_spec.ts +++ b/packages/language-service/test/typescript_host_spec.ts @@ -46,4 +46,20 @@ describe('completions', () => { ngHost = new TypeScriptServiceHost(host, service); expect(() => ngHost.getAnalyzedModules()).not.toThrow(); }); + + it('should clear the caches if program changes', () => { + // First create a TypescriptHost with empty script names + host = new MockTypescriptHost([], toh); + service = ts.createLanguageService(host); + ngHost = new TypeScriptServiceHost(host, service); + expect(ngHost.getAnalyzedModules().ngModules).toEqual([]); + // Now add a script, this would change the program + const fileName = '/app/main.ts'; + const content = (host as MockTypescriptHost).getFileContent(fileName) !; + (host as MockTypescriptHost).addScript(fileName, content); + // If the caches are not cleared, we would get back an empty array. + // But if the caches are cleared then the analyzed modules will be non-empty. + expect(ngHost.getAnalyzedModules().ngModules.length).not.toEqual(0); + }); + });