diff --git a/src/vs/workbench/contrib/debug/browser/debugToolbar.ts b/src/vs/workbench/contrib/debug/browser/debugToolbar.ts index 12911060ada2f64de828d582f2b201ef3895b7e0..7dae7e4ea698ffa21ee1d169ad3c5aafbcbea111 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolbar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolbar.ts @@ -14,7 +14,6 @@ import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/act import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IDebugConfiguration, IDebugService, State } from 'vs/workbench/contrib/debug/common/debug'; -import { AbstractDebugAction, PauseAction, ContinueAction, StepBackAction, ReverseContinueAction, StopAction, DisconnectAction, StepOverAction, StepIntoAction, StepOutAction, RestartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { FocusSessionActionItem } from 'vs/workbench/contrib/debug/browser/debugActionItems'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -28,11 +27,10 @@ import { IContextViewService, IContextMenuService } from 'vs/platform/contextvie import { INotificationService } from 'vs/platform/notification/common/notification'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils'; import { fillInActionBarActions, MenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem'; import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition'; const DEBUG_TOOLBAR_Y_KEY = 'debug.actionswidgety'; @@ -53,7 +51,6 @@ export class DebugToolbar extends Themable implements IWorkbenchContribution { private $el: HTMLElement; private dragArea: HTMLElement; private actionBar: ActionBar; - private allActions: AbstractDebugAction[] = []; private activeActions: IAction[]; private updateScheduler: RunOnceScheduler; private debugToolbarMenu: IMenu; @@ -109,7 +106,7 @@ export class DebugToolbar extends Themable implements IWorkbenchContribution { return this.hide(); } - const actions = DebugToolbar.getActions(this.debugToolbarMenu, this.allActions, this.toDispose, this.debugService, this.keybindingService, this.instantiationService); + const actions = DebugToolbar.getActions(this.debugToolbarMenu, this.debugService, this.instantiationService); if (!arrays.equals(actions, this.activeActions, (first, second) => first.id === second.id)) { this.actionBar.clear(); this.actionBar.push(actions, { icon: true, label: false }); @@ -267,48 +264,8 @@ export class DebugToolbar extends Themable implements IWorkbenchContribution { dom.hide(this.$el); } - public static getActions(menu: IMenu, allActions: AbstractDebugAction[], toDispose: IDisposable[], debugService: IDebugService, keybindingService: IKeybindingService, instantiationService: IInstantiationService): IAction[] { - if (allActions.length === 0) { - allActions.push(new ContinueAction(ContinueAction.ID, ContinueAction.LABEL, debugService, keybindingService)); - allActions.push(new PauseAction(PauseAction.ID, PauseAction.LABEL, debugService, keybindingService)); - allActions.push(new StopAction(StopAction.ID, StopAction.LABEL, debugService, keybindingService)); - allActions.push(new DisconnectAction(DisconnectAction.ID, DisconnectAction.LABEL, debugService, keybindingService)); - allActions.push(new StepOverAction(StepOverAction.ID, StepOverAction.LABEL, debugService, keybindingService)); - allActions.push(new StepIntoAction(StepIntoAction.ID, StepIntoAction.LABEL, debugService, keybindingService)); - allActions.push(new StepOutAction(StepOutAction.ID, StepOutAction.LABEL, debugService, keybindingService)); - allActions.push(instantiationService.createInstance(RestartAction, RestartAction.ID, RestartAction.LABEL)); - allActions.push(new StepBackAction(StepBackAction.ID, StepBackAction.LABEL, debugService, keybindingService)); - allActions.push(new ReverseContinueAction(ReverseContinueAction.ID, ReverseContinueAction.LABEL, debugService, keybindingService)); - allActions.forEach(a => toDispose.push(a)); - } - - const state = debugService.state; - const session = debugService.getViewModel().focusedSession; - const attached = session && session.configuration.request === 'attach' && !isExtensionHostDebugging(session.configuration); - - const actions: IAction[] = allActions.filter(a => { - if (a.id === ContinueAction.ID) { - return state !== State.Running; - } - if (a.id === PauseAction.ID) { - return state === State.Running; - } - if (a.id === StepBackAction.ID) { - return session && session.capabilities.supportsStepBack; - } - if (a.id === ReverseContinueAction.ID) { - return session && session.capabilities.supportsStepBack; - } - if (a.id === DisconnectAction.ID) { - return attached; - } - if (a.id === StopAction.ID) { - return !attached; - } - - return true; - }).sort((first, second) => (first.weight || 0) - (second.weight || 0)); - + public static getActions(menu: IMenu, debugService: IDebugService, instantiationService: IInstantiationService): IAction[] { + const actions: IAction[] = []; fillInActionBarActions(menu, undefined, actions, () => false); if (debugService.getViewModel().isMultiSessionView()) { actions.push(instantiationService.createInstance(FocusSessionAction, FocusSessionAction.ID, FocusSessionAction.LABEL)); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 92ea667e3cc86afd64efb402414c61dcddbfca35..ca15e72511cc3b47ab415e2b6a8243e1ab7f210e 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -10,7 +10,7 @@ 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, AbstractDebugAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; +import { StartAction, ToggleReplAction, 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'; @@ -38,7 +38,6 @@ export class DebugViewlet extends ViewContainerViewlet { private progressRunner: IProgressRunner; private breakpointView: ViewletPanel; private panelListeners = new Map(); - private allActions: AbstractDebugAction[] = []; private debugToolbarMenu: IMenu; constructor( @@ -112,7 +111,7 @@ export class DebugViewlet extends ViewContainerViewlet { this.debugToolbarMenu = this.menuService.createMenu(MenuId.DebugToolbar, this.contextKeyService); this.toDispose.push(this.debugToolbarMenu); } - return DebugToolbar.getActions(this.debugToolbarMenu, this.allActions, this.toDispose, this.debugService, this.keybindingService, this.instantiationService); + return DebugToolbar.getActions(this.debugToolbarMenu, this.debugService, this.instantiationService); } get showInitialDebugActions(): boolean { diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index fb7bac29730b75c2a965a1cf90edce5226cc03ed..5134488b1fe9c7812d8671eddda224811e8454e2 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -51,6 +51,8 @@ export const CONTEXT_BREAKPOINT_SELECTED = new RawContextKey('breakpoin export const CONTEXT_CALLSTACK_ITEM_TYPE = new RawContextKey('callStackItemType', undefined); export const CONTEXT_LOADED_SCRIPTS_SUPPORTED = new RawContextKey('loadedScriptsSupported', false); export const CONTEXT_LOADED_SCRIPTS_ITEM_TYPE = new RawContextKey('loadedScriptsItemType', undefined); +export const CONTEXT_FOCUSED_SESSION_IS_ATTACH = new RawContextKey('focusedSessionIsAttach', false); +export const CONTEXT_STEP_BACK_SUPPORTED = new RawContextKey('stepBackSupported', false); export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug'; export const DEBUG_SCHEME = 'debug'; diff --git a/src/vs/workbench/contrib/debug/common/debugViewModel.ts b/src/vs/workbench/contrib/debug/common/debugViewModel.ts index 9f0eb34aca631d568b8304ef4e17f6b40ee6ca66..179e57ff34b643ac80d4413683dc3004c79b1993 100644 --- a/src/vs/workbench/contrib/debug/common/debugViewModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugViewModel.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 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 } 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 } 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'; export class ViewModel implements IViewModel { @@ -23,6 +24,8 @@ export class ViewModel implements IViewModel { private expressionSelectedContextKey: IContextKey; private breakpointSelectedContextKey: IContextKey; private loadedScriptsSupportedContextKey: IContextKey; + private stepBackSupportedContextKey: IContextKey; + private focusedSessionIsAttach: IContextKey; constructor(contextKeyService: IContextKeyService) { this._onDidFocusSession = new Emitter(); @@ -32,6 +35,8 @@ export class ViewModel implements IViewModel { this.expressionSelectedContextKey = CONTEXT_EXPRESSION_SELECTED.bindTo(contextKeyService); this.breakpointSelectedContextKey = CONTEXT_BREAKPOINT_SELECTED.bindTo(contextKeyService); 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); } getId(): string { @@ -59,6 +64,9 @@ export class ViewModel implements IViewModel { this._focusedSession = session; this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false); + this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false); + const attach = !!session && session.configuration.request === 'attach' && !isExtensionHostDebugging(session.configuration); + this.focusedSessionIsAttach.set(attach); if (shouldEmitForSession) { this._onDidFocusSession.fire(session); diff --git a/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts index 5cd18589cf696d16357aac1f0ffbd6b6ed14ccf1..bda8da684a762eee2fc088e42d310a7f4b9fbcda 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debug.contribution.ts @@ -22,14 +22,14 @@ 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_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, } 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 + ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction, TerminateThreadAction, StepBackAction, ReverseContinueAction, } 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'; @@ -240,6 +240,36 @@ registerCommands(); const statusBar = Registry.as(StatusExtensions.Statusbar); statusBar.registerStatusbarItem(new StatusbarItemDescriptor(DebugStatus, StatusbarAlignment.LEFT, 30 /* Low Priority */)); +// Debug toolbar + +const registerDebugToolbarItem = (id: string, title: string, icon: string, order: number, when?: ContextKeyExpr, precondition?: ContextKeyExpr) => { + MenuRegistry.appendMenuItem(MenuId.DebugToolbar, { + group: 'navigation', + when, + order, + command: { + id, + title, + iconLocation: { + light: URI.parse(require.toUrl(`vs/workbench/contrib/debug/browser/media/${icon}.svg`)), + dark: URI.parse(require.toUrl(`vs/workbench/contrib/debug/browser/media/${icon}-inverse.svg`)) + }, + precondition + } + }); +}; + +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')); + // View menu MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {