debug.ts 14.3 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';
J
Johannes Rieken 已提交
7
import { TPromise } from 'vs/base/common/winjs.base';
8
import Event from 'vs/base/common/event';
E
Erich Gamma 已提交
9
import severity from 'vs/base/common/severity';
J
Johannes Rieken 已提交
10
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
I
isidor 已提交
11
import { IModel as EditorIModel, IEditorContribution } from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
12 13 14 15 16
import { Position } from 'vs/editor/common/core/position';
import { ISuggestion } from 'vs/editor/common/modes';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { Range } from 'vs/editor/common/core/range';
import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
E
Erich Gamma 已提交
17

I
isidor 已提交
18 19 20
export const VIEWLET_ID = 'workbench.view.debug';
export const REPL_ID = 'workbench.panel.repl';
export const DEBUG_SERVICE_ID = 'debugService';
A
Alex Dima 已提交
21
export const CONTEXT_IN_DEBUG_MODE = new RawContextKey<boolean>('inDebugMode', false);
22 23 24
export const CONTEXT_NOT_IN_DEBUG_MODE: ContextKeyExpr = CONTEXT_IN_DEBUG_MODE.toNegated();
export const CONTEXT_IN_DEBUG_REPL = new RawContextKey<boolean>('inDebugRepl', false);
export const CONTEXT_NOT_IN_DEBUG_REPL: ContextKeyExpr = CONTEXT_IN_DEBUG_REPL.toNegated();
25 26
export const CONTEXT_ON_FIRST_DEBUG_REPL_LINE = new RawContextKey<boolean>('onFirsteDebugReplLine', false);
export const CONTEXT_ON_LAST_DEBUG_REPL_LINE = new RawContextKey<boolean>('onLastDebugReplLine', false);
I
isidor 已提交
27
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
I
isidor 已提交
28
export const DEBUG_SCHEME = 'debug';
E
Erich Gamma 已提交
29

I
isidor 已提交
30
// raw
E
Erich Gamma 已提交
31 32 33

export interface IRawModelUpdate {
	threadId: number;
34
	sessionId: string;
E
Erich Gamma 已提交
35 36
	thread?: DebugProtocol.Thread;
	callStack?: DebugProtocol.StackFrame[];
I
isidor 已提交
37
	stoppedDetails?: IRawStoppedDetails;
38
	allThreadsStopped?: boolean;
I
isidor 已提交
39 40 41 42 43 44
}

export interface IRawStoppedDetails {
	reason: string;
	threadId?: number;
	text?: string;
I
isidor 已提交
45
	totalFrames?: number;
46
	framesErrorMessage?: string;
E
Erich Gamma 已提交
47 48
}

I
isidor 已提交
49
// model
E
Erich Gamma 已提交
50 51 52 53 54 55

export interface ITreeElement {
	getId(): string;
}

export interface IExpressionContainer extends ITreeElement {
56
	stackFrame: IStackFrame;
57
	hasChildren: boolean;
E
Erich Gamma 已提交
58 59 60 61 62 63
	getChildren(debugService: IDebugService): TPromise<IExpression[]>;
}

export interface IExpression extends ITreeElement, IExpressionContainer {
	name: string;
	value: string;
64
	valueChanged: boolean;
65
	type?: string;
E
Erich Gamma 已提交
66 67
}

68 69 70 71 72 73
export enum SessionRequestType {
	LAUNCH,
	ATTACH,
	LAUNCH_NO_DEBUG
}

I
isidor 已提交
74
export interface ISession {
75
	requestType: SessionRequestType;
76 77 78 79
	stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>;
	scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
	variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
	evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
80 81 82 83 84

	configuration: { type: string, capabilities: DebugProtocol.Capabilities };
	disconnect(restart?: boolean, force?: boolean): TPromise<DebugProtocol.DisconnectResponse>;
	custom(request: string, args: any): TPromise<DebugProtocol.Response>;
	onDidEvent: Event<DebugProtocol.Event>;
I
isidor 已提交
85
	restartFrame(args: DebugProtocol.RestartFrameArguments): TPromise<DebugProtocol.RestartFrameResponse>;
86

87
	next(args: DebugProtocol.NextArguments): TPromise<DebugProtocol.NextResponse>;
88 89 90 91 92
	stepIn(args: DebugProtocol.StepInArguments): TPromise<DebugProtocol.StepInResponse>;
	stepOut(args: DebugProtocol.StepOutArguments): TPromise<DebugProtocol.StepOutResponse>;
	stepBack(args: DebugProtocol.StepBackArguments): TPromise<DebugProtocol.StepBackResponse>;
	continue(args: DebugProtocol.ContinueArguments): TPromise<DebugProtocol.ContinueResponse>;
	pause(args: DebugProtocol.PauseArguments): TPromise<DebugProtocol.PauseResponse>;
I
isidor 已提交
93 94

