From 9e3d285def2dd99623226e1479309d47522b97eb Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 17 Sep 2019 15:48:00 +0200 Subject: [PATCH] breakpoints: interaction on inline breakpoint decorations --- .../browser/breakpointEditorContribution.ts | 62 ++++++++++++++----- .../contrib/debug/browser/breakpointWidget.ts | 11 ++-- .../contrib/debug/browser/breakpointsView.ts | 4 +- .../contrib/debug/browser/debugActions.ts | 6 +- .../debug/browser/debugEditorActions.ts | 2 +- .../workbench/contrib/debug/common/debug.ts | 2 +- 6 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts index 53be1139b22..8b613a2058a 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts @@ -19,7 +19,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { RemoveBreakpointAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, BreakpointWidgetContext, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug'; import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ContextSubMenu } from 'vs/base/browser/contextmenu'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { BreakpointWidget } from 'vs/workbench/contrib/debug/browser/breakpointWidget'; @@ -28,6 +27,7 @@ import { MarkdownString } from 'vs/base/common/htmlContent'; import { getBreakpointMessageAndClassName } from 'vs/workbench/contrib/debug/browser/breakpointsView'; import { generateUuid } from 'vs/base/common/uuid'; import { memoize } from 'vs/base/common/decorators'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; const $ = dom.$; @@ -100,7 +100,6 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution { @IContextMenuService private readonly contextMenuService: IContextMenuService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextKeyService contextKeyService: IContextKeyService, - @IKeybindingService private readonly keybindingService: IKeybindingService, @IDialogService private readonly dialogService: IDialogService, ) { this.breakpointWidgetVisible = CONTEXT_BREAKPOINT_WIDGET_VISIBLE.bindTo(contextKeyService); @@ -208,17 +207,17 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution { this.toDispose.push(this.editor.onDidChangeModelDecorations(() => this.onModelDecorationsChanged())); } - private getContextMenuActions(breakpoints: ReadonlyArray, uri: uri, lineNumber: number): Array { + private getContextMenuActions(breakpoints: ReadonlyArray, uri: uri, lineNumber: number, column?: number): Array { const actions: Array = []; if (breakpoints.length === 1) { const breakpointType = breakpoints[0].logMessage ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint"); - actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService, this.keybindingService)); + actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService)); actions.push(new Action( 'workbench.debug.action.editBreakpointAction', nls.localize('editBreakpoint', "Edit {0}...", breakpointType), undefined, true, - () => Promise.resolve(this.showBreakpointWidget(breakpoints[0].lineNumber)) + () => Promise.resolve(this.showBreakpointWidget(breakpoints[0].lineNumber, breakpoints[0].column)) )); actions.push(new Action( @@ -243,7 +242,7 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution { bp.column ? nls.localize('editInlineBreakpointOnColumn', "Edit Inline Breakpoint on Column {0}", bp.column) : nls.localize('editLineBrekapoint', "Edit Line Breakpoint"), undefined, true, - () => Promise.resolve(this.showBreakpointWidget(bp.lineNumber)) + () => Promise.resolve(this.showBreakpointWidget(bp.lineNumber, bp.column)) ) ))); @@ -261,14 +260,14 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution { nls.localize('addBreakpoint', "Add Breakpoint"), undefined, true, - () => this.debugService.addBreakpoints(uri, [{ lineNumber }], `debugEditorContextMenu`) + () => this.debugService.addBreakpoints(uri, [{ lineNumber, column }], `debugEditorContextMenu`) )); actions.push(new Action( 'addConditionalBreakpoint', nls.localize('addConditionalBreakpoint', "Add Conditional Breakpoint..."), undefined, true, - () => Promise.resolve(this.showBreakpointWidget(lineNumber)) + () => Promise.resolve(this.showBreakpointWidget(lineNumber, column)) )); actions.push(new Action( 'addLogPoint', @@ -330,12 +329,20 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution { bpd.inlineWidget.dispose(); } }); - this.breakpointDecorations = decorationIds.map((decorationId, index) => ({ - decorationId, - breakpointId: breakpoints[index].getId(), - range: desiredDecorations[index].range, - inlineWidget: breakpoints[index].column ? new InlineBreakpointWidget(activeCodeEditor, decorationId, desiredDecorations[index].options.glyphMarginClassName) : undefined - })); + this.breakpointDecorations = decorationIds.map((decorationId, index) => { + let inlineWidget: InlineBreakpointWidget | undefined = undefined; + const breakpoint = breakpoints[index]; + if (breakpoint.column) { + inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, desiredDecorations[index].options.glyphMarginClassName, breakpoint, this.debugService, this.contextMenuService, () => this.getContextMenuActions([breakpoint], activeCodeEditor.getModel().uri, breakpoint.lineNumber, breakpoint.column)); + } + + return { + decorationId, + breakpointId: breakpoint.getId(), + range: desiredDecorations[index].range, + inlineWidget + }; + }); } finally { this.ignoreDecorationsChangedEvent = false; } @@ -389,13 +396,13 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution { } // breakpoint widget - showBreakpointWidget(lineNumber: number, context?: BreakpointWidgetContext): void { + showBreakpointWidget(lineNumber: number, column: number | undefined, context?: BreakpointWidgetContext): void { if (this.breakpointWidget) { this.breakpointWidget.dispose(); } - this.breakpointWidget = this.instantiationService.createInstance(BreakpointWidget, this.editor, lineNumber, context); - this.breakpointWidget.show({ lineNumber, column: 1 }, 2); + this.breakpointWidget = this.instantiationService.createInstance(BreakpointWidget, this.editor, lineNumber, column, context); + this.breakpointWidget.show({ lineNumber, column: 1 }); this.breakpointWidgetVisible.set(true); } @@ -431,6 +438,10 @@ class InlineBreakpointWidget implements IContentWidget, IDisposable { private readonly editor: IActiveCodeEditor, private readonly decorationId: string, cssClass: string | null | undefined, + private readonly breakpoint: IBreakpoint | undefined, + private readonly debugService: IDebugService, + private readonly contextMenuService: IContextMenuService, + private readonly getContextMenuActions: () => ReadonlyArray ) { this.range = this.editor.getModel().getDecorationRange(decorationId); this.toDispose.push(this.editor.onDidChangeModelDecorations(() => { @@ -452,6 +463,23 @@ class InlineBreakpointWidget implements IContentWidget, IDisposable { if (cssClass) { this.domNode.classList.add(cssClass); } + this.toDispose.push(dom.addDisposableListener(this.domNode, dom.EventType.CLICK, async e => { + if (this.breakpoint) { + await this.debugService.removeBreakpoints(this.breakpoint.getId()); + } else { + await this.debugService.addBreakpoints(this.editor.getModel().uri, [{ lineNumber: this.range!.startLineNumber, column: this.range!.startColumn }], 'debugEditorInlineWidget'); + } + })); + this.toDispose.push(dom.addDisposableListener(this.domNode, dom.EventType.CONTEXT_MENU, async e => { + const event = new StandardMouseEvent(e); + const anchor = { x: event.posx, y: event.posy }; + + this.contextMenuService.showContextMenu({ + getAnchor: () => anchor, + getActions: () => this.getContextMenuActions(), + getActionsContext: () => this.breakpoint + }); + })); } @memoize diff --git a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts index 52dda729604..85f2ac93bf1 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts @@ -37,7 +37,7 @@ import { IRange, Range } from 'vs/editor/common/core/range'; import { onUnexpectedError } from 'vs/base/common/errors'; const $ = dom.$; -const IPrivateBreakpointWidgetService = createDecorator('privateBreakopintWidgetService'); +const IPrivateBreakpointWidgetService = createDecorator('privateBreakpointWidgetService'); export interface IPrivateBreakpointWidgetService { _serviceBrand: undefined; close(success: boolean): void; @@ -55,7 +55,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi private logMessageInput = ''; private breakpoint: IBreakpoint | undefined; - constructor(editor: ICodeEditor, private lineNumber: number, private context: Context, + constructor(editor: ICodeEditor, private lineNumber: number, private column: number | undefined, private context: Context, @IContextViewService private readonly contextViewService: IContextViewService, @IDebugService private readonly debugService: IDebugService, @IThemeService private readonly themeService: IThemeService, @@ -70,7 +70,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi const model = this.editor.getModel(); if (model) { const uri = model.uri; - const breakpoints = this.debugService.getModel().getBreakpoints({ lineNumber: this.lineNumber, uri }); + const breakpoints = this.debugService.getModel().getBreakpoints({ lineNumber: this.lineNumber, column: this.column, uri }); this.breakpoint = breakpoints.length ? breakpoints[0] : undefined; } @@ -130,12 +130,12 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi } } - show(rangeOrPos: IRange | IPosition, heightInLines: number) { + show(rangeOrPos: IRange | IPosition): void { const lineNum = this.input.getModel().getLineCount(); super.show(rangeOrPos, lineNum + 1); } - fitHeightToContent() { + fitHeightToContent(): void { const lineNum = this.input.getModel().getLineCount(); this._relayout(lineNum + 1); } @@ -293,6 +293,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi if (model) { this.debugService.addBreakpoints(model.uri, [{ lineNumber: this.lineNumber, + column: this.column, enabled: true, condition, hitCondition, diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 9db0d99399e..1eafaff8e61 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -167,7 +167,7 @@ export class BreakpointsView extends ViewletPanel { if (editor) { const codeEditor = editor.getControl(); if (isCodeEditor(codeEditor)) { - codeEditor.getContribution(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(element.lineNumber); + codeEditor.getContribution(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(element.lineNumber, element.column); } } }); @@ -180,7 +180,7 @@ export class BreakpointsView extends ViewletPanel { actions.push(new Separator()); } - actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService, this.keybindingService)); + actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService)); if (this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getFunctionBreakpoints().length > 1) { actions.push(new RemoveAllBreakpointsAction(RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL, this.debugService, this.keybindingService)); diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index 5d71d9aa40f..cc4091769a1 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -181,12 +181,12 @@ export class SelectAndStartAction extends AbstractDebugAction { } } -export class RemoveBreakpointAction extends AbstractDebugAction { +export class RemoveBreakpointAction extends Action { static readonly ID = 'workbench.debug.viewlet.action.removeBreakpoint'; static LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint"); - constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) { - super(id, label, 'debug-action remove', debugService, keybindingService); + constructor(id: string, label: string, @IDebugService private readonly debugService: IDebugService) { + super(id, label, 'debug-action remove'); } public run(breakpoint: IBreakpoint): Promise { diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts index 7b40caea504..784694a387a 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorActions.ts @@ -75,7 +75,7 @@ class ConditionalBreakpointAction extends EditorAction { const position = editor.getPosition(); if (position && editor.hasModel() && debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) { - editor.getContribution(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(position.lineNumber); + editor.getContribution(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(position.lineNumber, undefined); } } } diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 748f0b389b7..a531f430188 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -855,7 +855,7 @@ export interface IDebugEditorContribution extends IEditorContribution { } export interface IBreakpointEditorContribution extends IEditorContribution { - showBreakpointWidget(lineNumber: number, context?: BreakpointWidgetContext): void; + showBreakpointWidget(lineNumber: number, column: number | undefined, context?: BreakpointWidgetContext): void; closeBreakpointWidget(): void; } -- GitLab