debugActions.ts 31.6 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import nls = require('vs/nls');
import actions = require('vs/base/common/actions');
import lifecycle = require('vs/base/common/lifecycle');
I
isidor 已提交
9
import { TPromise } from 'vs/base/common/winjs.base';
I
isidor 已提交
10
import { Range } from 'vs/editor/common/core/range';
E
Erich Gamma 已提交
11
import editorCommon = require('vs/editor/common/editorCommon');
I
isidor 已提交
12
import editorbrowser = require('vs/editor/browser/editorBrowser');
A
Alex Dima 已提交
13 14
import { EditorAction } from 'vs/editor/common/editorAction';
import { Behaviour } from 'vs/editor/common/editorActionEnablement';
15
import { IEventService } from 'vs/platform/event/common/event';
I
isidor 已提交
16
import { IKeybindingService } from 'vs/platform/keybinding/common/keybindingService';
17
import { EventType, CompositeEvent } from 'vs/workbench/common/events';
E
Erich Gamma 已提交
18 19
import debug = require('vs/workbench/parts/debug/common/debug');
import model = require('vs/workbench/parts/debug/common/debugModel');
I
isidor 已提交
20 21
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
E
Erich Gamma 已提交
22
import { IViewletService } from 'vs/workbench/services/viewlet/common/viewletService';
23
import { clipboard } from 'electron';
E
Erich Gamma 已提交
24 25 26 27 28 29 30
import IDebugService = debug.IDebugService;

export class AbstractDebugAction extends actions.Action {

	protected debugService: IDebugService;
	private keybindingService: IKeybindingService;
	protected toDispose: lifecycle.IDisposable[];
31
	private keybinding: string;
E
Erich Gamma 已提交
32 33 34 35 36 37

	constructor(id: string, label: string, cssClass: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, cssClass, false);
		this.debugService = debugService;
		this.keybindingService = keybindingService;
		this.toDispose = [];
38
		this.toDispose.push(this.debugService.onDidChangeState(() => this.updateEnablement()));
E
Erich Gamma 已提交
39

I
isidor 已提交
40
		const keys = this.keybindingService.lookupKeybindings(id).map(k => this.keybindingService.getLabelFor(k));
E
Erich Gamma 已提交
41
		if (keys && keys.length) {
42
			this.keybinding = keys[0];
E
Erich Gamma 已提交
43 44
		}

45
		this.updateLabel(label);
E
Erich Gamma 已提交
46 47 48
		this.updateEnablement();
	}

I
isidor 已提交
49
	public run(e?: any): TPromise<any> {
E
Erich Gamma 已提交
50 51 52
		throw new Error('implement me');
	}

53 54 55 56 57 58 59 60
	protected updateLabel(newLabel: string): void {
		if (this.keybinding) {
			this.label = nls.localize('debugActionLabelAndKeybinding', "{0} ({1})", newLabel, this.keybinding);
		} else {
			this.label = newLabel;
		}
	}

E
Erich Gamma 已提交
61 62 63 64 65 66 67 68 69 70
	protected updateEnablement(): void {
		this.enabled = this.isEnabled();
	}

	protected isEnabled(): boolean {
		return this.debugService.getState() !== debug.State.Disabled;
	}

	public dispose(): void {
		this.debugService = null;
J
Joao Moreno 已提交
71
		this.toDispose = lifecycle.dispose(this.toDispose);
E
Erich Gamma 已提交
72 73 74 75 76 77 78

		super.dispose();
	}
}

export class ConfigureAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.configure';
I
isidor 已提交
79
	static LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json');
E
Erich Gamma 已提交
80 81

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
82
		super(id, label, 'debug-action configure', debugService, keybindingService);
83 84
		this.toDispose.push(debugService.getConfigurationManager().onDidConfigurationChange((configurationName) => {
			this.class = configurationName ? 'debug-action configure' : 'debug-action configure notification';
85
		}));
E
Erich Gamma 已提交
86 87
	}

