From 038dc54910bdb828ca4075a300d39abbbe44abdb Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 25 Jul 2019 12:28:46 +0000 Subject: [PATCH] [debug] fix ##3807: added inline breakpoints support Signed-off-by: Anton Kosyakov --- .../browser/breakpoint/breakpoint-manager.ts | 13 +++- ...debug-frontend-application-contribution.ts | 61 ++++++++++++---- .../src/browser/debug-session-manager.ts | 17 ++++- packages/debug/src/browser/debug-session.tsx | 2 +- .../src/browser/editor/debug-editor-model.ts | 72 +++++++++++++------ .../browser/editor/debug-editor-service.ts | 19 +++++ .../browser/model/debug-source-breakpoint.tsx | 16 ++--- packages/debug/src/browser/style/index.css | 41 ++++++++--- .../src/main/browser/debug/debug-main.ts | 3 +- 9 files changed, 182 insertions(+), 62 deletions(-) diff --git a/packages/debug/src/browser/breakpoint/breakpoint-manager.ts b/packages/debug/src/browser/breakpoint/breakpoint-manager.ts index d6a4a81d6bc46..fdd7acac3f622 100644 --- a/packages/debug/src/browser/breakpoint/breakpoint-manager.ts +++ b/packages/debug/src/browser/breakpoint/breakpoint-manager.ts @@ -77,10 +77,17 @@ export class BreakpointManager extends MarkerManager { return result; } - getBreakpoint(uri: URI, line: number): SourceBreakpoint | undefined { - const marker = this.findMarkers({ + getLineBreakpoints(uri: URI, line: number): SourceBreakpoint[] { + return this.findMarkers({ uri, dataFilter: breakpoint => breakpoint.raw.line === line + }).map(({ data }) => data); + } + + getInlineBreakpoint(uri: URI, line: number, column: number): SourceBreakpoint | undefined { + const marker = this.findMarkers({ + uri, + dataFilter: breakpoint => breakpoint.raw.line === line && breakpoint.raw.column === column })[0]; return marker && marker.data; } @@ -96,7 +103,7 @@ export class BreakpointManager extends MarkerManager { addBreakpoint(breakpoint: SourceBreakpoint): boolean { const uri = new URI(breakpoint.uri); const breakpoints = this.getBreakpoints(uri); - const newBreakpoints = breakpoints.filter(({ raw }) => raw.line !== breakpoint.raw.line); + const newBreakpoints = breakpoints.filter(({ raw }) => !(raw.line === breakpoint.raw.line && raw.column === breakpoint.raw.column)); if (breakpoints.length === newBreakpoints.length) { newBreakpoints.push(breakpoint); this.setBreakpoints(uri, newBreakpoints); diff --git a/packages/debug/src/browser/debug-frontend-application-contribution.ts b/packages/debug/src/browser/debug-frontend-application-contribution.ts index b1f7e30688400..762e03b1da2ff 100644 --- a/packages/debug/src/browser/debug-frontend-application-contribution.ts +++ b/packages/debug/src/browser/debug-frontend-application-contribution.ts @@ -47,6 +47,7 @@ import { DebugWatchWidget } from './view/debug-watch-widget'; import { DebugWatchExpression } from './view/debug-watch-expression'; import { DebugWatchManager } from './debug-watch-manager'; import { DebugFunctionBreakpoint } from './model/debug-function-breakpoint'; +import { DebugBreakpoint } from './model/debug-breakpoint'; export namespace DebugMenus { export const DEBUG = [...MAIN_MENU_BAR, '6_debug']; @@ -54,7 +55,9 @@ export namespace DebugMenus { export const DEBUG_CONFIGURATION = [...DEBUG, 'b_configuration']; export const DEBUG_THREADS = [...DEBUG, 'c_threads']; export const DEBUG_SESSIONS = [...DEBUG, 'd_sessions']; - export const DEBUG_BREAKPOINTS = [...DEBUG, 'e_breakpoints']; + export const DEBUG_BREAKPOINT = [...DEBUG, 'e_breakpoint']; + export const DEBUG_NEW_BREAKPOINT = [...DEBUG_BREAKPOINT, 'a_new_breakpoint']; + export const DEBUG_BREAKPOINTS = [...DEBUG, 'f_breakpoints']; } export namespace DebugCommands { @@ -140,6 +143,11 @@ export namespace DebugCommands { category: DEBUG_CATEGORY, label: 'Toggle Breakpoint', }; + export const INLINE_BREAKPOINT: Command = { + id: 'editor.debug.action.inlineBreakpoint', + category: DEBUG_CATEGORY, + label: 'Inline Breakpoint', + }; export const ADD_CONDITIONAL_BREAKPOINT: Command = { id: 'debug.breakpoint.add.conditional', category: DEBUG_CATEGORY, @@ -503,8 +511,17 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi DebugCommands.CONTINUE_ALL, DebugCommands.PAUSE_ALL ); + registerMenuActions(DebugMenus.DEBUG_BREAKPOINT, + DebugCommands.TOGGLE_BREAKPOINT + ); + menus.registerSubmenu(DebugMenus.DEBUG_NEW_BREAKPOINT, 'New Breakpoint'); + registerMenuActions(DebugMenus.DEBUG_NEW_BREAKPOINT, + DebugCommands.ADD_CONDITIONAL_BREAKPOINT, + DebugCommands.INLINE_BREAKPOINT, + DebugCommands.ADD_FUNCTION_BREAKPOINT, + DebugCommands.ADD_LOGPOINT, + ); registerMenuActions(DebugMenus.DEBUG_BREAKPOINTS, - DebugCommands.TOGGLE_BREAKPOINT, DebugCommands.ENABLE_ALL_BREAKPOINTS, DebugCommands.DISABLE_ALL_BREAKPOINTS, DebugCommands.REMOVE_ALL_BREAKPOINTS @@ -718,6 +735,10 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi execute: () => this.editors.toggleBreakpoint(), isEnabled: () => !!this.editors.model }); + registry.registerCommand(DebugCommands.INLINE_BREAKPOINT, { + execute: () => this.editors.addInlineBreakpoint(), + isEnabled: () => !!this.editors.model && !this.editors.inlineBreakpoint + }); registry.registerCommand(DebugCommands.ADD_CONDITIONAL_BREAKPOINT, { execute: () => this.editors.addBreakpoint('condition'), isEnabled: () => !!this.editors.model && !this.editors.anyBreakpoint @@ -745,13 +766,15 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi }); registry.registerCommand(DebugCommands.EDIT_BREAKPOINT, { execute: async () => { - const { selectedBreakpoint } = this; + const { selectedBreakpoint, selectedFunctionBreakpoint } = this; if (selectedBreakpoint) { await this.editors.editBreakpoint(selectedBreakpoint); + } else if (selectedFunctionBreakpoint) { + await selectedFunctionBreakpoint.open(); } }, - isEnabled: () => !!this.selectedBreakpoint, - isVisible: () => !!this.selectedBreakpoint + isEnabled: () => !!this.selectedBreakpoint || !!this.selectedFunctionBreakpoint, + isVisible: () => !!this.selectedBreakpoint || !!this.selectedFunctionBreakpoint }); registry.registerCommand(DebugCommands.EDIT_LOGPOINT, { execute: async () => { @@ -765,13 +788,13 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi }); registry.registerCommand(DebugCommands.REMOVE_BREAKPOINT, { execute: () => { - const { selectedBreakpoint } = this; + const selectedBreakpoint = this.selectedBreakpoint || this.selectedFunctionBreakpoint; if (selectedBreakpoint) { selectedBreakpoint.remove(); } }, - isEnabled: () => !!this.selectedBreakpoint, - isVisible: () => !!this.selectedBreakpoint + isEnabled: () => !!this.selectedBreakpoint || !!this.selectedFunctionBreakpoint, + isVisible: () => !!this.selectedBreakpoint || !!this.selectedFunctionBreakpoint, }); registry.registerCommand(DebugCommands.REMOVE_LOGPOINT, { execute: () => { @@ -856,7 +879,7 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi isVisible: () => !this.editors.anyBreakpoint }); registry.registerCommand(DebugEditorContextCommands.REMOVE_BREAKPOINT, { - execute: () => this.editors.toggleBreakpoint(), + execute: () => this.editors.removeBreakpoint(), isEnabled: () => !!this.editors.breakpoint, isVisible: () => !!this.editors.breakpoint }); @@ -876,7 +899,7 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi isVisible: () => !!this.editors.breakpointEnabled }); registry.registerCommand(DebugEditorContextCommands.REMOVE_LOGPOINT, { - execute: () => this.editors.toggleBreakpoint(), + execute: () => this.editors.removeBreakpoint(), isEnabled: () => !!this.editors.logpoint, isVisible: () => !!this.editors.logpoint }); @@ -1018,6 +1041,11 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi keybinding: 'f9', context: EditorKeybindingContexts.editorTextFocus }); + keybindings.registerKeybinding({ + command: DebugCommands.INLINE_BREAKPOINT.id, + keybinding: 'shift+f9', + context: EditorKeybindingContexts.editorTextFocus + }); keybindings.registerKeybinding({ command: DebugBreakpointWidgetCommands.ACCEPT.id, @@ -1170,17 +1198,22 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi const { currentWidget } = this.shell; return currentWidget instanceof DebugBreakpointsWidget && currentWidget || undefined; } - get selectedAnyBreakpoint(): DebugSourceBreakpoint | undefined { + get selectedAnyBreakpoint(): DebugBreakpoint | undefined { const { breakpoints } = this; - return breakpoints && breakpoints.selectedElement instanceof DebugSourceBreakpoint && breakpoints.selectedElement || undefined; + const selectedElement = breakpoints && breakpoints.selectedElement; + return selectedElement instanceof DebugBreakpoint ? selectedElement : undefined; } get selectedBreakpoint(): DebugSourceBreakpoint | undefined { const breakpoint = this.selectedAnyBreakpoint; - return breakpoint && !breakpoint.logMessage ? breakpoint : undefined; + return breakpoint && breakpoint instanceof DebugSourceBreakpoint && !breakpoint.logMessage ? breakpoint : undefined; } get selectedLogpoint(): DebugSourceBreakpoint | undefined { const breakpoint = this.selectedAnyBreakpoint; - return breakpoint && !!breakpoint.logMessage ? breakpoint : undefined; + return breakpoint && breakpoint instanceof DebugSourceBreakpoint && !!breakpoint.logMessage ? breakpoint : undefined; + } + get selectedFunctionBreakpoint(): DebugFunctionBreakpoint | undefined { + const breakpoint = this.selectedAnyBreakpoint; + return breakpoint && breakpoint instanceof DebugFunctionBreakpoint ? breakpoint : undefined; } get variables(): DebugVariablesWidget | undefined { diff --git a/packages/debug/src/browser/debug-session-manager.ts b/packages/debug/src/browser/debug-session-manager.ts index 3d7eca4d2f79d..5856904e1df64 100644 --- a/packages/debug/src/browser/debug-session-manager.ts +++ b/packages/debug/src/browser/debug-session-manager.ts @@ -368,12 +368,23 @@ export class DebugSessionManager { return this.breakpoints.findMarkers({ uri }).map(({ data }) => new DebugSourceBreakpoint(data, { labelProvider, breakpoints, editorManager })); } - getBreakpoint(uri: URI, line: number): DebugSourceBreakpoint | undefined { + getLineBreakpoints(uri: URI, line: number): DebugSourceBreakpoint[] { const session = this.currentSession; if (session && session.state > DebugState.Initializing) { - return session.getSourceBreakpoints(uri).filter(breakpoint => breakpoint.line === line)[0]; + return session.getSourceBreakpoints(uri).filter(breakpoint => breakpoint.line === line); } - const origin = this.breakpoints.getBreakpoint(uri, line); + const { labelProvider, breakpoints, editorManager } = this; + return this.breakpoints.getLineBreakpoints(uri, line).map(origin => + new DebugSourceBreakpoint(origin, { labelProvider, breakpoints, editorManager }) + ); + } + + getInlineBreakpoint(uri: URI, line: number, column: number): DebugSourceBreakpoint | undefined { + const session = this.currentSession; + if (session && session.state > DebugState.Initializing) { + return session.getSourceBreakpoints(uri).filter(breakpoint => breakpoint.line === line && breakpoint.column === column)[0]; + } + const origin = this.breakpoints.getInlineBreakpoint(uri, line, column); const { labelProvider, breakpoints, editorManager } = this; return origin && new DebugSourceBreakpoint(origin, { labelProvider, breakpoints, editorManager }); } diff --git a/packages/debug/src/browser/debug-session.tsx b/packages/debug/src/browser/debug-session.tsx index b8f982aadc435..c38afbba36f1c 100644 --- a/packages/debug/src/browser/debug-session.tsx +++ b/packages/debug/src/browser/debug-session.tsx @@ -510,7 +510,7 @@ export class DebugSession implements CompositeTreeElement { if (body.reason === 'new') { if (raw.source && typeof raw.line === 'number') { const uri = DebugSource.toUri(raw.source); - const origin = SourceBreakpoint.create(uri, { line: raw.line, column: 1 }); + const origin = SourceBreakpoint.create(uri, { line: raw.line, column: raw.column }); if (this.breakpoints.addBreakpoint(origin)) { const breakpoints = this.getSourceBreakpoints(uri); const breakpoint = new DebugSourceBreakpoint(origin, this.asDebugBreakpointOptions()); diff --git a/packages/debug/src/browser/editor/debug-editor-model.ts b/packages/debug/src/browser/editor/debug-editor-model.ts index 4f664c2c766b1..4ef07e9cba3a7 100644 --- a/packages/debug/src/browser/editor/debug-editor-model.ts +++ b/packages/debug/src/browser/editor/debug-editor-model.ts @@ -27,6 +27,7 @@ import { DebugEditor } from './debug-editor'; import { DebugHoverWidget, createDebugHoverWidgetContainer } from './debug-hover-widget'; import { DebugBreakpointWidget } from './debug-breakpoint-widget'; import { DebugExceptionWidget } from './debug-exception-widget'; +import { DebugProtocol } from 'vscode-debugprotocol'; export const DebugEditorModelFactory = Symbol('DebugEditorModelFactory'); export type DebugEditorModelFactory = (editor: DebugEditor) => DebugEditorModel; @@ -192,7 +193,8 @@ export class DebugEditorModel implements Disposable { } protected createBreakpointDecoration(breakpoint: SourceBreakpoint): monaco.editor.IModelDeltaDecoration { const lineNumber = breakpoint.raw.line; - const range = new monaco.Range(lineNumber, 1, lineNumber, 2); + const column = breakpoint.raw.column; + const range = typeof column === 'number' ? new monaco.Range(lineNumber, column, lineNumber, column + 1) : new monaco.Range(lineNumber, 1, lineNumber, 2); return { range, options: { @@ -218,14 +220,16 @@ export class DebugEditorModel implements Disposable { } protected createCurrentBreakpointDecoration(breakpoint: DebugSourceBreakpoint): monaco.editor.IModelDeltaDecoration { const lineNumber = breakpoint.line; - const range = new monaco.Range(lineNumber, 1, lineNumber, 1); + const column = breakpoint.column; + const range = typeof column === 'number' ? new monaco.Range(lineNumber, column, lineNumber, column + 1) : new monaco.Range(lineNumber, 1, lineNumber, 1) const { className, message } = breakpoint.getDecoration(); return { range, options: { glyphMarginClassName: className, glyphMarginHoverMessage: message.map(value => ({ value })), - stickiness: DebugEditorModel.STICKINESS + stickiness: DebugEditorModel.STICKINESS, + beforeContentClassName: typeof column === 'number' ? `theia-debug-breakpoint-column ${className}-column` : undefined } }; } @@ -257,9 +261,10 @@ export class DebugEditorModel implements Disposable { const range = this.editor.getControl().getModel().getDecorationRange(decoration); if (range && !lines.has(range.startLineNumber)) { const line = range.startLineNumber; + const column = range.startColumn; const oldRange = this.breakpointRanges.get(decoration); - const oldBreakpoint = oldRange && this.breakpoints.getBreakpoint(uri, oldRange.startLineNumber); - const breakpoint = SourceBreakpoint.create(uri, { line, column: 1 }, oldBreakpoint); + const oldBreakpoint = oldRange && this.breakpoints.getInlineBreakpoint(uri, oldRange.startLineNumber, oldRange.startColumn); + const breakpoint = SourceBreakpoint.create(uri, { line, column }, oldBreakpoint); breakpoints.push(breakpoint); lines.add(line); } @@ -271,39 +276,62 @@ export class DebugEditorModel implements Disposable { get position(): monaco.Position { return this._position || this.editor.getControl().getPosition(); } + get breakpoint(): DebugSourceBreakpoint | undefined { - return this.getBreakpoint(); + return this.inlineBreakpoint || this.getLineBreakpoints()[0]; } - protected getBreakpoint(position: monaco.Position = this.position) { - return this.sessions.getBreakpoint(this.uri, position.lineNumber); + + get inlineBreakpoint(): DebugSourceBreakpoint | undefined { + return this.getInlineBreakpoint(); + } + + protected getInlineBreakpoint(position: monaco.Position = this.position): DebugSourceBreakpoint | undefined { + return this.sessions.getInlineBreakpoint(this.uri, position.lineNumber, position.column); + } + + protected getLineBreakpoints(position: monaco.Position = this.position): DebugSourceBreakpoint[] { + return this.sessions.getLineBreakpoints(this.uri, position.lineNumber); + } + + protected addBreakpoint(raw: DebugProtocol.SourceBreakpoint): void { + this.breakpoints.addBreakpoint(SourceBreakpoint.create(this.uri, raw)); } + toggleBreakpoint(): void { this.doToggleBreakpoint(); } protected doToggleBreakpoint(position: monaco.Position = this.position) { - const breakpoint = this.getBreakpoint(position); - if (breakpoint) { - breakpoint.remove(); + const { lineNumber } = position; + const breakpoints = this.getLineBreakpoints(position); + if (breakpoints.length) { + for (const breakpoint of breakpoints) { + breakpoint.remove(); + } } else { - this.breakpoints.addBreakpoint(SourceBreakpoint.create(this.uri, { - line: position.lineNumber, - column: 1 - })); + this.addBreakpoint({ line: lineNumber }); + } + } + + addInlineBreakpoint(): void { + const { position } = this; + const { lineNumber, column } = position; + const breakpoint = this.getInlineBreakpoint(position); + if (breakpoint) { + return; } + this.addBreakpoint({ line: lineNumber, column }); } acceptBreakpoint(): void { const { position, values } = this.breakpointWidget; if (position && values) { - const breakpoint = this.getBreakpoint(position); + const breakpoint = position.column > 0 ? this.getInlineBreakpoint(position) : this.getLineBreakpoints(position)[0]; if (breakpoint) { breakpoint.updateOrigins(values); } else { - this.breakpoints.addBreakpoint(SourceBreakpoint.create(this.uri, { - line: position.lineNumber, - column: 1, - ...values - })); + const { lineNumber } = position; + const column = position.column > 0 ? position.column : undefined; + this.addBreakpoint({ line: lineNumber, column, ...values }); } this.breakpointWidget.hide(); } @@ -342,7 +370,7 @@ export class DebugEditorModel implements Disposable { protected createHintDecorations(event: monaco.editor.IEditorMouseEvent): monaco.editor.IModelDeltaDecoration[] { if (event.target && event.target.type === monaco.editor.MouseTargetType.GUTTER_GLYPH_MARGIN) { const lineNumber = event.target.position.lineNumber; - if (!!this.sessions.getBreakpoint(this.uri, lineNumber)) { + if (this.getLineBreakpoints(event.target.position).length) { return []; } return [{ diff --git a/packages/debug/src/browser/editor/debug-editor-service.ts b/packages/debug/src/browser/editor/debug-editor-service.ts index bd3c73624688b..916ab0c134442 100644 --- a/packages/debug/src/browser/editor/debug-editor-service.ts +++ b/packages/debug/src/browser/editor/debug-editor-service.ts @@ -102,6 +102,10 @@ export class DebugEditorService { return breakpoint && breakpoint.enabled; } + get inlineBreakpoint(): DebugSourceBreakpoint | undefined { + return this.model && this.model.inlineBreakpoint; + } + get anyBreakpoint(): DebugSourceBreakpoint | undefined { return this.model && this.model.breakpoint; } @@ -112,6 +116,14 @@ export class DebugEditorService { model.toggleBreakpoint(); } } + + removeBreakpoint(): void { + const { anyBreakpoint } = this; + if (anyBreakpoint) { + anyBreakpoint.remove(); + } + } + setBreakpointEnabled(enabled: boolean): void { const { anyBreakpoint } = this; if (anyBreakpoint) { @@ -119,6 +131,13 @@ export class DebugEditorService { } } + addInlineBreakpoint(): void { + const { model } = this; + if (model) { + model.addInlineBreakpoint(); + } + } + showHover(): void { const { model } = this; if (model) { diff --git a/packages/debug/src/browser/model/debug-source-breakpoint.tsx b/packages/debug/src/browser/model/debug-source-breakpoint.tsx index 7ee0c9c576e7d..294c615d86bca 100644 --- a/packages/debug/src/browser/model/debug-source-breakpoint.tsx +++ b/packages/debug/src/browser/model/debug-source-breakpoint.tsx @@ -49,14 +49,14 @@ export class DebugSourceBreakpoint extends DebugBreakpoint imp setEnabled(enabled: boolean): void { const { uri, raw } = this; let shouldUpdate = false; - let breakpoints = raw && this.doRemove(this.origins.filter(origin => origin.raw.line !== raw.line)); + let breakpoints = raw && this.doRemove(this.origins.filter(origin => !(origin.raw.line === raw.line && origin.raw.column === raw.column))); if (breakpoints) { shouldUpdate = true; } else { breakpoints = this.breakpoints.getBreakpoints(uri); } for (const breakpoint of breakpoints) { - if (breakpoint.raw.line === this.origin.raw.line && breakpoint.enabled !== enabled) { + if (breakpoint.raw.line === this.origin.raw.line && breakpoint.raw.column === this.origin.raw.column && breakpoint.enabled !== enabled) { breakpoint.enabled = enabled; shouldUpdate = true; } @@ -69,10 +69,10 @@ export class DebugSourceBreakpoint extends DebugBreakpoint imp updateOrigins(data: Partial): void { const breakpoints = this.breakpoints.getBreakpoints(this.uri); let shouldUpdate = false; - const originLines = new Set(); - this.origins.forEach(origin => originLines.add(origin.raw.line)); + const originPositions = new Set(); + this.origins.forEach(origin => originPositions.add(origin.raw.line + ':' + origin.raw.column)); for (const breakpoint of breakpoints) { - if (originLines.has(breakpoint.raw.line)) { + if (originPositions.has(breakpoint.raw.line + ':' + breakpoint.raw.column)) { Object.assign(breakpoint.raw, data); shouldUpdate = true; } @@ -149,7 +149,7 @@ export class DebugSourceBreakpoint extends DebugBreakpoint imp {this.labelProvider.getName(this.uri)} {this.labelProvider.getLongName(this.uri.parent)} - {this.line} + {this.line}{typeof this.column === 'number' ? ':' + this.column : ''} ; } @@ -216,12 +216,12 @@ export class DebugSourceBreakpoint extends DebugBreakpoint imp } const { uri } = this; const toRemove = new Set(); - origins.forEach(origin => toRemove.add(origin.raw.line)); + origins.forEach(origin => toRemove.add(origin.raw.line + ':' + origin.raw.column)); let shouldUpdate = false; const breakpoints = this.breakpoints.findMarkers({ uri, dataFilter: data => { - const result = !toRemove.has(data.raw.line); + const result = !toRemove.has(data.raw.line + ':' + data.raw.column); shouldUpdate = shouldUpdate || !result; return result; } diff --git a/packages/debug/src/browser/style/index.css b/packages/debug/src/browser/style/index.css index 97c4a56165b87..ff74ae51eca00 100644 --- a/packages/debug/src/browser/style/index.css +++ b/packages/debug/src/browser/style/index.css @@ -214,36 +214,46 @@ margin-left: 0px !important; } -.theia-debug-breakpoint { +.theia-debug-breakpoint, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-breakpoint-column::before { background: url('breakpoint.svg') center center no-repeat; } -.theia-debug-breakpoint-disabled { +.theia-debug-breakpoint-disabled, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-breakpoint-disabled-column::before { background: url('breakpoint-disabled.svg') center center no-repeat; } -.theia-debug-breakpoint-unverified { +.theia-debug-breakpoint-unverified, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-breakpoint-unverified-column::before { background: url('breakpoint-unverified.svg') center center no-repeat; } -.theia-debug-breakpoint-unsupported { +.theia-debug-breakpoint-unsupported, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-breakpoint-unsupported-column::before { background: url('breakpoint-unsupported.svg') center center no-repeat; } -.theia-debug-conditional-breakpoint { +.theia-debug-conditional-breakpoint, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-conditional-breakpoint-column::before { background: url('breakpoint-conditional.svg') center center no-repeat; } -.theia-debug-conditional-breakpoint-disabled { +.theia-debug-conditional-breakpoint-disabled, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-conditional-breakpoint-disabled-column::before { background: url('breakpoint-conditional-disabled.svg') center center no-repeat; } -.theia-debug-conditional-breakpoint-unverified { +.theia-debug-conditional-breakpoint-unverified, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-conditional-breakpoint-unverified-column::before { background: url('breakpoint-conditional-unverified.svg') center center no-repeat; } -.theia-debug-logpoint { +.theia-debug-logpoint, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-logpoint-column::before { background: url('breakpoint-log.svg') center center no-repeat; } -.theia-debug-logpoint-disabled { +.theia-debug-logpoint-disabled, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-logpoint-disabled-column::before { background: url('breakpoint-log-disabled.svg') center center no-repeat; } -.theia-debug-logpoint-unverified { +.theia-debug-logpoint-unverified, +.monaco-editor .theia-debug-breakpoint-column.theia-debug-logpoint-unverified-column::before { background: url('breakpoint-log-unverified.svg') center center no-repeat; } @@ -283,6 +293,17 @@ background: #7abd7a4d; } +.monaco-editor .theia-debug-breakpoint-column::before +.monaco-editor .theia-debug-top-stack-frame-column::before { + content: " "; + width: 1.3em; + height: 1.3em; + display: inline-block; + vertical-align: text-bottom; + margin-right: 2px; + margin-left: 2px; +} + /** Toolbars */ .theia-debug-configure { diff --git a/packages/plugin-ext/src/main/browser/debug/debug-main.ts b/packages/plugin-ext/src/main/browser/debug/debug-main.ts index fdd77b010e47f..f7c593b60012f 100644 --- a/packages/plugin-ext/src/main/browser/debug/debug-main.ts +++ b/packages/plugin-ext/src/main/browser/debug/debug-main.ts @@ -183,13 +183,14 @@ export class DebugMainImpl implements DebugMain { for (const breakpoint of newBreakpoints.values()) { if (breakpoint.location) { const location = breakpoint.location; + const column = breakpoint.location.range.startColumn; this.breakpointsManager.addBreakpoint({ id: breakpoint.id, uri: Uri.revive(location.uri).toString(), enabled: breakpoint.enabled, raw: { line: breakpoint.location.range.startLineNumber + 1, - column: 1, + column: column > 0 ? column + 1 : undefined, condition: breakpoint.condition, hitCondition: breakpoint.hitCondition, logMessage: breakpoint.logMessage