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

import uri from 'vs/base/common/uri';
I
isidor 已提交
7
import { TPromise } from 'vs/base/common/winjs.base';
8
import { IActionRunner } from 'vs/base/common/actions';
9
import Event from 'vs/base/common/event';
E
Erich Gamma 已提交
10 11
import ee = require('vs/base/common/eventEmitter');
import severity from 'vs/base/common/severity';
I
isidor 已提交
12
import { IViewletView } from 'vs/workbench/browser/viewlet';
E
Erich Gamma 已提交
13 14
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import editor = require('vs/editor/common/editorCommon');
I
isidor 已提交
15
import editorbrowser = require('vs/editor/browser/editorBrowser');
I
isidor 已提交
16
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
E
Erich Gamma 已提交
17

I
isidor 已提交
18 19 20 21
export const VIEWLET_ID = 'workbench.view.debug';
export const REPL_ID = 'workbench.panel.repl';
export const DEBUG_SERVICE_ID = 'debugService';
export const CONTEXT_IN_DEBUG_MODE = 'inDebugMode';
I
isidor 已提交
22
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
E
Erich Gamma 已提交
23

I
isidor 已提交
24
// raw
E
Erich Gamma 已提交
25 26 27 28 29

export interface IRawModelUpdate {
	threadId: number;
	thread?: DebugProtocol.Thread;
	callStack?: DebugProtocol.StackFrame[];
I
isidor 已提交
30
	stoppedDetails?: IRawStoppedDetails;
31
	allThreadsStopped?: boolean;
I
isidor 已提交
32 33 34 35 36 37
}

export interface IRawStoppedDetails {
	reason: string;
	threadId?: number;
	text?: string;
I
isidor 已提交
38
	totalFrames?: number;
E
Erich Gamma 已提交
39 40
}

I
isidor 已提交
41
// model
E
Erich Gamma 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54

export interface ITreeElement {
	getId(): string;
}

export interface IExpressionContainer extends ITreeElement {
	reference: number;
	getChildren(debugService: IDebugService): TPromise<IExpression[]>;
}

export interface IExpression extends ITreeElement, IExpressionContainer {
	name: string;
	value: string;
55
	valueChanged: boolean;
E
Erich Gamma 已提交
56 57 58 59 60
}

export interface IThread extends ITreeElement {
	threadId: number;
	name: string;
I
isidor 已提交
61
	stoppedDetails: IRawStoppedDetails;
62 63 64 65 66

	/**
	 * Queries the debug adapter for the callstack and returns a promise with
	 * the stack frames of the callstack.
	 * If the thread is not stopped, it returns a promise to an empty array.
I
isidor 已提交
67 68
	 * Only gets the first 20 stack frames. Calling this method consecutive times
	 * with getAdditionalStackFrames = true gets the remainder of the call stack.
69
	 */
I
isidor 已提交
70
	getCallStack(debugService: IDebugService, getAdditionalStackFrames?: boolean): TPromise<IStackFrame[]>;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

	/**
	 * Gets the callstack if it has already been received from the debug
	 * adapter, otherwise it returns undefined.
	 */
	getCachedCallStack(): IStackFrame[];

	/**
	 * Invalidates the callstack cache
	 */
	clearCallStack(): void;

	/**
	 * Indicates whether this thread is stopped. The callstack for stopped
	 * threads can be retrieved from the debug adapter.
	 */
	stopped: boolean;
E
Erich Gamma 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
}

export interface IScope extends IExpressionContainer {
	name: string;
	expensive: boolean;
}

export interface IStackFrame extends ITreeElement {
	threadId: number;
	name: string;
	lineNumber: number;
	column: number;
	frameId: number;
	source: Source;
	getScopes(debugService: IDebugService): TPromise<IScope[]>;
}

export interface IEnablement extends ITreeElement {
	enabled: boolean;
}

109 110 111 112 113 114 115
export interface IRawBreakpoint {
	uri: uri;
	lineNumber: number;
	enabled: boolean;
	condition?: string;
}

E
Erich Gamma 已提交
116 117 118 119
export interface IBreakpoint extends IEnablement {
	source: Source;
	lineNumber: number;
	desiredLineNumber: number;
I
isidor 已提交
120
	condition: string;
121
	verified: boolean;
122
	idFromAdapter: number;
I
isidor 已提交
123
	message: string;
E
Erich Gamma 已提交
124 125
}