I
isidor 已提交
88
	public run(event?: any): TPromise<any> {
I
isidor 已提交
89
		const sideBySide = !!(event && (event.ctrlKey || event.metaKey));
90
		return this.debugService.getConfigurationManager().openConfigFile(sideBySide);
E
Erich Gamma 已提交
91 92 93 94 95 96 97 98 99 100 101
	}
}

export class SelectConfigAction extends AbstractDebugAction {
	static ID = 'workbench.debug.action.setActiveConfig';
	static LABEL = nls.localize('selectConfig', "Select Configuration");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action select-active-config', debugService, keybindingService);
	}

I
isidor 已提交
102
	public run(configName: string): TPromise<any> {
103
		return this.debugService.getConfigurationManager().setConfiguration(configName);
E
Erich Gamma 已提交
104 105 106 107 108 109 110 111 112
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Inactive;
	}
}

export class StartDebugAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.start';
113
	static LABEL = nls.localize('startDebug', "Start Debugging");
E
Erich Gamma 已提交
114 115 116 117 118 119

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action start', debugService, keybindingService);
		this.updateEnablement();
	}

I
isidor 已提交
120
	public run(): TPromise<any> {
I
isidor 已提交
121
		return this.debugService.createSession(false);
E
Erich Gamma 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Inactive;
	}
}

export class RestartDebugAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.restart';
	static LABEL = nls.localize('restartDebug', "Restart");
	static RECONNECT_LABEL = nls.localize('reconnectDebug', "Reconnect");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action restart', debugService, keybindingService);
		this.updateEnablement();
137
		this.toDispose.push(this.debugService.onDidChangeState(() => {
138 139
			const session = this.debugService.getActiveSession();
			if (session) {
140
				this.updateLabel(session.isAttach ? RestartDebugAction.RECONNECT_LABEL : RestartDebugAction.LABEL);
E
Erich Gamma 已提交
141 142 143 144
			}
		}));
	}

I
isidor 已提交
145
	public run(): TPromise<any> {
E
Erich Gamma 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
		return this.debugService.restartSession();
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() !== debug.State.Inactive;
	}
}

export class StepOverDebugAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.stepOver';
	static LABEL = nls.localize('stepOverDebug', "Step Over");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action step-over', debugService, keybindingService);
	}

I
isidor 已提交
162
	public run(): TPromise<any> {
163
		return this.debugService.getActiveSession().next({ threadId: this.debugService.getViewModel().getFocusedThreadId() });
E
Erich Gamma 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Stopped;
	}
}

export class StepIntoDebugAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.stepInto';
	static LABEL = nls.localize('stepIntoDebug', "Step Into");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action step-into', debugService, keybindingService);
	}

I
isidor 已提交
179
	public run(): TPromise<any> {
E
Erich Gamma 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
		return this.debugService.getActiveSession().stepIn({ threadId: this.debugService.getViewModel().getFocusedThreadId() });
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Stopped;
	}
}

export class StepOutDebugAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.stepOut';
	static LABEL = nls.localize('stepOutDebug', "Step Out");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action step-out', debugService, keybindingService);
	}

I
isidor 已提交
196
	public run(): TPromise<any> {
E
Erich Gamma 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
		return this.debugService.getActiveSession().stepOut({ threadId: this.debugService.getViewModel().getFocusedThreadId() });
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Stopped;
	}
}

export class StopDebugAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.stop';
	static LABEL = nls.localize('stopDebug', "Stop");
	static DISCONNECT_LABEL = nls.localize('disconnectDebug', "Disconnect");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action stop', debugService, keybindingService);
212
		this.toDispose.push(this.debugService.onDidChangeState(() => {
213 214
			const session = this.debugService.getActiveSession();
			if (session) {
215
				this.updateLabel(session.isAttach ? StopDebugAction.DISCONNECT_LABEL : StopDebugAction.LABEL);
E
Erich Gamma 已提交
216 217 218 219
			}
		}));
	}

