提交 099c23fe 编写于 作者: I isidor

repl: allow to inspect repl output of inactive sessions

上级 5bd6ebe2
......@@ -190,7 +190,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
public $customDebugAdapterRequest(sessionId: DebugSessionUUID, request: string, args: any): Thenable<any> {
const session = this.debugService.getSession(sessionId);
const session = this.debugService.getModel().getSessions(true).filter(s => s.getId() === sessionId).pop();
if (session) {
return session.customRequest(request, args).then(response => {
if (response && response.success) {
......
......@@ -12,7 +12,7 @@ import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { SelectActionItem, IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugService } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, IDebugSession } from 'vs/workbench/parts/debug/common/debug';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
......@@ -190,7 +190,7 @@ export class StartDebugActionItem implements IActionItem {
export class FocusSessionActionItem extends SelectActionItem {
constructor(
action: IAction,
@IDebugService private debugService: IDebugService,
@IDebugService protected debugService: IDebugService,
@IThemeService themeService: IThemeService,
@IContextViewService contextViewService: IContextViewService,
) {
......@@ -201,7 +201,7 @@ export class FocusSessionActionItem extends SelectActionItem {
this.toDispose.push(this.debugService.getViewModel().onDidFocusSession(() => {
const session = this.debugService.getViewModel().focusedSession;
if (session) {
const index = this.debugService.getModel().getSessions().indexOf(session);
const index = this.getSessions().indexOf(session);
this.select(index);
}
}));
......@@ -214,8 +214,12 @@ export class FocusSessionActionItem extends SelectActionItem {
private update() {
const session = this.debugService.getViewModel().focusedSession;
const sessions = this.debugService.getModel().getSessions();
const sessions = this.getSessions();
const names = sessions.map(s => s.getLabel());
this.setOptions(names, session ? sessions.indexOf(session) : undefined);
}
protected getSessions(): ReadonlyArray<IDebugSession> {
return this.debugService.getModel().getSessions();
}
}
......@@ -9,7 +9,6 @@ import * as lifecycle from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files';
import { IDebugService, State, IDebugSession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID }
......@@ -677,30 +676,6 @@ export class RemoveAllWatchExpressionsAction extends AbstractDebugAction {
}
}
export class ClearReplAction extends AbstractDebugAction {
static readonly ID = 'workbench.debug.panel.action.clearReplAction';
static LABEL = nls.localize('clearRepl', "Clear Console");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IPanelService private panelService: IPanelService
) {
super(id, label, 'debug-action clear-repl', debugService, keybindingService);
}
public run(): TPromise<any> {
const session = this.debugService.getViewModel().focusedSession;
if (session) {
session.removeReplExpressions();
aria.status(nls.localize('debugConsoleCleared', "Debug console was cleared"));
}
// focus back to repl
return this.panelService.openPanel(REPL_ID, true);
}
}
export class ToggleReplAction extends TogglePanelAction {
static readonly ID = 'workbench.debug.action.toggleRepl';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console');
......
......@@ -376,7 +376,7 @@ export interface IViewModel extends ITreeElement {
}
export interface IDebugModel extends ITreeElement {
getSessions(): ReadonlyArray<IDebugSession>;
getSessions(includeInactive?: boolean): ReadonlyArray<IDebugSession>;
getBreakpoints(filter?: { uri?: uri, lineNumber?: number, column?: number, enabledOnly?: boolean }): ReadonlyArray<IBreakpoint>;
areBreakpointsActivated(): boolean;
getFunctionBreakpoints(): ReadonlyArray<IFunctionBreakpoint>;
......@@ -772,11 +772,6 @@ export interface IDebugService {
*/
sourceIsNotAvailable(uri: uri): void;
/**
* returns Session with the given ID (or undefined if ID is not found)
*/
getSession(sessionId: string): IDebugSession;
/**
* Gets the current debug model.
*/
......
......@@ -17,7 +17,7 @@ import { distinct } from 'vs/base/common/arrays';
import { Range, IRange } from 'vs/editor/common/core/range';
import {
ITreeElement, IExpression, IExpressionContainer, IDebugSession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IDebugModel, IReplElementSource,
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint, State
} from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { commonSuffixLength } from 'vs/base/common/strings';
......@@ -751,16 +751,16 @@ export class DebugModel implements IDebugModel {
return 'root';
}
public getSessions(): IDebugSession[] {
return this.sessions;
public getSessions(includeInactive = false): IDebugSession[] {
// By default do not return inactive sesions.
// However we are still holding onto inactive sessions due to repl and debug service session revival (eh scenario)
return this.sessions.filter(s => includeInactive || s.state !== State.Inactive);
}
public addSession(session: IDebugSession): void {
// Make sure to remove all inactive sessions once a new session is started
this.sessions = this.sessions.filter(s => s.state !== State.Inactive);
this.sessions.push(session);
}
public removeSession(id: string): void {
this.sessions = this.sessions.filter(p => p.getId() !== id);
this._onDidChangeCallStack.fire();
}
......
......@@ -30,7 +30,7 @@ import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { DebugEditorModelManager } from 'vs/workbench/parts/debug/browser/debugEditorModelManager';
import {
StepOverAction, ClearReplAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction,
StepOverAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction,
ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction, TerminateThreadAction
} from 'vs/workbench/parts/debug/browser/debugActions';
import { DebugToolbar } from 'vs/workbench/parts/debug/browser/debugToolbar';
......@@ -147,7 +147,6 @@ 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(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL), 'Debug: Clear Console', 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);
......
......@@ -81,7 +81,6 @@ export class DebugService implements IDebugService {
private model: DebugModel;
private viewModel: ViewModel;
private configurationManager: ConfigurationManager;
private allSessions = new Map<string, IDebugSession>();
private toDispose: IDisposable[];
private debugType: IContextKey<string>;
private debugState: IContextKey<string>;
......@@ -138,7 +137,7 @@ export class DebugService implements IDebugService {
this.lifecycleService.onShutdown(this.dispose, this);
this.toDispose.push(this.broadcastService.onBroadcast(broadcast => {
const session = this.getSession(broadcast.payload.debugId);
const session = this.model.getSessions(true).filter(s => s.getId() === broadcast.payload.debugId).pop();
if (session) {
switch (broadcast.channel) {
......@@ -179,10 +178,6 @@ export class DebugService implements IDebugService {
}));
}
getSession(sessionId: string): IDebugSession {
return this.allSessions.get(sessionId);
}
getModel(): IDebugModel {
return this.model;
}
......@@ -271,10 +266,6 @@ export class DebugService implements IDebugService {
this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined).then(() =>
this.extensionService.whenInstalledExtensionsRegistered().then(() => {
if (this.model.getSessions().length === 0) {
this.allSessions.clear();
}
let config: IConfig, compound: ICompound;
if (!configOrName) {
configOrName = this.configurationManager.selectedConfiguration.name;
......@@ -431,7 +422,6 @@ export class DebugService implements IDebugService {
private doCreateSession(root: IWorkspaceFolder, configuration: { resolved: IConfig, unresolved: IConfig }): TPromise<boolean> {
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model);
this.allSessions.set(session.getId(), session);
// register listeners as the very first thing!
this.registerSessionListeners(session);
......
......@@ -90,6 +90,10 @@ export class DebugSession implements IDebugSession {
}
get state(): State {
if (!this.raw) {
return State.Inactive;
}
const focusedThread = this.debugService.getViewModel().focusedThread;
if (focusedThread && focusedThread.session === this) {
return focusedThread.stopped ? State.Stopped : State.Running;
......@@ -98,7 +102,7 @@ export class DebugSession implements IDebugSession {
return State.Stopped;
}
return !!this.raw ? State.Running : State.Inactive;
return State.Running;
}
get capabilities(): DebugProtocol.Capabilities {
......@@ -747,14 +751,13 @@ export class DebugSession implements IDebugSession {
shutdown(): void {
dispose(this.rawListeners);
this.model.clearThreads(this.getId(), true);
this.model.removeSession(this.getId());
this._onDidChangeState.fire();
this.fetchThreadsScheduler = undefined;
if (this.raw) {
this.raw.disconnect();
}
this.raw = undefined;
this.model.clearThreads(this.getId(), true);
this._onDidChangeState.fire();
}
//---- sources
......
......@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
import { URI as uri } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import * as errors from 'vs/base/common/errors';
import { IAction, IActionItem } from 'vs/base/common/actions';
import { IAction, IActionItem, Action } from 'vs/base/common/actions';
import * as dom from 'vs/base/browser/dom';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { isMacintosh } from 'vs/base/common/platform';
......@@ -29,7 +29,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ReplExpressionsRenderer, ReplExpressionsController, ReplExpressionsDataSource, ReplExpressionsActionProvider, ReplExpressionsAccessibilityProvider } from 'vs/workbench/parts/debug/electron-browser/replViewer';
import { ClearReplAction, FocusSessionAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { Panel } from 'vs/workbench/browser/panel';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
......@@ -41,7 +40,7 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { OpenMode, ClickBehavior } from 'vs/base/parts/tree/browser/treeDefaults';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { IDebugService, REPL_ID, DEBUG_SCHEME, CONTEXT_IN_DEBUG_REPL } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, REPL_ID, DEBUG_SCHEME, CONTEXT_IN_DEBUG_REPL, IDebugSession, State } from 'vs/workbench/parts/debug/common/debug';
import { HistoryNavigator } from 'vs/base/common/history';
import { IHistoryNavigationWidget } from 'vs/base/browser/history';
import { createAndBindHistoryNavigationWidgetScopedContextKeyService } from 'vs/platform/widget/browser/contextScopedHistoryWidget';
......@@ -68,10 +67,12 @@ export interface IPrivateReplService {
_serviceBrand: any;
acceptReplInput(): void;
getVisibleContent(): string;
selectSession(session: IDebugSession): void;
clearRepl(): void;
}
export class Repl extends Panel implements IPrivateReplService, IHistoryNavigationWidget {
public _serviceBrand: any;
_serviceBrand: any;
private static readonly HALF_WIDTH_TYPICAL = 'n';
......@@ -91,6 +92,8 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
private replInputHeight: number;
private model: ITextModel;
private historyNavigationEnablement: IContextKey<boolean>;
private scopedInstantiationService: IInstantiationService;
private replElementsChangeListener: IDisposable;
constructor(
@IDebugService private debugService: IDebugService,
......@@ -112,33 +115,11 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
private registerListeners(): void {
let replElementsChangeListener: IDisposable;
this._register(this.debugService.getViewModel().onDidFocusSession(session => {
if (replElementsChangeListener) {
replElementsChangeListener.dispose();
}
if (session) {
replElementsChangeListener = session.onDidChangeReplElements(() => {
this.refreshReplElements(session.getReplElements().length === 0);
});
if (this.tree && this.isVisible()) {
this.tree.setInput(session);
}
}
this.replInput.updateOptions({ readOnly: !session });
if (this.isVisible()) {
this.updateInputDecoration();
}
this.selectSession(session);
}));
this._register(this.panelService.onDidPanelOpen(panel => this.refreshReplElements(true)));
this._register(this.panelService.onDidPanelOpen(() => this.refreshReplElements(true)));
this._register(this.debugService.onDidNewSession(() => this.updateTitleArea()));
this._register(this.debugService.onDidEndSession(() => {
if (this.debugService.getModel().getSessions().length === 0) {
// Only hide the session drop down when there are 0 sessions
this.updateTitleArea();
}
}));
this._register(this.themeService.onThemeChange(() => {
if (this.isVisible()) {
this.updateInputDecoration();
......@@ -166,14 +147,14 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
}
public async create(parent: HTMLElement): Promise<void> {
async create(parent: HTMLElement): Promise<void> {
await super.create(parent);
this.container = dom.append(parent, $('.repl'));
this.treeContainer = dom.append(this.container, $('.repl-tree'));
this.createReplInput(this.container);
this.renderer = this.instantiationService.createInstance(ReplExpressionsRenderer);
const controller = this.instantiationService.createInstance(ReplExpressionsController, new ReplExpressionsActionProvider(this.instantiationService, this.replInput), MenuId.DebugConsoleContext, { openMode: OpenMode.SINGLE_CLICK, clickBehavior: ClickBehavior.ON_MOUSE_UP /* do not change, to preserve focus behaviour in input field */ });
const controller = this.instantiationService.createInstance(ReplExpressionsController, new ReplExpressionsActionProvider(this.clearReplAction, this.replInput), MenuId.DebugConsoleContext, { openMode: OpenMode.SINGLE_CLICK, clickBehavior: ClickBehavior.ON_MOUSE_UP /* do not change, to preserve focus behaviour in input field */ });
controller.toFocusOnClick = this.replInput;
this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, {
......@@ -184,7 +165,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}, replTreeOptions);
}
public setVisible(visible: boolean): Promise<void> {
setVisible(visible: boolean): Promise<void> {
if (!visible) {
dispose(this.model);
} else {
......@@ -193,7 +174,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
this.updateInputDecoration();
const focusedSession = this.debugService.getViewModel().focusedSession;
if (focusedSession && this.tree.getInput() !== focusedSession) {
this.tree.setInput(focusedSession);
this.selectSession(focusedSession);
}
}
......@@ -208,11 +189,11 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
this._register(scopedContextKeyService);
CONTEXT_IN_DEBUG_REPL.bindTo(scopedContextKeyService).set(true);
const scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection(
this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection(
[IContextKeyService, scopedContextKeyService], [IPrivateReplService, this]));
const options = getSimpleEditorOptions();
options.readOnly = true;
this.replInput = scopedInstantiationService.createInstance(CodeEditorWidget, this.replInputContainer, options, getSimpleCodeEditorWidgetOptions());
this.replInput = this.scopedInstantiationService.createInstance(CodeEditorWidget, this.replInputContainer, options, getSimpleCodeEditorWidgetOptions());
modes.CompletionProviderRegistry.register({ scheme: DEBUG_SCHEME, pattern: '**/replinput', hasAccessToAllModels: true }, {
triggerCharacters: ['.'],
......@@ -265,19 +246,44 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
}
public showPreviousValue(): void {
showPreviousValue(): void {
this.navigateHistory(true);
}
public showNextValue(): void {
showNextValue(): void {
this.navigateHistory(false);
}
public acceptReplInput(): void {
const viewModel = this.debugService.getViewModel();
const session = viewModel.focusedSession;
selectSession(session: IDebugSession): void {
if (this.replElementsChangeListener) {
this.replElementsChangeListener.dispose();
}
if (session) {
session.addReplExpression(viewModel.focusedStackFrame, this.replInput.getValue());
this.replElementsChangeListener = session.onDidChangeReplElements(() => {
this.refreshReplElements(session.getReplElements().length === 0);
});
if (this.tree && this.isVisible() && this.tree.getInput() !== session) {
this.tree.setInput(session);
}
}
this.replInput.updateOptions({ readOnly: this.isReadonly });
if (this.isVisible()) {
this.updateInputDecoration();
}
}
clearRepl(): void {
const session: IDebugSession = this.tree.getInput();
session.removeReplExpressions();
this.replInput.focus();
}
acceptReplInput(): void {
const session: IDebugSession = this.tree.getInput();
if (session) {
session.addReplExpression(this.debugService.getViewModel().focusedStackFrame, this.replInput.getValue());
this.history.add(this.replInput.getValue());
this.replInput.setValue('');
// Trigger a layout to shrink a potential multi line input
......@@ -286,7 +292,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
}
public getVisibleContent(): string {
getVisibleContent(): string {
let text = '';
const navigator = this.tree.getNavigator();
// skip first navigator element - the root node
......@@ -300,7 +306,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
return text;
}
public layout(dimension: dom.Dimension): void {
layout(dimension: dom.Dimension): void {
this.dimension = dimension;
if (this.tree) {
this.renderer.setWidth(dimension.width - 25, this.characterWidth);
......@@ -313,6 +319,16 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
this.replInput.layout({ width: dimension.width - 20, height: this.replInputHeight });
}
get isReadonly(): boolean {
// Do not allow to edit inactive sessions
const session: IDebugSession = this.tree.getInput();
if (session && session.state !== State.Inactive) {
return false;
}
return true;
}
@memoize
private get characterWidth(): number {
const characterWidthSurveyor = dom.append(this.container, $('.surveyor'));
......@@ -325,22 +341,22 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
return characterWidthSurveyor.clientWidth / characterWidthSurveyor.textContent.length;
}
public focus(): void {
focus(): void {
this.replInput.focus();
}
getActionItem(action: IAction): IActionItem {
if (action.id === FocusSessionAction.ID) {
return this.focusSessionActionItem;
if (action.id === SelectReplAction.ID) {
return this.instantiationService.createInstance(SelectReplActionItem, this.selectReplAction);
}
return undefined;
}
public getActions(): IAction[] {
getActions(): IAction[] {
const result: IAction[] = [];
if (this.debugService.getModel().getSessions().length > 1) {
result.push(this.focusSessionAction);
if (this.debugService.getModel().getSessions(true).length > 1) {
result.push(this.selectReplAction);
}
result.push(this.clearReplAction);
......@@ -349,7 +365,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
return result;
}
public shutdown(): void {
shutdown(): void {
const replHistory = this.history.getHistory();
if (replHistory.length) {
this.storageService.store(HISTORY_STORAGE_KEY, JSON.stringify(replHistory), StorageScope.WORKSPACE);
......@@ -359,17 +375,13 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
@memoize
private get focusSessionAction(): FocusSessionAction {
return this.instantiationService.createInstance(FocusSessionAction, FocusSessionAction.ID, FocusSessionAction.LABEL);
private get selectReplAction(): SelectReplAction {
return this.scopedInstantiationService.createInstance(SelectReplAction, SelectReplAction.ID, SelectReplAction.LABEL);
}
@memoize
private get clearReplAction(): ClearReplAction {
return this.instantiationService.createInstance(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL);
}
private get focusSessionActionItem(): FocusSessionActionItem {
return this.instantiationService.createInstance(FocusSessionActionItem, this.focusSessionAction);
return this.scopedInstantiationService.createInstance(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL);
}
private updateInputDecoration(): void {
......@@ -378,7 +390,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
const decorations: IDecorationOptions[] = [];
if (!this.debugService.getViewModel().focusedSession) {
if (this.isReadonly) {
decorations.push({
range: {
startLineNumber: 0,
......@@ -398,7 +410,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
this.replInput.setDecorations(DECORATION_KEY, decorations);
}
public dispose(): void {
dispose(): void {
this.replInput.dispose();
super.dispose();
}
......@@ -420,7 +432,7 @@ class AcceptReplInputAction extends EditorAction {
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void | TPromise<void> {
run(accessor: ServicesAccessor, editor: ICodeEditor): void | TPromise<void> {
SuggestController.get(editor).acceptSelectedSuggestion();
accessor.get(IPrivateReplService).acceptReplInput();
}
......@@ -437,7 +449,7 @@ export class ReplCopyAllAction extends EditorAction {
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void | TPromise<void> {
run(accessor: ServicesAccessor, editor: ICodeEditor): void | TPromise<void> {
clipboard.writeText(accessor.get(IPrivateReplService).getVisibleContent());
}
}
......@@ -456,3 +468,54 @@ registerEditorCommand(new SuggestCommand({
primary: KeyCode.RightArrow
}
}));
class SelectReplActionItem extends FocusSessionActionItem {
protected getSessions(): ReadonlyArray<IDebugSession> {
return this.debugService.getModel().getSessions(true);
}
}
class SelectReplAction extends Action {
static readonly ID = 'workbench.action.debug.selectRepl';
static LABEL = nls.localize('selectRepl', "Select Debug Console");
constructor(id: string, label: string,
@IDebugService private debugService: IDebugService,
@IPrivateReplService private replService: IPrivateReplService
) {
super(id, label);
}
run(sessionName: string): TPromise<any> {
const session = this.debugService.getModel().getSessions(true).filter(p => p.getLabel() === sessionName).pop();
// If session is already the focused session we need to manualy update the tree since view model will not send a focused change event
if (session && session.state !== State.Inactive && session !== this.debugService.getViewModel().focusedSession) {
this.debugService.focusStackFrame(undefined, undefined, session, true);
} else {
this.replService.selectSession(session);
}
return Promise.resolve(undefined);
}
}
class ClearReplAction extends Action {
static readonly ID = 'workbench.debug.panel.action.clearReplAction';
static LABEL = nls.localize('clearRepl', "Clear Console");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IPrivateReplService private replService: IPrivateReplService
) {
super(id, label, 'debug-action clear-repl');
}
public run(): TPromise<any> {
this.replService.clearRepl();
aria.status(nls.localize('debugConsoleCleared', "Debug console was cleared"));
// focus back to repl
return Promise.resolve(undefined);
}
}
......@@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { IAction } from 'vs/base/common/actions';
import { IAction, Action } from 'vs/base/common/actions';
import * as lifecycle from 'vs/base/common/lifecycle';
import { isFullWidthCharacter, removeAnsiEscapeCodes, endsWith } from 'vs/base/common/strings';
import { IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
......@@ -17,7 +17,7 @@ import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults';
import { IExpressionContainer, IExpression, IReplElementSource } from 'vs/workbench/parts/debug/common/debug';
import { RawObjectReplElement, Expression, SimpleReplElement, Variable } from 'vs/workbench/parts/debug/common/debugModel';
import { renderVariable, renderExpressionValue, IVariableTemplateData, BaseDebugController } from 'vs/workbench/parts/debug/browser/baseDebugView';
import { ClearReplAction, ReplCollapseAllAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { ReplCollapseAllAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { CopyAction, CopyAllAction } from 'vs/workbench/parts/debug/electron-browser/electronDebugActions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -317,7 +317,7 @@ export class ReplExpressionsAccessibilityProvider implements IAccessibilityProvi
export class ReplExpressionsActionProvider implements IActionProvider {
constructor(private instantiationService: IInstantiationService, private toFocus: { focus(): void }) {
constructor(private clearReplAction: Action, private toFocus: { focus(): void }) {
// noop
}
......@@ -339,7 +339,7 @@ export class ReplExpressionsActionProvider implements IActionProvider {
actions.push(new CopyAllAction(CopyAllAction.ID, CopyAllAction.LABEL, tree));
actions.push(new ReplCollapseAllAction(tree, this.toFocus));
actions.push(new Separator());
actions.push(this.instantiationService.createInstance(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL));
actions.push(this.clearReplAction);
return Promise.resolve(actions);
}
......
......@@ -17,10 +17,6 @@ export class MockDebugService implements IDebugService {
public _serviceBrand: any;
getSession(sessionId: string): IDebugSession {
return undefined;
}
public get state(): State {
return null;
}
......
......@@ -113,7 +113,7 @@ suite('Debug - Model', () => {
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
model.addSession(session);
assert.equal(model.getSessions().length, 1);
assert.equal(model.getSessions(true).length, 1);
model.rawUpdate({
sessionId: session.getId(),
threadId: threadId,
......@@ -127,9 +127,7 @@ suite('Debug - Model', () => {
model.clearThreads(session.getId(), true);
assert.equal(session.getThread(threadId), null);
assert.equal(model.getSessions().length, 1);
model.removeSession(session.getId());
assert.equal(model.getSessions().length, 0);
assert.equal(model.getSessions(true).length, 1);
});
test('threads multiple wtih allThreadsStopped', () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册