VSCode merge (#4610)

* Merge from vscode e388c734f30757875976c7e326d6cfeee77710de

* fix yarn lcoks

* remove small issue
This commit is contained in:
Anthony Dresser
2019-03-20 10:39:09 -07:00
committed by GitHub
parent 87765e8673
commit c814b92557
310 changed files with 6606 additions and 2129 deletions

View File

@@ -15,10 +15,8 @@ import { MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions'
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView';
import { IAction } from 'vs/base/common/actions';
import { RestartAction, StopAction, ContinueAction, StepOverAction, StepIntoAction, StepOutAction, PauseAction, RestartFrameAction, TerminateThreadAction, CopyStackTraceAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IViewletPanelOptions, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
import { ILabelService } from 'vs/platform/label/common/label';
@@ -264,32 +262,13 @@ export class CallStackView extends ViewletPanel {
}
private onContextMenu(e: ITreeContextMenuEvent<CallStackItem>): void {
const actions: IAction[] = [];
const element = e.element;
if (isDebugSession(element)) {
this.callStackItemType.set('session');
actions.push(this.instantiationService.createInstance(RestartAction, RestartAction.ID, RestartAction.LABEL));
actions.push(new StopAction(StopAction.ID, StopAction.LABEL, this.debugService, this.keybindingService));
} else if (element instanceof Thread) {
this.callStackItemType.set('thread');
const thread = <Thread>element;
if (thread.stopped) {
actions.push(new ContinueAction(ContinueAction.ID, ContinueAction.LABEL, this.debugService, this.keybindingService));
actions.push(new StepOverAction(StepOverAction.ID, StepOverAction.LABEL, this.debugService, this.keybindingService));
actions.push(new StepIntoAction(StepIntoAction.ID, StepIntoAction.LABEL, this.debugService, this.keybindingService));
actions.push(new StepOutAction(StepOutAction.ID, StepOutAction.LABEL, this.debugService, this.keybindingService));
} else {
actions.push(new PauseAction(PauseAction.ID, PauseAction.LABEL, this.debugService, this.keybindingService));
}
actions.push(new Separator());
actions.push(new TerminateThreadAction(TerminateThreadAction.ID, TerminateThreadAction.LABEL, this.debugService, this.keybindingService));
} else if (element instanceof StackFrame) {
this.callStackItemType.set('stackFrame');
if (element.thread.session.capabilities.supportsRestartFrame) {
actions.push(new RestartFrameAction(RestartFrameAction.ID, RestartFrameAction.LABEL, this.debugService, this.keybindingService));
}
actions.push(this.instantiationService.createInstance(CopyStackTraceAction, CopyStackTraceAction.ID, CopyStackTraceAction.LABEL));
} else {
this.callStackItemType.reset();
}
@@ -297,7 +276,8 @@ export class CallStackView extends ViewletPanel {
this.contextMenuService.showContextMenu({
getAnchor: () => e.anchor,
getActions: () => {
fillInContextMenuActions(this.contributedContextMenu, { arg: this.getContextForContributedActions(element) }, actions, this.contextMenuService);
const actions: IAction[] = [];
fillInContextMenuActions(this.contributedContextMenu, { arg: this.getContextForContributedActions(element), shouldForwardArgs: true }, actions, this.contextMenuService);
return actions;
},
getActionsContext: () => element
@@ -315,6 +295,9 @@ export class CallStackView extends ViewletPanel {
if (element instanceof Thread) {
return element.threadId;
}
if (isDebugSession(element)) {
return element.getId();
}
return undefined;
}

View File

@@ -9,8 +9,8 @@ import { List } from 'vs/base/browser/ui/list/listWidget';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService } from 'vs/platform/list/browser/listService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig } from 'vs/workbench/contrib/debug/common/debug';
import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
import { IDebugService, IEnablement, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution, CONTEXT_IN_DEBUG_MODE, CONTEXT_EXPRESSION_SELECTED, CONTEXT_BREAKPOINT_SELECTED, IConfig, IStackFrame, IThread, IDebugSession, CONTEXT_DEBUG_STATE, REPL_ID } from 'vs/workbench/contrib/debug/common/debug';
import { Expression, Variable, Breakpoint, FunctionBreakpoint, Thread } from 'vs/workbench/contrib/debug/common/debugModel';
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ICodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
@@ -25,12 +25,188 @@ import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { PanelFocusContext } from 'vs/workbench/common/panel';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { startDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
export const ADD_CONFIGURATION_ID = 'debug.addConfiguration';
export const TOGGLE_INLINE_BREAKPOINT_ID = 'editor.debug.action.toggleInlineBreakpoint';
export const COPY_STACK_TRACE_ID = 'debug.copyStackTrace';
export const REVERSE_CONTINUE_ID = 'workbench.action.debug.reverseContinue';
export const STEP_BACK_ID = 'workbench.action.debug.stepBack';
export const RESTART_SESSION_ID = 'workbench.action.debug.restart';
export const TERMINATE_THREAD_ID = 'workbench.action.debug.terminateThread';
export const STEP_OVER_ID = 'workbench.action.debug.stepOver';
export const STEP_INTO_ID = 'workbench.action.debug.stepInto';
export const STEP_OUT_ID = 'workbench.action.debug.stepOut';
export const PAUSE_ID = 'workbench.action.debug.pause';
export const DISCONNECT_ID = 'workbench.action.debug.disconnect';
export const STOP_ID = 'workbench.action.debug.stop';
export const RESTART_FRAME_ID = 'workbench.action.debug.restartFrame';
export const CONTINUE_ID = 'workbench.action.debug.continue';
export const FOCUS_REPL_ID = 'workbench.debug.action.focusRepl';
function getThreadAndRun(accessor: ServicesAccessor, thread: IThread | undefined, run: (thread: IThread) => Promise<void>, ): void {
const debugService = accessor.get(IDebugService);
if (!(thread instanceof Thread)) {
thread = debugService.getViewModel().focusedThread;
}
if (thread) {
run(thread).then(undefined, onUnexpectedError);
}
}
export function registerCommands(): void {
CommandsRegistry.registerCommand({
id: COPY_STACK_TRACE_ID,
handler: (accessor: ServicesAccessor, _: string, frame: IStackFrame) => {
const textResourcePropertiesService = accessor.get(ITextResourcePropertiesService);
const clipboardService = accessor.get(IClipboardService);
const eol = textResourcePropertiesService.getEOL(frame.source.uri);
clipboardService.writeText(frame.thread.getCallStack().map(sf => sf.toString()).join(eol));
}
});
CommandsRegistry.registerCommand({
id: REVERSE_CONTINUE_ID,
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.reverseContinue());
}
});
CommandsRegistry.registerCommand({
id: STEP_BACK_ID,
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.stepBack());
}
});
CommandsRegistry.registerCommand({
id: TERMINATE_THREAD_ID,
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.terminate());
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: RESTART_SESSION_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.F5,
when: CONTEXT_IN_DEBUG_MODE,
handler: (accessor: ServicesAccessor, _: string, session: IDebugSession | undefined) => {
const debugService = accessor.get(IDebugService);
if (!session || !session.getId) {
session = debugService.getViewModel().focusedSession;
}
if (!session) {
const historyService = accessor.get(IHistoryService);
startDebugging(debugService, historyService, false);
} else {
session.removeReplExpressions();
debugService.restartSession(session).then(undefined, onUnexpectedError);
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: STEP_OVER_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyCode.F10,
when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'),
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.next());
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: STEP_INTO_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyCode.F11,
when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'),
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.stepIn());
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: STEP_OUT_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyMod.Shift | KeyCode.F11,
when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'),
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.stepOut());
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: PAUSE_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyCode.F6,
when: CONTEXT_DEBUG_STATE.isEqualTo('running'),
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.pause());
}
});
CommandsRegistry.registerCommand({
id: DISCONNECT_ID,
handler: (accessor: ServicesAccessor) => {
const debugService = accessor.get(IDebugService);
const session = debugService.getViewModel().focusedSession;
debugService.stopSession(session).then(undefined, onUnexpectedError);
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: STOP_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyMod.Shift | KeyCode.F5,
when: CONTEXT_IN_DEBUG_MODE,
handler: (accessor: ServicesAccessor, _: string, session: IDebugSession | undefined) => {
const debugService = accessor.get(IDebugService);
if (!session || !session.getId) {
session = debugService.getViewModel().focusedSession;
}
debugService.stopSession(session).then(undefined, onUnexpectedError);
}
});
CommandsRegistry.registerCommand({
id: RESTART_FRAME_ID,
handler: (accessor: ServicesAccessor, _: string, frame: IStackFrame | undefined) => {
const debugService = accessor.get(IDebugService);
if (!frame) {
frame = debugService.getViewModel().focusedStackFrame;
}
return frame!.restart();
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CONTINUE_ID,
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyCode.F5,
when: CONTEXT_IN_DEBUG_MODE,
handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => {
getThreadAndRun(accessor, thread, thread => thread.continue());
}
});
CommandsRegistry.registerCommand({
id: FOCUS_REPL_ID,
handler: (accessor) => {
const panelService = accessor.get(IPanelService);
panelService.openPanel(REPL_ID, true);
}
});
CommandsRegistry.registerCommand({
id: 'debug.startFromConfig',
handler: (accessor, config: IConfig) => {

View File

@@ -9,8 +9,8 @@ import { IAction } from 'vs/base/common/actions';
import * as DOM from 'vs/base/browser/dom';
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration } from 'vs/workbench/contrib/debug/common/debug';
import { StartAction, ToggleReplAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, REPL_ID } from 'vs/workbench/contrib/debug/common/debug';
import { StartAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { StartDebugActionItem, FocusSessionActionItem } from 'vs/workbench/contrib/debug/browser/debugActionItems';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -31,6 +31,8 @@ import { IMenu, MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TogglePanelAction } from 'vs/workbench/browser/panel';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
export class DebugViewlet extends ViewContainerViewlet {
@@ -193,3 +195,15 @@ export class DebugViewlet extends ViewContainerViewlet {
}
}
}
class ToggleReplAction extends TogglePanelAction {
static readonly ID = 'debug.toggleRepl';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console');
constructor(id: string, label: string,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IPanelService panelService: IPanelService
) {
super(id, label, REPL_ID, panelService, layoutService, 'debug-action toggle-repl');
}
}

View File

@@ -52,7 +52,6 @@ import { renderExpressionValue } from 'vs/workbench/contrib/debug/browser/baseDe
import { handleANSIOutput } from 'vs/workbench/contrib/debug/browser/debugANSIHandling';
import { ILabelService } from 'vs/platform/label/common/label';
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
import { ReplCollapseAllAction, CopyAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { removeAnsiEscapeCodes } from 'vs/base/common/strings';
@@ -452,12 +451,19 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
private onContextMenu(e: ITreeContextMenuEvent<IReplElement>): void {
const actions: IAction[] = [];
actions.push(new CopyAction(CopyAction.ID, CopyAction.LABEL, this.clipboardService));
actions.push(new Action('debug.replCopy', nls.localize('copy', "Copy"), undefined, true, () => {
this.clipboardService.writeText(window.getSelection().toString());
return Promise.resolve();
}));
actions.push(new Action('workbench.debug.action.copyAll', nls.localize('copyAll', "Copy All"), undefined, true, () => {
this.clipboardService.writeText(this.getVisibleContent());
return Promise.resolve(undefined);
}));
actions.push(new ReplCollapseAllAction(this.tree, this.replInput));
actions.push(new Action('debug.collapseRepl', nls.localize('collapse', "Collapse All"), undefined, true, () => {
this.tree.collapseAll();
this.replInput.focus();
return Promise.resolve();
}));
actions.push(new Separator());
actions.push(this.clearReplAction);

View File

@@ -13,8 +13,8 @@ import { Variable, Scope } from 'vs/workbench/contrib/debug/common/debugModel';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
import { IAction } from 'vs/base/common/actions';
import { SetValueAction, AddToWatchExpressionsAction, CopyValueAction, CopyEvaluatePathAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { IAction, Action } from 'vs/base/common/actions';
import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IViewletPanelOptions, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
@@ -27,6 +27,7 @@ import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
import { onUnexpectedError } from 'vs/base/common/errors';
import { FuzzyScore, createMatches } from 'vs/base/common/filters';
import { HighlightedLabel, IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
const $ = dom.$;
@@ -45,6 +46,7 @@ export class VariablesView extends ViewletPanel {
@IKeybindingService keybindingService: IKeybindingService,
@IConfigurationService configurationService: IConfigurationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IClipboardService private readonly clipboardService: IClipboardService
) {
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: nls.localize('variablesSection', "Variables Section") }, keybindingService, contextMenuService, configurationService);
@@ -129,20 +131,33 @@ export class VariablesView extends ViewletPanel {
}
private onContextMenu(e: ITreeContextMenuEvent<IExpression | IScope>): void {
const element = e.element;
if (element instanceof Variable && !!element.value) {
const variable = e.element;
if (variable instanceof Variable && !!variable.value) {
const actions: IAction[] = [];
const variable = element as Variable;
actions.push(new SetValueAction(SetValueAction.ID, SetValueAction.LABEL, variable, this.debugService, this.keybindingService));
const session = this.debugService.getViewModel().focusedSession;
if (session && session.capabilities.supportsSetVariable) {
actions.push(new Action('workbench.setValue', nls.localize('setValue', "Set Value"), undefined, true, () => {
this.debugService.getViewModel().setSelectedExpression(variable);
return Promise.resolve();
}));
}
actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, variable, 'variables'));
actions.push(this.instantiationService.createInstance(CopyEvaluatePathAction, CopyEvaluatePathAction.ID, CopyEvaluatePathAction.LABEL, variable));
actions.push(new Separator());
actions.push(new AddToWatchExpressionsAction(AddToWatchExpressionsAction.ID, AddToWatchExpressionsAction.LABEL, variable, this.debugService, this.keybindingService));
if (variable.evaluateName) {
actions.push(new Action('debug.copyEvaluatePath', nls.localize('copyAsExpression', "Copy as Expression"), undefined, true, () => {
this.clipboardService.writeText(variable.evaluateName!);
return Promise.resolve();
}));
actions.push(new Separator());
actions.push(new Action('debug.addToWatchExpressions', nls.localize('addToWatchExpressions', "Add to Watch"), undefined, true, () => {
this.debugService.addWatchExpression(variable.evaluateName);
return Promise.resolve(undefined);
}));
}
this.contextMenuService.showContextMenu({
getAnchor: () => e.anchor,
getActions: () => actions,
getActionsContext: () => element
getActionsContext: () => variable
});
}
}

View File

@@ -10,11 +10,11 @@ import { CollapseAction } from 'vs/workbench/browser/viewlet';
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IDebugService, IExpression, CONTEXT_WATCH_EXPRESSIONS_FOCUSED } from 'vs/workbench/contrib/debug/common/debug';
import { Expression, Variable } from 'vs/workbench/contrib/debug/common/debugModel';
import { AddWatchExpressionAction, RemoveAllWatchExpressionsAction, EditWatchExpressionAction, RemoveWatchExpressionAction, CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { AddWatchExpressionAction, RemoveAllWatchExpressionsAction, CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IAction } from 'vs/base/common/actions';
import { IAction, Action } from 'vs/base/common/actions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -144,13 +144,19 @@ export class WatchExpressionsView extends ViewletPanel {
if (element instanceof Expression) {
const expression = <Expression>element;
actions.push(new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
actions.push(new EditWatchExpressionAction(EditWatchExpressionAction.ID, EditWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
actions.push(new Action('debug.editWatchExpression', nls.localize('editWatchExpression', "Edit Expression"), undefined, true, () => {
this.debugService.getViewModel().setSelectedExpression(expression);
return Promise.resolve();
}));
if (!expression.hasChildren) {
actions.push(this.instantiationService.createInstance(CopyValueAction, CopyValueAction.ID, CopyValueAction.LABEL, expression.value, 'watch', this.debugService));
}
actions.push(new Separator());
actions.push(new RemoveWatchExpressionAction(RemoveWatchExpressionAction.ID, RemoveWatchExpressionAction.LABEL, this.debugService, this.keybindingService));
actions.push(new Action('debug.removeWatchExpression', nls.localize('removeWatchExpression', "Remove Expression"), undefined, true, () => {
this.debugService.removeWatchExpressions(expression.getId());
return Promise.resolve();
}));
actions.push(new RemoveAllWatchExpressionsAction(RemoveAllWatchExpressionsAction.ID, RemoveAllWatchExpressionsAction.LABEL, this.debugService, this.keybindingService));
} else {
actions.push(new AddWatchExpressionAction(AddWatchExpressionAction.ID, AddWatchExpressionAction.LABEL, this.debugService, this.keybindingService));

View File

@@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { IDebugAdapter } from 'vs/workbench/contrib/debug/common/debug';
/**
* Abstract implementation of the low level API for a debug adapter.
* Missing is how this API communicates with the debug adapter.
*/
export abstract class AbstractDebugAdapter implements IDebugAdapter {
private sequence: number;
private pendingRequests: Map<number, (e: DebugProtocol.Response) => void>;
private requestCallback: (request: DebugProtocol.Request) => void;
private eventCallback: (request: DebugProtocol.Event) => void;
private messageCallback: (message: DebugProtocol.ProtocolMessage) => void;
protected readonly _onError: Emitter<Error>;
protected readonly _onExit: Emitter<number | null>;
constructor() {
this.sequence = 1;
this.pendingRequests = new Map();
this._onError = new Emitter<Error>();
this._onExit = new Emitter<number>();
}
abstract startSession(): Promise<void>;
abstract stopSession(): Promise<void>;
abstract sendMessage(message: DebugProtocol.ProtocolMessage): void;
get onError(): Event<Error> {
return this._onError.event;
}
get onExit(): Event<number | null> {
return this._onExit.event;
}
onMessage(callback: (message: DebugProtocol.ProtocolMessage) => void): void {
if (this.eventCallback) {
this._onError.fire(new Error(`attempt to set more than one 'Message' callback`));
}
this.messageCallback = callback;
}
onEvent(callback: (event: DebugProtocol.Event) => void): void {
if (this.eventCallback) {
this._onError.fire(new Error(`attempt to set more than one 'Event' callback`));
}
this.eventCallback = callback;
}
onRequest(callback: (request: DebugProtocol.Request) => void): void {
if (this.requestCallback) {
this._onError.fire(new Error(`attempt to set more than one 'Request' callback`));
}
this.requestCallback = callback;
}
sendResponse(response: DebugProtocol.Response): void {
if (response.seq > 0) {
this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`));
}
else {
this.internalSend('response', response);
}
}
sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void {
const request: any = {
command: command
};
if (args && Object.keys(args).length > 0) {
request.arguments = args;
}
this.internalSend('request', request);
if (typeof timeout === 'number') {
const timer = setTimeout(() => {
clearTimeout(timer);
const clb = this.pendingRequests.get(request.seq);
if (clb) {
this.pendingRequests.delete(request.seq);
const err: DebugProtocol.Response = {
type: 'response',
seq: 0,
request_seq: request.seq,
success: false,
command,
message: `timeout after ${timeout} ms`
};
clb(err);
}
}, timeout);
}
if (clb) {
// store callback for this request
this.pendingRequests.set(request.seq, clb);
}
}
acceptMessage(message: DebugProtocol.ProtocolMessage): void {
if (this.messageCallback) {
this.messageCallback(message);
}
else {
switch (message.type) {
case 'event':
if (this.eventCallback) {
this.eventCallback(<DebugProtocol.Event>message);
}
break;
case 'request':
if (this.requestCallback) {
this.requestCallback(<DebugProtocol.Request>message);
}
break;
case 'response':
const response = <DebugProtocol.Response>message;
const clb = this.pendingRequests.get(response.request_seq);
if (clb) {
this.pendingRequests.delete(response.request_seq);
clb(response);
}
break;
}
}
}
private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void {
message.type = typ;
message.seq = this.sequence++;
this.sendMessage(message);
}
protected cancelPending() {
const pending = this.pendingRequests;
this.pendingRequests = new Map();
setTimeout(_ => {
pending.forEach((callback, request_seq) => {
const err: DebugProtocol.Response = {
type: 'response',
seq: 0,
request_seq,
success: false,
command: 'canceled',
message: 'canceled'
};
callback(err);
});
}, 1000);
}
dispose(): void {
this.cancelPending();
}
}

View File

@@ -53,6 +53,7 @@ export const CONTEXT_LOADED_SCRIPTS_SUPPORTED = new RawContextKey<boolean>('load
export const CONTEXT_LOADED_SCRIPTS_ITEM_TYPE = new RawContextKey<string>('loadedScriptsItemType', undefined);
export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey<boolean>('focusedSessionIsAttach', false);
export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey<boolean>('stepBackSupported', false);
export const CONTEXT_RESTART_FRAME_SUPPORTED = new RawContextKey<boolean>('restartFrameSupported', false);
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
export const DEBUG_SCHEME = 'debug';

View File

@@ -4,13 +4,32 @@
*--------------------------------------------------------------------------------------------*/
import { equalsIgnoreCase } from 'vs/base/common/strings';
import { IConfig, IDebuggerContribution } from 'vs/workbench/contrib/debug/common/debug';
import { IConfig, IDebuggerContribution, IDebugService } from 'vs/workbench/contrib/debug/common/debug';
import { URI as uri } from 'vs/base/common/uri';
import { isAbsolute } from 'vs/base/common/path';
import { deepClone } from 'vs/base/common/objects';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { first } from 'vs/base/common/arrays';
const _formatPIIRegexp = /{([^}]+)}/g;
export function startDebugging(debugService: IDebugService, historyService: IHistoryService, noDebug: boolean, ): Promise<boolean> {
const configurationManager = debugService.getConfigurationManager();
let launch = configurationManager.selectedConfiguration.launch;
if (!launch || launch.getConfigurationNames().length === 0) {
const rootUri = historyService.getLastActiveWorkspaceRoot();
launch = configurationManager.getLaunch(rootUri);
if (!launch || launch.getConfigurationNames().length === 0) {
const launches = configurationManager.getLaunches();
launch = first(launches, l => !!(l && l.getConfigurationNames().length), launch);
}
configurationManager.selectConfiguration(launch);
}
return debugService.startDebugging(launch, undefined, noDebug);
}
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
return value.replace(_formatPIIRegexp, function (match, group) {
if (excludePII && group.length > 0 && group[0] !== '_') {

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH } from 'vs/workbench/contrib/debug/common/debug';
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_RESTART_FRAME_SUPPORTED } from 'vs/workbench/contrib/debug/common/debug';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
@@ -26,6 +26,7 @@ export class ViewModel implements IViewModel {
private loadedScriptsSupportedContextKey: IContextKey<boolean>;
private stepBackSupportedContextKey: IContextKey<boolean>;
private focusedSessionIsAttach: IContextKey<boolean>;
private restartFrameSupportedContextKey: IContextKey<boolean>;
constructor(contextKeyService: IContextKeyService) {
this._onDidFocusSession = new Emitter<IDebugSession | undefined>();
@@ -37,6 +38,7 @@ export class ViewModel implements IViewModel {
this.loadedScriptsSupportedContextKey = CONTEXT_LOADED_SCRIPTS_SUPPORTED.bindTo(contextKeyService);
this.stepBackSupportedContextKey = CONTEXT_STEP_BACK_SUPPORTED.bindTo(contextKeyService);
this.focusedSessionIsAttach = CONTEXT_FOCUSED_SESSION_IS_ATTACH.bindTo(contextKeyService);
this.restartFrameSupportedContextKey = CONTEXT_RESTART_FRAME_SUPPORTED.bindTo(contextKeyService);
}
getId(): string {
@@ -65,6 +67,7 @@ export class ViewModel implements IViewModel {
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
const attach = !!session && session.configuration.request === 'attach' && !isExtensionHostDebugging(session.configuration);
this.focusedSessionIsAttach.set(attach);

View File

@@ -10,7 +10,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { KeybindingWeight, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions } from 'vs/workbench/common/actions';
import { ShowViewletAction, Extensions as ViewletExtensions, ViewletRegistry, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
@@ -22,19 +22,16 @@ import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView'
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import {
IDebugService, VIEWLET_ID, REPL_ID, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA,
CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, VIEW_CONTAINER, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED,
CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, VIEW_CONTAINER, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED,
} from 'vs/workbench/contrib/debug/common/debug';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { DebugEditorModelManager } from 'vs/workbench/contrib/debug/browser/debugEditorModelManager';
import {
StepOverAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction,
ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction, TerminateThreadAction, StepBackAction, ReverseContinueAction,
} from 'vs/workbench/contrib/debug/browser/debugActions';
import { StartAction, AddFunctionBreakpointAction, ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions';
import { DebugToolbar } from 'vs/workbench/contrib/debug/browser/debugToolbar';
import * as service from 'vs/workbench/contrib/debug/electron-browser/debugService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider';
import { IViewsRegistry, Extensions as ViewExtensions } from 'vs/workbench/common/views';
@@ -119,6 +116,8 @@ viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callSt
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: { ctor: BreakpointsView }, order: 40, weight: 20, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' } }], VIEW_CONTAINER);
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: { ctor: LoadedScriptsView }, order: 35, weight: 5, canToggleVisibility: true, collapsed: true, when: CONTEXT_LOADED_SCRIPTS_SUPPORTED }], VIEW_CONTAINER);
registerCommands();
// register action to open viewlet
const registry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionRegistryExtensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL, openPanelKb), 'View: Debug Console', nls.localize('view', "View"));
@@ -132,15 +131,6 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
const debugCategory = nls.localize('debugCategory', "Debug");
registry.registerWorkbenchAction(new SyncActionDescriptor(StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE.toNegated()), 'Debug: Start Debugging', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOverAction, StepOverAction.ID, StepOverAction.LABEL, { primary: KeyCode.F10 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Over', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepIntoAction, StepIntoAction.ID, StepIntoAction.LABEL, { primary: KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE, KeybindingWeight.WorkbenchContrib + 1), 'Debug: Step Into', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOutAction, StepOutAction.ID, StepOutAction.LABEL, { primary: KeyMod.Shift | KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Out', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(RestartAction, RestartAction.ID, RestartAction.LABEL, { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Restart', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StopAction, StopAction.ID, StopAction.LABEL, { primary: KeyMod.Shift | KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Stop', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(DisconnectAction, DisconnectAction.ID, DisconnectAction.LABEL), 'Debug: Disconnect', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ContinueAction, ContinueAction.ID, ContinueAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Continue', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(PauseAction, PauseAction.ID, PauseAction.LABEL, { primary: KeyCode.F6 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Pause', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(TerminateThreadAction, TerminateThreadAction.ID, TerminateThreadAction.LABEL, undefined, CONTEXT_IN_DEBUG_MODE), 'Debug: Terminate Thread', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory);
@@ -148,10 +138,38 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.I
registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveAllBreakpointsAction, RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL), 'Debug: Remove All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(EnableAllBreakpointsAction, EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL), 'Debug: Enable All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(DisableAllBreakpointsAction, DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL), 'Debug: Disable All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusReplAction, FocusReplAction.ID, FocusReplAction.LABEL), 'Debug: Focus on Debug Console View', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SelectAndStartAction, SelectAndStartAction.ID, SelectAndStartAction.LABEL), 'Debug: Select and Start Debugging', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL), 'Debug: Clear Console', debugCategory);
const registerDebugCommandPaletteItem = (id: string, title: string, when?: ContextKeyExpr, precondition?: ContextKeyExpr) => {
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
when,
command: {
id,
title: `Debug: ${title}`,
precondition
}
});
};
const restartLabel = nls.localize('restartDebug', "Restart");
const stepOverLabel = nls.localize('stepOverDebug', "Step Over");
const stepIntoLabel = nls.localize('stepIntoDebug', "Step Into");
const stepOutLabel = nls.localize('stepOutDebug', "Step Out");
const pauseLabel = nls.localize('pauseDebug', "Pause");
const disconnectLabel = nls.localize('disconnect', "Disconnect");
const stopLabel = nls.localize('stop', "Stop");
const continueLabel = nls.localize('continueDebug', "Continue");
registerDebugCommandPaletteItem(RESTART_SESSION_ID, restartLabel);
registerDebugCommandPaletteItem(TERMINATE_THREAD_ID, nls.localize('terminateThread', "Terminate Thread"), CONTEXT_IN_DEBUG_MODE);
registerDebugCommandPaletteItem(STEP_OVER_ID, stepOverLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCommandPaletteItem(STEP_INTO_ID, stepIntoLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCommandPaletteItem(STEP_OUT_ID, stepOutLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCommandPaletteItem(PAUSE_ID, pauseLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('running'));
registerDebugCommandPaletteItem(DISCONNECT_ID, disconnectLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
registerDebugCommandPaletteItem(STOP_ID, stopLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
registerDebugCommandPaletteItem(CONTINUE_ID, continueLabel, CONTEXT_IN_DEBUG_MODE, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCommandPaletteItem(FOCUS_REPL_ID, nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusConsole' }, 'Focus on Debug Console View'));
// Register Quick Open
(Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
@@ -235,8 +253,6 @@ configurationRegistry.registerConfiguration({
}
});
registerCommands();
// Register Debug Status
const statusBar = Registry.as<IStatusbarRegistry>(StatusExtensions.Statusbar);
statusBar.registerStatusbarItem(new StatusbarItemDescriptor(DebugStatus, StatusbarAlignment.LEFT, 30 /* Low Priority */));
@@ -260,16 +276,40 @@ const registerDebugToolbarItem = (id: string, title: string, icon: string, order
});
};
registerDebugToolbarItem(ContinueAction.ID, ContinueAction.LABEL, 'continue', 10, CONTEXT_DEBUG_STATE.notEqualsTo('running'));
registerDebugToolbarItem(PauseAction.ID, PauseAction.LABEL, 'pause', 10, CONTEXT_DEBUG_STATE.isEqualTo('running'));
registerDebugToolbarItem(StopAction.ID, StopAction.LABEL, 'stop', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
registerDebugToolbarItem(DisconnectAction.ID, DisconnectAction.LABEL, 'disconnect', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
registerDebugToolbarItem(StepOverAction.ID, StepOverAction.LABEL, 'step-over', 20, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(StepIntoAction.ID, StepIntoAction.LABEL, 'step-into', 30, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(StepOutAction.ID, StepOutAction.LABEL, 'step-out', 40, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(RestartAction.ID, RestartAction.LABEL, 'restart', 60);
registerDebugToolbarItem(StepBackAction.ID, StepBackAction.LABEL, 'step-back', 50, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(ReverseContinueAction.ID, ReverseContinueAction.LABEL, 'reverse-continue', 60, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(CONTINUE_ID, continueLabel, 'continue', 10, CONTEXT_DEBUG_STATE.notEqualsTo('running'));
registerDebugToolbarItem(PAUSE_ID, pauseLabel, 'pause', 10, CONTEXT_DEBUG_STATE.isEqualTo('running'));
registerDebugToolbarItem(STOP_ID, stopLabel, 'stop', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH.toNegated());
registerDebugToolbarItem(DISCONNECT_ID, disconnectLabel, 'disconnect', 70, CONTEXT_FOCUSED_SESSION_IS_ATTACH);
registerDebugToolbarItem(STEP_OVER_ID, stepOverLabel, 'step-over', 20, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(STEP_INTO_ID, stepIntoLabel, 'step-into', 30, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(STEP_OUT_ID, stepOutLabel, 'step-out', 40, undefined, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(RESTART_SESSION_ID, restartLabel, 'restart', 60);
registerDebugToolbarItem(STEP_BACK_ID, nls.localize('stepBackDebug', "Step Back"), 'step-back', 50, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugToolbarItem(REVERSE_CONTINUE_ID, nls.localize('reverseContinue', "Reverse"), 'reverse-continue', 60, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
// Debug callstack context menu
const registerDebugCallstackItem = (id: string, title: string, order: number, when?: ContextKeyExpr, precondition?: ContextKeyExpr, group = 'navigation') => {
MenuRegistry.appendMenuItem(MenuId.DebugCallStackContext, {
group,
when,
order,
command: {
id,
title,
precondition
}
});
};
registerDebugCallstackItem(RESTART_SESSION_ID, restartLabel, 10, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'));
registerDebugCallstackItem(STOP_ID, stopLabel, 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('session'));
registerDebugCallstackItem(PAUSE_ID, pauseLabel, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('running')));
registerDebugCallstackItem(CONTINUE_ID, continueLabel, 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped')));
registerDebugCallstackItem(STEP_OVER_ID, stepOverLabel, 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCallstackItem(STEP_INTO_ID, stepIntoLabel, 30, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCallstackItem(STEP_OUT_ID, stepOutLabel, 40, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), CONTEXT_DEBUG_STATE.isEqualTo('stopped'));
registerDebugCallstackItem(TERMINATE_THREAD_ID, nls.localize('terminateThread', "Terminate Thread"), 10, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('thread'), undefined, 'termination');
registerDebugCallstackItem(RESTART_FRAME_ID, nls.localize('restartFrame', "Restart Frame"), 10, ContextKeyExpr.and(CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('stackFrame'), CONTEXT_RESTART_FRAME_SUPPORTED));
registerDebugCallstackItem(COPY_STACK_TRACE_ID, nls.localize('copyStackTrace', "Copy Call Stack"), 20, CONTEXT_CALLSTACK_ITEM_TYPE.isEqualTo('stackFrame'));
// View menu
@@ -318,7 +358,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
group: '1_debug',
command: {
id: StopAction.ID,
id: STOP_ID,
title: nls.localize({ key: 'miStopDebugging', comment: ['&& denotes a mnemonic'] }, "&&Stop Debugging"),
precondition: CONTEXT_IN_DEBUG_MODE
},
@@ -328,7 +368,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
group: '1_debug',
command: {
id: RestartAction.ID,
id: RESTART_SESSION_ID,
title: nls.localize({ key: 'miRestart Debugging', comment: ['&& denotes a mnemonic'] }, "&&Restart Debugging"),
precondition: CONTEXT_IN_DEBUG_MODE
},
@@ -358,7 +398,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
group: '3_step',
command: {
id: StepOverAction.ID,
id: STEP_OVER_ID,
title: nls.localize({ key: 'miStepOver', comment: ['&& denotes a mnemonic'] }, "Step &&Over"),
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
},
@@ -368,7 +408,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
group: '3_step',
command: {
id: StepIntoAction.ID,
id: STEP_INTO_ID,
title: nls.localize({ key: 'miStepInto', comment: ['&& denotes a mnemonic'] }, "Step &&Into"),
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
},
@@ -378,7 +418,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
group: '3_step',
command: {
id: StepOutAction.ID,
id: STEP_OUT_ID,
title: nls.localize({ key: 'miStepOut', comment: ['&& denotes a mnemonic'] }, "Step O&&ut"),
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
},
@@ -388,7 +428,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
MenuRegistry.appendMenuItem(MenuId.MenubarDebugMenu, {
group: '3_step',
command: {
id: ContinueAction.ID,
id: CONTINUE_ID,
title: nls.localize({ key: 'miContinue', comment: ['&& denotes a mnemonic'] }, "&&Continue"),
precondition: CONTEXT_DEBUG_STATE.isEqualTo('stopped')
},
@@ -502,11 +542,11 @@ if (isMacintosh) {
registerTouchBarEntry(StartAction.ID, StartAction.LABEL, 0, CONTEXT_IN_DEBUG_MODE.toNegated(), 'continue-tb.png');
registerTouchBarEntry(RunAction.ID, RunAction.LABEL, 1, CONTEXT_IN_DEBUG_MODE.toNegated(), 'continue-without-debugging-tb.png');
registerTouchBarEntry(ContinueAction.ID, ContinueAction.LABEL, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'continue-tb.png');
registerTouchBarEntry(PauseAction.ID, PauseAction.LABEL, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), 'pause-tb.png');
registerTouchBarEntry(StepOverAction.ID, StepOverAction.LABEL, 2, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepover-tb.png');
registerTouchBarEntry(StepIntoAction.ID, StepIntoAction.LABEL, 3, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepinto-tb.png');
registerTouchBarEntry(StepOutAction.ID, StepOutAction.LABEL, 4, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepout-tb.png');
registerTouchBarEntry(RestartAction.ID, RestartAction.LABEL, 5, CONTEXT_IN_DEBUG_MODE, 'restart-tb.png');
registerTouchBarEntry(StopAction.ID, StopAction.LABEL, 6, CONTEXT_IN_DEBUG_MODE, 'stop-tb.png');
registerTouchBarEntry(CONTINUE_ID, continueLabel, 0, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'continue-tb.png');
registerTouchBarEntry(PAUSE_ID, pauseLabel, 1, ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, ContextKeyExpr.notEquals('debugState', 'stopped')), 'pause-tb.png');
registerTouchBarEntry(STEP_OVER_ID, stepOverLabel, 2, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepover-tb.png');
registerTouchBarEntry(STEP_INTO_ID, stepIntoLabel, 3, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepinto-tb.png');
registerTouchBarEntry(STEP_OUT_ID, stepOutLabel, 4, CONTEXT_DEBUG_STATE.isEqualTo('stopped'), 'stepout-tb.png');
registerTouchBarEntry(RESTART_SESSION_ID, restartLabel, 5, CONTEXT_IN_DEBUG_MODE, 'restart-tb.png');
registerTouchBarEntry(STOP_ID, stopLabel, 6, CONTEXT_IN_DEBUG_MODE, 'stop-tb.png');
}

View File

@@ -12,170 +12,11 @@ import * as path from 'vs/base/common/path';
import * as strings from 'vs/base/common/strings';
import * as objects from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { Emitter, Event } from 'vs/base/common/event';
import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
import { IDebugAdapter, IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
/**
* Abstract implementation of the low level API for a debug adapter.
* Missing is how this API communicates with the debug adapter.
*/
export abstract class AbstractDebugAdapter implements IDebugAdapter {
private sequence: number;
private pendingRequests: Map<number, (e: DebugProtocol.Response) => void>;
private requestCallback: (request: DebugProtocol.Request) => void;
private eventCallback: (request: DebugProtocol.Event) => void;
private messageCallback: (message: DebugProtocol.ProtocolMessage) => void;
protected readonly _onError: Emitter<Error>;
protected readonly _onExit: Emitter<number | null>;
constructor() {
this.sequence = 1;
this.pendingRequests = new Map();
this._onError = new Emitter<Error>();
this._onExit = new Emitter<number>();
}
abstract startSession(): Promise<void>;
abstract stopSession(): Promise<void>;
abstract sendMessage(message: DebugProtocol.ProtocolMessage): void;
get onError(): Event<Error> {
return this._onError.event;
}
get onExit(): Event<number | null> {
return this._onExit.event;
}
onMessage(callback: (message: DebugProtocol.ProtocolMessage) => void): void {
if (this.eventCallback) {
this._onError.fire(new Error(`attempt to set more than one 'Message' callback`));
}
this.messageCallback = callback;
}
onEvent(callback: (event: DebugProtocol.Event) => void): void {
if (this.eventCallback) {
this._onError.fire(new Error(`attempt to set more than one 'Event' callback`));
}
this.eventCallback = callback;
}
onRequest(callback: (request: DebugProtocol.Request) => void): void {
if (this.requestCallback) {
this._onError.fire(new Error(`attempt to set more than one 'Request' callback`));
}
this.requestCallback = callback;
}
sendResponse(response: DebugProtocol.Response): void {
if (response.seq > 0) {
this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`));
} else {
this.internalSend('response', response);
}
}
sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void {
const request: any = {
command: command
};
if (args && Object.keys(args).length > 0) {
request.arguments = args;
}
this.internalSend('request', request);
if (typeof timeout === 'number') {
const timer = setTimeout(() => {
clearTimeout(timer);
const clb = this.pendingRequests.get(request.seq);
if (clb) {
this.pendingRequests.delete(request.seq);
const err: DebugProtocol.Response = {
type: 'response',
seq: 0,
request_seq: request.seq,
success: false,
command,
message: `timeout after ${timeout} ms`
};
clb(err);
}
}, timeout);
}
if (clb) {
// store callback for this request
this.pendingRequests.set(request.seq, clb);
}
}
acceptMessage(message: DebugProtocol.ProtocolMessage): void {
if (this.messageCallback) {
this.messageCallback(message);
} else {
switch (message.type) {
case 'event':
if (this.eventCallback) {
this.eventCallback(<DebugProtocol.Event>message);
}
break;
case 'request':
if (this.requestCallback) {
this.requestCallback(<DebugProtocol.Request>message);
}
break;
case 'response':
const response = <DebugProtocol.Response>message;
const clb = this.pendingRequests.get(response.request_seq);
if (clb) {
this.pendingRequests.delete(response.request_seq);
clb(response);
}
break;
}
}
}
private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void {
message.type = typ;
message.seq = this.sequence++;
this.sendMessage(message);
}
protected cancelPending() {
const pending = this.pendingRequests;
this.pendingRequests = new Map();
setTimeout(_ => {
pending.forEach((callback, request_seq) => {
const err: DebugProtocol.Response = {
type: 'response',
seq: 0,
request_seq,
success: false,
command: 'canceled',
message: 'canceled'
};
callback(err);
});
}, 1000);
}
dispose(): void {
this.cancelPending();
}
}
import { AbstractDebugAdapter } from '../common/abstractDebugAdapter';
/**
* An implementation that communicates via two streams with the debug adapter.