Skip to content

Commit

Permalink
WIP fix #3312: complete support of source breakpoints
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <[email protected]>
  • Loading branch information
akosyakov committed Jan 2, 2019
1 parent ec797b0 commit f2bade6
Show file tree
Hide file tree
Showing 20 changed files with 834 additions and 73 deletions.
10 changes: 4 additions & 6 deletions packages/debug/src/browser/breakpoint/breakpoint-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
********************************************************************************/

import { injectable, inject } from 'inversify';
import { DebugProtocol } from 'vscode-debugprotocol';
import { StorageService } from '@theia/core/lib/browser';
import { MarkerManager } from '@theia/markers/lib/browser/marker-manager';
import URI from '@theia/core/lib/common/uri';
Expand Down Expand Up @@ -48,17 +49,14 @@ export class BreakpointManager extends MarkerManager<SourceBreakpoint> {
this.setMarkers(uri, this.owner, breakpoints.sort((a, b) => a.raw.line - b.raw.line));
}

addBreakpoint(uri: URI, line: number, column?: number): void {
addBreakpoint(uri: URI, data: DebugProtocol.SourceBreakpoint): void {
const breakpoints = this.getBreakpoints(uri);
const newBreakpoints = breakpoints.filter(({ raw }) => raw.line !== line);
const newBreakpoints = breakpoints.filter(({ raw }) => raw.line !== data.line);
if (breakpoints.length === newBreakpoints.length) {
newBreakpoints.push({
uri: uri.toString(),
enabled: true,
raw: {
line,
column
}
raw: data
});
this.setBreakpoints(uri, newBreakpoints);
}
Expand Down
178 changes: 172 additions & 6 deletions packages/debug/src/browser/debug-frontend-application-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ export namespace DebugCommands {
category: DEBUG_CATEGORY,
label: 'Toggle Breakpoint',
};
export const ADD_CONDITIONAL_BREAKPOINT: Command = {
id: 'debug.breakpoint.add.conditional',
category: DEBUG_CATEGORY,
label: 'Add Conditional Breakpoint...',
};
export const ADD_LOGPOINT: Command = {
id: 'debug.breakpoint.add.logpoint',
category: DEBUG_CATEGORY,
label: 'Add Logpoint...',
};
export const ENABLE_ALL_BREAKPOINTS: Command = {
id: 'debug.breakpoint.enableAll',
category: DEBUG_CATEGORY,
Expand All @@ -143,11 +153,26 @@ export namespace DebugCommands {
category: DEBUG_CATEGORY,
label: 'Disable All Breakpoints',
};
export const EDIT_BREAKPOINT: Command = {
id: 'debug.breakpoint.edit',
category: DEBUG_CATEGORY,
label: 'Edit Breakpoint...',
};
export const EDIT_LOGPOINT: Command = {
id: 'debug.logpoint.edit',
category: DEBUG_CATEGORY,
label: 'Edit Logpoint...',
};
export const REMOVE_BREAKPOINT: Command = {
id: 'debug.breakpoint.remove',
category: DEBUG_CATEGORY,
label: 'Remove Breakpoint',
};
export const REMOVE_LOGPOINT: Command = {
id: 'debug.logpoint.remove',
category: DEBUG_CATEGORY,
label: 'Remove Logpoint',
};
export const REMOVE_ALL_BREAKPOINTS: Command = {
id: 'debug.breakpoint.removeAll',
category: DEBUG_CATEGORY,
Expand Down Expand Up @@ -235,15 +260,44 @@ export namespace DebugEditorContextCommands {
export const ADD_BREAKPOINT = {
id: 'debug.editor.context.addBreakpoint'
};
export const ADD_CONDITIONAL_BREAKPOINT = {
id: 'debug.editor.context.addBreakpoint.conditional'
};
export const ADD_LOGPOINT = {
id: 'debug.editor.context.add.logpoint'
};
export const REMOVE_BREAKPOINT = {
id: 'debug.editor.context.removeBreakpoint'
};
export const EDIT_BREAKPOINT = {
id: 'debug.editor.context.edit.breakpoint'
};
export const ENABLE_BREAKPOINT = {
id: 'debug.editor.context.enableBreakpoint'
};
export const DISABLE_BREAKPOINT = {
id: 'debug.editor.context.disableBreakpoint'
};
export const REMOVE_LOGPOINT = {
id: 'debug.editor.context.logpoint.remove'
};
export const EDIT_LOGPOINT = {
id: 'debug.editor.context.logpoint.edit'
};
export const ENABLE_LOGPOINT = {
id: 'debug.editor.context.logpoint.enable'
};
export const DISABLE_LOGPOINT = {
id: 'debug.editor.context.logpoint.disable'
};
}
export namespace DebugBreakpointWidgetCommands {
export const ACCEPT = {
id: 'debug.breakpointWidget.accept'
};
export const CLOSE = {
id: 'debug.breakpointWidget.close'
};
}

const darkCss = require('../../src/browser/style/debug-dark.useable.css');
Expand Down Expand Up @@ -421,8 +475,13 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi
DebugCommands.COPY_VAIRABLE_AS_EXPRESSION
);

registerMenuActions(DebugBreakpointsWidget.EDIT_MENU,
DebugCommands.EDIT_BREAKPOINT,
DebugCommands.EDIT_LOGPOINT
);
registerMenuActions(DebugBreakpointsWidget.REMOVE_MENU,
DebugCommands.REMOVE_BREAKPOINT,
DebugCommands.REMOVE_LOGPOINT,
DebugCommands.REMOVE_ALL_BREAKPOINTS
);
registerMenuActions(DebugBreakpointsWidget.ENABLE_MENU,
Expand All @@ -432,9 +491,16 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi

registerMenuActions(DebugEditorModel.CONTEXT_MENU,
{ ...DebugEditorContextCommands.ADD_BREAKPOINT, label: 'Add Breakpoint' },
{ ...DebugEditorContextCommands.REMOVE_BREAKPOINT, label: 'Remove Breakpoint' },
{ ...DebugEditorContextCommands.ADD_CONDITIONAL_BREAKPOINT, label: DebugCommands.ADD_CONDITIONAL_BREAKPOINT.label },
{ ...DebugEditorContextCommands.ADD_LOGPOINT, label: DebugCommands.ADD_LOGPOINT.label },
{ ...DebugEditorContextCommands.REMOVE_BREAKPOINT, label: DebugCommands.REMOVE_BREAKPOINT.label },
{ ...DebugEditorContextCommands.EDIT_BREAKPOINT, label: DebugCommands.EDIT_BREAKPOINT.label },
{ ...DebugEditorContextCommands.ENABLE_BREAKPOINT, label: 'Enable Breakpoint' },
{ ...DebugEditorContextCommands.DISABLE_BREAKPOINT, label: 'Disable Breakpoint' }
{ ...DebugEditorContextCommands.DISABLE_BREAKPOINT, label: 'Disable Breakpoint' },
{ ...DebugEditorContextCommands.REMOVE_LOGPOINT, label: DebugCommands.REMOVE_LOGPOINT.label },
{ ...DebugEditorContextCommands.EDIT_LOGPOINT, label: DebugCommands.EDIT_LOGPOINT.label },
{ ...DebugEditorContextCommands.ENABLE_LOGPOINT, label: 'Enable Logpoint' },
{ ...DebugEditorContextCommands.DISABLE_LOGPOINT, label: 'Disable Logpoint' }
);
}

Expand Down Expand Up @@ -573,6 +639,14 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi
execute: () => this.editors.toggleBreakpoint(),
isEnabled: () => !!this.editors.model
});
registry.registerCommand(DebugCommands.ADD_CONDITIONAL_BREAKPOINT, {
execute: () => this.editors.addBreakpoint('condition'),
isEnabled: () => !!this.editors.model && !this.editors.anyBreakpoint
});
registry.registerCommand(DebugCommands.ADD_LOGPOINT, {
execute: () => this.editors.addBreakpoint('logMessage'),
isEnabled: () => !!this.editors.model && !this.editors.anyBreakpoint
});
registry.registerCommand(DebugCommands.ENABLE_ALL_BREAKPOINTS, {
execute: () => this.breakpointManager.enableAllBreakpoints(true),
isEnabled: () => !!this.breakpointManager.getUris().next().value
Expand All @@ -581,14 +655,45 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi
execute: () => this.breakpointManager.enableAllBreakpoints(false),
isEnabled: () => !!this.breakpointManager.getUris().next().value
});
registry.registerCommand(DebugCommands.EDIT_BREAKPOINT, {
execute: async () => {
const { selectedBreakpoint } = this;
if (selectedBreakpoint) {
await this.editors.editBreakpoint(selectedBreakpoint);
}
},
isEnabled: () => !!this.selectedBreakpoint,
isVisible: () => !!this.selectedBreakpoint
});
registry.registerCommand(DebugCommands.EDIT_LOGPOINT, {
execute: async () => {
const { selectedLogpoint } = this;
if (selectedLogpoint) {
await this.editors.editBreakpoint(selectedLogpoint);
}
},
isEnabled: () => !!this.selectedLogpoint,
isVisible: () => !!this.selectedLogpoint
});
registry.registerCommand(DebugCommands.REMOVE_BREAKPOINT, {
execute: () => {
const { selectedBreakpoint } = this;
if (selectedBreakpoint) {
selectedBreakpoint.remove();
}
},
isEnabled: () => !!this.selectedBreakpoint
isEnabled: () => !!this.selectedBreakpoint,
isVisible: () => !!this.selectedBreakpoint
});
registry.registerCommand(DebugCommands.REMOVE_LOGPOINT, {
execute: () => {
const { selectedLogpoint } = this;
if (selectedLogpoint) {
selectedLogpoint.remove();
}
},
isEnabled: () => !!this.selectedLogpoint,
isVisible: () => !!this.selectedLogpoint
});
registry.registerCommand(DebugCommands.REMOVE_ALL_BREAKPOINTS, {
execute: () => this.breakpointManager.cleanAllMarkers(),
Expand Down Expand Up @@ -634,14 +739,29 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi

registry.registerCommand(DebugEditorContextCommands.ADD_BREAKPOINT, {
execute: () => this.editors.toggleBreakpoint(),
isEnabled: () => !this.editors.breakpoint,
isVisible: () => !this.editors.breakpoint
isEnabled: () => !this.editors.anyBreakpoint,
isVisible: () => !this.editors.anyBreakpoint
});
registry.registerCommand(DebugEditorContextCommands.ADD_CONDITIONAL_BREAKPOINT, {
execute: () => this.editors.addBreakpoint('condition'),
isEnabled: () => !this.editors.anyBreakpoint,
isVisible: () => !this.editors.anyBreakpoint
});
registry.registerCommand(DebugEditorContextCommands.ADD_LOGPOINT, {
execute: () => this.editors.addBreakpoint('logMessage'),
isEnabled: () => !this.editors.anyBreakpoint,
isVisible: () => !this.editors.anyBreakpoint
});
registry.registerCommand(DebugEditorContextCommands.REMOVE_BREAKPOINT, {
execute: () => this.editors.toggleBreakpoint(),
isEnabled: () => !!this.editors.breakpoint,
isVisible: () => !!this.editors.breakpoint
});
registry.registerCommand(DebugEditorContextCommands.EDIT_BREAKPOINT, {
execute: () => this.editors.editBreakpoint(),
isEnabled: () => !!this.editors.breakpoint,
isVisible: () => !!this.editors.breakpoint
});
registry.registerCommand(DebugEditorContextCommands.ENABLE_BREAKPOINT, {
execute: () => this.editors.setBreakpointEnabled(true),
isEnabled: () => this.editors.breakpointEnabled === false,
Expand All @@ -652,6 +772,33 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi
isEnabled: () => !!this.editors.breakpointEnabled,
isVisible: () => !!this.editors.breakpointEnabled
});
registry.registerCommand(DebugEditorContextCommands.REMOVE_LOGPOINT, {
execute: () => this.editors.toggleBreakpoint(),
isEnabled: () => !!this.editors.logpoint,
isVisible: () => !!this.editors.logpoint
});
registry.registerCommand(DebugEditorContextCommands.EDIT_LOGPOINT, {
execute: () => this.editors.editBreakpoint(),
isEnabled: () => !!this.editors.logpoint,
isVisible: () => !!this.editors.logpoint
});
registry.registerCommand(DebugEditorContextCommands.ENABLE_LOGPOINT, {
execute: () => this.editors.setBreakpointEnabled(true),
isEnabled: () => this.editors.logpointEnabled === false,
isVisible: () => this.editors.logpointEnabled === false
});
registry.registerCommand(DebugEditorContextCommands.DISABLE_LOGPOINT, {
execute: () => this.editors.setBreakpointEnabled(false),
isEnabled: () => !!this.editors.logpointEnabled,
isVisible: () => !!this.editors.logpointEnabled
});

registry.registerCommand(DebugBreakpointWidgetCommands.ACCEPT, {
execute: () => this.editors.acceptBreakpoint()
});
registry.registerCommand(DebugBreakpointWidgetCommands.CLOSE, {
execute: () => this.editors.closeBreakpoint()
});
}

registerKeybindings(keybindings: KeybindingRegistry): void {
Expand Down Expand Up @@ -706,6 +853,17 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi
keybinding: 'f9',
context: EditorKeybindingContexts.editorTextFocus
});

keybindings.registerKeybinding({
command: DebugBreakpointWidgetCommands.ACCEPT.id,
keybinding: 'enter',
context: DebugKeybindingContexts.inBreakpointWidget
});
keybindings.registerKeybinding({
command: DebugBreakpointWidgetCommands.CLOSE.id,
keybinding: 'esc',
context: DebugKeybindingContexts.inBreakpointWidget
});
}

