Skip to content

Commit 7eb5c6c

Browse files
authored
cell diagnostic actions (microsoft#208261)
* add command to open cell error diagnostic quickfix menu * add keybinding, filter actions * context key for has cell diagnostics * clear diagnostics on content change
1 parent 78d4f34 commit 7eb5c6c

File tree

5 files changed

+62
-5
lines changed

5 files changed

+62
-5
lines changed

src/vs/workbench/contrib/notebook/browser/contrib/cellCommands/cellCommands.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
1414
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
1515
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
1616
import { changeCellToKind, computeCellLinesContents, copyCellRange, joinCellsWithSurrounds, joinSelectedCells, moveCellRange } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
17-
import { cellExecutionArgs, CellOverflowToolbarGroups, CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, INotebookCellActionContext, INotebookCellToolbarActionContext, INotebookCommandContext, NotebookCellAction, NotebookMultiCellAction, parseMultiCellExecutionArgs } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
17+
import { cellExecutionArgs, CellOverflowToolbarGroups, CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, INotebookCellActionContext, INotebookCellToolbarActionContext, INotebookCommandContext, NotebookCellAction, NotebookMultiCellAction, parseMultiCellExecutionArgs, findTargetCellEditor } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
1818
import { CellFocusMode, EXPAND_CELL_INPUT_COMMAND_ID, EXPAND_CELL_OUTPUT_COMMAND_ID, ICellOutputViewModel, ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
19-
import { NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
19+
import { NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_ERROR_DIAGNOSTICS, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
2020
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
2121
import { CellEditType, CellKind, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
2222
import { INotificationService } from 'vs/platform/notification/common/notification';
2323
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
2424
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
25+
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
26+
import { Range } from 'vs/editor/common/core/range';
27+
import { CodeActionController } from 'vs/editor/contrib/codeAction/browser/codeActionController';
28+
import { CodeActionKind, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/common/types';
2529

2630
//#region Move/Copy cells
2731
const MOVE_CELL_UP_COMMAND_ID = 'notebook.cell.moveUp';
@@ -353,6 +357,7 @@ const COLLAPSE_ALL_CELL_OUTPUTS_COMMAND_ID = 'notebook.cell.collapseAllCellOutpu
353357
const EXPAND_ALL_CELL_OUTPUTS_COMMAND_ID = 'notebook.cell.expandAllCellOutputs';
354358
const TOGGLE_CELL_OUTPUTS_COMMAND_ID = 'notebook.cell.toggleOutputs';
355359
const TOGGLE_CELL_OUTPUT_SCROLLING = 'notebook.cell.toggleOutputScrolling';
360+
const OPEN_CELL_FAILURE_ACTIONS_COMMAND_ID = 'notebook.cell.openFailureActions';
356361

357362
registerAction2(class CollapseCellInputAction extends NotebookMultiCellAction {
358363
constructor() {
@@ -579,6 +584,45 @@ registerAction2(class ToggleCellOutputScrolling extends NotebookMultiCellAction
579584
}
580585
});
581586

587+
registerAction2(class ExpandAllCellOutputsAction extends NotebookCellAction {
588+
constructor() {
589+
super({
590+
id: OPEN_CELL_FAILURE_ACTIONS_COMMAND_ID,
591+
title: localize2('notebookActions.cellFailureActions', "Show Cell Failure Actions"),
592+
precondition: ContextKeyExpr.and(NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_ERROR_DIAGNOSTICS, NOTEBOOK_CELL_EDITOR_FOCUSED.toNegated()),
593+
f1: true,
594+
keybinding: {
595+
when: ContextKeyExpr.and(NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_ERROR_DIAGNOSTICS, NOTEBOOK_CELL_EDITOR_FOCUSED.toNegated()),
596+
primary: KeyMod.CtrlCmd | KeyCode.Period,
597+
weight: KeybindingWeight.WorkbenchContrib
598+
}
599+
});
600+
}
601+
602+
async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
603+
if (context.cell instanceof CodeCellViewModel) {
604+
const error = context.cell.cellErrorDetails;
605+
if (error?.location) {
606+
const location = Range.lift({
607+
startLineNumber: error.location.startLineNumber + 1,
608+
startColumn: error.location.startColumn + 1,
609+
endLineNumber: error.location.endLineNumber + 1,
610+
endColumn: error.location.endColumn + 1
611+
});
612+
context.notebookEditor.setCellEditorSelection(context.cell, Range.lift(location));
613+
const editor = findTargetCellEditor(context, context.cell);
614+
if (editor) {
615+
const controller = CodeActionController.get(editor);
616+
controller?.manualTriggerAtCurrentPosition(
617+
localize('cellCommands.quickFix.noneMessage', "No code actions available"),
618+
CodeActionTriggerSource.Default,
619+
{ include: CodeActionKind.QuickFix });
620+
}
621+
}
622+
}
623+
}
624+
});
625+
582626
//#endregion
583627

584628
function forEachCell(editor: INotebookEditor, callback: (cell: ICellViewModel, index: number) => void) {

src/vs/workbench/contrib/notebook/browser/contrib/cellDiagnostics/cellDiagnostics.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ export class CellDiagnostics extends Disposable {
7070
}
7171

7272
public clear() {
73-
this.clearDiagnostics();
73+
if (this.ErrorDetails) {
74+
this.clearDiagnostics();
75+
}
7476
}
7577

7678
private clearDiagnostics() {

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cell
1313
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
1414
import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel';
1515
import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
16-
import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_RESOURCE, NOTEBOOK_CELL_TYPE, NOTEBOOK_CELL_GENERATED_BY_CHAT } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
16+
import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_RESOURCE, NOTEBOOK_CELL_TYPE, NOTEBOOK_CELL_GENERATED_BY_CHAT, NOTEBOOK_CELL_HAS_ERROR_DIAGNOSTICS } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
1717
import { INotebookExecutionStateService, NotebookExecutionType } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
1818

1919
export class CellContextKeyPart extends CellContentPart {
@@ -47,6 +47,7 @@ export class CellContextKeyManager extends Disposable {
4747
private cellLineNumbers!: IContextKey<'on' | 'off' | 'inherit'>;
4848
private cellResource!: IContextKey<string>;
4949
private cellGeneratedByChat!: IContextKey<boolean>;
50+
private cellHasErrorDiagnostics!: IContextKey<boolean>;
5051

5152
private markdownEditMode!: IContextKey<boolean>;
5253

@@ -74,6 +75,7 @@ export class CellContextKeyManager extends Disposable {
7475
this.cellLineNumbers = NOTEBOOK_CELL_LINE_NUMBERS.bindTo(this._contextKeyService);
7576
this.cellGeneratedByChat = NOTEBOOK_CELL_GENERATED_BY_CHAT.bindTo(this._contextKeyService);
7677
this.cellResource = NOTEBOOK_CELL_RESOURCE.bindTo(this._contextKeyService);
78+
this.cellHasErrorDiagnostics = NOTEBOOK_CELL_HAS_ERROR_DIAGNOSTICS.bindTo(this._contextKeyService);
7779

7880
if (element) {
7981
this.updateForElement(element);
@@ -200,6 +202,10 @@ export class CellContextKeyManager extends Disposable {
200202
this.cellRunState.set('idle');
201203
this.cellExecuting.set(false);
202204
}
205+
206+
if (this.element instanceof CodeCellViewModel) {
207+
this.cellHasErrorDiagnostics.set(!!this.element.cellErrorDetails);
208+
}
203209
}
204210

205211
private updateForEditState() {

src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
4747
private _outputCollection: number[] = [];
4848

4949
private readonly _cellDiagnostics: CellDiagnostics;
50+
get cellErrorDetails() {
51+
return this._cellDiagnostics.ErrorDetails;
52+
}
5053

5154
private _outputsTop: PrefixSumComputer | null = null;
5255

@@ -171,7 +174,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
171174
if (outputLayoutChange) {
172175
this.layoutChange({ outputHeight: true }, 'CodeCellViewModel#model.onDidChangeOutputs');
173176
}
174-
if (this._outputCollection.length === 0 && this._cellDiagnostics.ErrorDetails) {
177+
if (this._outputCollection.length === 0) {
175178
this._cellDiagnostics.clear();
176179
}
177180
dispose(removedOutputs);
@@ -433,6 +436,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
433436

434437
protected onDidChangeTextModelContent(): void {
435438
if (this.getEditState() !== CellEditState.Editing) {
439+
this._cellDiagnostics.clear();
436440
this.updateEditState(CellEditState.Editing, 'onDidChangeTextModelContent');
437441
this._onDidChangeState.fire({ contentChanged: true });
438442
}

src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const NOTEBOOK_CELL_INPUT_COLLAPSED = new RawContextKey<boolean>('noteboo
4747
export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey<boolean>('notebookCellOutputIsCollapsed', false);
4848
export const NOTEBOOK_CELL_RESOURCE = new RawContextKey<string>('notebookCellResource', '');
4949
export const NOTEBOOK_CELL_GENERATED_BY_CHAT = new RawContextKey<boolean>('notebookCellGenerateByChat', false);
50+
export const NOTEBOOK_CELL_HAS_ERROR_DIAGNOSTICS = new RawContextKey<boolean>('notebookCellHasErrorDiagnostics', false);
5051

5152
// Kernels
5253
export const NOTEBOOK_KERNEL = new RawContextKey<string>('notebookKernel', undefined);

0 commit comments

Comments
 (0)