I
isidor 已提交
220
	public run(): TPromise<any> {
E
Erich Gamma 已提交
221
		var session = this.debugService.getActiveSession();
A
Alex Dima 已提交
222
		return session ? session.disconnect(false, true) : TPromise.as(null);
E
Erich Gamma 已提交
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() !== debug.State.Inactive;
	}
}

export class ContinueAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.continue';
	static LABEL = nls.localize('continueDebug', "Continue");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action continue', debugService, keybindingService);
	}

I
isidor 已提交
238
	public run(): TPromise<any> {
E
Erich Gamma 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
		return this.debugService.getActiveSession().continue({ threadId: this.debugService.getViewModel().getFocusedThreadId() });
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Stopped;
	}
}

export class PauseAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.pause';
	static LABEL = nls.localize('pauseDebug', "Pause");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action pause', debugService, keybindingService);
	}

I
isidor 已提交
255
	public run(): TPromise<any> {
E
Erich Gamma 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
		return this.debugService.getActiveSession().pause({ threadId: this.debugService.getViewModel().getFocusedThreadId() });
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Running;
	}
}

export class RemoveBreakpointAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.removeBreakpoint';
	static LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action remove', debugService, keybindingService);
		this.updateEnablement();
	}

I
isidor 已提交
273
	public run(breakpoint: debug.IBreakpoint): TPromise<any> {
274
		return breakpoint instanceof model.Breakpoint ? this.debugService.toggleBreakpoint({ uri: breakpoint.source.uri, lineNumber: breakpoint.lineNumber })
275
			: this.debugService.removeFunctionBreakpoints(breakpoint.getId());
E
Erich Gamma 已提交
276 277 278 279 280 281 282 283
	}
}

export class RemoveAllBreakpointsAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.removeAllBreakpoints';
	static LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
284
		super(id, label, 'debug-action remove-all', debugService, keybindingService);
285
		this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
E
Erich Gamma 已提交
286 287
	}

I
isidor 已提交
288 289
	public run(): TPromise<any> {
		return TPromise.join([this.debugService.removeAllBreakpoints(), this.debugService.removeFunctionBreakpoints()]);
E
Erich Gamma 已提交
290 291 292
	}

	protected isEnabled(): boolean {
293
		return super.isEnabled() && (this.debugService.getModel().getBreakpoints().length > 0 || this.debugService.getModel().getFunctionBreakpoints().length > 0);
E
Erich Gamma 已提交
294 295 296 297 298
	}
}

export class ToggleEnablementAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.toggleBreakpointEnablement';
299
	static LABEL = nls.localize('toggleEnablement', "Enable/Disable Breakpoint");
E
Erich Gamma 已提交
300 301 302 303 304

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action toggle-enablement', debugService, keybindingService);
	}

I
isidor 已提交
305
	public run(element: debug.IEnablement): TPromise<any> {
E
Erich Gamma 已提交
306 307 308 309 310 311 312 313 314 315
		return this.debugService.toggleEnablement(element);
	}
}

export class EnableAllBreakpointsAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.enableAllBreakpoints';
	static LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action enable-all-breakpoints', debugService, keybindingService);
316
		this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
E
Erich Gamma 已提交
317 318
	}

I
isidor 已提交
319
	public run(): TPromise<any> {
E
Erich Gamma 已提交
320 321 322 323
		return this.debugService.enableOrDisableAllBreakpoints(true);
	}

	protected isEnabled(): boolean {
324 325
		const model = this.debugService.getModel();
		return super.isEnabled() && (<debug.IEnablement[]> model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled);
E
Erich Gamma 已提交
326 327 328 329 330 331 332 333 334
	}
}

export class DisableAllBreakpointsAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.disableAllBreakpoints';
	static LABEL = nls.localize('disableAllBreakpoints', "Disable All Breakpoints");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action disable-all-breakpoints', debugService, keybindingService);
335
		this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
