@theia/debug 1.18.0 → 1.21.0-next.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/console/debug-console-contribution.d.ts +1 -0
- package/lib/browser/console/debug-console-contribution.d.ts.map +1 -1
- package/lib/browser/console/debug-console-contribution.js +8 -6
- package/lib/browser/console/debug-console-contribution.js.map +1 -1
- package/lib/browser/console/debug-console-session.d.ts +1 -1
- package/lib/browser/console/debug-console-session.js +2 -2
- package/lib/browser/console/debug-console-session.js.map +1 -1
- package/lib/browser/debug-configuration-manager.d.ts.map +1 -1
- package/lib/browser/debug-configuration-manager.js +8 -7
- package/lib/browser/debug-configuration-manager.js.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.d.ts +5 -12
- package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.js +139 -112
- package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
- package/lib/browser/debug-preferences.d.ts +1 -0
- package/lib/browser/debug-preferences.d.ts.map +1 -1
- package/lib/browser/debug-preferences.js +22 -6
- package/lib/browser/debug-preferences.js.map +1 -1
- package/lib/browser/debug-prefix-configuration.d.ts.map +1 -1
- package/lib/browser/debug-prefix-configuration.js +3 -3
- package/lib/browser/debug-prefix-configuration.js.map +1 -1
- package/lib/browser/debug-session-connection.d.ts +23 -18
- package/lib/browser/debug-session-connection.d.ts.map +1 -1
- package/lib/browser/debug-session-connection.js +86 -65
- package/lib/browser/debug-session-connection.js.map +1 -1
- package/lib/browser/debug-session-contribution.d.ts +1 -1
- package/lib/browser/debug-session-contribution.d.ts.map +1 -1
- package/lib/browser/debug-session-contribution.js +1 -1
- package/lib/browser/debug-session-contribution.js.map +1 -1
- package/lib/browser/debug-session-manager.d.ts +6 -14
- package/lib/browser/debug-session-manager.d.ts.map +1 -1
- package/lib/browser/debug-session-manager.js +41 -44
- package/lib/browser/debug-session-manager.js.map +1 -1
- package/lib/browser/debug-session.d.ts +9 -8
- package/lib/browser/debug-session.d.ts.map +1 -1
- package/lib/browser/debug-session.js +55 -58
- package/lib/browser/debug-session.js.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.js +4 -3
- package/lib/browser/model/debug-function-breakpoint.js.map +1 -1
- package/lib/browser/preferences/launch-preferences.d.ts.map +1 -1
- package/lib/browser/preferences/launch-preferences.js +2 -1
- package/lib/browser/preferences/launch-preferences.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.d.ts +0 -1
- package/lib/browser/view/debug-breakpoints-source.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.js +1 -7
- package/lib/browser/view/debug-breakpoints-source.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-widget.js +2 -1
- package/lib/browser/view/debug-breakpoints-widget.js.map +1 -1
- package/lib/browser/view/debug-configuration-widget.d.ts +1 -1
- package/lib/browser/view/debug-configuration-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-configuration-widget.js +8 -8
- package/lib/browser/view/debug-configuration-widget.js.map +1 -1
- package/lib/browser/view/debug-session-widget.d.ts +2 -1
- package/lib/browser/view/debug-session-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-session-widget.js +12 -6
- package/lib/browser/view/debug-session-widget.js.map +1 -1
- package/lib/browser/view/debug-stack-frames-source.d.ts +0 -1
- package/lib/browser/view/debug-stack-frames-source.d.ts.map +1 -1
- package/lib/browser/view/debug-stack-frames-source.js +2 -5
- package/lib/browser/view/debug-stack-frames-source.js.map +1 -1
- package/lib/browser/view/debug-stack-frames-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-stack-frames-widget.js +2 -1
- package/lib/browser/view/debug-stack-frames-widget.js.map +1 -1
- package/lib/browser/view/debug-threads-source.d.ts +0 -1
- package/lib/browser/view/debug-threads-source.d.ts.map +1 -1
- package/lib/browser/view/debug-threads-source.js +1 -7
- package/lib/browser/view/debug-threads-source.js.map +1 -1
- package/lib/browser/view/debug-threads-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-threads-widget.js +2 -1
- package/lib/browser/view/debug-threads-widget.js.map +1 -1
- package/lib/browser/view/debug-toolbar-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-toolbar-widget.js +9 -8
- package/lib/browser/view/debug-toolbar-widget.js.map +1 -1
- package/lib/browser/view/debug-variables-source.d.ts +0 -1
- package/lib/browser/view/debug-variables-source.d.ts.map +1 -1
- package/lib/browser/view/debug-variables-source.js +2 -5
- package/lib/browser/view/debug-variables-source.js.map +1 -1
- package/lib/browser/view/debug-variables-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-variables-widget.js +2 -1
- package/lib/browser/view/debug-variables-widget.js.map +1 -1
- package/lib/browser/view/debug-view-model.js +3 -3
- package/lib/browser/view/debug-view-model.js.map +1 -1
- package/lib/browser/view/debug-watch-source.d.ts +0 -1
- package/lib/browser/view/debug-watch-source.d.ts.map +1 -1
- package/lib/browser/view/debug-watch-source.js +2 -5
- package/lib/browser/view/debug-watch-source.js.map +1 -1
- package/lib/browser/view/debug-watch-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-watch-widget.js +2 -1
- package/lib/browser/view/debug-watch-widget.js.map +1 -1
- package/lib/browser/view/debug-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-widget.js +2 -1
- package/lib/browser/view/debug-widget.js.map +1 -1
- package/lib/common/debug-service.d.ts +10 -0
- package/lib/common/debug-service.d.ts.map +1 -1
- package/lib/node/debug-adapter-contribution-registry.d.ts +1 -1
- package/lib/node/debug-adapter-contribution-registry.d.ts.map +1 -1
- package/lib/node/debug-adapter-contribution-registry.js +1 -1
- package/lib/node/debug-adapter-contribution-registry.js.map +1 -1
- package/lib/node/debug-adapter-factory.d.ts +4 -4
- package/lib/node/debug-adapter-factory.d.ts.map +1 -1
- package/lib/node/debug-adapter-factory.js +10 -12
- package/lib/node/debug-adapter-factory.js.map +1 -1
- package/lib/node/debug-adapter-session-manager.d.ts +1 -1
- package/lib/node/debug-adapter-session-manager.d.ts.map +1 -1
- package/lib/node/debug-adapter-session-manager.js +1 -2
- package/lib/node/debug-adapter-session-manager.js.map +1 -1
- package/lib/node/debug-adapter-session.d.ts +7 -13
- package/lib/node/debug-adapter-session.d.ts.map +1 -1
- package/lib/node/debug-adapter-session.js +25 -68
- package/lib/node/debug-adapter-session.js.map +1 -1
- package/lib/node/debug-backend-module.js +1 -1
- package/lib/node/debug-backend-module.js.map +1 -1
- package/lib/{common → node}/debug-model.d.ts +37 -19
- package/lib/node/debug-model.d.ts.map +1 -0
- package/lib/{common → node}/debug-model.js +0 -0
- package/lib/node/debug-model.js.map +1 -0
- package/lib/node/inline-debug-adapter.d.ts +34 -0
- package/lib/node/inline-debug-adapter.d.ts.map +1 -0
- package/lib/node/inline-debug-adapter.js +45 -0
- package/lib/node/inline-debug-adapter.js.map +1 -0
- package/lib/node/stream-debug-adapter.d.ts +52 -0
- package/lib/node/stream-debug-adapter.d.ts.map +1 -0
- package/lib/node/stream-debug-adapter.js +113 -0
- package/lib/node/stream-debug-adapter.js.map +1 -0
- package/lib/node/vscode/vscode-debug-adapter-contribution.d.ts +1 -1
- package/lib/node/vscode/vscode-debug-adapter-contribution.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/browser/console/debug-console-contribution.tsx +9 -6
- package/src/browser/console/debug-console-session.ts +2 -2
- package/src/browser/debug-configuration-manager.ts +10 -8
- package/src/browser/debug-frontend-application-contribution.ts +160 -125
- package/src/browser/debug-preferences.ts +23 -6
- package/src/browser/debug-prefix-configuration.ts +4 -4
- package/src/browser/debug-session-connection.ts +102 -76
- package/src/browser/debug-session-contribution.ts +3 -4
- package/src/browser/debug-session-manager.ts +45 -47
- package/src/browser/debug-session.tsx +54 -57
- package/src/browser/model/debug-function-breakpoint.tsx +4 -3
- package/src/browser/preferences/launch-preferences.ts +2 -1
- package/src/browser/view/debug-breakpoints-source.tsx +0 -6
- package/src/browser/view/debug-breakpoints-widget.ts +2 -1
- package/src/browser/view/debug-configuration-widget.tsx +8 -7
- package/src/browser/view/debug-session-widget.ts +12 -6
- package/src/browser/view/debug-stack-frames-source.tsx +0 -6
- package/src/browser/view/debug-stack-frames-widget.ts +2 -1
- package/src/browser/view/debug-threads-source.tsx +0 -6
- package/src/browser/view/debug-threads-widget.ts +2 -1
- package/src/browser/view/debug-toolbar-widget.tsx +13 -8
- package/src/browser/view/debug-variables-source.ts +0 -6
- package/src/browser/view/debug-variables-widget.ts +2 -1
- package/src/browser/view/debug-view-model.ts +3 -3
- package/src/browser/view/debug-watch-source.ts +0 -6
- package/src/browser/view/debug-watch-widget.ts +2 -1
- package/src/browser/view/debug-widget.ts +2 -1
- package/src/common/debug-service.ts +13 -0
- package/src/node/debug-adapter-contribution-registry.ts +1 -1
- package/src/node/debug-adapter-factory.ts +17 -17
- package/src/node/debug-adapter-session-manager.ts +1 -2
- package/src/node/debug-adapter-session.ts +32 -80
- package/src/node/debug-backend-module.ts +1 -1
- package/src/{common → node}/debug-model.ts +38 -18
- package/src/node/inline-debug-adapter.ts +47 -0
- package/src/node/stream-debug-adapter.ts +126 -0
- package/src/node/vscode/vscode-debug-adapter-contribution.ts +1 -1
- package/lib/common/debug-model.d.ts.map +0 -1
- package/lib/common/debug-model.js.map +0 -1
|
@@ -19,13 +19,9 @@
|
|
|
19
19
|
import { DebugProtocol } from 'vscode-debugprotocol';
|
|
20
20
|
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
21
21
|
import { Event, Emitter, DisposableCollection, Disposable, MaybePromise } from '@theia/core';
|
|
22
|
-
import { OutputChannel } from '@theia/output/lib/
|
|
23
|
-
import { IWebSocket } from '@theia/core/shared/vscode-ws-jsonrpc';
|
|
22
|
+
import { OutputChannel } from '@theia/output/lib/browser/output-channel';
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
code?: number
|
|
27
|
-
reason?: string | Error
|
|
28
|
-
}
|
|
24
|
+
import { Channel } from '../common/debug-service';
|
|
29
25
|
|
|
30
26
|
export type DebugRequestHandler = (request: DebugProtocol.Request) => MaybePromise<any>;
|
|
31
27
|
|
|
@@ -78,7 +74,7 @@ export interface DebugEventTypes {
|
|
|
78
74
|
'breakpoint': DebugProtocol.BreakpointEvent
|
|
79
75
|
'capabilities': DebugProtocol.CapabilitiesEvent
|
|
80
76
|
'continued': DebugProtocol.ContinuedEvent
|
|
81
|
-
'exited':
|
|
77
|
+
'exited': DebugProtocol.ExitedEvent,
|
|
82
78
|
'initialized': DebugProtocol.InitializedEvent
|
|
83
79
|
'invalidated': DebugProtocol.InvalidatedEvent
|
|
84
80
|
'loadedSource': DebugProtocol.LoadedSourceEvent
|
|
@@ -92,6 +88,15 @@ export interface DebugEventTypes {
|
|
|
92
88
|
'terminated': DebugProtocol.TerminatedEvent
|
|
93
89
|
'thread': DebugProtocol.ThreadEvent
|
|
94
90
|
}
|
|
91
|
+
|
|
92
|
+
export type DebugEventNames = keyof DebugEventTypes;
|
|
93
|
+
|
|
94
|
+
export namespace DebugEventTypes {
|
|
95
|
+
export function isStandardEvent(evt: string): evt is DebugEventNames {
|
|
96
|
+
return standardDebugEvents.has(evt);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
95
100
|
const standardDebugEvents = new Set<string>([
|
|
96
101
|
'breakpoint',
|
|
97
102
|
'capabilities',
|
|
@@ -115,14 +120,19 @@ export class DebugSessionConnection implements Disposable {
|
|
|
115
120
|
|
|
116
121
|
private sequence = 1;
|
|
117
122
|
|
|
118
|
-
protected readonly pendingRequests = new Map<number,
|
|
119
|
-
protected readonly
|
|
123
|
+
protected readonly pendingRequests = new Map<number, Deferred<DebugProtocol.Response>>();
|
|
124
|
+
protected readonly connectionPromise: Promise<Channel>;
|
|
120
125
|
|
|
121
126
|
protected readonly requestHandlers = new Map<string, DebugRequestHandler>();
|
|
122
127
|
|
|
123
128
|
protected readonly onDidCustomEventEmitter = new Emitter<DebugProtocol.Event>();
|
|
124
129
|
readonly onDidCustomEvent: Event<DebugProtocol.Event> = this.onDidCustomEventEmitter.event;
|
|
125
130
|
|
|
131
|
+
protected readonly onDidCloseEmitter = new Emitter<void>();
|
|
132
|
+
readonly onDidClose: Event<void> = this.onDidCloseEmitter.event;
|
|
133
|
+
|
|
134
|
+
protected isClosed = false;
|
|
135
|
+
|
|
126
136
|
protected readonly toDispose = new DisposableCollection(
|
|
127
137
|
this.onDidCustomEventEmitter,
|
|
128
138
|
Disposable.create(() => this.pendingRequests.clear()),
|
|
@@ -131,15 +141,16 @@ export class DebugSessionConnection implements Disposable {
|
|
|
131
141
|
|
|
132
142
|
constructor(
|
|
133
143
|
readonly sessionId: string,
|
|
134
|
-
|
|
144
|
+
connectionFactory: (sessionId: string) => Promise<Channel>,
|
|
135
145
|
protected readonly traceOutputChannel: OutputChannel | undefined
|
|
136
146
|
) {
|
|
137
|
-
this.
|
|
147
|
+
this.connectionPromise = this.createConnection(connectionFactory);
|
|
138
148
|
}
|
|
139
149
|
|
|
140
150
|
get disposed(): boolean {
|
|
141
151
|
return this.toDispose.disposed;
|
|
142
152
|
}
|
|
153
|
+
|
|
143
154
|
protected checkDisposed(): void {
|
|
144
155
|
if (this.disposed) {
|
|
145
156
|
throw new Error('the debug session connection is disposed, id: ' + this.sessionId);
|
|
@@ -150,23 +161,20 @@ export class DebugSessionConnection implements Disposable {
|
|
|
150
161
|
this.toDispose.dispose();
|
|
151
162
|
}
|
|
152
163
|
|
|
153
|
-
protected async createConnection(): Promise<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
connection.onMessage(data => this.handleMessage(data));
|
|
163
|
-
return connection;
|
|
164
|
-
}
|
|
164
|
+
protected async createConnection(connectionFactory: (sessionId: string) => Promise<Channel>): Promise<Channel> {
|
|
165
|
+
const connection = await connectionFactory(this.sessionId);
|
|
166
|
+
connection.onClose(() => {
|
|
167
|
+
this.isClosed = true;
|
|
168
|
+
this.cancelPendingRequests();
|
|
169
|
+
this.onDidCloseEmitter.fire();
|
|
170
|
+
});
|
|
171
|
+
connection.onMessage(data => this.handleMessage(data));
|
|
172
|
+
return connection;
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
protected allThreadsContinued = true;
|
|
168
|
-
async sendRequest<K extends keyof DebugRequestTypes>(command: K, args: DebugRequestTypes[K][0]): Promise<DebugRequestTypes[K][1]> {
|
|
169
|
-
const result = await this.doSendRequest(command, args);
|
|
176
|
+
async sendRequest<K extends keyof DebugRequestTypes>(command: K, args: DebugRequestTypes[K][0], timeout?: number): Promise<DebugRequestTypes[K][1]> {
|
|
177
|
+
const result = await this.doSendRequest(command, args, timeout);
|
|
170
178
|
if (command === 'next' || command === 'stepIn' ||
|
|
171
179
|
command === 'stepOut' || command === 'stepBack' ||
|
|
172
180
|
command === 'reverseContinue' || command === 'restartFrame') {
|
|
@@ -186,56 +194,69 @@ export class DebugSessionConnection implements Disposable {
|
|
|
186
194
|
sendCustomRequest<T extends DebugProtocol.Response>(command: string, args?: any): Promise<T> {
|
|
187
195
|
return this.doSendRequest<T>(command, args);
|
|
188
196
|
}
|
|
189
|
-
|
|
197
|
+
|
|
198
|
+
protected cancelPendingRequests(): void {
|
|
199
|
+
this.pendingRequests.forEach((deferred, requestId) => {
|
|
200
|
+
deferred.reject(new Error(`Request ${requestId} cancelled on connection close`));
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
protected doSendRequest<K extends DebugProtocol.Response>(command: string, args?: any, timeout?: number): Promise<K> {
|
|
190
205
|
const result = new Deferred<K>();
|
|
191
206
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
207
|
+
if (this.isClosed) {
|
|
208
|
+
result.reject(new Error('Connection is closed'));
|
|
209
|
+
} else {
|
|
210
|
+
const request: DebugProtocol.Request = {
|
|
211
|
+
seq: this.sequence++,
|
|
212
|
+
type: 'request',
|
|
213
|
+
command: command,
|
|
214
|
+
arguments: args
|
|
215
|
+
};
|
|
198
216
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
this.pendingRequests.set(request.seq, result);
|
|
218
|
+
if (timeout) {
|
|
219
|
+
const handle = setTimeout(() => {
|
|
220
|
+
const pendingRequest = this.pendingRequests.get(request.seq);
|
|
221
|
+
if (pendingRequest) {
|
|
222
|
+
// request has not been handled
|
|
223
|
+
this.pendingRequests.delete(request.seq);
|
|
224
|
+
const error: DebugProtocol.Response = {
|
|
225
|
+
type: 'response',
|
|
226
|
+
seq: 0,
|
|
227
|
+
request_seq: request.seq,
|
|
228
|
+
success: false,
|
|
229
|
+
command,
|
|
230
|
+
message: `Request #${request.seq}: ${request.command} timed out`
|
|
231
|
+
};
|
|
232
|
+
pendingRequest.reject(error);
|
|
233
|
+
}
|
|
234
|
+
}, timeout);
|
|
235
|
+
result.promise.finally(() => clearTimeout(handle));
|
|
210
236
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
onDispose.dispose();
|
|
214
|
-
if (!response.success) {
|
|
215
|
-
result.reject(response);
|
|
216
|
-
} else {
|
|
217
|
-
result.resolve(response);
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
await this.send(request);
|
|
237
|
+
this.send(request);
|
|
238
|
+
}
|
|
222
239
|
return result.promise;
|
|
223
240
|
}
|
|
224
241
|
|
|
225
242
|
protected async send(message: DebugProtocol.ProtocolMessage): Promise<void> {
|
|
226
|
-
const connection = await this.
|
|
243
|
+
const connection = await this.connectionPromise;
|
|
227
244
|
const messageStr = JSON.stringify(message);
|
|
228
245
|
if (this.traceOutputChannel) {
|
|
229
|
-
|
|
246
|
+
const now = new Date();
|
|
247
|
+
const dateStr = `${now.toLocaleString(undefined, { hour12: false })}.${now.getMilliseconds()}`;
|
|
248
|
+
this.traceOutputChannel.appendLine(`${this.sessionId.substring(0, 8)} ${dateStr} theia -> adapter: ${JSON.stringify(message, undefined, 4)}`);
|
|
230
249
|
}
|
|
231
250
|
connection.send(messageStr);
|
|
232
251
|
}
|
|
233
252
|
|
|
234
253
|
protected handleMessage(data: string): void {
|
|
254
|
+
const message: DebugProtocol.ProtocolMessage = JSON.parse(data);
|
|
235
255
|
if (this.traceOutputChannel) {
|
|
236
|
-
|
|
256
|
+
const now = new Date();
|
|
257
|
+
const dateStr = `${now.toLocaleString(undefined, { hour12: false })}.${now.getMilliseconds()}`;
|
|
258
|
+
this.traceOutputChannel.appendLine(`${this.sessionId.substring(0, 8)} ${dateStr} theia <- adapter: ${JSON.stringify(message, undefined, 4)}`);
|
|
237
259
|
}
|
|
238
|
-
const message: DebugProtocol.ProtocolMessage = JSON.parse(data);
|
|
239
260
|
if (message.type === 'request') {
|
|
240
261
|
this.handleRequest(message as DebugProtocol.Request);
|
|
241
262
|
} else if (message.type === 'response') {
|
|
@@ -246,10 +267,14 @@ export class DebugSessionConnection implements Disposable {
|
|
|
246
267
|
}
|
|
247
268
|
|
|
248
269
|
protected handleResponse(response: DebugProtocol.Response): void {
|
|
249
|
-
const
|
|
250
|
-
if (
|
|
270
|
+
const pendingRequest = this.pendingRequests.get(response.request_seq);
|
|
271
|
+
if (pendingRequest) {
|
|
251
272
|
this.pendingRequests.delete(response.request_seq);
|
|
252
|
-
|
|
273
|
+
if (!response.success) {
|
|
274
|
+
pendingRequest.reject(response);
|
|
275
|
+
} else {
|
|
276
|
+
pendingRequest.resolve(response);
|
|
277
|
+
}
|
|
253
278
|
}
|
|
254
279
|
}
|
|
255
280
|
|
|
@@ -280,36 +305,37 @@ export class DebugSessionConnection implements Disposable {
|
|
|
280
305
|
}
|
|
281
306
|
|
|
282
307
|
protected handleEvent(event: DebugProtocol.Event): void {
|
|
283
|
-
if (
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
this.doFire(event.event, event);
|
|
289
|
-
} else {
|
|
290
|
-
this.onDidCustomEventEmitter.fire(event);
|
|
291
|
-
}
|
|
308
|
+
if (event.event === 'continued') {
|
|
309
|
+
this.allThreadsContinued = (<DebugProtocol.ContinuedEvent>event).body.allThreadsContinued === false ? false : true;
|
|
310
|
+
}
|
|
311
|
+
if (DebugEventTypes.isStandardEvent(event.event)) {
|
|
312
|
+
this.doFire(event.event, event);
|
|
292
313
|
} else {
|
|
293
|
-
this.fire(
|
|
314
|
+
this.onDidCustomEventEmitter.fire(event);
|
|
294
315
|
}
|
|
295
316
|
}
|
|
296
317
|
|
|
297
|
-
protected readonly emitters = new Map<string, Emitter<DebugProtocol.Event
|
|
318
|
+
protected readonly emitters = new Map<string, Emitter<DebugProtocol.Event>>();
|
|
298
319
|
on<K extends keyof DebugEventTypes>(kind: K, listener: (e: DebugEventTypes[K]) => any): Disposable {
|
|
299
320
|
return this.getEmitter(kind).event(listener);
|
|
300
321
|
}
|
|
322
|
+
|
|
323
|
+
onEvent<K extends keyof DebugEventTypes>(kind: K): Event<DebugEventTypes[K]> {
|
|
324
|
+
return this.getEmitter(kind).event;
|
|
325
|
+
}
|
|
326
|
+
|
|
301
327
|
protected fire<K extends keyof DebugEventTypes>(kind: K, e: DebugEventTypes[K]): void {
|
|
302
328
|
this.doFire(kind, e);
|
|
303
329
|
}
|
|
304
|
-
protected doFire(kind:
|
|
330
|
+
protected doFire<K extends keyof DebugEventTypes>(kind: K, e: DebugEventTypes[K]): void {
|
|
305
331
|
this.getEmitter(kind).fire(e);
|
|
306
332
|
}
|
|
307
|
-
protected getEmitter(kind:
|
|
333
|
+
protected getEmitter<K extends keyof DebugEventTypes>(kind: K): Emitter<DebugEventTypes[K]> {
|
|
308
334
|
const emitter = this.emitters.get(kind) || this.newEmitter();
|
|
309
335
|
this.emitters.set(kind, emitter);
|
|
310
|
-
return emitter;
|
|
336
|
+
return <Emitter<DebugEventTypes[K]>>emitter;
|
|
311
337
|
}
|
|
312
|
-
protected newEmitter(): Emitter<DebugProtocol.Event
|
|
338
|
+
protected newEmitter(): Emitter<DebugProtocol.Event> {
|
|
313
339
|
const emitter = new Emitter();
|
|
314
340
|
this.checkDisposed();
|
|
315
341
|
this.toDispose.push(emitter);
|
|
@@ -23,11 +23,10 @@ import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging/w
|
|
|
23
23
|
import { DebugSession } from './debug-session';
|
|
24
24
|
import { BreakpointManager } from './breakpoint/breakpoint-manager';
|
|
25
25
|
import { DebugSessionOptions } from './debug-session-options';
|
|
26
|
-
import { OutputChannelManager, OutputChannel } from '@theia/output/lib/
|
|
26
|
+
import { OutputChannelManager, OutputChannel } from '@theia/output/lib/browser/output-channel';
|
|
27
27
|
import { DebugPreferences } from './debug-preferences';
|
|
28
28
|
import { DebugSessionConnection } from './debug-session-connection';
|
|
29
|
-
import {
|
|
30
|
-
import { DebugAdapterPath } from '../common/debug-service';
|
|
29
|
+
import { Channel, DebugAdapterPath } from '../common/debug-service';
|
|
31
30
|
import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
|
32
31
|
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
33
32
|
import { DebugContribution } from './debug-contribution';
|
|
@@ -119,7 +118,7 @@ export class DefaultDebugSessionFactory implements DebugSessionFactory {
|
|
|
119
118
|
get(sessionId: string, options: DebugSessionOptions, parentSession?: DebugSession): DebugSession {
|
|
120
119
|
const connection = new DebugSessionConnection(
|
|
121
120
|
sessionId,
|
|
122
|
-
() => new Promise<
|
|
121
|
+
() => new Promise<Channel>(resolve =>
|
|
123
122
|
this.connectionProvider.openChannel(`${DebugAdapterPath}/${sessionId}`, channel => {
|
|
124
123
|
resolve(channel);
|
|
125
124
|
}, { reconnecting: false })
|
|
@@ -278,51 +278,73 @@ export class DebugSessionManager {
|
|
|
278
278
|
const restart = event.body && event.body.restart;
|
|
279
279
|
if (restart) {
|
|
280
280
|
// postDebugTask isn't run in case of auto restart as well as preLaunchTask
|
|
281
|
-
this.doRestart(session, restart);
|
|
281
|
+
this.doRestart(session, !!restart);
|
|
282
282
|
} else {
|
|
283
|
-
session.
|
|
283
|
+
await session.disconnect(false, () => this.debug.terminateDebugSession(session.id));
|
|
284
284
|
await this.runTask(session.options.workspaceFolderUri, session.configuration.postDebugTask);
|
|
285
285
|
}
|
|
286
286
|
});
|
|
287
|
-
|
|
288
|
-
session.
|
|
287
|
+
|
|
288
|
+
session.on('exited', async event => {
|
|
289
|
+
await session.disconnect(false, () => this.debug.terminateDebugSession(session.id));
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
session.onDispose(() => this.cleanup(session));
|
|
293
|
+
session.start().then(() => this.onDidStartDebugSessionEmitter.fire(session)).catch(e => {
|
|
294
|
+
session.stop(false, () => {
|
|
295
|
+
this.debug.terminateDebugSession(session.id);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
289
298
|
session.onDidCustomEvent(({ event, body }) =>
|
|
290
299
|
this.onDidReceiveDebugSessionCustomEventEmitter.fire({ event, body, session })
|
|
291
300
|
);
|
|
292
301
|
return session;
|
|
293
302
|
}
|
|
294
303
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
304
|
+
protected cleanup(session: DebugSession): void {
|
|
305
|
+
if (this.remove(session.id)) {
|
|
306
|
+
this.onDidDestroyDebugSessionEmitter.fire(session);
|
|
307
|
+
}
|
|
299
308
|
}
|
|
300
|
-
|
|
301
|
-
|
|
309
|
+
|
|
310
|
+
protected async doRestart(session: DebugSession, isRestart: boolean): Promise<DebugSession | undefined> {
|
|
311
|
+
if (session.canRestart()) {
|
|
312
|
+
await session.restart();
|
|
302
313
|
return session;
|
|
303
314
|
}
|
|
304
|
-
await session.terminate(true);
|
|
305
315
|
const { options, configuration } = session;
|
|
306
|
-
|
|
316
|
+
session.stop(isRestart, () => this.debug.terminateDebugSession(session.id));
|
|
317
|
+
configuration.__restart = isRestart;
|
|
307
318
|
return this.start(options);
|
|
308
319
|
}
|
|
309
320
|
|
|
310
|
-
async
|
|
311
|
-
|
|
312
|
-
|
|
321
|
+
async terminateSession(session?: DebugSession): Promise<void> {
|
|
322
|
+
if (!session) {
|
|
323
|
+
this.updateCurrentSession(this._currentSession);
|
|
324
|
+
session = this._currentSession;
|
|
325
|
+
}
|
|
326
|
+
if (session) {
|
|
327
|
+
session.stop(false, () => this.debug.terminateDebugSession(session!.id));
|
|
328
|
+
}
|
|
313
329
|
}
|
|
314
330
|
|
|
315
|
-
async
|
|
316
|
-
|
|
317
|
-
|
|
331
|
+
async restartSession(session?: DebugSession): Promise<DebugSession | undefined> {
|
|
332
|
+
if (!session) {
|
|
333
|
+
this.updateCurrentSession(this._currentSession);
|
|
334
|
+
session = this._currentSession;
|
|
335
|
+
}
|
|
336
|
+
if (session) {
|
|
337
|
+
return this.doRestart(session, true);
|
|
338
|
+
}
|
|
318
339
|
}
|
|
319
340
|
|
|
320
|
-
protected remove(sessionId: string):
|
|
321
|
-
this._sessions.delete(sessionId);
|
|
341
|
+
protected remove(sessionId: string): boolean {
|
|
342
|
+
const existed = this._sessions.delete(sessionId);
|
|
322
343
|
const { currentSession } = this;
|
|
323
344
|
if (currentSession && currentSession.id === sessionId) {
|
|
324
345
|
this.updateCurrentSession(undefined);
|
|
325
346
|
}
|
|
347
|
+
return existed;
|
|
326
348
|
}
|
|
327
349
|
|
|
328
350
|
getSession(sessionId: string): DebugSession | undefined {
|
|
@@ -334,7 +356,7 @@ export class DebugSessionManager {
|
|
|
334
356
|
}
|
|
335
357
|
|
|
336
358
|
protected _currentSession: DebugSession | undefined;
|
|
337
|
-
protected readonly
|
|
359
|
+
protected readonly disposeOnCurrentSessionChanged = new DisposableCollection();
|
|
338
360
|
get currentSession(): DebugSession | undefined {
|
|
339
361
|
return this._currentSession;
|
|
340
362
|
}
|
|
@@ -342,12 +364,12 @@ export class DebugSessionManager {
|
|
|
342
364
|
if (this._currentSession === current) {
|
|
343
365
|
return;
|
|
344
366
|
}
|
|
345
|
-
this.
|
|
367
|
+
this.disposeOnCurrentSessionChanged.dispose();
|
|
346
368
|
const previous = this.currentSession;
|
|
347
369
|
this._currentSession = current;
|
|
348
370
|
this.onDidChangeActiveDebugSessionEmitter.fire({ previous, current });
|
|
349
371
|
if (current) {
|
|
350
|
-
this.
|
|
372
|
+
this.disposeOnCurrentSessionChanged.push(current.onDidChange(() => {
|
|
351
373
|
if (this.currentFrame === this.topFrame) {
|
|
352
374
|
this.open();
|
|
353
375
|
}
|
|
@@ -403,30 +425,6 @@ export class DebugSessionManager {
|
|
|
403
425
|
return currentThread && currentThread.topFrame;
|
|
404
426
|
}
|
|
405
427
|
|
|
406
|
-
/**
|
|
407
|
-
* Destroy the debug session. If session identifier isn't provided then
|
|
408
|
-
* all active debug session will be destroyed.
|
|
409
|
-
* @param sessionId The session identifier
|
|
410
|
-
*/
|
|
411
|
-
destroy(sessionId?: string): void {
|
|
412
|
-
if (sessionId) {
|
|
413
|
-
const session = this._sessions.get(sessionId);
|
|
414
|
-
if (session) {
|
|
415
|
-
this.doDestroy(session);
|
|
416
|
-
}
|
|
417
|
-
} else {
|
|
418
|
-
this._sessions.forEach(session => this.doDestroy(session));
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
private doDestroy(session: DebugSession): void {
|
|
423
|
-
this.debug.terminateDebugSession(session.id);
|
|
424
|
-
|
|
425
|
-
session.dispose();
|
|
426
|
-
this.remove(session.id);
|
|
427
|
-
this.onDidDestroyDebugSessionEmitter.fire(session);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
428
|
getFunctionBreakpoints(session: DebugSession | undefined = this.currentSession): DebugFunctionBreakpoint[] {
|
|
431
429
|
if (session && session.state > DebugState.Initializing) {
|
|
432
430
|
return session.getFunctionBreakpoints();
|
|
@@ -40,6 +40,7 @@ import { TerminalWidgetOptions, TerminalWidget } from '@theia/terminal/lib/brows
|
|
|
40
40
|
import { DebugFunctionBreakpoint } from './model/debug-function-breakpoint';
|
|
41
41
|
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
42
42
|
import { DebugContribution } from './debug-contribution';
|
|
43
|
+
import { waitForEvent } from '@theia/core/lib/common/promise-util';
|
|
43
44
|
|
|
44
45
|
export enum DebugState {
|
|
45
46
|
Inactive,
|
|
@@ -63,9 +64,10 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
protected readonly childSessions = new Map<string, DebugSession>();
|
|
66
|
-
|
|
67
67
|
protected readonly toDispose = new DisposableCollection();
|
|
68
68
|
|
|
69
|
+
private isStopping: boolean = false;
|
|
70
|
+
|
|
69
71
|
constructor(
|
|
70
72
|
readonly id: string,
|
|
71
73
|
readonly options: DebugSessionOptions,
|
|
@@ -80,6 +82,9 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
80
82
|
protected readonly debugContributionProvider: ContributionProvider<DebugContribution>
|
|
81
83
|
) {
|
|
82
84
|
this.connection.onRequest('runInTerminal', (request: DebugProtocol.RunInTerminalRequest) => this.runInTerminal(request));
|
|
85
|
+
this.connection.onDidClose(() => {
|
|
86
|
+
this.toDispose.dispose();
|
|
87
|
+
});
|
|
83
88
|
this.registerDebugContributions(options.configuration.type, this.connection);
|
|
84
89
|
|
|
85
90
|
if (parentSession) {
|
|
@@ -88,6 +93,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
88
93
|
this.parentSession?.childSessions?.delete(id);
|
|
89
94
|
}));
|
|
90
95
|
}
|
|
96
|
+
this.connection.onDidClose(() => this.toDispose.dispose());
|
|
91
97
|
this.toDispose.pushAll([
|
|
92
98
|
this.onDidChangeEmitter,
|
|
93
99
|
this.onDidChangeBreakpointsEmitter,
|
|
@@ -96,19 +102,18 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
96
102
|
this.doUpdateThreads([]);
|
|
97
103
|
}),
|
|
98
104
|
this.connection,
|
|
99
|
-
this.on('initialized', () => this.configure()),
|
|
100
|
-
this.on('breakpoint', ({ body }) => this.updateBreakpoint(body)),
|
|
101
|
-
this.on('continued', e => this.handleContinued(e)),
|
|
102
|
-
this.on('stopped', e => this.handleStopped(e)),
|
|
103
|
-
this.on('thread', e => this.handleThread(e)),
|
|
104
|
-
this.on('
|
|
105
|
-
this.on('capabilities', event => this.updateCapabilities(event.body.capabilities)),
|
|
105
|
+
this.connection.on('initialized', () => this.configure()),
|
|
106
|
+
this.connection.on('breakpoint', ({ body }) => this.updateBreakpoint(body)),
|
|
107
|
+
this.connection.on('continued', e => this.handleContinued(e)),
|
|
108
|
+
this.connection.on('stopped', e => this.handleStopped(e)),
|
|
109
|
+
this.connection.on('thread', e => this.handleThread(e)),
|
|
110
|
+
this.connection.on('capabilities', event => this.updateCapabilities(event.body.capabilities)),
|
|
106
111
|
this.breakpoints.onDidChangeMarkers(uri => this.updateBreakpoints({ uri, sourceModified: true }))
|
|
107
112
|
]);
|
|
108
113
|
}
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
this.toDispose.
|
|
115
|
+
get onDispose(): Event<void> {
|
|
116
|
+
return this.toDispose.onDispose;
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
get configuration(): DebugConfiguration {
|
|
@@ -278,8 +283,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
278
283
|
try {
|
|
279
284
|
await this.sendRequest((this.configuration.request as keyof DebugRequestTypes), this.configuration);
|
|
280
285
|
} catch (reason) {
|
|
281
|
-
this.
|
|
282
|
-
await this.messages.showMessage({
|
|
286
|
+
this.messages.showMessage({
|
|
283
287
|
type: MessageType.Error,
|
|
284
288
|
text: reason.message || 'Debug session initialization failed. See console for details.',
|
|
285
289
|
options: {
|
|
@@ -308,59 +312,48 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
308
312
|
await this.updateThreads(undefined);
|
|
309
313
|
}
|
|
310
314
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (!this.terminated && this.capabilities.supportsTerminateRequest && this.configuration.request === 'launch') {
|
|
314
|
-
this.terminated = true;
|
|
315
|
-
await this.connection.sendRequest('terminate', { restart });
|
|
316
|
-
if (!await this.exited(1000)) {
|
|
317
|
-
await this.disconnect(restart);
|
|
318
|
-
}
|
|
319
|
-
} else {
|
|
320
|
-
await this.disconnect(restart);
|
|
321
|
-
}
|
|
315
|
+
canTerminate(): boolean {
|
|
316
|
+
return !!this.capabilities.supportsTerminateRequest;
|
|
322
317
|
}
|
|
323
318
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
Promise.race([
|
|
327
|
-
this.sendRequest('disconnect', { restart }),
|
|
328
|
-
new Promise(reject => setTimeout(reject, TIMEOUT_MS, new Error('TIMEOUT_ERR')))
|
|
329
|
-
]).then(res => {
|
|
330
|
-
if (res instanceof Error) {
|
|
331
|
-
this.fireExited(res);
|
|
332
|
-
}
|
|
333
|
-
}).catch(() => this.fireExited());
|
|
319
|
+
canRestart(): boolean {
|
|
320
|
+
return !!this.capabilities.supportsRestartRequest;
|
|
334
321
|
}
|
|
335
322
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
this.
|
|
339
|
-
} catch (e) {
|
|
340
|
-
console.error(e);
|
|
323
|
+
async restart(): Promise<void> {
|
|
324
|
+
if (this.canRestart()) {
|
|
325
|
+
await this.sendRequest('restart', {});
|
|
341
326
|
}
|
|
342
327
|
}
|
|
343
328
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
329
|
+
async stop(isRestart: boolean, callback: () => void): Promise<void> {
|
|
330
|
+
if (!this.isStopping) {
|
|
331
|
+
this.isStopping = true;
|
|
332
|
+
if (this.canTerminate()) {
|
|
333
|
+
const terminated = this.waitFor('terminated', 5000);
|
|
334
|
+
try {
|
|
335
|
+
await this.connection.sendRequest('terminate', { restart: isRestart }, 5000);
|
|
336
|
+
await terminated;
|
|
337
|
+
} catch (e) {
|
|
338
|
+
console.error('Did not receive terminated event in time', e);
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
try {
|
|
342
|
+
await this.sendRequest('disconnect', { restart: isRestart }, 5000);
|
|
343
|
+
} catch (e) {
|
|
344
|
+
console.error('Error on disconnect', e);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
callback();
|
|
348
|
+
}
|
|
355
349
|
}
|
|
356
350
|
|
|
357
|
-
async
|
|
358
|
-
if (this.
|
|
359
|
-
this.
|
|
360
|
-
await this.sendRequest('
|
|
361
|
-
|
|
351
|
+
async disconnect(isRestart: boolean, callback: () => void): Promise<void> {
|
|
352
|
+
if (!this.isStopping) {
|
|
353
|
+
this.isStopping = true;
|
|
354
|
+
await this.sendRequest('disconnect', { restart: isRestart });
|
|
355
|
+
callback();
|
|
362
356
|
}
|
|
363
|
-
return false;
|
|
364
357
|
}
|
|
365
358
|
|
|
366
359
|
async completions(text: string, column: number, line: number): Promise<DebugProtocol.CompletionItem[]> {
|
|
@@ -375,8 +368,8 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
375
368
|
return response.body;
|
|
376
369
|
}
|
|
377
370
|
|
|
378
|
-
sendRequest<K extends keyof DebugRequestTypes>(command: K, args: DebugRequestTypes[K][0]): Promise<DebugRequestTypes[K][1]> {
|
|
379
|
-
return this.connection.sendRequest(command, args);
|
|
371
|
+
sendRequest<K extends keyof DebugRequestTypes>(command: K, args: DebugRequestTypes[K][0], timeout?: number): Promise<DebugRequestTypes[K][1]> {
|
|
372
|
+
return this.connection.sendRequest(command, args, timeout);
|
|
380
373
|
}
|
|
381
374
|
|
|
382
375
|
sendCustomRequest<T extends DebugProtocol.Response>(command: string, args?: any): Promise<T> {
|
|
@@ -387,6 +380,10 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
387
380
|
return this.connection.on(kind, listener);
|
|
388
381
|
}
|
|
389
382
|
|
|
383
|
+
waitFor<K extends keyof DebugEventTypes>(kind: K, ms: number): Promise<void> {
|
|
384
|
+
return waitForEvent(this.connection.onEvent(kind), ms).then();
|
|
385
|
+
}
|
|
386
|
+
|
|
390
387
|
get onDidCustomEvent(): Event<DebugProtocol.Event> {
|
|
391
388
|
return this.connection.onDidCustomEvent;
|
|
392
389
|
}
|