debug.ts 12.5 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
import severity from 'vs/base/common/severity';
I
isidor 已提交
11
import { IViewletView } from 'vs/workbench/browser/viewlet';
E
Erich Gamma 已提交
12 13
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import editor = require('vs/editor/common/editorCommon');
I
isidor 已提交
14
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
E
Erich Gamma 已提交
15

I
isidor 已提交
16 17 18 19
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 已提交
20
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
E
Erich Gamma 已提交
21

I
isidor 已提交
22
// raw
E
Erich Gamma 已提交
23 24 25 26 27

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

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

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

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;
54
	valueChanged: boolean;
E
Erich Gamma 已提交
55 56 57
}

export interface IThread extends ITreeElement {
I
isidor 已提交
58 59 60
	/**
	 * Id of the thread generated by the debug adapter backend.
	 */
E
Erich Gamma 已提交
61
	threadId: number;
I
isidor 已提交
62 63 64 65

	/**
	 * Name of the thread.
	 */
E
Erich Gamma 已提交
66
	name: string;
I
isidor 已提交
67 68 69 70

	/**
	 * Information about the current thread stop event. Null if thread is not stopped.
	 */
I
isidor 已提交
71
	stoppedDetails: IRawStoppedDetails;
72 73 74 75 76

	/**
	 * 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 已提交
77 78
	 * Only gets the first 20 stack frames. Calling this method consecutive times
	 * with getAdditionalStackFrames = true gets the remainder of the call stack.
79
	 */
I
isidor 已提交
80
	getCallStack(debugService: IDebugService, getAdditionalStackFrames?: boolean): TPromise<IStackFrame[]>;
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

	/**
	 * 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 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}

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;
}

119 120 121
export interface IRawBreakpoint {
	uri: uri;
	lineNumber: number;
122
	enabled?: boolean;
123 124 125
	condition?: string;
}

E
Erich Gamma 已提交
126 127 128 129
export interface IBreakpoint extends IEnablement {
	source: Source;
	lineNumber: number;
	desiredLineNumber: number;
I
isidor 已提交
130
	condition: string;
131
	verified: boolean;
132
	idFromAdapter: number;
I
isidor 已提交
133
	message: string;
E
Erich Gamma 已提交
134 135
}

I
isidor 已提交
136
export interface IFunctionBreakpoint extends IEnablement {
137
	name: string;
I
isidor 已提交
138
	verified: boolean;
139
	idFromAdapter: number;
I
isidor 已提交
140 141
}

E
Erich Gamma 已提交
142
export interface IExceptionBreakpoint extends IEnablement {
143 144
	filter: string;
	label: string;
E
Erich Gamma 已提交
145 146
}

I
isidor 已提交
147
// model interfaces
E
Erich Gamma 已提交
148

149
export interface IViewModel extends ITreeElement {
E
Erich Gamma 已提交
150 151 152 153
	getFocusedStackFrame(): IStackFrame;
	getSelectedExpression(): IExpression;
	getFocusedThreadId(): number;
	setSelectedExpression(expression: IExpression);
I
isidor 已提交
154 155
	getSelectedFunctionBreakpoint(): IFunctionBreakpoint;
	setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint): void;
156 157 158 159

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

162
export interface IModel extends ITreeElement {
163
	getThreads(): { [threadId: number]: IThread; };
E
Erich Gamma 已提交
164 165
	getBreakpoints(): IBreakpoint[];
	areBreakpointsActivated(): boolean;
I
isidor 已提交
166
	getFunctionBreakpoints(): IFunctionBreakpoint[];
E
Erich Gamma 已提交
167 168 169
	getExceptionBreakpoints(): IExceptionBreakpoint[];
	getWatchExpressions(): IExpression[];
	getReplElements(): ITreeElement[];
170 171 172 173

	onDidChangeBreakpoints: Event<void>;
	onDidChangeCallStack: Event<void>;
	onDidChangeWatchExpressions: Event<IExpression>;
174
	onDidChangeReplElements: Event<void>;
175
};
E
Erich Gamma 已提交
176

I
isidor 已提交
177
// service enums
E
Erich Gamma 已提交
178 179 180 181 182 183

export enum State {
	Disabled,
	Inactive,
	Initializing,
	Stopped,
I
isidor 已提交
184 185
	Running,
	RunningNoDebug
E
Erich Gamma 已提交
186 187
}

I
isidor 已提交
188
// service interfaces
E
Erich Gamma 已提交
189 190 191

export interface IGlobalConfig {
	version: string;
192
	debugServer?: number;
E
Erich Gamma 已提交
193 194 195 196
	configurations: IConfig[];
}

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

export interface IRawEnvAdapter {
I
isidor 已提交
219 220 221 222 223 224
	type?: string;
	label?: string;
	program?: string;
	args?: string[];
	runtime?: string;
	runtimeArgs?: string[];
E
Erich Gamma 已提交
225 226 227
}

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

239
export interface IRawDebugSession {
I
isidor 已提交
240 241
	configuration: { type: string, isAttach: boolean, capabilities: DebugProtocol.Capabilites };

242
	disconnect(restart?: boolean, force?: boolean): TPromise<DebugProtocol.DisconnectResponse>;
E
Erich Gamma 已提交
243

244
	stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>;
E
Erich Gamma 已提交
245
	scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
246
	variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
E
Erich Gamma 已提交
247
	evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
248

249 250
	custom(request: string, args: any): TPromise<DebugProtocol.Response>;

251 252 253 254
	/**
	 * Allows to register on each debug session stop event.
	 */
	onDidStop: Event<DebugProtocol.StoppedEvent>;
255 256

