diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index 4c0d0911296..4ecef4ac7b6 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { Logger } from '../logger'; import { MarkdownContentProvider } from './previewContentProvider'; -import { disposeAll } from '../util/dispose'; +import { Disposable } from '../util/dispose'; import * as nls from 'vscode-nls'; import { getVisibleLine, MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor'; @@ -60,7 +60,7 @@ interface PreviewStyleLoadErrorMessage extends WebviewMessage { }; } -export class MarkdownPreview { +export class MarkdownPreview extends Disposable { public static viewType = 'markdown.preview'; @@ -70,7 +70,6 @@ export class MarkdownPreview { private readonly editor: vscode.WebviewPanel; private throttleTimer: any; private line: number | undefined = undefined; - private readonly disposables: vscode.Disposable[] = []; private firstUpdate = true; private currentVersion?: { resource: vscode.Uri, version: number }; private forceUpdate = false; @@ -149,17 +148,18 @@ export class MarkdownPreview { topmostLineMonitor: MarkdownFileTopmostLineMonitor, private readonly _contributionProvider: MarkdownContributionProvider, ) { + super(); this._resource = resource; this._locked = locked; this.editor = webview; this.editor.onDidDispose(() => { this.dispose(); - }, null, this.disposables); + }, null, this._disposables); this.editor.onDidChangeViewState(e => { this._onDidChangeViewStateEmitter.fire(e); - }, null, this.disposables); + }, null, this._disposables); this.editor.webview.onDidReceiveMessage((e: CacheImageSizesMessage | RevealLineMessage | DidClickMessage | ClickLinkMessage | ShowPreviewSecuritySelectorMessage | PreviewStyleLoadErrorMessage) => { if (e.source !== this._resource.toString()) { @@ -191,19 +191,19 @@ export class MarkdownPreview { vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", e.body.unloadedStyles.join(', '))); break; } - }, null, this.disposables); + }, null, this._disposables); vscode.workspace.onDidChangeTextDocument(event => { if (this.isPreviewOf(event.document.uri)) { this.refresh(); } - }, null, this.disposables); + }, null, this._disposables); topmostLineMonitor.onDidChangeTopmostLine(event => { if (this.isPreviewOf(event.resource)) { this.updateForView(event.resource, event.line); } - }, null, this.disposables); + }, null, this._disposables); vscode.window.onDidChangeTextEditorSelection(event => { if (this.isPreviewOf(event.textEditor.document.uri)) { @@ -213,13 +213,13 @@ export class MarkdownPreview { source: this.resource.toString() }); } - }, null, this.disposables); + }, null, this._disposables); vscode.window.onDidChangeActiveTextEditor(editor => { if (editor && isMarkdownFile(editor.document) && !this._locked) { this.update(editor.document.uri); } - }, null, this.disposables); + }, null, this._disposables); } private readonly _onDisposeEmitter = new vscode.EventEmitter(); @@ -242,18 +242,17 @@ export class MarkdownPreview { } public dispose() { + super.dispose(); if (this._disposed) { return; } this._disposed = true; this._onDisposeEmitter.fire(); - this._onDisposeEmitter.dispose(); + this._onDidChangeViewStateEmitter.dispose(); this.editor.dispose(); - - disposeAll(this.disposables); } public update(resource: vscode.Uri) { diff --git a/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts b/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts index 12e51c75d76..73e04269fce 100644 --- a/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts +++ b/extensions/markdown-language-features/src/features/workspaceSymbolProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { disposeAll } from '../util/dispose'; +import { Disposable } from '../util/dispose'; import { isMarkdownFile } from '../util/file'; import { Lazy, lazy } from '../util/lazy'; import MDDocumentSymbolProvider from './documentSymbolProvider'; @@ -18,25 +18,13 @@ export interface WorkspaceMarkdownDocumentProvider { readonly onDidDeleteMarkdownDocument: vscode.Event; } -class VSCodeWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocumentProvider { +class VSCodeWorkspaceMarkdownDocumentProvider extends Disposable implements WorkspaceMarkdownDocumentProvider { - private readonly _onDidChangeMarkdownDocumentEmitter = new vscode.EventEmitter(); - private readonly _onDidCreateMarkdownDocumentEmitter = new vscode.EventEmitter(); - private readonly _onDidDeleteMarkdownDocumentEmitter = new vscode.EventEmitter(); + private readonly _onDidChangeMarkdownDocumentEmitter = this._register(new vscode.EventEmitter()); + private readonly _onDidCreateMarkdownDocumentEmitter = this._register(new vscode.EventEmitter()); + private readonly _onDidDeleteMarkdownDocumentEmitter = this._register(new vscode.EventEmitter()); private _watcher: vscode.FileSystemWatcher | undefined; - private _disposables: vscode.Disposable[] = []; - - public dispose() { - this._onDidChangeMarkdownDocumentEmitter.dispose(); - this._onDidDeleteMarkdownDocumentEmitter.dispose(); - - if (this._watcher) { - this._watcher.dispose(); - } - - disposeAll(this._disposables); - } async getAllMarkdownDocuments() { const resources = await vscode.workspace.findFiles('**/*.md', '**/node_modules/**'); @@ -64,7 +52,7 @@ class VSCodeWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocume return; } - this._watcher = vscode.workspace.createFileSystemWatcher('**/*.md'); + this._watcher = this._register(vscode.workspace.createFileSystemWatcher('**/*.md')); this._watcher.onDidChange(async resource => { const document = await this.getMarkdownDocument(resource); @@ -98,15 +86,16 @@ class VSCodeWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocume } -export default class MarkdownWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider { +export default class MarkdownWorkspaceSymbolProvider extends Disposable implements vscode.WorkspaceSymbolProvider { private _symbolCache = new Map>>(); private _symbolCachePopulated: boolean = false; - private _disposables: vscode.Disposable[] = []; public constructor( private _symbolProvider: MDDocumentSymbolProvider, private _workspaceMarkdownDocumentProvider: WorkspaceMarkdownDocumentProvider = new VSCodeWorkspaceMarkdownDocumentProvider() - ) { } + ) { + super(); + } public async provideWorkspaceSymbols(query: string): Promise { if (!this._symbolCachePopulated) { @@ -130,10 +119,6 @@ export default class MarkdownWorkspaceSymbolProvider implements vscode.Workspace } } - public dispose(): void { - disposeAll(this._disposables); - } - private getSymbols(document: SkinnyTextDocument): Lazy> { return lazy(async () => { return this._symbolProvider.provideDocumentSymbolInformation(document); diff --git a/extensions/markdown-language-features/src/util/dispose.ts b/extensions/markdown-language-features/src/util/dispose.ts index 19b3b3f4f19..548094c28e5 100644 --- a/extensions/markdown-language-features/src/util/dispose.ts +++ b/extensions/markdown-language-features/src/util/dispose.ts @@ -14,3 +14,29 @@ export function disposeAll(disposables: vscode.Disposable[]) { } } +export abstract class Disposable { + private _isDisposed = false; + + protected _disposables: vscode.Disposable[] = []; + + public dispose(): any { + if (this._isDisposed) { + return; + } + this._isDisposed = true; + disposeAll(this._disposables); + } + + protected _register(value: T): T { + if (this._isDisposed) { + value.dispose(); + } else { + this._disposables.push(value); + } + return value; + } + + protected get isDisposed() { + return this._isDisposed; + } +} \ No newline at end of file