E
Erich Gamma 已提交
336 337
	}

I
isidor 已提交
338
	public run(): TPromise<any> {
E
Erich Gamma 已提交
339 340 341 342
		return this.debugService.enableOrDisableAllBreakpoints(false);
	}

	protected isEnabled(): boolean {
343 344
		const model = this.debugService.getModel();
		return super.isEnabled() && (<debug.IEnablement[]> model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled);
E
Erich Gamma 已提交
345 346 347 348 349 350 351 352 353 354
	}
}

export class ToggleBreakpointsActivatedAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.toggleBreakpointsActivatedAction';
	static ACTIVATE_LABEL = nls.localize('activateBreakpoints', "Activate Breakpoints");
	static DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action breakpoints-activate', debugService, keybindingService);
355 356
		this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL);

357
		this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => {
358
			this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL);
359
			this.updateEnablement();
E
Erich Gamma 已提交
360 361 362
		}));
	}

I
isidor 已提交
363
	public run(): TPromise<any> {
E
Erich Gamma 已提交
364 365
		return this.debugService.toggleBreakpointsActivated();
	}
366 367 368 369

	protected isEnabled(): boolean {
		return (this.debugService.getModel().getFunctionBreakpoints().length + this.debugService.getModel().getBreakpoints().length) > 0;
	}
E
Erich Gamma 已提交
370 371 372 373 374 375 376
}

export class ReapplyBreakpointsAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.reapplyBreakpointsAction';
	static LABEL = nls.localize('reapplyAllBreakpoints', "Reapply All Breakpoints");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
377
		super(id, label, null, debugService, keybindingService);
378
		this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
E
Erich Gamma 已提交
379 380
	}

I
isidor 已提交
381
	public run(): TPromise<any> {
E
Erich Gamma 已提交
382 383 384 385
		return this.debugService.sendAllBreakpoints();
	}

	protected isEnabled(): boolean {
386 387
		return super.isEnabled() && this.debugService.getState() !== debug.State.Disabled && this.debugService.getState() !== debug.State.Inactive &&
			((this.debugService.getModel().getFunctionBreakpoints().length + this.debugService.getModel().getBreakpoints().length) > 0);
E
Erich Gamma 已提交
388 389 390
	}
}

I
isidor 已提交
391 392 393 394 395 396 397 398
export class AddFunctionBreakpointAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction';
	static LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action add-function-breakpoint', debugService, keybindingService);
	}

I
isidor 已提交
399
	public run(): TPromise<any> {
I
isidor 已提交
400
		this.debugService.addFunctionBreakpoint();
A
Alex Dima 已提交
401
		return TPromise.as(null);
I
isidor 已提交
402 403 404
	}
}

405 406 407 408 409 410 411 412 413 414 415 416 417 418
export class RenameFunctionBreakpointAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.renameFunctionBreakpointAction';
	static LABEL = nls.localize('renameFunctionBreakpoint', "Rename Function Breakpoint");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, null, debugService, keybindingService);
	}

	public run(fbp: debug.IFunctionBreakpoint): TPromise<any> {
		this.debugService.getViewModel().setSelectedFunctionBreakpoint(fbp);
		return TPromise.as(null);
	}
}

419 420 421 422
export class AddConditionalBreakpointAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.addConditionalBreakpointAction';
	static LABEL = nls.localize('addConditionalBreakpoint', "Add Conditional Breakpoint");

I
isidor 已提交
423
	constructor(id: string, label: string, private editor: editorbrowser.ICodeEditor, private lineNumber: number, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
424 425 426
		super(id, label, null, debugService, keybindingService);
	}

I
isidor 已提交
427
	public run(): TPromise<any> {
I
isidor 已提交
428
		return this.debugService.editBreakpoint(this.editor, this.lineNumber);
429 430 431 432 433 434 435
	}
}

export class EditConditionalBreakpointAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.editConditionalBreakpointAction';
	static LABEL = nls.localize('editConditionalBreakpoint', "Edit Breakpoint");

