Skip to content

Commit

Permalink
breakpoints: interaction on inline breakpoint decorations
Browse files Browse the repository at this point in the history
  • Loading branch information
isidorn committed Sep 17, 2019
1 parent a8d5382 commit 9e3d285
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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.$;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -208,17 +207,17 @@ class BreakpointEditorContribution implements IBreakpointEditorContribution {
this.toDispose.push(this.editor.onDidChangeModelDecorations(() => this.onModelDecorationsChanged()));
}

private getContextMenuActions(breakpoints: ReadonlyArray<IBreakpoint>, uri: uri, lineNumber: number): Array<IAction | ContextSubMenu> {
private getContextMenuActions(breakpoints: ReadonlyArray<IBreakpoint>, uri: uri, lineNumber: number, column?: number): Array<IAction | ContextSubMenu> {
const actions: Array<IAction | ContextSubMenu> = [];
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(
Expand All @@ -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))
)
)));

Expand All @@ -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',
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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<IAction | ContextSubMenu>
) {
this.range = this.editor.getModel().getDecorationRange(decorationId);
this.toDispose.push(this.editor.onDidChangeModelDecorations(() => {
Expand All @@ -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
Expand Down
11 changes: 6 additions & 5 deletions src/vs/workbench/contrib/debug/browser/breakpointWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<IPrivateBreakpointWidgetService>('privateBreakopintWidgetService');
const IPrivateBreakpointWidgetService = createDecorator<IPrivateBreakpointWidgetService>('privateBreakpointWidgetService');
export interface IPrivateBreakpointWidgetService {
_serviceBrand: undefined;
close(success: boolean): void;
Expand All @@ -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,
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/debug/browser/breakpointsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export class BreakpointsView extends ViewletPanel {
if (editor) {
const codeEditor = editor.getControl();
if (isCodeEditor(codeEditor)) {
codeEditor.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(element.lineNumber);
codeEditor.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(element.lineNumber, element.column);
}
}
});
Expand All @@ -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));
Expand Down
6 changes: 3 additions & 3 deletions src/vs/workbench/contrib/debug/browser/debugActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class ConditionalBreakpointAction extends EditorAction {

const position = editor.getPosition();
if (position && editor.hasModel() && debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
editor.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(position.lineNumber);
editor.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(position.lineNumber, undefined);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/debug/common/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 9e3d285

Please sign in to comment.