diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 2d2887db014..39de73bac0d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -28,7 +28,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl'; -import { CellKind, CellToolbarLocKey, CellUri, DisplayOrderKey, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NOTEBOOK_WORKING_COPY_TYPE_PREFIX, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellToolbarLocKey, CellUri, DisplayOrderKey, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; @@ -436,11 +436,7 @@ class NotebookWorkingCopyEditorHandler extends Disposable implements IWorkbenchC } private getViewType(workingCopy: IWorkingCopyIdentifier): string | undefined { - if (workingCopy.typeId.startsWith(NOTEBOOK_WORKING_COPY_TYPE_PREFIX)) { - return workingCopy.typeId.substr(NOTEBOOK_WORKING_COPY_TYPE_PREFIX.length); - } - - return undefined; + return NotebookWorkingCopyTypeIdentifier.parse(workingCopy.typeId); } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 7ea304f760f..4f811c09c8b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -302,6 +302,9 @@ export class NotebookService extends Disposable implements INotebookService, IEd readonly onDidAddNotebookDocument = this._onDidAddNotebookDocument.event; readonly onDidRemoveNotebookDocument = this._onDidRemoveNotebookDocument.event; + private readonly _onWillRemoveViewType = this._register(new Emitter()); + readonly onWillRemoveViewType = this._onWillRemoveViewType.event; + private readonly _onDidChangeEditorTypes = this._register(new Emitter()); onDidChangeEditorTypes: Event = this._onDidChangeEditorTypes.event; @@ -471,15 +474,19 @@ export class NotebookService extends Disposable implements INotebookService, IEd return this._notebookProviders.has(viewType); } - private _registerProviderData(viewType: string, data: SimpleNotebookProviderInfo | ComplexNotebookProviderInfo): void { + private _registerProviderData(viewType: string, data: SimpleNotebookProviderInfo | ComplexNotebookProviderInfo): IDisposable { if (this._notebookProviders.has(viewType)) { throw new Error(`notebook controller for viewtype '${viewType}' already exists`); } this._notebookProviders.set(viewType, data); + return toDisposable(() => { + this._onWillRemoveViewType.fire(viewType); + this._notebookProviders.delete(viewType); + }); } registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: INotebookContentProvider): IDisposable { - this._registerProviderData(viewType, new ComplexNotebookProviderInfo(viewType, controller, extensionData)); + const reg = this._registerProviderData(viewType, new ComplexNotebookProviderInfo(viewType, controller, extensionData)); if (controller.viewOptions && !this._notebookProviderInfoStore.get(viewType)) { // register this content provider to the static contribution, if it does not exist const info = new NotebookProviderInfo({ @@ -504,16 +511,13 @@ export class NotebookService extends Disposable implements INotebookService, IEd this._onDidChangeEditorTypes.fire(); return toDisposable(() => { - this._notebookProviders.delete(viewType); + reg.dispose(); this._onDidChangeEditorTypes.fire(); }); } registerNotebookSerializer(viewType: string, extensionData: NotebookExtensionDescription, serializer: INotebookSerializer): IDisposable { - this._registerProviderData(viewType, new SimpleNotebookProviderInfo(viewType, serializer, extensionData)); - return toDisposable(() => { - this._notebookProviders.delete(viewType); - }); + return this._registerProviderData(viewType, new SimpleNotebookProviderInfo(viewType, serializer, extensionData)); } async withNotebookDataProvider(resource: URI, viewType?: string): Promise { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 8ca69efbbb1..4e24c40de09 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -843,4 +843,18 @@ export interface INotebookDecorationRenderOptions { top?: editorCommon.IContentDecorationRenderOptions; } -export const NOTEBOOK_WORKING_COPY_TYPE_PREFIX = 'notebook/'; +export class NotebookWorkingCopyTypeIdentifier { + + private static _prefix = 'notebook/'; + + static create(viewType: string): string { + return `${NotebookWorkingCopyTypeIdentifier._prefix}/${viewType}`; + } + + static parse(candidate: string): string | undefined { + if (candidate.startsWith(NotebookWorkingCopyTypeIdentifier._prefix)) { + return candidate.substr(NotebookWorkingCopyTypeIdentifier._prefix.length); + } + return undefined; + } +} diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts index 17b474798ab..0446bafc28b 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts @@ -5,9 +5,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; -import { CellUri, IResolvedNotebookEditorModel, NOTEBOOK_WORKING_COPY_TYPE_PREFIX } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellUri, IResolvedNotebookEditorModel, NotebookWorkingCopyTypeIdentifier } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ComplexNotebookEditorModel, NotebookFileWorkingCopyModel, NotebookFileWorkingCopyModelFactory, SimpleNotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookEditorModel'; -import { combinedDisposable, dispose, IDisposable, IReference, ReferenceCollection, toDisposable } from 'vs/base/common/lifecycle'; +import { combinedDisposable, DisposableStore, dispose, IDisposable, IReference, ReferenceCollection, toDisposable } from 'vs/base/common/lifecycle'; import { ComplexNotebookProviderInfo, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService'; import { ILogService } from 'vs/platform/log/common/log'; import { Emitter, Event } from 'vs/base/common/event'; @@ -19,6 +19,7 @@ import { ResourceMap } from 'vs/base/common/map'; class NotebookModelReferenceCollection extends ReferenceCollection> { + private readonly _disposables = new DisposableStore(); private readonly _workingCopyManagers = new Map>(); private readonly _modelListener = new Map(); @@ -36,9 +37,17 @@ class NotebookModelReferenceCollection extends ReferenceCollection { + const manager = this._workingCopyManagers.get(NotebookWorkingCopyTypeIdentifier.create(viewType)); + if (manager) { + manager.dispose(); + } + })); } dispose(): void { + this._disposables.dispose(); this._onDidSaveNotebook.dispose(); this._onDidChangeDirty.dispose(); dispose(this._modelListener.values()); @@ -60,7 +69,7 @@ class NotebookModelReferenceCollection extends ReferenceCollection>this._instantiationService.createInstance( diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index 1b09f73800d..3ae5df68f83 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -60,9 +60,10 @@ export interface INotebookService { readonly _serviceBrand: undefined; canResolve(viewType: string): Promise; - onDidCreateNotebookDocument: Event; - onDidAddNotebookDocument: Event; - onDidRemoveNotebookDocument: Event; + readonly onWillRemoveViewType: Event; + readonly onDidCreateNotebookDocument: Event; + readonly onDidAddNotebookDocument: Event; + readonly onDidRemoveNotebookDocument: Event; registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: INotebookContentProvider): IDisposable; registerNotebookSerializer(viewType: string, extensionData: NotebookExtensionDescription, serializer: INotebookSerializer): IDisposable;