I
isidor 已提交
436
	constructor(id: string, label: string, private editor: editorbrowser.ICodeEditor, private lineNumber: number, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
437 438 439
		super(id, label, null, debugService, keybindingService);
	}

I
isidor 已提交
440
	public run(breakpoint: debug.IBreakpoint): TPromise<any> {
I
isidor 已提交
441
		return this.debugService.editBreakpoint(this.editor, this.lineNumber);
442 443 444
	}
}

E
Erich Gamma 已提交
445 446 447
export class ToggleBreakpointAction extends EditorAction {
	static ID = 'editor.debug.action.toggleBreakpoint';

I
isidor 已提交
448
	constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, @IDebugService private debugService: IDebugService) {
E
Erich Gamma 已提交
449 450 451
		super(descriptor, editor, Behaviour.TextFocus);
	}

I
isidor 已提交
452
	public run(): TPromise<any> {
E
Erich Gamma 已提交
453
		if (this.debugService.getState() !== debug.State.Disabled) {
I
isidor 已提交
454 455
			const lineNumber = this.editor.getPosition().lineNumber;
			const modelUrl = this.editor.getModel().getAssociatedResource();
456
			if (this.debugService.getConfigurationManager().canSetBreakpointsIn(this.editor.getModel())) {
457
				return this.debugService.toggleBreakpoint({ uri: modelUrl, lineNumber: lineNumber });
E
Erich Gamma 已提交
458 459 460
			}
		}

461 462 463 464 465 466 467 468 469 470 471
		return TPromise.as(null);
	}
}

export class EditorConditionalBreakpointAction extends EditorAction {
	static ID = 'editor.debug.action.conditionalBreakpoint';

	constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, @IDebugService private debugService: IDebugService) {
		super(descriptor, editor, Behaviour.TextFocus);
	}

I
isidor 已提交
472
	public run(): TPromise<any> {
473 474
		if (this.debugService.getState() !== debug.State.Disabled) {
			const lineNumber = this.editor.getPosition().lineNumber;
475
			if (this.debugService.getConfigurationManager().canSetBreakpointsIn(this.editor.getModel())) {
476 477 478 479
				return this.debugService.editBreakpoint(<editorbrowser.ICodeEditor>this.editor, lineNumber);
			}
		}

E
Erich Gamma 已提交
480 481 482 483 484 485 486 487 488 489 490 491
		return TPromise.as(null);
	}
}

export class CopyValueAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.copyValue';
	static LABEL = nls.localize('copyValue', "Copy Value");

	constructor(id: string, label: string, private value: any, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action copy-value', debugService, keybindingService);
	}

I
isidor 已提交
492
	public run(): TPromise<any> {
E
Erich Gamma 已提交
493 494 495
		if (this.value instanceof model.Variable) {
			const frameId = this.debugService.getViewModel().getFocusedStackFrame().frameId;
			const session = this.debugService.getActiveSession();
496
			return session.evaluate({ expression: model.getFullExpressionName(this.value, session.getType()), frameId }).then(result => {
E
Erich Gamma 已提交
497 498 499 500 501
				clipboard.writeText(result.body.result);
			}, err => clipboard.writeText(this.value.value));
		}

		clipboard.writeText(this.value);
A
Alex Dima 已提交
502
		return TPromise.as(null);
E
Erich Gamma 已提交
503 504 505 506 507 508 509 510 511 512 513 514 515 516
	}
}

export class RunToCursorAction extends EditorAction {
	static ID = 'editor.debug.action.runToCursor';

	private debugService: IDebugService;

	constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor, @IDebugService debugService: IDebugService) {
		super(descriptor, editor, Behaviour.TextFocus);
		this.debugService = debugService;
	}

	public run(): TPromise<boolean> {
I
isidor 已提交
517 518
		const lineNumber = this.editor.getPosition().lineNumber;
		const uri = this.editor.getModel().getAssociatedResource();
E
Erich Gamma 已提交
519 520

		this.debugService.getActiveSession().addOneTimeListener(debug.SessionEvents.STOPPED, () => {
521
			this.debugService.toggleBreakpoint({ uri, lineNumber });
E
Erich Gamma 已提交
522 523
		});

524
		return this.debugService.toggleBreakpoint({ uri, lineNumber }).then(() => {
E
Erich Gamma 已提交
525 526 527 528 529 530 531
			return this.debugService.getActiveSession().continue({ threadId: this.debugService.getViewModel().getFocusedThreadId() }).then(response => {
				return response.success;
			});
		});
	}

	public getGroupId(): string {
532
		return '5_debug/1_run_to_cursor';
E
Erich Gamma 已提交
533 534 535 536 537 538 539
	}

	public shouldShowInContextMenu(): boolean {
		if (this.debugService.getState() !== debug.State.Stopped) {
			return false;
		}

I
isidor 已提交
540 541 542
		const lineNumber = this.editor.getPosition().lineNumber;
		const uri = this.editor.getModel().getAssociatedResource();
		const bps = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === lineNumber && bp.source.uri.toString() === uri.toString());
E
Erich Gamma 已提交
543

I
isidor 已提交
544
		// breakpoint must not be on position (no need for this action).
E
Erich Gamma 已提交
545 546 547 548 549 550 551 552 553 554
		return bps.length === 0;
	}
}

export class AddWatchExpressionAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.addWatchExpression';
	static LABEL = nls.localize('addWatchExpression', "Add Expression");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action add-watch-expression', debugService, keybindingService);
555
		this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement()));
E
Erich Gamma 已提交
556 557
	}

I
isidor 已提交
558
	public run(): TPromise<any> {
E
Erich Gamma 已提交
559 560 561 562 563 564 565 566 567 568 569
		return this.debugService.addWatchExpression();
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getModel().getWatchExpressions().every(we => !!we.name);
	}
}

export class SelectionToWatchExpressionsAction extends EditorAction {
	static ID = 'editor.debug.action.selectionToWatch';

I
isidor 已提交
570
	constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor, @IDebugService private debugService: IDebugService, @IViewletService private viewletService: IViewletService) {
E
Erich Gamma 已提交
571 572 573
		super(descriptor, editor, Behaviour.TextFocus);
	}

I
isidor 已提交
574
	public run(): TPromise<any> {
I
isidor 已提交
575
		const text = this.editor.getModel().getValueInRange(this.editor.getSelection());
E
Erich Gamma 已提交
576 577 578 579
		return this.viewletService.openViewlet(debug.VIEWLET_ID).then(() => this.debugService.addWatchExpression(text));
	}

	public getGroupId(): string {
580
		return '5_debug/3_selection_to_watch';
E
Erich Gamma 已提交
581 582 583
	}

	public shouldShowInContextMenu(): boolean {
I
isidor 已提交
584 585
		const selection = this.editor.getSelection();
		const text = this.editor.getModel().getValueInRange(selection);
E
Erich Gamma 已提交
586

587
		return !!selection && !selection.isEmpty() && this.debugService.getConfigurationManager().configurationName && text && /\S/.test(text);
E
Erich Gamma 已提交
588 589 590 591 592 593
	}
}

export class SelectionToReplAction extends EditorAction {
	static ID = 'editor.debug.action.selectionToRepl';

594 595 596 597 598 599
	constructor(
		descriptor: editorCommon.IEditorActionDescriptorData,
		editor: editorCommon.ICommonCodeEditor,
		@IDebugService private debugService: IDebugService,
		@IPanelService private panelService: IPanelService
	) {
E
Erich Gamma 已提交
600 601 602
		super(descriptor, editor, Behaviour.TextFocus);
	}

I
isidor 已提交
603
	public run(): TPromise<any> {
I
isidor 已提交
604
		const text = this.editor.getModel().getValueInRange(this.editor.getSelection());
605 606
		return this.debugService.addReplExpression(text)
			.then(() => this.panelService.openPanel(debug.REPL_ID, true));
E
Erich Gamma 已提交
607 608 609
	}

