diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint/untitledTextEditorHint.ts index 10cee894f7d..0a6b3917b17 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint/untitledTextEditorHint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint/untitledTextEditorHint.ts @@ -21,7 +21,6 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { IContentActionHandler, renderFormattedText } from 'vs/base/browser/formattedTextRenderer'; import { ApplyFileSnippetAction } from 'vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets'; import { IInlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; -import { isEqual } from 'vs/base/common/resources'; const $ = dom.$; @@ -49,8 +48,8 @@ export class UntitledTextEditorHintContribution implements IEditorContribution { this.update(); } })); - this.toDispose.push(inlineChatSessionService.onWillStartSession(uri => { - if (isEqual(uri, this.editor.getModel()?.uri)) { + this.toDispose.push(inlineChatSessionService.onWillStartSession(editor => { + if (this.editor === editor) { this.untitledTextHintContentWidget?.dispose(); } })); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 01b8cf0ff17..b90efefc890 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -10,7 +10,6 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { isEqual } from 'vs/base/common/resources'; import { StopWatch } from 'vs/base/common/stopwatch'; import { assertType } from 'vs/base/common/types'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -35,8 +34,6 @@ import { InlineChatZoneWidget } from 'vs/workbench/contrib/inlineChat/browser/in import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, CTX_INLINE_CHAT_LAST_FEEDBACK, IInlineChatRequest, IInlineChatResponse, INLINE_CHAT_ID, EditMode, InlineChatResponseFeedbackKind, CTX_INLINE_CHAT_LAST_RESPONSE_TYPE, InlineChatResponseType, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION, InlineChateResponseTypes, CTX_INLINE_CHAT_RESPONSE_TYPES } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; import { IChatAccessibilityService, IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; -import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; -import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Lazy } from 'vs/base/common/lazy'; @@ -111,7 +108,6 @@ export class InlineChatController implements IEditorContribution { @ILogService private readonly _logService: ILogService, @IConfigurationService private readonly _configurationService: IConfigurationService, @IModelService private readonly _modelService: IModelService, - @INotebookEditorService private readonly _notebookEditorService: INotebookEditorService, @IDialogService private readonly _dialogService: IDialogService, @IContextKeyService contextKeyService: IContextKeyService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @@ -144,7 +140,7 @@ export class InlineChatController implements IEditorContribution { dispose(): void { this._stashedSession.clear(); - this._finishExistingSession(); + this.finishExistingSession(); this._store.dispose(); this._log('controller disposed'); } @@ -177,25 +173,13 @@ export class InlineChatController implements IEditorContribution { async run(options: InlineChatRunOptions | undefined = {}): Promise { this._log('session starting'); - await this._finishExistingSession(); + await this.finishExistingSession(); this._stashedSession.clear(); await this._nextState(State.CREATE_SESSION, options); this._log('session done or paused'); } - private async _finishExistingSession(): Promise { - if (this._activeSession) { - if (this._activeSession.editMode === EditMode.Preview) { - this._log('finishing existing session, using CANCEL', this._activeSession.editMode); - this.cancelSession(); - } else { - this._log('finishing existing session, using APPLY', this._activeSession.editMode); - this.acceptSession(); - } - } - } - // ---- state machine private _showWidget(initialRender: boolean = false) { @@ -296,8 +280,6 @@ export class InlineChatController implements IEditorContribution { // hide/cancel inline completions when invoking IE InlineCompletionsController.get(this._editor)?.hide(); - this._cancelNotebookSiblingEditors(); - this._sessionStore.clear(); const wholeRangeDecoration = this._editor.createDecorationsCollection(); @@ -348,7 +330,7 @@ export class InlineChatController implements IEditorContribution { if (editIsOutsideOfWholeRange) { this._log('text changed outside of whole range, FINISH session'); - this._finishExistingSession(); + this.finishExistingSession(); } })); @@ -375,35 +357,6 @@ export class InlineChatController implements IEditorContribution { return result; } - private _cancelNotebookSiblingEditors(): void { - if (!this._editor.hasModel()) { - return; - } - const candidate = CellUri.parse(this._editor.getModel().uri); - if (!candidate) { - return; - } - for (const editor of this._notebookEditorService.listNotebookEditors()) { - if (isEqual(editor.textModel?.uri, candidate.notebook)) { - let found = false; - const editors: ICodeEditor[] = []; - for (const [, codeEditor] of editor.codeEditors) { - editors.push(codeEditor); - found = codeEditor === this._editor || found; - } - if (found) { - // found the this editor in the outer notebook editor -> make sure to - // cancel all sibling sessions - for (const editor of editors) { - if (editor !== this._editor) { - InlineChatController.get(editor)?._finishExistingSession(); - } - } - break; - } - } - } - } private async [State.WAIT_FOR_INPUT](options: InlineChatRunOptions): Promise { assertType(this._activeSession); @@ -818,6 +771,18 @@ export class InlineChatController implements IEditorContribution { return result; } + async finishExistingSession(): Promise { + if (this._activeSession) { + if (this._activeSession.editMode === EditMode.Preview) { + this._log('finishing existing session, using CANCEL', this._activeSession.editMode); + this.cancelSession(); + } else { + this._log('finishing existing session, using APPLY', this._activeSession.editMode); + this.acceptSession(); + } + } + } + unstashLastSession(): Session | undefined { return this._stashedSession.value?.unstash(); } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.ts index a7ad855a4f2..7846aa594a9 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.ts @@ -4,20 +4,25 @@ *--------------------------------------------------------------------------------------------*/ import { illegalState } from 'vs/base/common/errors'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { isEqual } from 'vs/base/common/resources'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController'; import { IInlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class InlineChatNotebookContribution { + private readonly _store = new DisposableStore(); + constructor( @IInlineChatSessionService sessionService: IInlineChatSessionService, @INotebookEditorService notebookEditorService: INotebookEditorService, ) { - sessionService.registerSessionKeyComputer(Schemas.vscodeNotebookCell, { + this._store.add(sessionService.registerSessionKeyComputer(Schemas.vscodeNotebookCell, { getComparisonKey: (_editor, uri) => { const data = CellUri.parse(uri); if (!data) { @@ -30,6 +35,37 @@ export class InlineChatNotebookContribution { } throw illegalState('Expected notebook'); } - }); + })); + + this._store.add(sessionService.onWillStartSession(newSessionEditor => { + const candidate = CellUri.parse(newSessionEditor.getModel().uri); + if (!candidate) { + return; + } + for (const notebookEditor of notebookEditorService.listNotebookEditors()) { + if (isEqual(notebookEditor.textModel?.uri, candidate.notebook)) { + let found = false; + const editors: ICodeEditor[] = []; + for (const [, codeEditor] of notebookEditor.codeEditors) { + editors.push(codeEditor); + found = codeEditor === newSessionEditor || found; + } + if (found) { + // found the this editor in the outer notebook editor -> make sure to + // cancel all sibling sessions + for (const editor of editors) { + if (editor !== newSessionEditor) { + InlineChatController.get(editor)?.finishExistingSession(); + } + } + break; + } + } + } + })); + } + + dispose(): void { + this._store.dispose(); } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 65458687334..83aa7b064ff 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -363,7 +363,7 @@ export const IInlineChatSessionService = createDecorator; + onWillStartSession: Event; createSession(editor: IActiveCodeEditor, options: { editMode: EditMode; wholeRange?: IRange }, token: CancellationToken): Promise; @@ -387,8 +387,8 @@ export class InlineChatSessionService implements IInlineChatSessionService { declare _serviceBrand: undefined; - private readonly _onWillStartSession = new Emitter(); - readonly onWillStartSession: Event = this._onWillStartSession.event; + private readonly _onWillStartSession = new Emitter(); + readonly onWillStartSession: Event = this._onWillStartSession.event; private readonly _sessions = new Map(); private readonly _keyComputers = new Map(); @@ -416,7 +416,7 @@ export class InlineChatSessionService implements IInlineChatSessionService { return undefined; } - this._onWillStartSession.fire(editor.getModel().uri); + this._onWillStartSession.fire(editor); const textModel = editor.getModel(); const selection = editor.getSelection();