Add delete and undo support for get most recently failed cell (#157032)

* "Go To" last failing cell should disappear when deleting that cell
Fixes #156299
This commit is contained in:
Andrea Mah 2022-08-05 12:20:53 -07:00 committed by GitHub
parent 60c53f18dd
commit 97d94fc23b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 11 deletions

View file

@ -13,7 +13,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellEditType, CellUri, ICellEditOperation, NotebookCellExecutionState, NotebookCellInternalMetadata, NotebookTextModelWillAddRemoveEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellExecutionUpdateType, INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, ICellExecutionStateUpdate, INotebookCellExecution, INotebookExecutionStateService, INotebookFailStateChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, ICellExecutionStateUpdate, IFailedCellInfo, INotebookCellExecution, INotebookExecutionStateService, INotebookFailStateChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
export class NotebookExecutionStateService extends Disposable implements INotebookExecutionStateService {
@ -22,7 +22,7 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
private readonly _executions = new ResourceMap<Map<number, CellExecution>>();
private readonly _notebookListeners = new ResourceMap<NotebookExecutionListeners>();
private readonly _cellListeners = new ResourceMap<IDisposable>();
private readonly _lastFailedCells = new ResourceMap<number>();
private readonly _lastFailedCells = new ResourceMap<IFailedCellInfo>();
private readonly _onDidChangeCellExecution = this._register(new Emitter<ICellExecutionStateChangedEvent>());
onDidChangeCellExecution = this._onDidChangeCellExecution.event;
@ -39,7 +39,8 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
}
getLastFailedCellForNotebook(notebook: URI): number | undefined {
return this._lastFailedCells.get(notebook);
const failedCell = this._lastFailedCells.get(notebook);
return failedCell?.visible ? failedCell.cellHandle : undefined;
}
forceCancelNotebookExecutions(notebookUri: URI): void {
@ -142,14 +143,68 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
return exe;
}
private _setLastFailedCell(notebook: URI, cellHandle: number) {
this._lastFailedCells.set(notebook, cellHandle);
this._onDidChangeLastRunFailState.fire({ failed: true, notebook });
private _setLastFailedCell(notebookURI: URI, cellHandle: number): void {
const prevLastFailedCellInfo = this._lastFailedCells.get(notebookURI);
const notebook = this._notebookService.getNotebookTextModel(notebookURI);
if (!notebook) {
return;
}
const newLastFailedCellInfo: IFailedCellInfo = {
cellHandle: cellHandle,
disposable: prevLastFailedCellInfo ? prevLastFailedCellInfo.disposable : this._getFailedCellListener(notebook),
visible: true
};
this._lastFailedCells.set(notebookURI, newLastFailedCellInfo);
this._onDidChangeLastRunFailState.fire({ visible: true, notebook: notebookURI });
}
private _clearLastFailedCell(notebook: URI) {
this._lastFailedCells.delete(notebook);
this._onDidChangeLastRunFailState.fire({ failed: false, notebook: notebook });
private _setLastFailedCellVisibility(notebookURI: URI, visible: boolean): void {
const lastFailedCellInfo = this._lastFailedCells.get(notebookURI);
if (lastFailedCellInfo) {
this._lastFailedCells.set(notebookURI, {
cellHandle: lastFailedCellInfo.cellHandle,
disposable: lastFailedCellInfo.disposable,
visible: visible,
});
}
this._onDidChangeLastRunFailState.fire({ visible: visible, notebook: notebookURI });
}
private _clearLastFailedCell(notebookURI: URI): void {
const lastFailedCellInfo = this._lastFailedCells.get(notebookURI);
if (lastFailedCellInfo) {
lastFailedCellInfo.disposable?.dispose();
this._lastFailedCells.delete(notebookURI);
}
this._onDidChangeLastRunFailState.fire({ visible: false, notebook: notebookURI });
}
private _getFailedCellListener(notebook: NotebookTextModel): IDisposable {
return notebook.onWillAddRemoveCells((e: NotebookTextModelWillAddRemoveEvent) => {
const lastFailedCell = this._lastFailedCells.get(notebook.uri)?.cellHandle;
if (lastFailedCell !== undefined) {
const lastFailedCellPos = notebook.cells.findIndex(c => c.handle === lastFailedCell);
e.rawEvent.changes.forEach(([start, deleteCount, addedCells]) => {
if (deleteCount) {
if (lastFailedCellPos >= start && lastFailedCellPos < start + deleteCount) {
this._setLastFailedCellVisibility(notebook.uri, false);
}
}
if (addedCells.some(cell => cell.handle === lastFailedCell)) {
this._setLastFailedCellVisibility(notebook.uri, true);
}
});
}
});
}
override dispose(): void {
@ -162,6 +217,7 @@ export class NotebookExecutionStateService extends Disposable implements INotebo
this._cellListeners.forEach(disposable => disposable.dispose());
this._notebookListeners.forEach(disposable => disposable.dispose());
this._lastFailedCells.forEach(elem => elem.disposable.dispose());
}
}

View file

@ -137,7 +137,7 @@ export class NotebookEditorContextKeys {
private _updateForLastRunFailState(e: INotebookFailStateChangedEvent): void {
if (e.notebook === this._editor.textModel?.uri) {
this._lastCellFailed.set(e.failed);
this._lastCellFailed.set(e.visible);
}
}

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@ -40,10 +41,16 @@ export interface ICellExecutionStateChangedEvent {
affectsNotebook(notebook: URI): boolean;
}
export interface INotebookFailStateChangedEvent {
failed: boolean;
visible: boolean;
notebook: URI;
}
export interface IFailedCellInfo {
cellHandle: number;
disposable: IDisposable;
visible: boolean;
}
export const INotebookExecutionStateService = createDecorator<INotebookExecutionStateService>('INotebookExecutionStateService');
export interface INotebookExecutionStateService {