	public getGroupId(): string {
610
		return '5_debug/2_selection_to_repl';
E
Erich Gamma 已提交
611 612 613
	}

	public shouldShowInContextMenu(): boolean {
I
isidor 已提交
614
		const selection = this.editor.getSelection();
E
Erich Gamma 已提交
615 616 617 618
		return !!selection && !selection.isEmpty() && this.debugService.getState() === debug.State.Stopped;
	}
}

I
isidor 已提交
619 620 621
export class ShowDebugHoverAction extends EditorAction {
	static ID = 'editor.debug.action.showDebugHover';

622
	constructor(descriptor: editorCommon.IEditorActionDescriptorData, editor: editorCommon.ICommonCodeEditor) {
I
isidor 已提交
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
		super(descriptor, editor, Behaviour.TextFocus);
	}

	public run(): TPromise<any> {
		const position = this.editor.getPosition();
		const word = this.editor.getModel().getWordAtPosition(position);
		if (!word) {
			return TPromise.as(null);
		}

		const range = new Range(position.lineNumber, position.column, position.lineNumber, word.endColumn);
		return (<debug.IDebugEditorContribution>this.editor.getContribution(debug.EDITOR_CONTRIBUTION_ID)).showHover(range, word.word, true);
	}
}

E
Erich Gamma 已提交
638 639 640 641 642 643 644 645
export class AddToWatchExpressionsAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.addToWatchExpressions';
	static LABEL = nls.localize('addToWatchExpressions', "Add to Watch");

	constructor(id: string, label: string, private expression: debug.IExpression, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action add-to-watch', debugService, keybindingService);
	}

I
isidor 已提交
646
	public run(): TPromise<any> {
647
		return this.debugService.addWatchExpression(model.getFullExpressionName(this.expression, this.debugService.getActiveSession().getType()));
E
Erich Gamma 已提交
648 649 650 651 652 653 654 655 656 657 658
	}
}

export class RenameWatchExpressionAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.renameWatchExpression';
	static LABEL = nls.localize('renameWatchExpression', "Rename Expression");

	constructor(id: string, label: string, private expression: model.Expression, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action rename', debugService, keybindingService);
	}

I
isidor 已提交
659
	public run(): TPromise<any> {
E
Erich Gamma 已提交
660
		this.debugService.getViewModel().setSelectedExpression(this.expression);
A
Alex Dima 已提交
661
		return TPromise.as(null);
E
Erich Gamma 已提交
662 663 664 665 666 667 668 669 670 671 672
	}
}

export class RemoveWatchExpressionAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.removeWatchExpression';
	static LABEL = nls.localize('removeWatchExpression', "Remove Expression");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, 'debug-action remove', debugService, keybindingService);
	}

I
isidor 已提交
673
	public run(expression: model.Expression): TPromise<any> {
E
Erich Gamma 已提交
674
		this.debugService.clearWatchExpressions(expression.getId());
A
Alex Dima 已提交
675
		return TPromise.as(null);
E
Erich Gamma 已提交
676 677 678 679 680 681 682 683
	}
}

export class RemoveAllWatchExpressionsAction extends AbstractDebugAction {
	static ID = 'workbench.debug.viewlet.action.removeAllWatchExpressions';
	static LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions");

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
684
		super(id, label, 'debug-action remove-all', debugService, keybindingService);
685
		this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement()));
E
Erich Gamma 已提交
686 687
	}

I
isidor 已提交
688
	public run(): TPromise<any> {
E
Erich Gamma 已提交
689
		this.debugService.clearWatchExpressions();
A
Alex Dima 已提交
690
		return TPromise.as(null);
E
Erich Gamma 已提交
691 692 693 694 695 696 697
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getModel().getWatchExpressions().length > 0;
	}
}