I
isidor 已提交
126
export interface IFunctionBreakpoint extends IEnablement {
127
	name: string;
I
isidor 已提交
128
	verified: boolean;
129
	idFromAdapter: number;
I
isidor 已提交
130 131
}

E
Erich Gamma 已提交
132
export interface IExceptionBreakpoint extends IEnablement {
133 134
	filter: string;
	label: string;
E
Erich Gamma 已提交
135 136 137
}

export var ServiceEvents = {
138
	STATE_CHANGED: 'StateChanged'
E
Erich Gamma 已提交
139 140 141 142 143 144 145 146 147
};

export var SessionEvents = {
	INITIALIZED: 'initialized',
	STOPPED: 'stopped',
	DEBUGEE_TERMINATED: 'terminated',
	SERVER_EXIT: 'exit',
	CONTINUED: 'continued',
	THREAD: 'thread',
I
isidor 已提交
148 149
	OUTPUT: 'output',
	BREAKPOINT: 'breakpoint'
E
Erich Gamma 已提交
150 151
};

I
isidor 已提交
152
// model interfaces
E
Erich Gamma 已提交
153

154
export interface IViewModel extends ITreeElement {
E
Erich Gamma 已提交
155 156 157 158
	getFocusedStackFrame(): IStackFrame;
	getSelectedExpression(): IExpression;
	getFocusedThreadId(): number;
	setSelectedExpression(expression: IExpression);
I
isidor 已提交
159 160
	getSelectedFunctionBreakpoint(): IFunctionBreakpoint;
	setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint): void;
161 162 163 164

	onDidFocusStackFrame: Event<IStackFrame>;
	onDidSelectExpression: Event<IExpression>;
	onDidSelectFunctionBreakpoint: Event<IFunctionBreakpoint>;
E
Erich Gamma 已提交
165 166
}

167
export interface IModel extends ITreeElement {
168
	getThreads(): { [threadId: number]: IThread; };
E
Erich Gamma 已提交
169 170
	getBreakpoints(): IBreakpoint[];
	areBreakpointsActivated(): boolean;
I
isidor 已提交
171
	getFunctionBreakpoints(): IFunctionBreakpoint[];
E
Erich Gamma 已提交
172 173 174
	getExceptionBreakpoints(): IExceptionBreakpoint[];
	getWatchExpressions(): IExpression[];
	getReplElements(): ITreeElement[];
175 176 177 178 179 180

	onDidChangeBreakpoints: Event<void>;
	onDidChangeCallStack: Event<void>;
	onDidChangeWatchExpressions: Event<IExpression>;
	onDidChangeREPLElements: Event<void>;
};
E
Erich Gamma 已提交
181

I
isidor 已提交
182
// service enums
E
Erich Gamma 已提交
183 184 185 186 187 188

export enum State {
	Disabled,
	Inactive,
	Initializing,
	Stopped,
I
isidor 已提交
189 190
	Running,
	RunningNoDebug
E
Erich Gamma 已提交
191 192
}

I
isidor 已提交
193
// service interfaces
E
Erich Gamma 已提交
194 195 196

export interface IGlobalConfig {
	version: string;
197
	debugServer?: number;
E
Erich Gamma 已提交
198 199 200 201
	configurations: IConfig[];
}

export interface IConfig {
202
	name?: string;
E
Erich Gamma 已提交
203 204
	type: string;
	request: string;
205 206 207 208 209 210 211 212 213 214 215 216 217 218
	program?: string;
	stopOnEntry?: boolean;
	args?: string[];
	cwd?: string;
	runtimeExecutable?: string;
	runtimeArgs?: string[];
	env?: { [key: string]: string; };
	sourceMaps?: boolean;
	outDir?: string;
	address?: string;
	port?: number;
	preLaunchTask?: string;
	externalConsole?: boolean;
	debugServer?: number;
I
isidor 已提交
219
	noDebug?: boolean;
E
Erich Gamma 已提交
220 221 222
}

