@jupyterlab/debugger 4.0.0-alpha.2 → 4.0.0-alpha.20
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/debugger.d.ts +4 -0
- package/lib/debugger.js +5 -1
- package/lib/debugger.js.map +1 -1
- package/lib/dialogs/evaluate.d.ts +5 -0
- package/lib/dialogs/evaluate.js +16 -6
- package/lib/dialogs/evaluate.js.map +1 -1
- package/lib/factory.d.ts +1 -1
- package/lib/factory.js +15 -9
- package/lib/factory.js.map +1 -1
- package/lib/handler.js +24 -9
- package/lib/handler.js.map +1 -1
- package/lib/handlers/console.js +9 -3
- package/lib/handlers/console.js.map +1 -1
- package/lib/handlers/editor.d.ts +33 -11
- package/lib/handlers/editor.js +177 -88
- package/lib/handlers/editor.js.map +1 -1
- package/lib/handlers/file.d.ts +1 -0
- package/lib/handlers/file.js +11 -2
- package/lib/handlers/file.js.map +1 -1
- package/lib/handlers/notebook.d.ts +0 -7
- package/lib/handlers/notebook.js +22 -18
- package/lib/handlers/notebook.js.map +1 -1
- package/lib/icons.d.ts +3 -0
- package/lib/icons.js +15 -0
- package/lib/icons.js.map +1 -1
- package/lib/model.d.ts +5 -0
- package/lib/model.js +4 -0
- package/lib/model.js.map +1 -1
- package/lib/panels/breakpoints/index.d.ts +18 -0
- package/lib/panels/breakpoints/index.js +10 -3
- package/lib/panels/breakpoints/index.js.map +1 -1
- package/lib/panels/breakpoints/pauseonexceptions.d.ts +53 -0
- package/lib/panels/breakpoints/pauseonexceptions.js +98 -0
- package/lib/panels/breakpoints/pauseonexceptions.js.map +1 -0
- package/lib/panels/callstack/index.d.ts +1 -1
- package/lib/panels/kernelSources/body.d.ts +45 -0
- package/lib/panels/kernelSources/body.js +76 -0
- package/lib/panels/kernelSources/body.js.map +1 -0
- package/lib/panels/kernelSources/filter.d.ts +11 -0
- package/lib/panels/kernelSources/filter.js +18 -0
- package/lib/panels/kernelSources/filter.js.map +1 -0
- package/lib/panels/kernelSources/index.d.ts +39 -0
- package/lib/panels/kernelSources/index.js +54 -0
- package/lib/panels/kernelSources/index.js.map +1 -0
- package/lib/panels/kernelSources/model.d.ts +73 -0
- package/lib/panels/kernelSources/model.js +120 -0
- package/lib/panels/kernelSources/model.js.map +1 -0
- package/lib/panels/sources/body.js +5 -3
- package/lib/panels/sources/body.js.map +1 -1
- package/lib/panels/variables/grid.d.ts +8 -2
- package/lib/panels/variables/grid.js +29 -364
- package/lib/panels/variables/grid.js.map +1 -1
- package/lib/panels/variables/gridpanel.d.ts +140 -0
- package/lib/panels/variables/gridpanel.js +363 -0
- package/lib/panels/variables/gridpanel.js.map +1 -0
- package/lib/panels/variables/index.d.ts +1 -9
- package/lib/panels/variables/index.js +1 -15
- package/lib/panels/variables/index.js.map +1 -1
- package/lib/panels/variables/mimerenderer.d.ts +15 -2
- package/lib/panels/variables/mimerenderer.js +56 -17
- package/lib/panels/variables/mimerenderer.js.map +1 -1
- package/lib/panels/variables/model.d.ts +3 -0
- package/lib/panels/variables/model.js +7 -0
- package/lib/panels/variables/model.js.map +1 -1
- package/lib/panels/variables/scope.js +4 -0
- package/lib/panels/variables/scope.js.map +1 -1
- package/lib/panels/variables/tree.d.ts +2 -5
- package/lib/panels/variables/tree.js +137 -47
- package/lib/panels/variables/tree.js.map +1 -1
- package/lib/service.d.ts +32 -2
- package/lib/service.js +122 -9
- package/lib/service.js.map +1 -1
- package/lib/session.d.ts +37 -1
- package/lib/session.js +89 -6
- package/lib/session.js.map +1 -1
- package/lib/sidebar.d.ts +7 -1
- package/lib/sidebar.js +10 -2
- package/lib/sidebar.js.map +1 -1
- package/lib/sources.d.ts +2 -2
- package/lib/sources.js +32 -17
- package/lib/sources.js.map +1 -1
- package/lib/tokens.d.ts +139 -24
- package/lib/tokens.js.map +1 -1
- package/package.json +39 -47
- package/src/config.ts +78 -0
- package/src/debugger.ts +154 -0
- package/src/dialogs/evaluate.ts +144 -0
- package/src/factory.ts +72 -0
- package/src/handler.ts +528 -0
- package/src/handlers/console.ts +118 -0
- package/src/handlers/editor.ts +469 -0
- package/src/handlers/file.ts +86 -0
- package/src/handlers/notebook.ts +128 -0
- package/src/hash.ts +69 -0
- package/src/icons.ts +64 -0
- package/src/index.ts +16 -0
- package/src/model.ts +155 -0
- package/src/panels/breakpoints/body.tsx +145 -0
- package/src/panels/breakpoints/index.ts +116 -0
- package/src/panels/breakpoints/model.ts +74 -0
- package/src/panels/breakpoints/pauseonexceptions.tsx +141 -0
- package/src/panels/callstack/body.tsx +96 -0
- package/src/panels/callstack/index.ts +152 -0
- package/src/panels/callstack/model.ts +86 -0
- package/src/panels/kernelSources/body.tsx +139 -0
- package/src/panels/kernelSources/filter.tsx +44 -0
- package/src/panels/kernelSources/index.tsx +106 -0
- package/src/panels/kernelSources/model.ts +160 -0
- package/src/panels/sources/body.ts +161 -0
- package/src/panels/sources/index.tsx +85 -0
- package/src/panels/sources/model.ts +94 -0
- package/src/panels/sources/sourcepath.tsx +28 -0
- package/src/panels/variables/grid.ts +144 -0
- package/src/panels/variables/gridpanel.ts +455 -0
- package/src/panels/variables/index.ts +199 -0
- package/src/panels/variables/mimerenderer.ts +125 -0
- package/src/panels/variables/model.ts +61 -0
- package/src/panels/variables/scope.tsx +132 -0
- package/src/panels/variables/tree.tsx +521 -0
- package/src/service.ts +1009 -0
- package/src/session.ts +342 -0
- package/src/sidebar.ts +194 -0
- package/src/sources.ts +327 -0
- package/src/svg.d.ts +9 -0
- package/src/tokens.ts +1071 -0
- package/style/base.css +2 -1
- package/style/breakpoints.css +21 -12
- package/style/icons/arrow-collapse.svg +1 -1
- package/style/icons/arrow-expand.svg +1 -1
- package/style/icons/exceptions.svg +10 -0
- package/style/icons/open-kernel-source.svg +6 -0
- package/style/icons/pause.svg +6 -0
- package/style/icons.css +9 -8
- package/style/index.css +1 -1
- package/style/index.js +1 -1
- package/style/kernelSources.css +45 -0
- package/style/sidebar.css +1 -1
- package/style/variables.css +82 -21
package/src/handler.ts
ADDED
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
5
|
+
import { ISessionContext, SessionContext } from '@jupyterlab/apputils';
|
|
6
|
+
import { ConsolePanel } from '@jupyterlab/console';
|
|
7
|
+
import { IChangedArgs } from '@jupyterlab/coreutils';
|
|
8
|
+
import { DocumentWidget } from '@jupyterlab/docregistry';
|
|
9
|
+
import { FileEditor } from '@jupyterlab/fileeditor';
|
|
10
|
+
import { NotebookPanel } from '@jupyterlab/notebook';
|
|
11
|
+
import { Kernel, KernelMessage, Session } from '@jupyterlab/services';
|
|
12
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
13
|
+
import { bugDotIcon, bugIcon, ToolbarButton } from '@jupyterlab/ui-components';
|
|
14
|
+
import { Debugger } from './debugger';
|
|
15
|
+
import { ConsoleHandler } from './handlers/console';
|
|
16
|
+
import { FileHandler } from './handlers/file';
|
|
17
|
+
import { NotebookHandler } from './handlers/notebook';
|
|
18
|
+
import { IDebugger } from './tokens';
|
|
19
|
+
|
|
20
|
+
const TOOLBAR_DEBUGGER_ITEM = 'debugger-icon';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Add a bug icon to the widget toolbar to enable and disable debugging.
|
|
24
|
+
*
|
|
25
|
+
* @param widget The widget to add the debug toolbar button to.
|
|
26
|
+
* @param onClick The callback when the toolbar button is clicked.
|
|
27
|
+
*/
|
|
28
|
+
function updateIconButton(
|
|
29
|
+
widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
|
|
30
|
+
onClick: () => void,
|
|
31
|
+
enabled?: boolean,
|
|
32
|
+
pressed?: boolean,
|
|
33
|
+
translator: ITranslator = nullTranslator
|
|
34
|
+
): ToolbarButton {
|
|
35
|
+
const trans = translator.load('jupyterlab');
|
|
36
|
+
const icon = new ToolbarButton({
|
|
37
|
+
className: 'jp-DebuggerBugButton',
|
|
38
|
+
icon: bugIcon,
|
|
39
|
+
tooltip: trans.__('Enable Debugger'),
|
|
40
|
+
pressedIcon: bugDotIcon,
|
|
41
|
+
pressedTooltip: trans.__('Disable Debugger'),
|
|
42
|
+
disabledTooltip: trans.__(
|
|
43
|
+
'Select a kernel that supports debugging to enable debugger'
|
|
44
|
+
),
|
|
45
|
+
enabled,
|
|
46
|
+
pressed,
|
|
47
|
+
onClick
|
|
48
|
+
});
|
|
49
|
+
if (!widget.toolbar.insertBefore('kernelName', TOOLBAR_DEBUGGER_ITEM, icon)) {
|
|
50
|
+
widget.toolbar.addItem(TOOLBAR_DEBUGGER_ITEM, icon);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return icon;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Updates button state to on/off,
|
|
58
|
+
* adds/removes css class to update styling
|
|
59
|
+
*
|
|
60
|
+
* @param widget the debug button widget
|
|
61
|
+
* @param pressed true if pressed, false otherwise
|
|
62
|
+
* @param enabled true if widget enabled, false otherwise
|
|
63
|
+
* @param onClick click handler
|
|
64
|
+
*/
|
|
65
|
+
function updateIconButtonState(
|
|
66
|
+
widget: ToolbarButton,
|
|
67
|
+
pressed: boolean,
|
|
68
|
+
enabled: boolean = true,
|
|
69
|
+
onClick?: () => void
|
|
70
|
+
) {
|
|
71
|
+
if (widget) {
|
|
72
|
+
widget.enabled = enabled;
|
|
73
|
+
widget.pressed = pressed;
|
|
74
|
+
if (onClick) {
|
|
75
|
+
widget.onClick = onClick;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A handler for debugging a widget.
|
|
82
|
+
*/
|
|
83
|
+
export class DebuggerHandler implements DebuggerHandler.IHandler {
|
|
84
|
+
/**
|
|
85
|
+
* Instantiate a new DebuggerHandler.
|
|
86
|
+
*
|
|
87
|
+
* @param options The instantiation options for a DebuggerHandler.
|
|
88
|
+
*/
|
|
89
|
+
constructor(options: DebuggerHandler.IOptions) {
|
|
90
|
+
this._type = options.type;
|
|
91
|
+
this._shell = options.shell;
|
|
92
|
+
this._service = options.service;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get the active widget.
|
|
97
|
+
*/
|
|
98
|
+
get activeWidget():
|
|
99
|
+
| DebuggerHandler.SessionWidget[DebuggerHandler.SessionType]
|
|
100
|
+
| null {
|
|
101
|
+
return this._activeWidget;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Update a debug handler for the given widget, and
|
|
106
|
+
* handle kernel changed events.
|
|
107
|
+
*
|
|
108
|
+
* @param widget The widget to update.
|
|
109
|
+
* @param connection The session connection.
|
|
110
|
+
*/
|
|
111
|
+
async update(
|
|
112
|
+
widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
|
|
113
|
+
connection: Session.ISessionConnection | null
|
|
114
|
+
): Promise<void> {
|
|
115
|
+
if (!connection) {
|
|
116
|
+
delete this._kernelChangedHandlers[widget.id];
|
|
117
|
+
delete this._statusChangedHandlers[widget.id];
|
|
118
|
+
delete this._iopubMessageHandlers[widget.id];
|
|
119
|
+
return this.updateWidget(widget, connection);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const kernelChanged = (): void => {
|
|
123
|
+
void this.updateWidget(widget, connection);
|
|
124
|
+
};
|
|
125
|
+
const kernelChangedHandler = this._kernelChangedHandlers[widget.id];
|
|
126
|
+
|
|
127
|
+
if (kernelChangedHandler) {
|
|
128
|
+
connection.kernelChanged.disconnect(kernelChangedHandler);
|
|
129
|
+
}
|
|
130
|
+
this._kernelChangedHandlers[widget.id] = kernelChanged;
|
|
131
|
+
connection.kernelChanged.connect(kernelChanged);
|
|
132
|
+
|
|
133
|
+
const statusChanged = (
|
|
134
|
+
_: Session.ISessionConnection,
|
|
135
|
+
status: Kernel.Status
|
|
136
|
+
): void => {
|
|
137
|
+
if (status.endsWith('restarting')) {
|
|
138
|
+
void this.updateWidget(widget, connection);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const statusChangedHandler = this._statusChangedHandlers[widget.id];
|
|
142
|
+
if (statusChangedHandler) {
|
|
143
|
+
connection.statusChanged.disconnect(statusChangedHandler);
|
|
144
|
+
}
|
|
145
|
+
connection.statusChanged.connect(statusChanged);
|
|
146
|
+
this._statusChangedHandlers[widget.id] = statusChanged;
|
|
147
|
+
|
|
148
|
+
const iopubMessage = (
|
|
149
|
+
_: Session.ISessionConnection,
|
|
150
|
+
msg: KernelMessage.IIOPubMessage
|
|
151
|
+
): void => {
|
|
152
|
+
if (
|
|
153
|
+
(msg.parent_header as KernelMessage.IHeader).msg_type ==
|
|
154
|
+
'execute_request' &&
|
|
155
|
+
this._service.isStarted &&
|
|
156
|
+
!this._service.hasStoppedThreads()
|
|
157
|
+
) {
|
|
158
|
+
void this._service.displayDefinedVariables();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const iopubMessageHandler = this._iopubMessageHandlers[widget.id];
|
|
162
|
+
if (iopubMessageHandler) {
|
|
163
|
+
connection.iopubMessage.disconnect(iopubMessageHandler);
|
|
164
|
+
}
|
|
165
|
+
connection.iopubMessage.connect(iopubMessage);
|
|
166
|
+
this._iopubMessageHandlers[widget.id] = iopubMessage;
|
|
167
|
+
this._activeWidget = widget;
|
|
168
|
+
|
|
169
|
+
return this.updateWidget(widget, connection);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Update a debug handler for the given widget, and
|
|
174
|
+
* handle connection kernel changed events.
|
|
175
|
+
*
|
|
176
|
+
* @param widget The widget to update.
|
|
177
|
+
* @param sessionContext The session context.
|
|
178
|
+
*/
|
|
179
|
+
async updateContext(
|
|
180
|
+
widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
|
|
181
|
+
sessionContext: ISessionContext
|
|
182
|
+
): Promise<void> {
|
|
183
|
+
const connectionChanged = (): void => {
|
|
184
|
+
const { session: connection } = sessionContext;
|
|
185
|
+
void this.update(widget, connection);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const contextKernelChangedHandlers =
|
|
189
|
+
this._contextKernelChangedHandlers[widget.id];
|
|
190
|
+
|
|
191
|
+
if (contextKernelChangedHandlers) {
|
|
192
|
+
sessionContext.kernelChanged.disconnect(contextKernelChangedHandlers);
|
|
193
|
+
}
|
|
194
|
+
this._contextKernelChangedHandlers[widget.id] = connectionChanged;
|
|
195
|
+
sessionContext.kernelChanged.connect(connectionChanged);
|
|
196
|
+
|
|
197
|
+
return this.update(widget, sessionContext.session);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Update a debug handler for the given widget.
|
|
202
|
+
*
|
|
203
|
+
* @param widget The widget to update.
|
|
204
|
+
* @param connection The session connection.
|
|
205
|
+
*/
|
|
206
|
+
async updateWidget(
|
|
207
|
+
widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
|
|
208
|
+
connection: Session.ISessionConnection | null
|
|
209
|
+
): Promise<void> {
|
|
210
|
+
if (!this._service.model || !connection) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const hasFocus = (): boolean => {
|
|
215
|
+
return this._shell.currentWidget === widget;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const updateAttribute = (): void => {
|
|
219
|
+
if (!this._handlers[widget.id]) {
|
|
220
|
+
widget.node.removeAttribute('data-jp-debugger');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
widget.node.setAttribute('data-jp-debugger', 'true');
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const createHandler = (): void => {
|
|
227
|
+
if (this._handlers[widget.id]) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
switch (this._type) {
|
|
232
|
+
case 'notebook':
|
|
233
|
+
this._handlers[widget.id] = new NotebookHandler({
|
|
234
|
+
debuggerService: this._service,
|
|
235
|
+
widget: widget as NotebookPanel
|
|
236
|
+
});
|
|
237
|
+
break;
|
|
238
|
+
case 'console':
|
|
239
|
+
this._handlers[widget.id] = new ConsoleHandler({
|
|
240
|
+
debuggerService: this._service,
|
|
241
|
+
widget: widget as ConsolePanel
|
|
242
|
+
});
|
|
243
|
+
break;
|
|
244
|
+
case 'file':
|
|
245
|
+
this._handlers[widget.id] = new FileHandler({
|
|
246
|
+
debuggerService: this._service,
|
|
247
|
+
widget: widget as DocumentWidget<FileEditor>
|
|
248
|
+
});
|
|
249
|
+
break;
|
|
250
|
+
default:
|
|
251
|
+
throw Error(`No handler for the type ${this._type}`);
|
|
252
|
+
}
|
|
253
|
+
updateAttribute();
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const removeHandlers = (): void => {
|
|
257
|
+
const handler = this._handlers[widget.id];
|
|
258
|
+
if (!handler) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
handler.dispose();
|
|
262
|
+
delete this._handlers[widget.id];
|
|
263
|
+
delete this._kernelChangedHandlers[widget.id];
|
|
264
|
+
delete this._statusChangedHandlers[widget.id];
|
|
265
|
+
delete this._iopubMessageHandlers[widget.id];
|
|
266
|
+
delete this._contextKernelChangedHandlers[widget.id];
|
|
267
|
+
|
|
268
|
+
// Clear the model if the handler being removed corresponds
|
|
269
|
+
// to the current active debug session, or if the connection
|
|
270
|
+
// does not have a kernel.
|
|
271
|
+
if (
|
|
272
|
+
this._service.session?.connection?.path === connection?.path ||
|
|
273
|
+
!this._service.session?.connection?.kernel
|
|
274
|
+
) {
|
|
275
|
+
const model = this._service.model;
|
|
276
|
+
model.clear();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
updateAttribute();
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const addToolbarButton = (enabled: boolean = true): void => {
|
|
283
|
+
const debugButton = this._iconButtons[widget.id];
|
|
284
|
+
if (!debugButton) {
|
|
285
|
+
this._iconButtons[widget.id] = updateIconButton(
|
|
286
|
+
widget,
|
|
287
|
+
toggleDebugging,
|
|
288
|
+
this._service.isStarted,
|
|
289
|
+
enabled
|
|
290
|
+
);
|
|
291
|
+
} else {
|
|
292
|
+
updateIconButtonState(
|
|
293
|
+
debugButton,
|
|
294
|
+
this._service.isStarted,
|
|
295
|
+
enabled,
|
|
296
|
+
toggleDebugging
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const isDebuggerOn = (): boolean => {
|
|
302
|
+
return (
|
|
303
|
+
this._service.isStarted &&
|
|
304
|
+
this._previousConnection?.id === connection?.id
|
|
305
|
+
);
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const stopDebugger = async (): Promise<void> => {
|
|
309
|
+
this._service.session!.connection = connection;
|
|
310
|
+
await this._service.stop();
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const startDebugger = async (): Promise<void> => {
|
|
314
|
+
this._service.session!.connection = connection;
|
|
315
|
+
this._previousConnection = connection;
|
|
316
|
+
await this._service.restoreState(true);
|
|
317
|
+
await this._service.displayDefinedVariables();
|
|
318
|
+
if (this._service.session?.capabilities?.supportsModulesRequest) {
|
|
319
|
+
await this._service.displayModules();
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const toggleDebugging = async (): Promise<void> => {
|
|
324
|
+
// bail if the widget doesn't have focus
|
|
325
|
+
if (!hasFocus()) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const debugButton = this._iconButtons[widget.id]!;
|
|
329
|
+
if (isDebuggerOn()) {
|
|
330
|
+
await stopDebugger();
|
|
331
|
+
removeHandlers();
|
|
332
|
+
updateIconButtonState(debugButton, false);
|
|
333
|
+
} else {
|
|
334
|
+
await startDebugger();
|
|
335
|
+
createHandler();
|
|
336
|
+
updateIconButtonState(debugButton, true);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
addToolbarButton(false);
|
|
341
|
+
|
|
342
|
+
// listen to the disposed signals
|
|
343
|
+
widget.disposed.connect(async () => {
|
|
344
|
+
if (isDebuggerOn()) {
|
|
345
|
+
await stopDebugger();
|
|
346
|
+
}
|
|
347
|
+
removeHandlers();
|
|
348
|
+
delete this._iconButtons[widget.id];
|
|
349
|
+
delete this._contextKernelChangedHandlers[widget.id];
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
const debuggingEnabled = await this._service.isAvailable(connection);
|
|
353
|
+
if (!debuggingEnabled) {
|
|
354
|
+
removeHandlers();
|
|
355
|
+
updateIconButtonState(this._iconButtons[widget.id]!, false, false);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// update the active debug session
|
|
360
|
+
if (!this._service.session) {
|
|
361
|
+
this._service.session = new Debugger.Session({
|
|
362
|
+
connection,
|
|
363
|
+
config: this._service.config
|
|
364
|
+
});
|
|
365
|
+
} else {
|
|
366
|
+
this._previousConnection = this._service.session!.connection?.kernel
|
|
367
|
+
? this._service.session.connection
|
|
368
|
+
: null;
|
|
369
|
+
this._service.session.connection = connection;
|
|
370
|
+
}
|
|
371
|
+
await this._service.restoreState(false);
|
|
372
|
+
if (this._service.isStarted && !this._service.hasStoppedThreads()) {
|
|
373
|
+
await this._service.displayDefinedVariables();
|
|
374
|
+
if (this._service.session?.capabilities?.supportsModulesRequest) {
|
|
375
|
+
await this._service.displayModules();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
updateIconButtonState(
|
|
380
|
+
this._iconButtons[widget.id]!,
|
|
381
|
+
this._service.isStarted,
|
|
382
|
+
true
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
// check the state of the debug session
|
|
386
|
+
if (!this._service.isStarted) {
|
|
387
|
+
removeHandlers();
|
|
388
|
+
this._service.session.connection = this._previousConnection ?? connection;
|
|
389
|
+
await this._service.restoreState(false);
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// if the debugger is started but there is no handler, create a new one
|
|
394
|
+
createHandler();
|
|
395
|
+
this._previousConnection = connection;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
private _type: DebuggerHandler.SessionType;
|
|
399
|
+
private _shell: JupyterFrontEnd.IShell;
|
|
400
|
+
private _service: IDebugger;
|
|
401
|
+
private _previousConnection: Session.ISessionConnection | null;
|
|
402
|
+
private _activeWidget:
|
|
403
|
+
| DebuggerHandler.SessionWidget[DebuggerHandler.SessionType]
|
|
404
|
+
| null;
|
|
405
|
+
private _handlers: {
|
|
406
|
+
[id: string]: DebuggerHandler.SessionHandler[DebuggerHandler.SessionType];
|
|
407
|
+
} = {};
|
|
408
|
+
|
|
409
|
+
private _contextKernelChangedHandlers: {
|
|
410
|
+
[id: string]: (
|
|
411
|
+
sender: SessionContext,
|
|
412
|
+
args: IChangedArgs<
|
|
413
|
+
Kernel.IKernelConnection,
|
|
414
|
+
Kernel.IKernelConnection,
|
|
415
|
+
'kernel'
|
|
416
|
+
>
|
|
417
|
+
) => void;
|
|
418
|
+
} = {};
|
|
419
|
+
private _kernelChangedHandlers: {
|
|
420
|
+
[id: string]: (
|
|
421
|
+
sender: Session.ISessionConnection,
|
|
422
|
+
args: IChangedArgs<
|
|
423
|
+
Kernel.IKernelConnection,
|
|
424
|
+
Kernel.IKernelConnection,
|
|
425
|
+
'kernel'
|
|
426
|
+
>
|
|
427
|
+
) => void;
|
|
428
|
+
} = {};
|
|
429
|
+
private _statusChangedHandlers: {
|
|
430
|
+
[id: string]: (
|
|
431
|
+
sender: Session.ISessionConnection,
|
|
432
|
+
status: Kernel.Status
|
|
433
|
+
) => void;
|
|
434
|
+
} = {};
|
|
435
|
+
private _iopubMessageHandlers: {
|
|
436
|
+
[id: string]: (
|
|
437
|
+
sender: Session.ISessionConnection,
|
|
438
|
+
msg: KernelMessage.IIOPubMessage
|
|
439
|
+
) => void;
|
|
440
|
+
} = {};
|
|
441
|
+
private _iconButtons: {
|
|
442
|
+
[id: string]: ToolbarButton | undefined;
|
|
443
|
+
} = {};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* A namespace for DebuggerHandler `statics`
|
|
448
|
+
*/
|
|
449
|
+
export namespace DebuggerHandler {
|
|
450
|
+
/**
|
|
451
|
+
* Instantiation options for a DebuggerHandler.
|
|
452
|
+
*/
|
|
453
|
+
export interface IOptions {
|
|
454
|
+
/**
|
|
455
|
+
* The type of session.
|
|
456
|
+
*/
|
|
457
|
+
type: SessionType;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* The application shell.
|
|
461
|
+
*/
|
|
462
|
+
shell: JupyterFrontEnd.IShell;
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* The debugger service.
|
|
466
|
+
*/
|
|
467
|
+
service: IDebugger;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* An interface for debugger handler.
|
|
472
|
+
*/
|
|
473
|
+
export interface IHandler {
|
|
474
|
+
/**
|
|
475
|
+
* Get the active widget.
|
|
476
|
+
*/
|
|
477
|
+
activeWidget:
|
|
478
|
+
| DebuggerHandler.SessionWidget[DebuggerHandler.SessionType]
|
|
479
|
+
| null;
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Update a debug handler for the given widget, and
|
|
483
|
+
* handle kernel changed events.
|
|
484
|
+
*
|
|
485
|
+
* @param widget The widget to update.
|
|
486
|
+
* @param connection The session connection.
|
|
487
|
+
*/
|
|
488
|
+
update(
|
|
489
|
+
widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
|
|
490
|
+
connection: Session.ISessionConnection | null
|
|
491
|
+
): Promise<void>;
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Update a debug handler for the given widget, and
|
|
495
|
+
* handle connection kernel changed events.
|
|
496
|
+
*
|
|
497
|
+
* @param widget The widget to update.
|
|
498
|
+
* @param sessionContext The session context.
|
|
499
|
+
*/
|
|
500
|
+
updateContext(
|
|
501
|
+
widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
|
|
502
|
+
sessionContext: ISessionContext
|
|
503
|
+
): Promise<void>;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* The types of sessions that can be debugged.
|
|
508
|
+
*/
|
|
509
|
+
export type SessionType = keyof SessionHandler;
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* The types of handlers.
|
|
513
|
+
*/
|
|
514
|
+
export type SessionHandler = {
|
|
515
|
+
notebook: NotebookHandler;
|
|
516
|
+
console: ConsoleHandler;
|
|
517
|
+
file: FileHandler;
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* The types of widgets that can be debugged.
|
|
522
|
+
*/
|
|
523
|
+
export type SessionWidget = {
|
|
524
|
+
notebook: NotebookPanel;
|
|
525
|
+
console: ConsolePanel;
|
|
526
|
+
file: DocumentWidget;
|
|
527
|
+
};
|
|
528
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { CodeConsole, ConsolePanel } from '@jupyterlab/console';
|
|
5
|
+
|
|
6
|
+
import { Cell, CodeCell } from '@jupyterlab/cells';
|
|
7
|
+
|
|
8
|
+
import { IObservableMap, ObservableMap } from '@jupyterlab/observables';
|
|
9
|
+
|
|
10
|
+
import { IDisposable } from '@lumino/disposable';
|
|
11
|
+
|
|
12
|
+
import { Signal } from '@lumino/signaling';
|
|
13
|
+
|
|
14
|
+
import { EditorHandler } from '../handlers/editor';
|
|
15
|
+
|
|
16
|
+
import { IDebugger } from '../tokens';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A handler for consoles.
|
|
20
|
+
*/
|
|
21
|
+
export class ConsoleHandler implements IDisposable {
|
|
22
|
+
/**
|
|
23
|
+
* Instantiate a new ConsoleHandler.
|
|
24
|
+
*
|
|
25
|
+
* @param options The instantiation options for a ConsoleHandler.
|
|
26
|
+
*/
|
|
27
|
+
constructor(options: ConsoleHandler.IOptions) {
|
|
28
|
+
this._debuggerService = options.debuggerService;
|
|
29
|
+
this._consolePanel = options.widget;
|
|
30
|
+
this._cellMap = new ObservableMap<EditorHandler>();
|
|
31
|
+
|
|
32
|
+
const codeConsole = this._consolePanel.console;
|
|
33
|
+
|
|
34
|
+
if (codeConsole.promptCell) {
|
|
35
|
+
this._addEditorHandler(codeConsole.promptCell);
|
|
36
|
+
}
|
|
37
|
+
codeConsole.promptCellCreated.connect((_: CodeConsole, cell: CodeCell) => {
|
|
38
|
+
this._addEditorHandler(cell);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const addHandlers = (): void => {
|
|
42
|
+
for (const cell of codeConsole.cells) {
|
|
43
|
+
this._addEditorHandler(cell);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
addHandlers();
|
|
47
|
+
this._consolePanel.console.cells.changed.connect(addHandlers);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether the handler is disposed.
|
|
52
|
+
*/
|
|
53
|
+
isDisposed: boolean;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Dispose the handler.
|
|
57
|
+
*/
|
|
58
|
+
dispose(): void {
|
|
59
|
+
if (this.isDisposed) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.isDisposed = true;
|
|
63
|
+
this._cellMap.values().forEach(handler => handler.dispose());
|
|
64
|
+
this._cellMap.dispose();
|
|
65
|
+
Signal.clearData(this);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Add a new editor handler for the given cell.
|
|
70
|
+
*
|
|
71
|
+
* @param cell The cell to add the handler to.
|
|
72
|
+
*/
|
|
73
|
+
private _addEditorHandler(cell: Cell): void {
|
|
74
|
+
const modelId = cell.model.id;
|
|
75
|
+
if (cell.model.type !== 'code' || this._cellMap.has(modelId)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const codeCell = cell as CodeCell;
|
|
79
|
+
const editorHandler = new EditorHandler({
|
|
80
|
+
debuggerService: this._debuggerService,
|
|
81
|
+
editorReady: async () => {
|
|
82
|
+
await codeCell.ready;
|
|
83
|
+
return codeCell.editor!;
|
|
84
|
+
},
|
|
85
|
+
getEditor: () => codeCell.editor,
|
|
86
|
+
src: cell.model.sharedModel
|
|
87
|
+
});
|
|
88
|
+
codeCell.disposed.connect(() => {
|
|
89
|
+
this._cellMap.delete(modelId);
|
|
90
|
+
editorHandler.dispose();
|
|
91
|
+
});
|
|
92
|
+
this._cellMap.set(modelId, editorHandler);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private _consolePanel: ConsolePanel;
|
|
96
|
+
private _debuggerService: IDebugger;
|
|
97
|
+
private _cellMap: IObservableMap<EditorHandler>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A namespace for ConsoleHandler `statics`.
|
|
102
|
+
*/
|
|
103
|
+
export namespace ConsoleHandler {
|
|
104
|
+
/**
|
|
105
|
+
* Instantiation options for `ConsoleHandler`.
|
|
106
|
+
*/
|
|
107
|
+
export interface IOptions {
|
|
108
|
+
/**
|
|
109
|
+
* The debugger service.
|
|
110
|
+
*/
|
|
111
|
+
debuggerService: IDebugger;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The widget to handle.
|
|
115
|
+
*/
|
|
116
|
+
widget: ConsolePanel;
|
|
117
|
+
}
|
|
118
|
+
}
|