From ddbac4875ca7bf06d114701169a2e9cd7e26dc30 Mon Sep 17 00:00:00 2001 From: Johannes Date: Fri, 26 May 2023 15:36:22 +0200 Subject: [PATCH] =?UTF-8?q?notebooks=20create/dispose=20editors.=20this=20?= =?UTF-8?q?means=20controllers=20must=20be=20created=20eagerly=20(?= =?UTF-8?q?=F0=9F=98=A2)=20and=20that=20notebooks=20need=20a=20custom=20wa?= =?UTF-8?q?y=20of=20plugging=20comparision=20keys=20for=20session.=20works?= =?UTF-8?q?=20unless=20creating=20another=20session=20for=20the=20same=20c?= =?UTF-8?q?ell=20of=20a=20duplicated=20editor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../browser/interactiveEditor.contribution.ts | 10 ++- .../browser/interactiveEditorNotebook.ts | 35 +++++++++++ .../browser/interactiveEditorSession.ts | 62 +++++++++++-------- 3 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorNotebook.ts diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditor.contribution.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditor.contribution.ts index 53031c86cc2..ad9d22eb694 100644 --- a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditor.contribution.ts +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditor.contribution.ts @@ -11,11 +11,15 @@ import { IInteractiveEditorService, INTERACTIVE_EDITOR_ID } from 'vs/workbench/c import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { InteractiveEditorServiceImpl } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditorServiceImpl'; import { IInteractiveEditorSessionService, InteractiveEditorSessionService } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorSession'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { InteractiveEditorNotebookContribution } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorNotebook'; registerSingleton(IInteractiveEditorService, InteractiveEditorServiceImpl, InstantiationType.Delayed); registerSingleton(IInteractiveEditorSessionService, InteractiveEditorSessionService, InstantiationType.Delayed); -registerEditorContribution(INTERACTIVE_EDITOR_ID, InteractiveEditorController, EditorContributionInstantiation.Lazy); +registerEditorContribution(INTERACTIVE_EDITOR_ID, InteractiveEditorController, EditorContributionInstantiation.Eager); // EAGER because of notebook dispose/create of editors registerAction2(interactiveEditorActions.StartSessionAction); registerAction2(interactiveEditorActions.UnstashSessionAction); @@ -42,3 +46,7 @@ registerAction2(interactiveEditorActions.FeebackUnhelpfulCommand); registerAction2(interactiveEditorActions.ApplyPreviewEdits); registerAction2(interactiveEditorActions.CopyRecordings); + + +Registry.as(Extensions.Workbench) + .registerWorkbenchContribution(InteractiveEditorNotebookContribution, LifecyclePhase.Restored); diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorNotebook.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorNotebook.ts new file mode 100644 index 00000000000..2b61e17fd10 --- /dev/null +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorNotebook.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { illegalState } from 'vs/base/common/errors'; +import { Schemas } from 'vs/base/common/network'; +import { isEqual } from 'vs/base/common/resources'; +import { IInteractiveEditorSessionService } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorSession'; +import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; +import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; + +export class InteractiveEditorNotebookContribution { + + constructor( + @IInteractiveEditorSessionService sessionService: IInteractiveEditorSessionService, + @INotebookEditorService notebookEditorService: INotebookEditorService, + ) { + + sessionService.registerSessionKeyComputer(Schemas.vscodeNotebookCell, { + getComparisonKey: (_editor, uri) => { + const data = CellUri.parse(uri); + if (!data) { + throw illegalState('Expected notebook'); + } + for (const editor of notebookEditorService.listNotebookEditors()) { + if (isEqual(editor.textModel?.uri, data.notebook)) { + return `${editor.getId()}#${uri}`; + } + } + throw illegalState('Expected notebook'); + } + }); + } +} diff --git a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorSession.ts b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorSession.ts index d6ffb8534c8..3dc04948fb0 100644 --- a/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorSession.ts +++ b/src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorSession.ts @@ -13,7 +13,6 @@ import { EditMode, IInteractiveEditorSessionProvider, IInteractiveEditorSession, import { IRange, Range } from 'vs/editor/common/core/range'; import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ResourceMap } from 'vs/base/common/map'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IModelService } from 'vs/editor/common/services/model'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -266,6 +265,10 @@ export class EditResponse { } } +export interface ISessionKeyComputer { + getComparisonKey(editor: ICodeEditor, uri: URI): string; +} + export const IInteractiveEditorSessionService = createDecorator('IInteractiveEditorSessionService'); export interface IInteractiveEditorSessionService { @@ -277,6 +280,8 @@ export interface IInteractiveEditorSessionService { releaseSession(session: Session): void; + registerSessionKeyComputer(scheme: string, value: ISessionKeyComputer): IDisposable; + // recordings(): readonly Recording[]; @@ -291,7 +296,8 @@ export class InteractiveEditorSessionService implements IInteractiveEditorSessio declare _serviceBrand: undefined; - private readonly _sessions = new Map>(); + private readonly _sessions = new Map(); + private readonly _keyComputers = new Map(); private _recordings: Recording[] = []; constructor( @@ -360,37 +366,27 @@ export class InteractiveEditorSessionService implements IInteractiveEditorSessio const session = new Session(options.editMode, editor, textModel0, textModel, provider, raw, wholeRangeDecorationId); - // store: editor -> uri -> session - let map = this._sessions.get(editor); - if (!map) { - map = new ResourceMap(); - this._sessions.set(editor, map); + // store: key -> session + const key = this._key(editor, textModel.uri); + if (this._sessions.has(key)) { + store.dispose(); + throw new Error(`Session already stored for ${key}`); } - if (map.has(textModel.uri)) { - throw new Error(`Session already stored for ${textModel.uri}`); - } - map.set(textModel.uri, { session, store }); + this._sessions.set(key, { session, store }); return session; } releaseSession(session: Session): void { - const { editor, textModelN } = session; + const { editor } = session; // cleanup - const map = this._sessions.get(editor); - if (map) { - const data = map.get(textModelN.uri); - if (data) { - data.store.dispose(); - data.session.session.dispose?.(); - - map.delete(textModelN.uri); - this._logService.trace(`[IE] did RELEASE session for ${editor.getId()}, ${session.provider.debugName}`); - - } - if (map.size === 0) { - this._sessions.delete(editor); + for (const [key, value] of this._sessions) { + if (value.session === session) { + value.store.dispose(); + this._sessions.delete(key); + this._logService.trace(`[IE] did RELEASED session for ${editor.getId()}, ${session.provider.debugName}`); + break; } } @@ -405,7 +401,21 @@ export class InteractiveEditorSessionService implements IInteractiveEditorSessio } getSession(editor: ICodeEditor, uri: URI): Session | undefined { - return this._sessions.get(editor)?.get(uri)?.session; + const key = this._key(editor, uri); + return this._sessions.get(key)?.session; + } + + private _key(editor: ICodeEditor, uri: URI): string { + const item = this._keyComputers.get(uri.scheme); + return item + ? item.getComparisonKey(editor, uri) + : `${editor.getId()}@${uri.toString()}`; + + } + + registerSessionKeyComputer(scheme: string, value: ISessionKeyComputer): IDisposable { + this._keyComputers.set(scheme, value); + return toDisposable(() => this._keyComputers.delete(scheme)); } // --- debug