diff --git a/extensions/typescript/src/features/bufferSyncSupport.ts b/extensions/typescript/src/features/bufferSyncSupport.ts index 1e6e9e60c90..89ade4b5e1a 100644 --- a/extensions/typescript/src/features/bufferSyncSupport.ts +++ b/extensions/typescript/src/features/bufferSyncSupport.ts @@ -2,9 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - 'use strict'; +import * as fs from 'fs'; + import { workspace, TextDocument, TextDocumentChangeEvent, TextDocumentContentChangeEvent, Disposable } from 'vscode'; import * as Proto from '../protocol'; import { ITypescriptServiceClient } from '../typescriptService'; @@ -67,12 +68,17 @@ class SyncedBuffer { } } +export interface Diagnostics { + delete(file: string): void; +} + export default class BufferSyncSupport { private client: ITypescriptServiceClient; private _validate: boolean; private modeIds: Map; + private diagnostics: Diagnostics; private disposables: Disposable[] = []; private syncedBuffers: Map; private closedFiles: Map; @@ -80,10 +86,11 @@ export default class BufferSyncSupport { private pendingDiagnostics: { [key: string]: number; }; private diagnosticDelayer: Delayer; - constructor(client: ITypescriptServiceClient, modeIds: string[], validate: boolean = true) { + constructor(client: ITypescriptServiceClient, modeIds: string[], diagnostics: Diagnostics, validate: boolean = true) { this.client = client; this.modeIds = Object.create(null); modeIds.forEach(modeId => this.modeIds[modeId] = true); + this.diagnostics = diagnostics; this._validate = validate; this.pendingDiagnostics = Object.create(null); @@ -94,10 +101,23 @@ export default class BufferSyncSupport { } public listen(): void { - workspace.onDidOpenTextDocument(this.onDidAddDocument, this, this.disposables); - workspace.onDidCloseTextDocument(this.onDidRemoveDocument, this, this.disposables); - workspace.onDidChangeTextDocument(this.onDidChangeDocument, this, this.disposables); - workspace.textDocuments.forEach(this.onDidAddDocument, this); + workspace.onDidOpenTextDocument(this.onDidOpenTextDocument, this, this.disposables); + workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, this.disposables); + workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, this.disposables); + workspace.textDocuments.forEach(this.onDidOpenTextDocument, this); + workspace.createFileSystemWatcher('**/*', true, true, false).onDidDelete((resource) => { + let filepath = this.client.asAbsolutePath(resource); + if (!filepath) { + return; + } + if (!this.syncedBuffers[filepath]) { + // The file is not synced (open in an editor) and got + // removed from disk. Make sure it is not in the closedFiles + // list since we shouldn't revalidate it. + delete this.closedFiles[filepath]; + this.diagnostics.delete(filepath); + } + }); } public get validate(): boolean { @@ -124,7 +144,7 @@ export default class BufferSyncSupport { } } - private onDidAddDocument(document: TextDocument): void { + private onDidOpenTextDocument(document: TextDocument): void { if (!this.modeIds[document.languageId]) { return; } @@ -143,7 +163,7 @@ export default class BufferSyncSupport { this.requestDiagnostic(filepath); } - private onDidRemoveDocument(document: TextDocument): void { + private onDidCloseTextDocument(document: TextDocument): void { let filepath: string = this.client.asAbsolutePath(document.uri); if (!filepath) { return; @@ -152,12 +172,19 @@ export default class BufferSyncSupport { if (!syncedBuffer) { return; } - this.closedFiles[filepath] = true; + // If the file still exists on disk keep on validating the file. + if (fs.existsSync(filepath)) { + this.closedFiles[filepath] = true; + } else { + // Ensure we don't have the file in the map and clear all errors. + delete this.closedFiles[filepath]; + this.diagnostics.delete(filepath); + } delete this.syncedBuffers[filepath]; syncedBuffer.close(); } - private onDidChangeDocument(e: TextDocumentChangeEvent): void { + private onDidChangeTextDocument(e: TextDocumentChangeEvent): void { let filepath: string = this.client.asAbsolutePath(e.document.uri); if (!filepath) { return; diff --git a/extensions/typescript/src/typescriptMain.ts b/extensions/typescript/src/typescriptMain.ts index 0f88c6beede..57e05ea5ac4 100644 --- a/extensions/typescript/src/typescriptMain.ts +++ b/extensions/typescript/src/typescriptMain.ts @@ -98,7 +98,11 @@ class LanguageProvider { this.description = description; this._validate = true; - this.bufferSyncSupport = new BufferSyncSupport(client, description.modeIds); + this.bufferSyncSupport = new BufferSyncSupport(client, description.modeIds, { + delete: (file: string) => { + this.currentDiagnostics.delete(Uri.file(file)); + } + }); this.syntaxDiagnostics = Object.create(null); this.currentDiagnostics = languages.createDiagnosticCollection(description.id);