	completions(args: DebugProtocol.CompletionsArguments): TPromise<DebugProtocol.CompletionsResponse>;
95
	setVariable(args: DebugProtocol.SetVariableArguments): TPromise<DebugProtocol.SetVariableResponse>;
96
	source(args: DebugProtocol.SourceArguments): TPromise<DebugProtocol.SourceResponse>;
97 98
}

I
isidor 已提交
99
export interface IProcess extends ITreeElement {
I
isidor 已提交
100
	name: string;
I
isidor 已提交
101
	session: ISession;
I
isidor 已提交
102 103
	getThread(threadId: number): IThread;
	getAllThreads(): IThread[];
104 105
}

E
Erich Gamma 已提交
106
export interface IThread extends ITreeElement {
107 108

	/**
109
	 * Process the thread belongs to
110
	 */
111
	process: IProcess;
112

I
isidor 已提交
113 114 115
	/**
	 * Id of the thread generated by the debug adapter backend.
	 */
E
Erich Gamma 已提交
116
	threadId: number;
I
isidor 已提交
117 118 119 120

	/**
	 * Name of the thread.
	 */
E
Erich Gamma 已提交
121
	name: string;
I
isidor 已提交
122 123 124 125

	/**
	 * Information about the current thread stop event. Null if thread is not stopped.
	 */
I
isidor 已提交
126
	stoppedDetails: IRawStoppedDetails;
127 128 129 130 131

	/**
	 * 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 已提交
132 133
	 * Only gets the first 20 stack frames. Calling this method consecutive times
	 * with getAdditionalStackFrames = true gets the remainder of the call stack.
134
	 */
135
	getCallStack(getAdditionalStackFrames?: boolean): TPromise<IStackFrame[]>;
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

	/**
	 * 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;
153 154 155 156 157 158 159

	next(): TPromise<any>;
	stepIn(): TPromise<any>;
	stepOut(): TPromise<any>;
	stepBack(): TPromise<any>;
	continue(): TPromise<any>;
	pause(): TPromise<any>;
E
Erich Gamma 已提交
160 161 162 163 164 165 166 167
}

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

export interface IStackFrame extends ITreeElement {
168
	thread: IThread;
E
Erich Gamma 已提交
169 170 171 172 173
	name: string;
	lineNumber: number;
	column: number;
	frameId: number;
	source: Source;
174
	getScopes(): TPromise<IScope[]>;
I
isidor 已提交
175
	restart(): TPromise<any>;
176
	completions(text: string, position: Position, overwriteBefore: number): TPromise<ISuggestion[]>;
E
Erich Gamma 已提交
177 178 179 180 181 182
}

export interface IEnablement extends ITreeElement {
	enabled: boolean;
}

183 184
export interface IRawBreakpoint {
	lineNumber: number;
185
	enabled?: boolean;
186
	condition?: string;
187
	hitCondition?: string;
188 189
}

E
Erich Gamma 已提交
190
export interface IBreakpoint extends IEnablement {
191
	uri: uri;
E
Erich Gamma 已提交
192 193
	lineNumber: number;
	desiredLineNumber: number;
I
isidor 已提交
194
	condition: string;
195
	hitCondition: string;
196
	verified: boolean;
197
	idFromAdapter: number;
I
isidor 已提交
198
	message: string;
E
Erich Gamma 已提交
199 200
}

I
isidor 已提交
201
export interface IFunctionBreakpoint extends IEnablement {
202
	name: string;
I
isidor 已提交
203
	verified: boolean;
204
	idFromAdapter: number;
205
	hitCondition: string;
I
isidor 已提交
206 207
}

E
Erich Gamma 已提交
208
export interface IExceptionBreakpoint extends IEnablement {
209 210
	filter: string;
	label: string;
E
Erich Gamma 已提交
211 212
}

I
isidor 已提交
213
// model interfaces
E
Erich Gamma 已提交
214

215
export interface IViewModel extends ITreeElement {
216
	/**
217
	 * Returns the focused debug process or null if no process is stopped.
218
	 */
219
	focusedProcess: IProcess;
220 221

	/**
222
	 * Returns the focused thread or null if no thread is stopped.
223
	 */
224
	focusedThread: IThread;
225 226

	/**
227
	 * Returns the focused stack frame or null if there are no stack frames.
228
	 */
229
	focusedStackFrame: IStackFrame;
E
Erich Gamma 已提交
230
	getSelectedExpression(): IExpression;
I
isidor 已提交
231
	getSelectedFunctionBreakpoint(): IFunctionBreakpoint;
232
	setSelectedExpression(expression: IExpression);
I
isidor 已提交
233
	setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint): void;
234

