From 57203b243dbd3a19ae65bf18c8cd418c663b124b Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 10 Nov 2020 19:16:56 +0100 Subject: [PATCH] debug: add ability to close exception widget fixes #88217 --- .../debug/browser/debugEditorActions.ts | 24 +++++++++++- .../debug/browser/debugEditorContribution.ts | 12 ++++-- .../contrib/debug/browser/exceptionWidget.ts | 38 +++++++++++++------ .../debug/browser/media/exceptionWidget.css | 10 ++++- .../workbench/contrib/debug/common/debug.ts | 2 + 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index 107cadbc7d3..d8ba1d55449 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { ServicesAccessor, registerEditorAction, EditorAction, IActionOptions } from 'vs/editor/browser/editorExtensions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, WATCH_VIEW_ID, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE, State, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, BreakpointWidgetContext, IBreakpoint, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, REPL_VIEW_ID, CONTEXT_STEP_INTO_TARGETS_SUPPORTED, WATCH_VIEW_ID, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_EXCEPTION_WIDGET_VISIBLE } from 'vs/workbench/contrib/debug/common/debug'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { openBreakpointSource } from 'vs/workbench/contrib/debug/browser/breakpointsView'; @@ -454,6 +454,27 @@ class GoToPreviousBreakpointAction extends GoToBreakpointAction { } } +class CloseExceptionWidgetAction extends EditorAction { + + constructor() { + super({ + id: 'editor.debug.action.closeExceptionWidget', + label: nls.localize('closeExceptionWidget', "Close Exception Widget"), + alias: 'Close Exception Widget', + precondition: CONTEXT_EXCEPTION_WIDGET_VISIBLE, + kbOpts: { + primary: KeyCode.Escape, + weight: KeybindingWeight.EditorContrib + } + }); + } + + async run(_accessor: ServicesAccessor, editor: ICodeEditor): Promise { + const contribution = editor.getContribution(EDITOR_CONTRIBUTION_ID); + contribution.closeExceptionWidget(); + } +} + export function registerEditorActions(): void { registerEditorAction(ToggleBreakpointAction); registerEditorAction(ConditionalBreakpointAction); @@ -465,4 +486,5 @@ export function registerEditorActions(): void { registerEditorAction(ShowDebugHoverAction); registerEditorAction(GoToNextBreakpointAction); registerEditorAction(GoToPreviousBreakpointAction); + registerEditorAction(CloseExceptionWidgetAction); } diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index 7cfc9d73082..56a078d3871 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -21,7 +21,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IDebugEditorContribution, IDebugService, State, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo, IDebugSession } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugEditorContribution, IDebugService, State, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo, IDebugSession, CONTEXT_EXCEPTION_WIDGET_VISIBLE } from 'vs/workbench/contrib/debug/common/debug'; import { ExceptionWidget } from 'vs/workbench/contrib/debug/browser/exceptionWidget'; import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets'; import { Position } from 'vs/editor/common/core/position'; @@ -39,6 +39,7 @@ import { HoverStartMode } from 'vs/editor/contrib/hover/hoverOperation'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { Event } from 'vs/base/common/event'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; const LAUNCH_JSON_REGEX = /\.vscode\/launch\.json$/; const INLINE_VALUE_DECORATION_KEY = 'inlinevaluedecoration'; @@ -173,6 +174,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { private hoverWidget: DebugHoverWidget; private hoverRange: Range | null = null; private mouseDown = false; + private exceptionWidgetVisible: IContextKey; private static readonly MEMOIZER = createMemoizer(); private exceptionWidget: ExceptionWidget | undefined; @@ -189,13 +191,15 @@ export class DebugEditorContribution implements IDebugEditorContribution { @ITelemetryService private readonly telemetryService: ITelemetryService, @IConfigurationService private readonly configurationService: IConfigurationService, @IHostService private readonly hostService: IHostService, - @IUriIdentityService private readonly uriIdentityService: IUriIdentityService + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, + @IContextKeyService contextKeyService: IContextKeyService ) { this.hoverWidget = this.instantiationService.createInstance(DebugHoverWidget, this.editor); this.toDispose = []; this.registerListeners(); this.updateConfigurationWidgetVisibility(); this.codeEditorService.registerDecorationType(INLINE_VALUE_DECORATION_KEY, {}); + this.exceptionWidgetVisible = CONTEXT_EXCEPTION_WIDGET_VISIBLE.bindTo(contextKeyService); this.toggleExceptionWidget(); } @@ -442,12 +446,14 @@ export class DebugEditorContribution implements IDebugEditorContribution { this.exceptionWidget = this.instantiationService.createInstance(ExceptionWidget, this.editor, exceptionInfo, debugSession); this.exceptionWidget.show({ lineNumber, column }, 0); this.editor.revealLine(lineNumber); + this.exceptionWidgetVisible.set(true); } - private closeExceptionWidget(): void { + closeExceptionWidget(): void { if (this.exceptionWidget) { this.exceptionWidget.dispose(); this.exceptionWidget = undefined; + this.exceptionWidgetVisible.set(false); } } diff --git a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts index 93f702fa33c..cd2ef11bb30 100644 --- a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts @@ -8,7 +8,7 @@ import * as nls from 'vs/nls'; import * as dom from 'vs/base/browser/dom'; import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { IExceptionInfo, IDebugSession } from 'vs/workbench/contrib/debug/common/debug'; +import { IExceptionInfo, IDebugSession, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID } from 'vs/workbench/contrib/debug/common/debug'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; @@ -16,6 +16,8 @@ import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import { Action } from 'vs/base/common/actions'; const $ = dom.$; // theming @@ -25,18 +27,19 @@ export const debugExceptionWidgetBackground = registerColor('debugExceptionWidge export class ExceptionWidget extends ZoneWidget { - private _backgroundColor?: Color; + private backgroundColor: Color | undefined; - constructor(editor: ICodeEditor, private exceptionInfo: IExceptionInfo, private debugSession: IDebugSession | undefined, + constructor( + editor: ICodeEditor, + private exceptionInfo: IExceptionInfo, + private debugSession: IDebugSession | undefined, @IThemeService themeService: IThemeService, @IInstantiationService private readonly instantiationService: IInstantiationService ) { super(editor, { showFrame: true, showArrow: true, frameWidth: 1, className: 'exception-widget-container' }); - this._backgroundColor = Color.white; - - this._applyTheme(themeService.getColorTheme()); - this._disposables.add(themeService.onDidColorThemeChange(this._applyTheme.bind(this))); + this.applyTheme(themeService.getColorTheme()); + this._disposables.add(themeService.onDidColorThemeChange(this.applyTheme.bind(this))); this.create(); const onDidLayoutChangeScheduler = new RunOnceScheduler(() => this._doLayout(undefined, undefined), 50); @@ -44,8 +47,8 @@ export class ExceptionWidget extends ZoneWidget { this._disposables.add(onDidLayoutChangeScheduler); } - private _applyTheme(theme: IColorTheme): void { - this._backgroundColor = theme.getColor(debugExceptionWidgetBackground); + private applyTheme(theme: IColorTheme): void { + this.backgroundColor = theme.getColor(debugExceptionWidgetBackground); const frameColor = theme.getColor(debugExceptionWidgetBorder); this.style({ arrowColor: frameColor, @@ -55,7 +58,7 @@ export class ExceptionWidget extends ZoneWidget { protected _applyStyles(): void { if (this.container) { - this.container.style.backgroundColor = this._backgroundColor ? this._backgroundColor.toString() : ''; + this.container.style.backgroundColor = this.backgroundColor ? this.backgroundColor.toString() : ''; } super._applyStyles(); } @@ -67,8 +70,19 @@ export class ExceptionWidget extends ZoneWidget { container.style.fontSize = `${fontInfo.fontSize}px`; container.style.lineHeight = `${fontInfo.lineHeight}px`; - let title = $('.title'); - title.textContent = this.exceptionInfo.id ? nls.localize('exceptionThrownWithId', 'Exception has occurred: {0}', this.exceptionInfo.id) : nls.localize('exceptionThrown', 'Exception has occurred.'); + const title = $('.title'); + const label = $('.label'); + dom.append(title, label); + const actions = $('.actions'); + dom.append(title, actions); + label.textContent = this.exceptionInfo.id ? nls.localize('exceptionThrownWithId', 'Exception has occurred: {0}', this.exceptionInfo.id) : nls.localize('exceptionThrown', 'Exception has occurred.'); + + const actionBar = new ActionBar(actions); + actionBar.push(new Action('editor.closeExceptionWidget', nls.localize('close', "Close"), 'codicon codicon-close', true, async () => { + const contribution = this.editor.getContribution(EDITOR_CONTRIBUTION_ID); + contribution.closeExceptionWidget(); + }), { label: false, icon: true }); + dom.append(container, title); if (this.exceptionInfo.description) { diff --git a/src/vs/workbench/contrib/debug/browser/media/exceptionWidget.css b/src/vs/workbench/contrib/debug/browser/media/exceptionWidget.css index df149d3b430..f9d7846d944 100644 --- a/src/vs/workbench/contrib/debug/browser/media/exceptionWidget.css +++ b/src/vs/workbench/contrib/debug/browser/media/exceptionWidget.css @@ -15,9 +15,17 @@ } .monaco-editor .zone-widget .zone-widget-container.exception-widget .title { + display: flex; +} + +.monaco-editor .zone-widget .zone-widget-container.exception-widget .title .label { font-weight: bold; } +.monaco-editor .zone-widget .zone-widget-container.exception-widget .title .actions { + flex: 1; +} + .monaco-editor .zone-widget .zone-widget-container.exception-widget .description, .monaco-editor .zone-widget .zone-widget-container.exception-widget .stack-trace { font-family: var(--monaco-monospace-font); @@ -27,7 +35,7 @@ margin-top: 0.5em; } -.monaco-editor .zone-widget .zone-widget-container.exception-widget a { +.monaco-editor .zone-widget .zone-widget-container.exception-widget .stack-trace a { text-decoration: underline; cursor: pointer; } diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 73e33459c95..f55cc9cd8fc 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -64,6 +64,7 @@ export const CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT = new RawContextKey('debugSetVariableSupported', false); export const CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED = new RawContextKey('breakWhenValueChangesSupported', false); export const CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT = new RawContextKey('variableEvaluateNamePresent', false); +export const CONTEXT_EXCEPTION_WIDGET_VISIBLE = new RawContextKey('exceptionWidgetVisible', false); export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug'; export const BREAKPOINT_EDITOR_CONTRIBUTION_ID = 'editor.contrib.breakpoint'; @@ -935,6 +936,7 @@ export const enum BreakpointWidgetContext { export interface IDebugEditorContribution extends editorCommon.IEditorContribution { showHover(range: Range, focus: boolean): Promise; addLaunchConfiguration(): Promise; + closeExceptionWidget(): void; } export interface IBreakpointEditorContribution extends editorCommon.IEditorContribution {