I
isidor 已提交
698 699 700
export class ClearReplAction extends AbstractDebugAction {
	static ID = 'workbench.debug.panel.action.clearReplAction';
	static LABEL = nls.localize('clearRepl', "Clear Console");
I
isidor 已提交
701

702 703 704 705 706
	constructor(id: string, label: string,
		@IDebugService debugService: IDebugService,
		@IKeybindingService keybindingService: IKeybindingService,
		@IPanelService private panelService: IPanelService
	) {
I
isidor 已提交
707 708 709
		super(id, label, 'debug-action clear-repl', debugService, keybindingService);
	}

I
isidor 已提交
710
	public run(): TPromise<any> {
I
isidor 已提交
711 712 713
		this.debugService.clearReplExpressions();

		// focus back to repl
714
		return this.panelService.openPanel(debug.REPL_ID, true);
I
isidor 已提交
715 716 717
	}
}

718 719 720 721 722 723 724 725 726 727
export class CopyAction extends actions.Action {
	static ID = 'workbench.debug.action.copy';
	static LABEL = nls.localize('copy', "Copy");

	public run(): TPromise<any> {
		clipboard.writeText(window.getSelection().toString());
		return TPromise.as(null);
	}
}

I
isidor 已提交
728
export class ToggleReplAction extends AbstractDebugAction {
I
isidor 已提交
729 730
	static ID = 'workbench.debug.action.toggleRepl';
	static LABEL = nls.localize('toggleRepl', "Debug Console");
E
Erich Gamma 已提交
731

I
isidor 已提交
732
	constructor(id: string, label: string,
I
isidor 已提交
733
		@IDebugService debugService: IDebugService,
I
isidor 已提交
734
		@IPartService private partService: IPartService,
I
isidor 已提交
735
		@IPanelService private panelService: IPanelService,
736 737
		@IKeybindingService keybindingService: IKeybindingService,
		@IEventService private eventService: IEventService
I
isidor 已提交
738
	) {
I
isidor 已提交
739
		super(id, label, 'debug-action toggle-repl', debugService, keybindingService);
E
Erich Gamma 已提交
740
		this.enabled = this.debugService.getState() !== debug.State.Disabled;
741
		this.registerListeners();
E
Erich Gamma 已提交
742 743
	}

I
isidor 已提交
744
	public run(): TPromise<any> {
745
		if (this.isReplVisible()) {
I
isidor 已提交
746
			this.partService.setPanelHidden(true);
A
Alex Dima 已提交
747
			return TPromise.as(null);
I
isidor 已提交
748 749
		}

750
		return this.panelService.openPanel(debug.REPL_ID, true);
E
Erich Gamma 已提交
751
	}
752 753

	private registerListeners(): void {
754
		this.toDispose.push(this.debugService.getModel().onDidChangeREPLElements(() => {
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
			if (!this.isReplVisible()) {
				this.class = 'debug-action toggle-repl notification';
			}
		}));
		this.toDispose.push(this.eventService.addListener2(EventType.COMPOSITE_OPENED, (e: CompositeEvent) => {
			if (e.compositeId === debug.REPL_ID) {
				this.class = 'debug-action toggle-repl';
			}
		}));
	}

	private isReplVisible(): boolean {
		const panel = this.panelService.getActivePanel();
		return panel && panel.getId() === debug.REPL_ID;
	}
E
Erich Gamma 已提交
770
}
I
isidor 已提交
771 772 773

export class RunAction extends AbstractDebugAction {
	static ID = 'workbench.action.debug.run';
774
	static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging");
I
isidor 已提交
775 776 777 778 779 780 781 782 783 784 785 786 787

	constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
		super(id, label, null, debugService, keybindingService);
	}

	public run(): TPromise<any> {
		return this.debugService.createSession(true);
	}

	protected isEnabled(): boolean {
		return super.isEnabled() && this.debugService.getState() === debug.State.Inactive;
	}
}