	onDidEvent: Event<DebugProtocol.Event>;
E
Erich Gamma 已提交
257 258
}

259 260 261 262 263 264 265 266 267 268 269 270 271
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 已提交
272 273
export var IDebugService = createDecorator<IDebugService>(DEBUG_SERVICE_ID);

274
export interface IDebugService {
E
Erich Gamma 已提交
275
	serviceId: ServiceIdentifier<any>;
276 277 278 279

	/**
	 * Gets the current debug state.
	 */
I
isidor 已提交
280
	state: State;
E
Erich Gamma 已提交
281

282 283 284 285 286
	/**
	 * Allows to register on debug state changes.
	 */
	onDidChangeState: Event<State>;

287 288 289 290
	/**
	 * Gets the current configuration manager.
	 */
	getConfigurationManager(): IConfigurationManager;
E
Erich Gamma 已提交
291

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

297
	/**
298
	 * Adds new breakpoints to the model. Notifies debug adapter of breakpoint changes.
299
	 */
300
	addBreakpoints(rawBreakpoints: IRawBreakpoint[]): TPromise<void[]>;
301 302 303 304 305 306 307 308 309 310 311

	/**
	 * Enables or disables all breakpoints. If breakpoint is passed only enables or disables the passed breakpoint.
	 * Notifies debug adapter of breakpoint changes.
	 */
	enableOrDisableBreakpoints(enable: boolean, breakpoint?: IEnablement): TPromise<void>;

	/**
	 * Sets the global activated property for all breakpoints.
	 * Notifies debug adapter of breakpoint changes.
	 */
312
	setBreakpointsActivated(activated: boolean): TPromise<void>;
313 314 315 316 317

	/**
	 * Removes all breakpoints. If id is passed only removes the breakpoint associated with that id.
	 * Notifies debug adapter of breakpoint changes.
	 */
318
	removeBreakpoints(id?: string): TPromise<any>;
I
isidor 已提交
319

320
	/**
321
	 * Adds a new no name function breakpoint. The function breakpoint should be renamed once user enters the name.
322
	 */
I
isidor 已提交
323
	addFunctionBreakpoint(): void;
324 325 326 327 328

	/**
	 * Renames an already existing function breakpoint.
	 * Notifies debug adapter of breakpoint changes.
	 */
I
isidor 已提交
329
	renameFunctionBreakpoint(id: string, newFunctionName: string): TPromise<void>;
330 331 332 333 334

	/**
	 * Removes all function breakpoints. If id is passed only removes the function breakpoint with the passed id.
	 * Notifies debug adapter of breakpoint changes.
	 */
I
isidor 已提交
335
	removeFunctionBreakpoints(id?: string): TPromise<void>;
E
Erich Gamma 已提交
336

337
	/**
338
	 * Adds a new expression to the repl.
339
	 */
I
isidor 已提交
340
	addReplExpression(name: string): TPromise<void>;
341 342 343 344

	/**
	 * Removes all repl expressions.
	 */
345
	removeReplExpressions(): void;
346 347 348 349