protected readonly sessionWidgets = new Map<string, DebugSessionWidget>();
Expand Down Expand Up @@ -793,10 +951,18 @@ export class DebugFrontendApplicationContribution extends AbstractViewContributi
const { currentWidget } = this.shell;
return currentWidget instanceof DebugBreakpointsWidget && currentWidget || undefined;
}
get selectedBreakpoint(): DebugBreakpoint | undefined {
get selectedAnyBreakpoint(): DebugBreakpoint | undefined {
const { breakpoints } = this;
return breakpoints && breakpoints.selectedElement instanceof DebugBreakpoint && breakpoints.selectedElement || undefined;
}
get selectedBreakpoint(): DebugBreakpoint | undefined {
const breakpoint = this.selectedAnyBreakpoint;
return breakpoint && !breakpoint.logMessage ? breakpoint : undefined;
}
get selectedLogpoint(): DebugBreakpoint | undefined {
const breakpoint = this.selectedAnyBreakpoint;
return breakpoint && !!breakpoint.logMessage ? breakpoint : undefined;
}

get variables(): DebugVariablesWidget | undefined {
const { currentWidget } = this.shell;
Expand Down
3 changes: 2 additions & 1 deletion packages/debug/src/browser/debug-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { BreakpointManager } from './breakpoint/breakpoint-manager';
import { DebugEditorService } from './editor/debug-editor-service';
import { DebugViewOptions } from './view/debug-view-model';
import { DebugSessionWidget, DebugSessionWidgetFactory } from './view/debug-session-widget';
import { InDebugModeContext } from './debug-keybinding-contexts';
import { InDebugModeContext, InBreakpointWidgetContext } from './debug-keybinding-contexts';
import { DebugEditorModelFactory, DebugEditorModel } from './editor/debug-editor-model';
import './debug-monaco-contribution';
import { bindDebugPreferences } from './debug-preferences';
Expand Down Expand Up @@ -71,6 +71,7 @@ export default new ContainerModule((bind: interfaces.Bind) => {
bind(ResourceResolver).toService(DebugResourceResolver);

bind(KeybindingContext).to(InDebugModeContext).inSingletonScope();
bind(KeybindingContext).to(InBreakpointWidgetContext).inSingletonScope();
bindViewContribution(bind, DebugFrontendApplicationContribution);
bind(FrontendApplicationContribution).toService(DebugFrontendApplicationContribution);

Expand Down
18 changes: 18 additions & 0 deletions packages/debug/src/browser/debug-keybinding-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ import { injectable, inject } from 'inversify';
import { KeybindingContext } from '@theia/core/lib/browser';
import { DebugSessionManager } from './debug-session-manager';
import { DebugState } from './debug-session';
import { DebugEditorService } from './editor/debug-editor-service';

export namespace DebugKeybindingContexts {

export const inDebugMode = 'inDebugMode';

export const inBreakpointWidget = 'inBreakpointWidget';

}

@injectable()
Expand All @@ -38,3 +41,18 @@ export class InDebugModeContext implements KeybindingContext {
}

}

@injectable()
export class InBreakpointWidgetContext implements KeybindingContext {

readonly id: string = DebugKeybindingContexts.inBreakpointWidget;

@inject(DebugEditorService)
protected readonly editors: DebugEditorService;

isEnabled(): boolean {
const model = this.editors.model;
return !!model && !!model.breakpointWidget.position;
}

}
8 changes: 6 additions & 2 deletions packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,18 @@ export class DebugSessionManager {

addBreakpoints(breakpoints: DebugBreakpoint[]): void {
breakpoints.forEach(breakpoint => {
this.breakpoints.addBreakpoint(breakpoint.uri, breakpoint.line, breakpoint.column);
this.fireDidChangeBreakpoints({ uri: breakpoint.uri });
this.breakpoints.addBreakpoint(breakpoint.uri, {
line: breakpoint.line,
column: breakpoint.column
});
});
}

deleteBreakpoints(breakpoints: DebugBreakpoint[]): void {
// FIXME: use `DebugBreakpoint.remove` instead
breakpoints.forEach(breakpoint => {
this.breakpoints.deleteBreakpoint(breakpoint.uri, breakpoint.line, breakpoint.column);
// FIXME: properly hook up in `BreakpointManager` and `DebugSession` to report all changes
this.fireDidChangeBreakpoints({ uri: breakpoint.uri });
});
}
Expand Down
Loading

0 comments on commit f2bade6

Please sign in to comment.