235 236 237
	selectedConfigurationName: string;
	setSelectedConfigurationName(name: string): void;

238 239
	isMultiProcessView(): boolean;

240
	onDidFocusStackFrame: Event<IStackFrame>;
I
isidor 已提交
241
	onDidFocusProcess: Event<IProcess>;
242 243
	onDidSelectExpression: Event<IExpression>;
	onDidSelectFunctionBreakpoint: Event<IFunctionBreakpoint>;
244 245 246 247
	/**
	 * Allows to register on change of selected debug configuration.
	 */
	onDidSelectConfigurationName: Event<string>;
E
Erich Gamma 已提交
248 249
}

250
export interface IModel extends ITreeElement {
251
	getProcesses(): IProcess[];
E
Erich Gamma 已提交
252 253
	getBreakpoints(): IBreakpoint[];
	areBreakpointsActivated(): boolean;
I
isidor 已提交
254
	getFunctionBreakpoints(): IFunctionBreakpoint[];
E
Erich Gamma 已提交
255 256 257
	getExceptionBreakpoints(): IExceptionBreakpoint[];
	getWatchExpressions(): IExpression[];
	getReplElements(): ITreeElement[];
258 259 260 261

	onDidChangeBreakpoints: Event<void>;
	onDidChangeCallStack: Event<void>;
	onDidChangeWatchExpressions: Event<IExpression>;
262
	onDidChangeReplElements: Event<void>;
263
};
E
Erich Gamma 已提交
264

I
isidor 已提交
265
// service enums
E
Erich Gamma 已提交
266 267 268 269 270 271

export enum State {
	Disabled,
	Inactive,
	Initializing,
	Stopped,
I
isidor 已提交
272 273
	Running,
	RunningNoDebug
E
Erich Gamma 已提交
274 275
}

I
isidor 已提交
276 277 278 279
// Service config

export interface IDebugConfiguration {
	allowBreakpointsEverywhere: boolean;
I
isidor 已提交
280
	openExplorerOnEnd: boolean;
I
isidor 已提交
281 282
}

I
isidor 已提交
283
// service interfaces
E
Erich Gamma 已提交
284 285 286

export interface IGlobalConfig {
	version: string;
287
	debugServer?: number;
E
Erich Gamma 已提交
288 289 290
	configurations: IConfig[];
}

291
export interface IEnvConfig {
292
	name?: string;
E
Erich Gamma 已提交
293 294
	type: string;
	request: string;
295
	internalConsoleOptions?: string;
296 297
	preLaunchTask?: string;
	debugServer?: number;
I
isidor 已提交
298
	noDebug?: boolean;
299
	silentlyAbort?: boolean;
300
	configurationNames?: string[];
E
Erich Gamma 已提交
301 302
}

303 304 305 306 307 308
export interface IConfig extends IEnvConfig {
	windows?: IEnvConfig;
	osx?: IEnvConfig;
	linux?: IEnvConfig;
}

E
Erich Gamma 已提交
309
export interface IRawEnvAdapter {
I
isidor 已提交
310 311 312 313 314 315
	type?: string;
	label?: string;
	program?: string;
	args?: string[];
	runtime?: string;
	runtimeArgs?: string[];
E
Erich Gamma 已提交
316 317 318
}

export interface IRawAdapter extends IRawEnvAdapter {
I
isidor 已提交
319 320
	enableBreakpointsFor?: { languageIds: string[] };
	configurationAttributes?: any;
321
	initialConfigurations?: any[] | string;
322
	variables: { [key: string]: string };
I
isidor 已提交
323
	aiKey?: string;
I
isidor 已提交
324
	win?: IRawEnvAdapter;
I
isidor 已提交
325
	winx86?: IRawEnvAdapter;
326
	windows?: IRawEnvAdapter;
I
isidor 已提交
327 328
	osx?: IRawEnvAdapter;
	linux?: IRawEnvAdapter;
E
Erich Gamma 已提交
329 330
}

331 332 333 334
export interface IRawBreakpointContribution {
	language: string;
}

335
export interface IConfigurationManager {
336 337 338 339 340

	/**
	 * Returns a resolved debug configuration.
	 * If nameOrConfig is null resolves the first configuration and returns it.
	 */
341
	getConfiguration(nameOrConfig: string | IConfig): TPromise<IConfig>;
342 343 344 345

	/**
	 * Opens the launch.json file
	 */
346
	openConfigFile(sideBySide: boolean): TPromise<boolean>;
347 348 349 350

	/**
	 * Returns true if breakpoints can be set for a given editor model. Depends on mode.
	 */
I
isidor 已提交
351
	canSetBreakpointsIn(model: EditorIModel): boolean;
352 353
}

B
Benjamin Pasero 已提交
354
export const IDebugService = createDecorator<IDebugService>(DEBUG_SERVICE_ID);
E
Erich Gamma 已提交
355