	/**
	 * Adds a new log to the repl. Either a string value or a dictionary (used to inspect complex objects printed to the repl).
	 */
350
	logToRepl(value: string | { [key: string]: any }, severity?: severity): void;
351 352 353 354

	/**
	 * Appends new output to the repl.
	 */
E
Erich Gamma 已提交
355 356
	appendReplOutput(value: string, severity?: severity): void;

357
	/**
358
	 * Adds a new watch expression and evaluates it against the debug adapter.
359
	 */
I
isidor 已提交
360
	addWatchExpression(name?: string): TPromise<void>;
361 362 363 364

	/**
	 * Renames a watch expression and evaluates it against the debug adapter.
	 */
I
isidor 已提交
365
	renameWatchExpression(id: string, newName: string): TPromise<void>;
366 367 368 369

	/**
	 * Removes all watch expressions. If id is passed only removes the watch expression with the passed id.
	 */
370
	removeWatchExpressions(id?: string): void;
E
Erich Gamma 已提交
371

I
isidor 已提交
372 373 374
	/**
	 * Creates a new debug session. Depending on the configuration will either 'launch' or 'attach'.
	 */
I
isidor 已提交
375
	createSession(noDebug: boolean): TPromise<any>;
I
isidor 已提交
376 377 378 379

	/**
	 * Restarts an active debug session or creates a new one if there is no active session.
	 */
I
isidor 已提交
380
	restartSession(): TPromise<any>;
I
isidor 已提交
381 382 383 384

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

I
isidor 已提交
387 388 389
	/**
	 * Gets the current debug model.
	 */
E
Erich Gamma 已提交
390
	getModel(): IModel;
I
isidor 已提交
391 392 393 394

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

I
isidor 已提交
397 398 399
	/**
	 * Opens a new or reveals an already visible editor showing the source.
	 */
400
	openOrRevealSource(source: Source, lineNumber: number, preserveFocus: boolean, sideBySide: boolean): TPromise<any>;
401 402 403 404 405 406

	next(threadId: number): TPromise<void>;
	stepIn(threadId: number): TPromise<void>;
	stepOut(threadId: number): TPromise<void>;
	continue(threadId: number): TPromise<void>;
	pause(threadId: number): TPromise<any>;
E
Erich Gamma 已提交
407 408
}

I
isidor 已提交
409 410 411 412 413
// Editor interfaces
export interface IDebugEditorContribution extends editor.IEditorContribution {
	showHover(range: editor.IEditorRange, hoveringOver: string, focus: boolean): TPromise<void>;
}

414
// Debug view registration
415

416
export interface IDebugViewConstructorSignature {
I
isidor 已提交
417
	new (actionRunner: IActionRunner, viewletSetings: any, ...services: { serviceId: ServiceIdentifier<any>; }[]): IViewletView;
418 419 420
}

export interface IDebugViewRegistry {
421 422
	registerDebugView(view: IDebugViewConstructorSignature, order: number): void;
	getDebugViews(): IDebugViewConstructorSignature[];
423 424 425
}

class DebugViewRegistryImpl implements IDebugViewRegistry {
426
	private debugViews: { view: IDebugViewConstructorSignature, order: number }[];
427 428 429 430 431

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

432 433
	public registerDebugView(view: IDebugViewConstructorSignature, order: number): void {
		this.debugViews.push({ view, order });
434 435
	}

436 437 438
	public getDebugViews(): IDebugViewConstructorSignature[] {
		return this.debugViews.sort((first, second) => first.order - second.order)
			.map(viewWithOrder => viewWithOrder.view);
439 440 441 442 443
	}
}

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

I
isidor 已提交
444
// utils
E
Erich Gamma 已提交
445

I
isidor 已提交
446
const _formatPIIRegexp = /{([^}]+)}/g;
E
Erich Gamma 已提交
447

I
isidor 已提交
448 449
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
	return value.replace(_formatPIIRegexp, function (match, group) {
E
Erich Gamma 已提交
450 451 452 453
		if (excludePII && group.length > 0 && group[0] !== '_') {
			return match;
		}

I
isidor 已提交
454
		return args && args.hasOwnProperty(group) ?
E
Erich Gamma 已提交
455 456
			args[group] :
			match;
I
isidor 已提交
457
	});
E
Erich Gamma 已提交
458
}