export interface IRawEnvAdapter {
I
isidor 已提交
223 224 225 226 227 228
	type?: string;
	label?: string;
	program?: string;
	args?: string[];
	runtime?: string;
	runtimeArgs?: string[];
E
Erich Gamma 已提交
229 230 231
}

export interface IRawAdapter extends IRawEnvAdapter {
I
isidor 已提交
232 233 234
	enableBreakpointsFor?: { languageIds: string[] };
	configurationAttributes?: any;
	initialConfigurations?: any[];
I
isidor 已提交
235
	aiKey?: string;
I
isidor 已提交
236
	win?: IRawEnvAdapter;
I
isidor 已提交
237
	winx86?: IRawEnvAdapter;
238
	windows?: IRawEnvAdapter;
I
isidor 已提交
239 240
	osx?: IRawEnvAdapter;
	linux?: IRawEnvAdapter;
E
Erich Gamma 已提交
241 242 243
}

export interface IRawDebugSession extends ee.EventEmitter {
I
isidor 已提交
244
	getType(): string;
245
	isAttach: boolean;
246
	capabilities: DebugProtocol.Capabilites;
247
	disconnect(restart?: boolean, force?: boolean): TPromise<DebugProtocol.DisconnectResponse>;
E
Erich Gamma 已提交
248

249
	next(args: DebugProtocol.NextArguments): TPromise<DebugProtocol.NextResponse>;
E
Erich Gamma 已提交
250 251 252 253 254
	stepIn(args: DebugProtocol.StepInArguments): TPromise<DebugProtocol.StepInResponse>;
	stepOut(args: DebugProtocol.StepOutArguments): TPromise<DebugProtocol.StepOutResponse>;
	continue(args: DebugProtocol.ContinueArguments): TPromise<DebugProtocol.ContinueResponse>;
	pause(args: DebugProtocol.PauseArguments): TPromise<DebugProtocol.PauseResponse>;

255
	stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>;
E
Erich Gamma 已提交
256
	scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
257
	variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
E
Erich Gamma 已提交
258 259 260
	evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
}

261 262 263 264 265 266 267 268 269 270 271 272 273
export interface IConfigurationManager {
	configurationName: string;
	setConfiguration(name: string): TPromise<void>;
	openConfigFile(sideBySide: boolean): TPromise<boolean>;
	loadLaunchConfig(): TPromise<IGlobalConfig>;
	canSetBreakpointsIn(model: editor.IModel): boolean;

	/**
	 * Allows to register on change of debug configuration.
	 */
	onDidConfigurationChange: Event<string>;
}

E
Erich Gamma 已提交
274 275 276 277
export var IDebugService = createDecorator<IDebugService>(DEBUG_SERVICE_ID);

export interface IDebugService extends ee.IEventEmitter {
	serviceId: ServiceIdentifier<any>;
278 279 280 281

	/**
	 * Gets the current debug state.
	 */
E
Erich Gamma 已提交
282 283
	getState(): State;

284 285 286 287
	/**
	 * Gets the current configuration manager.
	 */
	getConfigurationManager(): IConfigurationManager;
E
Erich Gamma 已提交
288

I
isidor 已提交
289 290 291 292
	/**
	 * Sets the focused stack frame and evaluates all expresions against the newly focused stack frame,
	 */
	setFocusedStackFrameAndEvaluate(focusedStackFrame: IStackFrame): TPromise<void>;
E
Erich Gamma 已提交
293

294 295 296 297
	/**
	 * Sets breakpoints for a model. Does not send them to the adapter.
	 */
	setBreakpointsForModel(modelUri: uri, rawData: IRawBreakpoint[]): void;
I
isidor 已提交
298 299 300 301 302 303 304
	toggleBreakpoint(IRawBreakpoint): TPromise<void>;
	enableOrDisableAllBreakpoints(enabled: boolean): TPromise<void>;
	toggleEnablement(element: IEnablement): TPromise<void>;
	toggleBreakpointsActivated(): TPromise<void>;
	removeAllBreakpoints(): TPromise<any>;
	sendAllBreakpoints(): TPromise<any>;
	editBreakpoint(editor: editorbrowser.ICodeEditor, lineNumber: number): TPromise<void>;
I
isidor 已提交
305

I
isidor 已提交
306
	addFunctionBreakpoint(): void;
I
isidor 已提交
307 308
	renameFunctionBreakpoint(id: string, newFunctionName: string): TPromise<void>;
	removeFunctionBreakpoints(id?: string): TPromise<void>;
E
Erich Gamma 已提交
309

I
isidor 已提交
310
	addReplExpression(name: string): TPromise<void>;
E
Erich Gamma 已提交
311 312 313 314 315 316 317
	clearReplExpressions(): void;