356
export interface IDebugService {
357
	_serviceBrand: any;
358 359 360 361

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

364 365 366
	/**
	 * Allows to register on debug state changes.
	 */
I
isidor 已提交
367
	onDidChangeState: Event<void>;
368

369 370 371 372
	/**
	 * Gets the current configuration manager.
	 */
	getConfigurationManager(): IConfigurationManager;
E
Erich Gamma 已提交
373

I
isidor 已提交
374 375 376
	/**
	 * Sets the focused stack frame and evaluates all expresions against the newly focused stack frame,
	 */
I
isidor 已提交
377
	setFocusedStackFrameAndEvaluate(focusedStackFrame: IStackFrame, process?: IProcess): TPromise<void>;
E
Erich Gamma 已提交
378

379
	/**
380
	 * Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes.
381
	 */
382
	addBreakpoints(uri: uri, rawBreakpoints: IRawBreakpoint[]): TPromise<void>;
383 384 385 386 387 388 389 390 391 392 393

	/**
	 * 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.
	 */
394
	setBreakpointsActivated(activated: boolean): TPromise<void>;
395 396 397 398 399

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

402
	/**
403
	 * Adds a new no name function breakpoint. The function breakpoint should be renamed once user enters the name.
404
	 */
I
isidor 已提交
405
	addFunctionBreakpoint(): void;
406 407 408 409 410

	/**
	 * Renames an already existing function breakpoint.
	 * Notifies debug adapter of breakpoint changes.
	 */
I
isidor 已提交
411
	renameFunctionBreakpoint(id: string, newFunctionName: string): TPromise<void>;
412 413 414 415 416

	/**
	 * 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 已提交
417
	removeFunctionBreakpoints(id?: string): TPromise<void>;
E
Erich Gamma 已提交
418

419
	/**
420
	 * Adds a new expression to the repl.
421
	 */
I
isidor 已提交
422
	addReplExpression(name: string): TPromise<void>;
423 424 425 426

	/**
	 * Removes all repl expressions.
	 */
427
	removeReplExpressions(): void;
428 429 430 431

	/**
	 * Adds a new log to the repl. Either a string value or a dictionary (used to inspect complex objects printed to the repl).
	 */
432
	logToRepl(value: string | { [key: string]: any }, severity?: severity): void;
433 434 435 436

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

439
	/**
440
	 * Adds a new watch expression and evaluates it against the debug adapter.
441
	 */
I
isidor 已提交
442
	addWatchExpression(name?: string): TPromise<void>;
443 444 445 446

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

I
isidor 已提交
449 450 451 452 453
	/**
	 * Moves a watch expression to a new possition. Used for reordering watch expressions.
	 */
	moveWatchExpression(id: string, position: number): void;

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

I
isidor 已提交
459
	/**
I
isidor 已提交
460
	 * Creates a new debug process. Depending on the configuration will either 'launch' or 'attach'.
I
isidor 已提交
461
	 */
I
isidor 已提交
462
	createProcess(configurationOrName: IConfig | string): TPromise<any>;
I
isidor 已提交
463 464

	/**
I
isidor 已提交
465
	 * Restarts a process or creates a new one if there is no active session.
I
isidor 已提交
466
	 */
I
isidor 已提交
467
	restartProcess(process: IProcess): TPromise<any>;
I
isidor 已提交
468 469 470 471

	/**
	 * Gets the current debug model.
	 */
E
Erich Gamma 已提交
472
	getModel(): IModel;
I
isidor 已提交
473 474 475 476

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

I
isidor 已提交
479 480 481
	/**
	 * Opens a new or reveals an already visible editor showing the source.
	 */
482
	openOrRevealSource(sourceOrUri: Source | uri, lineNumber: number, preserveFocus: boolean, sideBySide: boolean): TPromise<any>;
E
Erich Gamma 已提交
483 484
}

I
isidor 已提交
485
// Editor interfaces
I
isidor 已提交
486
export interface IDebugEditorContribution extends IEditorContribution {
487
	showHover(range: Range, hoveringOver: string, focus: boolean): TPromise<void>;
I
isidor 已提交
488 489
}

I
isidor 已提交
490
// utils
E
Erich Gamma 已提交
491

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

I
isidor 已提交
494 495
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
	return value.replace(_formatPIIRegexp, function (match, group) {
E
Erich Gamma 已提交
496 497 498 499
		if (excludePII && group.length > 0 && group[0] !== '_') {
			return match;
		}

I
isidor 已提交
500
		return args && args.hasOwnProperty(group) ?
E
Erich Gamma 已提交
501 502
			args[group] :
			match;
I
isidor 已提交
503
	});
E
Erich Gamma 已提交
504
}