@jupyterlab/debugger 4.5.0-beta.0 → 4.5.0-rc.0
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/displayregistry.d.ts +31 -0
- package/lib/displayregistry.js +39 -0
- package/lib/displayregistry.js.map +1 -0
- package/lib/handler.d.ts +11 -0
- package/lib/handler.js +13 -4
- package/lib/handler.js.map +1 -1
- package/lib/handlers/console.d.ts +7 -0
- package/lib/handlers/console.js +32 -0
- package/lib/handlers/console.js.map +1 -1
- package/lib/handlers/file.d.ts +7 -0
- package/lib/handlers/file.js +30 -1
- package/lib/handlers/file.js.map +1 -1
- package/lib/handlers/notebook.d.ts +7 -0
- package/lib/handlers/notebook.js +30 -0
- package/lib/handlers/notebook.js.map +1 -1
- package/lib/handlers/pausedoverlay.d.ts +37 -0
- package/lib/handlers/pausedoverlay.js +80 -0
- package/lib/handlers/pausedoverlay.js.map +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/model.d.ts +16 -1
- package/lib/model.js +10 -4
- package/lib/model.js.map +1 -1
- package/lib/panels/breakpoints/body.d.ts +0 -3
- package/lib/panels/breakpoints/body.js +8 -12
- package/lib/panels/breakpoints/body.js.map +1 -1
- package/lib/panels/breakpoints/model.d.ts +24 -1
- package/lib/panels/breakpoints/model.js +12 -1
- package/lib/panels/breakpoints/model.js.map +1 -1
- package/lib/panels/callstack/body.js +3 -11
- package/lib/panels/callstack/body.js.map +1 -1
- package/lib/panels/callstack/model.d.ts +33 -1
- package/lib/panels/callstack/model.js +15 -1
- package/lib/panels/callstack/model.js.map +1 -1
- package/lib/panels/sources/body.js +7 -6
- package/lib/panels/sources/body.js.map +1 -1
- package/lib/panels/sources/model.d.ts +15 -1
- package/lib/panels/sources/model.js +19 -0
- package/lib/panels/sources/model.js.map +1 -1
- package/lib/service.d.ts +11 -0
- package/lib/service.js +35 -13
- package/lib/service.js.map +1 -1
- package/lib/sidebar.d.ts +1 -1
- package/lib/tokens.d.ts +39 -1
- package/lib/tokens.js +4 -0
- package/lib/tokens.js.map +1 -1
- package/package.json +18 -17
- package/src/displayregistry.ts +59 -0
- package/src/handler.ts +26 -4
- package/src/handlers/console.ts +43 -0
- package/src/handlers/file.ts +41 -0
- package/src/handlers/notebook.ts +40 -0
- package/src/handlers/pausedoverlay.ts +112 -0
- package/src/index.ts +4 -1
- package/src/model.ts +27 -4
- package/src/panels/breakpoints/body.tsx +9 -12
- package/src/panels/breakpoints/index.ts +1 -0
- package/src/panels/breakpoints/model.ts +33 -2
- package/src/panels/callstack/body.tsx +2 -10
- package/src/panels/callstack/model.ts +49 -2
- package/src/panels/sources/body.ts +7 -5
- package/src/panels/sources/model.ts +28 -1
- package/src/service.ts +57 -11
- package/src/sidebar.ts +1 -1
- package/src/tokens.ts +49 -1
- package/style/base.css +36 -1
package/src/handlers/file.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { Signal } from '@lumino/signaling';
|
|
|
12
12
|
import { EditorHandler } from '../handlers/editor';
|
|
13
13
|
|
|
14
14
|
import { IDebugger } from '../tokens';
|
|
15
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
16
|
+
import { DebuggerPausedOverlay } from './pausedoverlay';
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* A handler for files.
|
|
@@ -25,6 +27,7 @@ export class FileHandler implements IDisposable {
|
|
|
25
27
|
constructor(options: FileHandler.IOptions) {
|
|
26
28
|
this._debuggerService = options.debuggerService;
|
|
27
29
|
this._fileEditor = options.widget.content;
|
|
30
|
+
this.translator = options.translator || nullTranslator;
|
|
28
31
|
|
|
29
32
|
this._hasLineNumber =
|
|
30
33
|
(this._fileEditor.editor.getOption('lineNumbers') as
|
|
@@ -36,6 +39,34 @@ export class FileHandler implements IDisposable {
|
|
|
36
39
|
getEditor: () => this._fileEditor.editor,
|
|
37
40
|
src: this._fileEditor.model.sharedModel
|
|
38
41
|
});
|
|
42
|
+
|
|
43
|
+
this._pausedOverlay = new DebuggerPausedOverlay({
|
|
44
|
+
debuggerService: this._debuggerService,
|
|
45
|
+
container: options.widget.node,
|
|
46
|
+
translator: this.translator
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
this._debuggerService.session?.eventMessage.connect((_, event) => {
|
|
50
|
+
const session = this._debuggerService.session;
|
|
51
|
+
const contextSession = options.widget.context.sessionContext.session;
|
|
52
|
+
|
|
53
|
+
if (!session || !contextSession) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (session.connection?.kernel?.id !== contextSession.kernel?.id) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (event.event === 'stopped') {
|
|
61
|
+
void this._pausedOverlay.show();
|
|
62
|
+
} else if (event.event === 'continued') {
|
|
63
|
+
void this._pausedOverlay.hide();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (this._debuggerService.hasStoppedThreads()) {
|
|
68
|
+
void this._pausedOverlay.show();
|
|
69
|
+
}
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
/**
|
|
@@ -51,6 +82,9 @@ export class FileHandler implements IDisposable {
|
|
|
51
82
|
return;
|
|
52
83
|
}
|
|
53
84
|
this.isDisposed = true;
|
|
85
|
+
|
|
86
|
+
this._pausedOverlay.dispose();
|
|
87
|
+
|
|
54
88
|
this._editorHandler?.dispose();
|
|
55
89
|
// Restore editor options
|
|
56
90
|
this._editorHandler?.editor!.setOptions({
|
|
@@ -62,7 +96,9 @@ export class FileHandler implements IDisposable {
|
|
|
62
96
|
private _fileEditor: FileEditor;
|
|
63
97
|
private _debuggerService: IDebugger;
|
|
64
98
|
private _editorHandler: EditorHandler;
|
|
99
|
+
private _pausedOverlay: DebuggerPausedOverlay;
|
|
65
100
|
private _hasLineNumber: boolean;
|
|
101
|
+
protected translator: ITranslator;
|
|
66
102
|
}
|
|
67
103
|
|
|
68
104
|
/**
|
|
@@ -82,5 +118,10 @@ export namespace FileHandler {
|
|
|
82
118
|
* The widget to handle.
|
|
83
119
|
*/
|
|
84
120
|
widget: DocumentWidget<FileEditor>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The application language translator.
|
|
124
|
+
*/
|
|
125
|
+
translator?: ITranslator;
|
|
85
126
|
}
|
|
86
127
|
}
|
package/src/handlers/notebook.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { IDisposable } from '@lumino/disposable';
|
|
|
12
12
|
import { Signal } from '@lumino/signaling';
|
|
13
13
|
import { IDebugger } from '../tokens';
|
|
14
14
|
import { EditorHandler } from './editor';
|
|
15
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
16
|
+
import { DebuggerPausedOverlay } from './pausedoverlay';
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* A handler for notebooks.
|
|
@@ -26,10 +28,38 @@ export class NotebookHandler implements IDisposable {
|
|
|
26
28
|
this._debuggerService = options.debuggerService;
|
|
27
29
|
this._notebookPanel = options.widget;
|
|
28
30
|
this._cellMap = new ObservableMap<EditorHandler>();
|
|
31
|
+
this.translator = options.translator || nullTranslator;
|
|
32
|
+
this._pausedOverlay = new DebuggerPausedOverlay({
|
|
33
|
+
debuggerService: this._debuggerService,
|
|
34
|
+
container: this._notebookPanel.node,
|
|
35
|
+
translator: this.translator
|
|
36
|
+
});
|
|
29
37
|
|
|
30
38
|
const notebook = this._notebookPanel.content;
|
|
31
39
|
notebook.model!.cells.changed.connect(this._onCellsChanged, this);
|
|
32
40
|
|
|
41
|
+
this._debuggerService.session?.eventMessage.connect((_, event) => {
|
|
42
|
+
const session = this._debuggerService.session;
|
|
43
|
+
const contextSession = this._notebookPanel.sessionContext.session;
|
|
44
|
+
|
|
45
|
+
if (!session || !contextSession) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (session.connection?.kernel?.id !== contextSession.kernel?.id) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (event.event === 'stopped') {
|
|
53
|
+
void this._pausedOverlay.show();
|
|
54
|
+
} else if (event.event === 'continued') {
|
|
55
|
+
void this._pausedOverlay.hide();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (this._debuggerService.hasStoppedThreads() === true) {
|
|
60
|
+
void this._pausedOverlay.show();
|
|
61
|
+
}
|
|
62
|
+
|
|
33
63
|
this._onCellsChanged();
|
|
34
64
|
}
|
|
35
65
|
|
|
@@ -46,6 +76,9 @@ export class NotebookHandler implements IDisposable {
|
|
|
46
76
|
return;
|
|
47
77
|
}
|
|
48
78
|
this.isDisposed = true;
|
|
79
|
+
|
|
80
|
+
this._pausedOverlay.dispose();
|
|
81
|
+
|
|
49
82
|
this._cellMap.values().forEach(handler => {
|
|
50
83
|
handler.dispose();
|
|
51
84
|
// Ensure to restore notebook editor settings
|
|
@@ -105,6 +138,8 @@ export class NotebookHandler implements IDisposable {
|
|
|
105
138
|
private _debuggerService: IDebugger;
|
|
106
139
|
private _notebookPanel: NotebookPanel;
|
|
107
140
|
private _cellMap: IObservableMap<EditorHandler>;
|
|
141
|
+
private _pausedOverlay: DebuggerPausedOverlay;
|
|
142
|
+
protected translator: ITranslator;
|
|
108
143
|
}
|
|
109
144
|
|
|
110
145
|
/**
|
|
@@ -124,5 +159,10 @@ export namespace NotebookHandler {
|
|
|
124
159
|
* The widget to handle.
|
|
125
160
|
*/
|
|
126
161
|
widget: NotebookPanel;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The application language translator.
|
|
165
|
+
*/
|
|
166
|
+
translator?: ITranslator;
|
|
127
167
|
}
|
|
128
168
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { IDisposable } from '@lumino/disposable';
|
|
5
|
+
import { IDebugger } from '../tokens';
|
|
6
|
+
import {
|
|
7
|
+
ITranslator,
|
|
8
|
+
nullTranslator,
|
|
9
|
+
TranslationBundle
|
|
10
|
+
} from '@jupyterlab/translation';
|
|
11
|
+
import { runIcon, stepOverIcon } from '@jupyterlab/ui-components';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A reusable helper to show a "Paused in Debugger" overlay and block interactions.
|
|
15
|
+
*/
|
|
16
|
+
export class DebuggerPausedOverlay implements IDisposable {
|
|
17
|
+
constructor(options: DebuggerPausedOverlay.IOptions) {
|
|
18
|
+
this._debuggerService = options.debuggerService;
|
|
19
|
+
this._container = options.container;
|
|
20
|
+
this._trans = (options.translator || nullTranslator).load('jupyterlab');
|
|
21
|
+
|
|
22
|
+
// Create overlay
|
|
23
|
+
const overlay = document.createElement('div');
|
|
24
|
+
overlay.className = 'jp-DebuggerPausedOverlay';
|
|
25
|
+
|
|
26
|
+
const text = document.createElement('span');
|
|
27
|
+
text.textContent = this._trans.__('Paused in Debugger');
|
|
28
|
+
overlay.appendChild(text);
|
|
29
|
+
|
|
30
|
+
const continueBtn = document.createElement('button');
|
|
31
|
+
continueBtn.className = 'jp-DebuggerPausedButton';
|
|
32
|
+
continueBtn.title = this._trans.__('Continue');
|
|
33
|
+
runIcon.element({ container: continueBtn, elementPosition: 'center' });
|
|
34
|
+
continueBtn.onclick = () => {
|
|
35
|
+
void this._debuggerService.continue();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const nextBtn = document.createElement('button');
|
|
39
|
+
nextBtn.className = 'jp-DebuggerPausedButton';
|
|
40
|
+
nextBtn.title = this._trans.__('Next');
|
|
41
|
+
stepOverIcon.element({ container: nextBtn, elementPosition: 'center' });
|
|
42
|
+
nextBtn.onclick = () => {
|
|
43
|
+
void this._debuggerService.next();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
overlay.appendChild(continueBtn);
|
|
47
|
+
overlay.appendChild(nextBtn);
|
|
48
|
+
|
|
49
|
+
overlay.style.pointerEvents = 'auto';
|
|
50
|
+
this._overlay = overlay;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Show the overlay, if enabled by user settings.
|
|
55
|
+
*/
|
|
56
|
+
show(): void {
|
|
57
|
+
if (this._isDisposed) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const showOverlay = document.body.dataset.showPausedOverlay !== 'false';
|
|
62
|
+
if (!showOverlay || !this._overlay || this._overlay.isConnected) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this._container.appendChild(this._overlay);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Hide and unmount the overlay.
|
|
71
|
+
*/
|
|
72
|
+
hide(): void {
|
|
73
|
+
if (this._isDisposed || !this._overlay || !this._overlay.isConnected) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this._container.style.pointerEvents = '';
|
|
77
|
+
this._overlay.remove();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Dispose of the overlay completely.
|
|
82
|
+
*/
|
|
83
|
+
dispose(): void {
|
|
84
|
+
if (this._isDisposed) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this._isDisposed = true;
|
|
88
|
+
this.hide();
|
|
89
|
+
this._overlay = null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the overlay has been disposed.
|
|
94
|
+
*/
|
|
95
|
+
get isDisposed(): boolean {
|
|
96
|
+
return this._isDisposed;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private _debuggerService: IDebugger;
|
|
100
|
+
private _container: HTMLElement;
|
|
101
|
+
private _trans: TranslationBundle;
|
|
102
|
+
private _overlay: HTMLDivElement | null;
|
|
103
|
+
private _isDisposed = false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export namespace DebuggerPausedOverlay {
|
|
107
|
+
export interface IOptions {
|
|
108
|
+
debuggerService: IDebugger;
|
|
109
|
+
container: HTMLElement;
|
|
110
|
+
translator?: ITranslator;
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
export { Debugger } from './debugger';
|
|
9
9
|
|
|
10
|
+
export { DebuggerDisplayRegistry } from './displayregistry';
|
|
11
|
+
|
|
10
12
|
export {
|
|
11
13
|
IDebugger,
|
|
12
14
|
IDebuggerConfig,
|
|
13
15
|
IDebuggerSources,
|
|
14
16
|
IDebuggerSidebar,
|
|
15
17
|
IDebuggerHandler,
|
|
16
|
-
IDebuggerSourceViewer
|
|
18
|
+
IDebuggerSourceViewer,
|
|
19
|
+
IDebuggerDisplayRegistry
|
|
17
20
|
} from './tokens';
|
package/src/model.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { SourcesModel } from './panels/sources/model';
|
|
|
14
14
|
import { KernelSourcesModel } from './panels/kernelSources/model';
|
|
15
15
|
|
|
16
16
|
import { VariablesModel } from './panels/variables/model';
|
|
17
|
+
import { IDebuggerDisplayRegistry } from './tokens';
|
|
18
|
+
import { DebuggerDisplayRegistry } from './displayregistry';
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* A model for a debugger.
|
|
@@ -22,12 +24,18 @@ export class DebuggerModel implements IDebugger.Model.IService {
|
|
|
22
24
|
/**
|
|
23
25
|
* Instantiate a new DebuggerModel
|
|
24
26
|
*/
|
|
25
|
-
constructor() {
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
constructor(options: DebuggerModel.IOptions) {
|
|
28
|
+
const displayRegistry =
|
|
29
|
+
options.displayRegistry ?? new DebuggerDisplayRegistry();
|
|
30
|
+
|
|
31
|
+
this.breakpoints = new BreakpointsModel({ displayRegistry });
|
|
32
|
+
this.callstack = new CallstackModel({
|
|
33
|
+
displayRegistry
|
|
34
|
+
});
|
|
28
35
|
this.variables = new VariablesModel();
|
|
29
36
|
this.sources = new SourcesModel({
|
|
30
|
-
currentFrameChanged: this.callstack.currentFrameChanged
|
|
37
|
+
currentFrameChanged: this.callstack.currentFrameChanged,
|
|
38
|
+
displayRegistry
|
|
31
39
|
});
|
|
32
40
|
this.kernelSources = new KernelSourcesModel();
|
|
33
41
|
}
|
|
@@ -164,3 +172,18 @@ export class DebuggerModel implements IDebugger.Model.IService {
|
|
|
164
172
|
private _title = '-';
|
|
165
173
|
private _titleChanged = new Signal<this, string>(this);
|
|
166
174
|
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* A namespace for DebuggerModel
|
|
178
|
+
*/
|
|
179
|
+
export namespace DebuggerModel {
|
|
180
|
+
/**
|
|
181
|
+
* Instantiation options for a DebuggerModel.
|
|
182
|
+
*/
|
|
183
|
+
export interface IOptions {
|
|
184
|
+
/**
|
|
185
|
+
* The display registry.
|
|
186
|
+
*/
|
|
187
|
+
displayRegistry?: IDebuggerDisplayRegistry | null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -34,9 +34,6 @@ export class BreakpointsBody extends ReactWidget {
|
|
|
34
34
|
this.addClass('jp-DebuggerBreakpoints-body');
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* Render the BreakpointsComponent.
|
|
39
|
-
*/
|
|
40
37
|
render(): JSX.Element {
|
|
41
38
|
return (
|
|
42
39
|
<BreakpointsComponent model={this._model} translator={this._translator} />
|
|
@@ -52,6 +49,7 @@ export class BreakpointsBody extends ReactWidget {
|
|
|
52
49
|
*
|
|
53
50
|
* @param {object} props The component props.
|
|
54
51
|
* @param props.model The model for the breakpoints.
|
|
52
|
+
* @returns A JSX element.
|
|
55
53
|
*/
|
|
56
54
|
const BreakpointsComponent = ({
|
|
57
55
|
model,
|
|
@@ -124,6 +122,7 @@ const BreakpointsComponent = ({
|
|
|
124
122
|
* @param {object} props The component props.
|
|
125
123
|
* @param props.breakpoints The list of breakpoints.
|
|
126
124
|
* @param props.model The model for the breakpoints.
|
|
125
|
+
* @returns A JSX element.
|
|
127
126
|
*/
|
|
128
127
|
const BreakpointCellComponent = ({
|
|
129
128
|
breakpoints,
|
|
@@ -164,6 +163,7 @@ const BreakpointCellComponent = ({
|
|
|
164
163
|
* @param {object} props The component props.
|
|
165
164
|
* @param props.breakpoint The breakpoint.
|
|
166
165
|
* @param props.model The model for the breakpoints.
|
|
166
|
+
* @returns A JSX element.
|
|
167
167
|
*/
|
|
168
168
|
const BreakpointComponent = ({
|
|
169
169
|
breakpoint,
|
|
@@ -176,15 +176,12 @@ const BreakpointComponent = ({
|
|
|
176
176
|
isSelected: boolean;
|
|
177
177
|
trans: TranslationBundle;
|
|
178
178
|
}): JSX.Element => {
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
? breakpointSourcePath.slice(1) + '/'
|
|
182
|
-
: breakpointSourcePath;
|
|
183
|
-
};
|
|
179
|
+
const display = model.getDisplayName(breakpoint);
|
|
180
|
+
|
|
184
181
|
return (
|
|
185
182
|
<div
|
|
186
|
-
className=
|
|
187
|
-
onClick={()
|
|
183
|
+
className="jp-DebuggerBreakpoint"
|
|
184
|
+
onClick={() => model.clicked.emit(breakpoint)}
|
|
188
185
|
title={breakpoint.source?.path}
|
|
189
186
|
>
|
|
190
187
|
<span className="jp-DebuggerBreakpoint-container">
|
|
@@ -199,9 +196,9 @@ const BreakpointComponent = ({
|
|
|
199
196
|
)}
|
|
200
197
|
</span>
|
|
201
198
|
<span className={'jp-DebuggerBreakpoint-source jp-left-truncated'}>
|
|
202
|
-
{
|
|
199
|
+
{display}
|
|
203
200
|
</span>
|
|
204
|
-
<span className=
|
|
201
|
+
<span className="jp-DebuggerBreakpoint-line">{breakpoint.line}</span>
|
|
205
202
|
</div>
|
|
206
203
|
);
|
|
207
204
|
};
|
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
3
|
|
|
4
4
|
import { ISignal, Signal } from '@lumino/signaling';
|
|
5
|
-
|
|
6
|
-
import {
|
|
5
|
+
import { IDebugger, IDebuggerDisplayRegistry } from '../../tokens';
|
|
6
|
+
import { DebuggerDisplayRegistry } from '../../displayregistry';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A model for a list of breakpoints.
|
|
10
10
|
*/
|
|
11
11
|
export class BreakpointsModel implements IDebugger.Model.IBreakpoints {
|
|
12
|
+
constructor(options: { displayRegistry?: IDebuggerDisplayRegistry }) {
|
|
13
|
+
this._displayRegistry =
|
|
14
|
+
options.displayRegistry ?? new DebuggerDisplayRegistry();
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
/**
|
|
13
18
|
* Signal emitted when the model changes.
|
|
14
19
|
*/
|
|
@@ -89,10 +94,36 @@ export class BreakpointsModel implements IDebugger.Model.IBreakpoints {
|
|
|
89
94
|
this._restored.emit();
|
|
90
95
|
}
|
|
91
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Get a human-readable display string for a breakpoint.
|
|
99
|
+
* Shows execution count if notebook cell, [*] if running, [ ] if never executed.
|
|
100
|
+
*/
|
|
101
|
+
getDisplayName(breakpoint: IDebugger.IBreakpoint): string {
|
|
102
|
+
return this._displayRegistry.getDisplayName(
|
|
103
|
+
breakpoint.source as IDebugger.Source
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
92
107
|
private _breakpoints = new Map<string, IDebugger.IBreakpoint[]>();
|
|
93
108
|
private _changed = new Signal<this, IDebugger.IBreakpoint[]>(this);
|
|
94
109
|
private _restored = new Signal<this, void>(this);
|
|
95
110
|
private _clicked = new Signal<this, IDebugger.IBreakpoint>(this);
|
|
96
111
|
private _selectedBreakpoint: IDebugger.IBreakpoint;
|
|
97
112
|
private _selectedChanged = new Signal<this, IDebugger.IBreakpoint>(this);
|
|
113
|
+
private _displayRegistry: IDebuggerDisplayRegistry;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Namespace for BreakpointsModel
|
|
118
|
+
*/
|
|
119
|
+
export namespace BreakpointsModel {
|
|
120
|
+
/**
|
|
121
|
+
* Instantiation options for a BreakpointsModel.
|
|
122
|
+
*/
|
|
123
|
+
export interface IOptions {
|
|
124
|
+
/**
|
|
125
|
+
* The debugger display registry.
|
|
126
|
+
*/
|
|
127
|
+
displayRegistry: IDebuggerDisplayRegistry;
|
|
128
|
+
}
|
|
98
129
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Jupyter Development Team.
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
3
|
|
|
4
|
-
import { PathExt } from '@jupyterlab/coreutils';
|
|
5
4
|
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
6
5
|
import React, { useEffect, useState } from 'react';
|
|
7
6
|
import { IDebugger } from '../../tokens';
|
|
@@ -36,6 +35,7 @@ export class CallstackBody extends ReactWidget {
|
|
|
36
35
|
*
|
|
37
36
|
* @param {object} props The component props.
|
|
38
37
|
* @param props.model The model for the callstack.
|
|
38
|
+
* @returns A JSX element.
|
|
39
39
|
*/
|
|
40
40
|
const FramesComponent = ({
|
|
41
41
|
model
|
|
@@ -62,14 +62,6 @@ const FramesComponent = ({
|
|
|
62
62
|
};
|
|
63
63
|
}, [model]);
|
|
64
64
|
|
|
65
|
-
const toShortLocation = (el: IDebugger.IStackFrame) => {
|
|
66
|
-
const path = el.source?.path || '';
|
|
67
|
-
const base = PathExt.basename(PathExt.dirname(path));
|
|
68
|
-
const filename = PathExt.basename(path);
|
|
69
|
-
const shortname = PathExt.join(base, filename);
|
|
70
|
-
return `${shortname}:${el.line}`;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
65
|
return (
|
|
74
66
|
<ul>
|
|
75
67
|
{frames.map(ele => (
|
|
@@ -87,7 +79,7 @@ const FramesComponent = ({
|
|
|
87
79
|
className={'jp-DebuggerCallstackFrame-location'}
|
|
88
80
|
title={ele.source?.path}
|
|
89
81
|
>
|
|
90
|
-
{
|
|
82
|
+
{model.getDisplayName?.(ele) ?? ele.source?.path}
|
|
91
83
|
</span>
|
|
92
84
|
</li>
|
|
93
85
|
))}
|
|
@@ -3,15 +3,23 @@
|
|
|
3
3
|
|
|
4
4
|
import { ISignal, Signal } from '@lumino/signaling';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import { DebuggerDisplayRegistry } from '../../displayregistry';
|
|
7
|
+
import { IDebugger, IDebuggerDisplayRegistry } from '../../tokens';
|
|
8
|
+
import { INotebookTracker } from '@jupyterlab/notebook';
|
|
9
|
+
import { IConsoleTracker } from '@jupyterlab/console';
|
|
8
10
|
/**
|
|
9
11
|
* A model for a callstack.
|
|
10
12
|
*/
|
|
11
13
|
export class CallstackModel implements IDebugger.Model.ICallstack {
|
|
14
|
+
constructor(options: { displayRegistry?: IDebuggerDisplayRegistry }) {
|
|
15
|
+
this._displayRegistry =
|
|
16
|
+
options.displayRegistry ?? new DebuggerDisplayRegistry();
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
/**
|
|
13
20
|
* Get all the frames.
|
|
14
21
|
*/
|
|
22
|
+
|
|
15
23
|
get frames(): IDebugger.IStackFrame[] {
|
|
16
24
|
return this._state;
|
|
17
25
|
}
|
|
@@ -63,12 +71,51 @@ export class CallstackModel implements IDebugger.Model.ICallstack {
|
|
|
63
71
|
return this._currentFrameChanged;
|
|
64
72
|
}
|
|
65
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Returns a human-readable display for a frame.
|
|
76
|
+
*/
|
|
77
|
+
getDisplayName(frame: IDebugger.IStackFrame): string {
|
|
78
|
+
let name = this._displayRegistry.getDisplayName(
|
|
79
|
+
frame.source as IDebugger.Source
|
|
80
|
+
);
|
|
81
|
+
if (frame.line !== undefined) {
|
|
82
|
+
name += `:${frame.line}`;
|
|
83
|
+
}
|
|
84
|
+
return name;
|
|
85
|
+
}
|
|
86
|
+
|
|
66
87
|
private _state: IDebugger.IStackFrame[] = [];
|
|
67
88
|
private _currentFrame: IDebugger.IStackFrame | null = null;
|
|
68
89
|
private _framesChanged = new Signal<this, IDebugger.IStackFrame[]>(this);
|
|
69
90
|
private _currentFrameChanged = new Signal<this, IDebugger.IStackFrame | null>(
|
|
70
91
|
this
|
|
71
92
|
);
|
|
93
|
+
private _displayRegistry: IDebuggerDisplayRegistry;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* A namespace for CallstackModel
|
|
98
|
+
*/
|
|
99
|
+
export namespace CallstackModel {
|
|
100
|
+
/**
|
|
101
|
+
* Instantiation options for CallstackModel
|
|
102
|
+
*/
|
|
103
|
+
export interface IOptions {
|
|
104
|
+
/**
|
|
105
|
+
* Debugger configuration.
|
|
106
|
+
*/
|
|
107
|
+
config: IDebugger.IConfig;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The notebook tracker.
|
|
111
|
+
*/
|
|
112
|
+
notebookTracker: INotebookTracker | null;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The console tracker.
|
|
116
|
+
*/
|
|
117
|
+
consoleTracker: IConsoleTracker | null;
|
|
118
|
+
}
|
|
72
119
|
}
|
|
73
120
|
|
|
74
121
|
/**
|
|
@@ -85,10 +85,11 @@ export class SourcesBody extends Widget {
|
|
|
85
85
|
* @param frame The current frame.
|
|
86
86
|
*/
|
|
87
87
|
private async _showSource(frame: IDebugger.IStackFrame): Promise<void> {
|
|
88
|
-
const
|
|
88
|
+
const displayPath = this._model.getDisplayName(frame);
|
|
89
|
+
|
|
89
90
|
const source = await this._debuggerService.getSource({
|
|
90
91
|
sourceReference: 0,
|
|
91
|
-
path
|
|
92
|
+
path: frame.source?.path
|
|
92
93
|
});
|
|
93
94
|
|
|
94
95
|
if (!source?.content) {
|
|
@@ -102,7 +103,8 @@ export class SourcesBody extends Widget {
|
|
|
102
103
|
|
|
103
104
|
const { content, mimeType } = source;
|
|
104
105
|
const editorMimeType =
|
|
105
|
-
mimeType ||
|
|
106
|
+
mimeType ||
|
|
107
|
+
this._mimeTypeService.getMimeTypeByFilePath(frame.source?.path ?? '');
|
|
106
108
|
|
|
107
109
|
this._editor.model.sharedModel.setSource(content);
|
|
108
110
|
this._editor.model.mimeType = editorMimeType;
|
|
@@ -111,14 +113,14 @@ export class SourcesBody extends Widget {
|
|
|
111
113
|
debuggerService: this._debuggerService,
|
|
112
114
|
editorReady: () => Promise.resolve(this._editor.editor),
|
|
113
115
|
getEditor: () => this._editor.editor,
|
|
114
|
-
path,
|
|
116
|
+
path: frame.source?.path ?? '',
|
|
115
117
|
src: this._editor.model.sharedModel
|
|
116
118
|
});
|
|
117
119
|
|
|
118
120
|
this._model.currentSource = {
|
|
119
121
|
content,
|
|
120
122
|
mimeType: editorMimeType,
|
|
121
|
-
path:
|
|
123
|
+
path: displayPath
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
requestAnimationFrame(() => {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import { ISignal, Signal } from '@lumino/signaling';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { DebuggerDisplayRegistry } from '../../displayregistry';
|
|
7
|
+
import { IDebugger, IDebuggerDisplayRegistry } from '../../tokens';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* The model to keep track of the current source being displayed.
|
|
@@ -16,6 +17,8 @@ export class SourcesModel implements IDebugger.Model.ISources {
|
|
|
16
17
|
*/
|
|
17
18
|
constructor(options: SourcesModel.IOptions) {
|
|
18
19
|
this.currentFrameChanged = options.currentFrameChanged;
|
|
20
|
+
this._displayRegistry =
|
|
21
|
+
options.displayRegistry ?? new DebuggerDisplayRegistry();
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -64,6 +67,24 @@ export class SourcesModel implements IDebugger.Model.ISources {
|
|
|
64
67
|
this._currentSourceOpened.emit(this._currentSource);
|
|
65
68
|
}
|
|
66
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Get a human-readable display for a frame.
|
|
72
|
+
*
|
|
73
|
+
* For notebook cells, shows execution count if available, [*] if running, or [ ] if never executed.
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
76
|
+
* Returns a human-readable display for a frame.
|
|
77
|
+
*/
|
|
78
|
+
getDisplayName(frame: IDebugger.IStackFrame): string {
|
|
79
|
+
let name = this._displayRegistry.getDisplayName(
|
|
80
|
+
frame.source as IDebugger.Source
|
|
81
|
+
);
|
|
82
|
+
if (frame.line !== undefined) {
|
|
83
|
+
name += `:${frame.line}`;
|
|
84
|
+
}
|
|
85
|
+
return name;
|
|
86
|
+
}
|
|
87
|
+
|
|
67
88
|
private _currentSource: IDebugger.Source | null;
|
|
68
89
|
private _currentSourceOpened = new Signal<
|
|
69
90
|
SourcesModel,
|
|
@@ -73,6 +94,7 @@ export class SourcesModel implements IDebugger.Model.ISources {
|
|
|
73
94
|
SourcesModel,
|
|
74
95
|
IDebugger.Source | null
|
|
75
96
|
>(this);
|
|
97
|
+
private _displayRegistry: IDebuggerDisplayRegistry;
|
|
76
98
|
}
|
|
77
99
|
|
|
78
100
|
/**
|
|
@@ -90,5 +112,10 @@ export namespace SourcesModel {
|
|
|
90
112
|
IDebugger.Model.ICallstack,
|
|
91
113
|
IDebugger.IStackFrame | null
|
|
92
114
|
>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The display registry.
|
|
118
|
+
*/
|
|
119
|
+
displayRegistry?: IDebuggerDisplayRegistry;
|
|
93
120
|
}
|
|
94
121
|
}
|