	logToRepl(value: string, severity?: severity): void;
	logToRepl(value: { [key: string]: any }, severity?: severity): void;

	appendReplOutput(value: string, severity?: severity): void;

I
isidor 已提交
318 319
	addWatchExpression(name?: string): TPromise<void>;
	renameWatchExpression(id: string, newName: string): TPromise<void>;
E
Erich Gamma 已提交
320 321
	clearWatchExpressions(id?: string): void;

I
isidor 已提交
322 323 324
	/**
	 * Creates a new debug session. Depending on the configuration will either 'launch' or 'attach'.
	 */
I
isidor 已提交
325
	createSession(noDebug: boolean): TPromise<any>;
I
isidor 已提交
326 327 328 329

	/**
	 * Restarts an active debug session or creates a new one if there is no active session.
	 */
I
isidor 已提交
330
	restartSession(): TPromise<any>;
I
isidor 已提交
331 332 333 334

	/**
	 * Returns the active debug session or null if debug is inactive.
	 */
E
Erich Gamma 已提交
335 336
	getActiveSession(): IRawDebugSession;

I
isidor 已提交
337 338 339
	/**
	 * Gets the current debug model.
	 */
E
Erich Gamma 已提交
340
	getModel(): IModel;
I
isidor 已提交
341 342 343 344

	/**
	 * Gets the current view model.
	 */
E
Erich Gamma 已提交
345 346
	getViewModel(): IViewModel;

I
isidor 已提交
347 348 349
	/**
	 * Opens a new or reveals an already visible editor showing the source.
	 */
I
isidor 已提交
350
	openOrRevealEditor(source: Source, lineNumber: number, preserveFocus: boolean, sideBySide: boolean): TPromise<any>;
E
Erich Gamma 已提交
351 352
}

I
isidor 已提交
353 354 355 356 357
// Editor interfaces
export interface IDebugEditorContribution extends editor.IEditorContribution {
	showHover(range: editor.IEditorRange, hoveringOver: string, focus: boolean): TPromise<void>;
}

358
// Debug view registration
359

360
export interface IDebugViewConstructorSignature {
I
isidor 已提交
361
	new (actionRunner: IActionRunner, viewletSetings: any, ...services: { serviceId: ServiceIdentifier<any>; }[]): IViewletView;
362 363 364
}

export interface IDebugViewRegistry {
365 366
	registerDebugView(view: IDebugViewConstructorSignature, order: number): void;
	getDebugViews(): IDebugViewConstructorSignature[];
367 368 369
}

class DebugViewRegistryImpl implements IDebugViewRegistry {
370
	private debugViews: { view: IDebugViewConstructorSignature, order: number }[];
371 372 373 374 375

	constructor() {
		this.debugViews = [];
	}

376 377
	public registerDebugView(view: IDebugViewConstructorSignature, order: number): void {
		this.debugViews.push({ view, order });
378 379
	}

380 381 382
	public getDebugViews(): IDebugViewConstructorSignature[] {
		return this.debugViews.sort((first, second) => first.order - second.order)
			.map(viewWithOrder => viewWithOrder.view);
383 384 385 386 387
	}
}

export var DebugViewRegistry = <IDebugViewRegistry>new DebugViewRegistryImpl();

I
isidor 已提交
388
// utils
E
Erich Gamma 已提交
389

I
isidor 已提交
390
const _formatPIIRegexp = /{([^}]+)}/g;
E
Erich Gamma 已提交
391 392 393 394 395 396 397

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] !== '_') {
			return match;
		}

I
isidor 已提交
398
		return args && args.hasOwnProperty(group) ?
E
Erich Gamma 已提交
399 400
			args[group] :
			match;
I
isidor 已提交
401
	});
E
Erich Gamma 已提交
402
}