@jupyterlab/debugger 4.0.0-alpha.9 → 4.0.0-beta.1
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 +3 -1
- package/lib/debugger.js +5 -3
- 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 +15 -7
- 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 +26 -12
- package/lib/handlers/editor.js +166 -89
- package/lib/handlers/editor.js.map +1 -1
- package/lib/handlers/file.js +6 -2
- package/lib/handlers/file.js.map +1 -1
- package/lib/handlers/notebook.d.ts +0 -7
- package/lib/handlers/notebook.js +11 -17
- package/lib/handlers/notebook.js.map +1 -1
- package/lib/icons.d.ts +2 -1
- package/lib/icons.js +6 -1
- package/lib/icons.js.map +1 -1
- package/lib/model.js +1 -0
- package/lib/model.js.map +1 -1
- package/lib/panels/breakpoints/index.d.ts +2 -2
- package/lib/panels/breakpoints/index.js +9 -7
- 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 +5 -7
- package/lib/panels/kernelSources/body.js +37 -47
- package/lib/panels/kernelSources/body.js.map +1 -1
- package/lib/panels/kernelSources/filter.d.ts +1 -2
- package/lib/panels/kernelSources/filter.js +2 -2
- package/lib/panels/kernelSources/filter.js.map +1 -1
- package/lib/panels/kernelSources/index.js +1 -1
- package/lib/panels/kernelSources/index.js.map +1 -1
- package/lib/panels/kernelSources/model.d.ts +10 -1
- package/lib/panels/kernelSources/model.js +19 -1
- package/lib/panels/kernelSources/model.js.map +1 -1
- package/lib/panels/sources/body.js +5 -3
- package/lib/panels/sources/body.js.map +1 -1
- package/lib/panels/sources/sourcepath.js +1 -1
- package/lib/panels/sources/sourcepath.js.map +1 -1
- package/lib/panels/variables/grid.d.ts +23 -10
- package/lib/panels/variables/grid.js +42 -367
- package/lib/panels/variables/grid.js.map +1 -1
- package/lib/panels/variables/gridpanel.d.ts +138 -0
- package/lib/panels/variables/gridpanel.js +362 -0
- package/lib/panels/variables/gridpanel.js.map +1 -0
- package/lib/panels/variables/mimerenderer.js +9 -1
- package/lib/panels/variables/mimerenderer.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 +1 -0
- package/lib/panels/variables/tree.js +136 -47
- package/lib/panels/variables/tree.js.map +1 -1
- package/lib/service.d.ts +20 -6
- package/lib/service.js +84 -59
- package/lib/service.js.map +1 -1
- package/lib/session.d.ts +20 -6
- package/lib/session.js +59 -11
- package/lib/session.js.map +1 -1
- package/lib/sidebar.js +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 +57 -13
- package/lib/tokens.js.map +1 -1
- package/package.json +38 -46
- 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 +31 -0
- package/src/panels/variables/grid.ts +145 -0
- package/src/panels/variables/gridpanel.ts +453 -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/breakpoints.css +21 -12
- package/style/callstack.css +2 -2
- package/style/icons/exceptions.svg +10 -0
- package/style/index.css +1 -1
- package/style/index.js +1 -1
- package/style/kernelSources.css +3 -9
- package/style/sources.css +1 -1
- package/style/variables.css +68 -21
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
5
|
+
|
|
6
|
+
import { ISignal, Signal } from '@lumino/signaling';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
caretDownEmptyIcon,
|
|
10
|
+
ReactWidget,
|
|
11
|
+
searchIcon
|
|
12
|
+
} from '@jupyterlab/ui-components';
|
|
13
|
+
|
|
14
|
+
import { ArrayExt } from '@lumino/algorithm';
|
|
15
|
+
|
|
16
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
17
|
+
|
|
18
|
+
import { DebugProtocol } from '@vscode/debugprotocol';
|
|
19
|
+
|
|
20
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
21
|
+
|
|
22
|
+
import { convertType } from '.';
|
|
23
|
+
|
|
24
|
+
import { Debugger } from '../../debugger';
|
|
25
|
+
|
|
26
|
+
import { IDebugger } from '../../tokens';
|
|
27
|
+
|
|
28
|
+
import { VariablesModel } from './model';
|
|
29
|
+
|
|
30
|
+
const BUTTONS_CLASS = 'jp-DebuggerVariables-buttons';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The body for tree of variables.
|
|
34
|
+
*/
|
|
35
|
+
export class VariablesBodyTree extends ReactWidget {
|
|
36
|
+
/**
|
|
37
|
+
* Instantiate a new Body for the tree of variables.
|
|
38
|
+
*
|
|
39
|
+
* @param options The instantiation options for a VariablesBodyTree.
|
|
40
|
+
*/
|
|
41
|
+
constructor(options: VariablesBodyTree.IOptions) {
|
|
42
|
+
super();
|
|
43
|
+
this._commands = options.commands;
|
|
44
|
+
this._service = options.service;
|
|
45
|
+
this._translator = options.translator;
|
|
46
|
+
this._hoverChanged = new Signal(this);
|
|
47
|
+
|
|
48
|
+
const model = (this.model = options.model);
|
|
49
|
+
model.changed.connect(this._updateScopes, this);
|
|
50
|
+
|
|
51
|
+
this.addClass('jp-DebuggerVariables-body');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Render the VariablesBodyTree.
|
|
56
|
+
*/
|
|
57
|
+
render(): JSX.Element {
|
|
58
|
+
const scope =
|
|
59
|
+
this._scopes.find(scope => scope.name === this._scope) ?? this._scopes[0];
|
|
60
|
+
|
|
61
|
+
const handleSelectVariable = (variable: IDebugger.IVariable) => {
|
|
62
|
+
this.model.selectedVariable = variable;
|
|
63
|
+
};
|
|
64
|
+
const collapserIcon = (
|
|
65
|
+
<caretDownEmptyIcon.react stylesheet="menuItem" tag="span" />
|
|
66
|
+
);
|
|
67
|
+
return scope ? (
|
|
68
|
+
<>
|
|
69
|
+
<VariablesBranch
|
|
70
|
+
key={scope.name}
|
|
71
|
+
commands={this._commands}
|
|
72
|
+
service={this._service}
|
|
73
|
+
data={scope.variables}
|
|
74
|
+
filter={this._filter}
|
|
75
|
+
translator={this._translator}
|
|
76
|
+
handleSelectVariable={handleSelectVariable}
|
|
77
|
+
onHoverChanged={(data: IHoverData) => {
|
|
78
|
+
this._hoverChanged.emit(data);
|
|
79
|
+
}}
|
|
80
|
+
collapserIcon={collapserIcon}
|
|
81
|
+
/>
|
|
82
|
+
<TreeButtons
|
|
83
|
+
commands={this._commands}
|
|
84
|
+
service={this._service}
|
|
85
|
+
hoverChanged={this._hoverChanged}
|
|
86
|
+
handleSelectVariable={handleSelectVariable}
|
|
87
|
+
/>
|
|
88
|
+
</>
|
|
89
|
+
) : (
|
|
90
|
+
<div></div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Set the variable filter list.
|
|
96
|
+
*/
|
|
97
|
+
set filter(filter: Set<string>) {
|
|
98
|
+
this._filter = filter;
|
|
99
|
+
this.update();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Set the current scope
|
|
104
|
+
*/
|
|
105
|
+
set scope(scope: string) {
|
|
106
|
+
this._scope = scope;
|
|
107
|
+
this.update();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Update the scopes and the tree of variables.
|
|
112
|
+
*
|
|
113
|
+
* @param model The variables model.
|
|
114
|
+
*/
|
|
115
|
+
private _updateScopes(model: VariablesModel): void {
|
|
116
|
+
if (ArrayExt.shallowEqual(this._scopes, model.scopes)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
this._scopes = model.scopes;
|
|
120
|
+
this.update();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected model: IDebugger.Model.IVariables;
|
|
124
|
+
private _commands: CommandRegistry;
|
|
125
|
+
private _scope = '';
|
|
126
|
+
private _scopes: IDebugger.IScope[] = [];
|
|
127
|
+
private _filter = new Set<string>();
|
|
128
|
+
private _service: IDebugger;
|
|
129
|
+
private _translator: ITranslator | undefined;
|
|
130
|
+
private _hoverChanged: Signal<VariablesBodyTree, IHoverData>;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface IHoverData {
|
|
134
|
+
/**
|
|
135
|
+
* The mouse target.
|
|
136
|
+
*/
|
|
137
|
+
target: (EventTarget & HTMLElement) | null;
|
|
138
|
+
/**
|
|
139
|
+
* The variable corresponding to node under cursor.
|
|
140
|
+
*/
|
|
141
|
+
variable: IDebugger.IVariable | null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
interface ITreeButtonsProps {
|
|
145
|
+
/**
|
|
146
|
+
* The commands registry.
|
|
147
|
+
*/
|
|
148
|
+
commands: CommandRegistry;
|
|
149
|
+
/**
|
|
150
|
+
* The debugger service.
|
|
151
|
+
*/
|
|
152
|
+
service: IDebugger;
|
|
153
|
+
/**
|
|
154
|
+
* The application language translator
|
|
155
|
+
*/
|
|
156
|
+
translator?: ITranslator;
|
|
157
|
+
/**
|
|
158
|
+
* Callback on variable selection
|
|
159
|
+
*/
|
|
160
|
+
handleSelectVariable: (variable: IDebugger.IVariable) => void;
|
|
161
|
+
/**
|
|
162
|
+
* Signal to be emitted on mouse over event.
|
|
163
|
+
*/
|
|
164
|
+
hoverChanged: ISignal<VariablesBodyTree, IHoverData>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The singleton buttons bar shown by the variables.
|
|
169
|
+
*/
|
|
170
|
+
const TreeButtons = (props: ITreeButtonsProps): JSX.Element => {
|
|
171
|
+
const { commands, service, translator, handleSelectVariable } = props;
|
|
172
|
+
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
173
|
+
|
|
174
|
+
const [buttonsTop, setButtonsTop] = useState<number>(0);
|
|
175
|
+
const [variable, setVariable] = useState<IDebugger.IVariable | null>(null);
|
|
176
|
+
|
|
177
|
+
let stateRefreshLock = 0;
|
|
178
|
+
|
|
179
|
+
// Empty dependency array is to only register once per lifetime.
|
|
180
|
+
const handleHover = useCallback((_: VariablesBodyTree, data: IHoverData) => {
|
|
181
|
+
const current = ++stateRefreshLock;
|
|
182
|
+
if (!data.variable) {
|
|
183
|
+
// Handle mouse leave.
|
|
184
|
+
if (current !== stateRefreshLock) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const target = data.target;
|
|
188
|
+
if (
|
|
189
|
+
target &&
|
|
190
|
+
// Note: Element, not HTMLElement to permit entering <svg> icon.
|
|
191
|
+
target instanceof Element &&
|
|
192
|
+
target.closest(`.${BUTTONS_CLASS}`)
|
|
193
|
+
) {
|
|
194
|
+
// Allow to enter the buttons.
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
setVariable(null);
|
|
198
|
+
} else {
|
|
199
|
+
// Handle mouse over.
|
|
200
|
+
setVariable(data.variable);
|
|
201
|
+
requestAnimationFrame(() => {
|
|
202
|
+
if (current !== stateRefreshLock || !data.target) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
setButtonsTop(data.target.offsetTop);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}, []);
|
|
209
|
+
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
props.hoverChanged.connect(handleHover);
|
|
212
|
+
return () => {
|
|
213
|
+
props.hoverChanged.disconnect(handleHover);
|
|
214
|
+
};
|
|
215
|
+
}, [handleHover]);
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
className={BUTTONS_CLASS}
|
|
220
|
+
style={
|
|
221
|
+
// Positioning and hiding is implemented using compositor-only
|
|
222
|
+
// properties (transform and opacity) for performance.
|
|
223
|
+
{
|
|
224
|
+
transform: `translateY(${buttonsTop}px)`,
|
|
225
|
+
opacity:
|
|
226
|
+
!variable ||
|
|
227
|
+
// Do not show buttons display for special entries, defined in debugpy:
|
|
228
|
+
// https://github.com/microsoft/debugpy/blob/cf0d684566edc339545b161da7c3dfc48af7c7d5/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_utils.py#L359
|
|
229
|
+
[
|
|
230
|
+
'special variables',
|
|
231
|
+
'protected variables',
|
|
232
|
+
'function variables',
|
|
233
|
+
'class variables'
|
|
234
|
+
].includes(variable.name)
|
|
235
|
+
? 0
|
|
236
|
+
: 1
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
>
|
|
240
|
+
<button
|
|
241
|
+
className="jp-DebuggerVariables-renderVariable"
|
|
242
|
+
disabled={
|
|
243
|
+
!variable ||
|
|
244
|
+
!service.model.hasRichVariableRendering ||
|
|
245
|
+
!commands.isEnabled(Debugger.CommandIDs.renderMimeVariable, {
|
|
246
|
+
name: variable.name,
|
|
247
|
+
frameID: service.model.callstack.frame?.id
|
|
248
|
+
} as any)
|
|
249
|
+
}
|
|
250
|
+
onClick={e => {
|
|
251
|
+
if (!variable || !handleSelectVariable) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
e.stopPropagation();
|
|
255
|
+
handleSelectVariable(variable);
|
|
256
|
+
commands
|
|
257
|
+
.execute(Debugger.CommandIDs.renderMimeVariable, {
|
|
258
|
+
name: variable.name,
|
|
259
|
+
frameID: service.model.callstack.frame?.id
|
|
260
|
+
} as any)
|
|
261
|
+
.catch(reason => {
|
|
262
|
+
console.error(
|
|
263
|
+
`Failed to render variable ${variable?.name}`,
|
|
264
|
+
reason
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
}}
|
|
268
|
+
title={trans.__('Render variable: %1', variable?.name)}
|
|
269
|
+
>
|
|
270
|
+
<searchIcon.react stylesheet="menuItem" tag="span" />
|
|
271
|
+
</button>
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
interface IVariablesBranchProps {
|
|
277
|
+
/**
|
|
278
|
+
* The commands registry.
|
|
279
|
+
*/
|
|
280
|
+
commands: CommandRegistry;
|
|
281
|
+
data: IDebugger.IVariable[];
|
|
282
|
+
service: IDebugger;
|
|
283
|
+
filter?: Set<string>;
|
|
284
|
+
/**
|
|
285
|
+
* The application language translator
|
|
286
|
+
*/
|
|
287
|
+
translator?: ITranslator;
|
|
288
|
+
/**
|
|
289
|
+
* Callback on variable selection
|
|
290
|
+
*/
|
|
291
|
+
handleSelectVariable?: (variable: IDebugger.IVariable) => void;
|
|
292
|
+
/**
|
|
293
|
+
* Callback on mouseOver/mouseLeave event.
|
|
294
|
+
*/
|
|
295
|
+
onHoverChanged?: (data: IHoverData) => void;
|
|
296
|
+
/**
|
|
297
|
+
* Collapser icon component
|
|
298
|
+
*/
|
|
299
|
+
collapserIcon: JSX.Element;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* A React component to display a list of variables.
|
|
304
|
+
*
|
|
305
|
+
* @param {object} props The component props.
|
|
306
|
+
* @param props.data An array of variables.
|
|
307
|
+
* @param props.service The debugger service.
|
|
308
|
+
* @param props.filter Optional variable filter list.
|
|
309
|
+
*/
|
|
310
|
+
const VariablesBranch = (props: IVariablesBranchProps): JSX.Element => {
|
|
311
|
+
const {
|
|
312
|
+
commands,
|
|
313
|
+
data,
|
|
314
|
+
service,
|
|
315
|
+
filter,
|
|
316
|
+
translator,
|
|
317
|
+
handleSelectVariable,
|
|
318
|
+
onHoverChanged,
|
|
319
|
+
collapserIcon
|
|
320
|
+
} = props;
|
|
321
|
+
const [variables, setVariables] = useState(data);
|
|
322
|
+
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
setVariables(data);
|
|
325
|
+
}, [data]);
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<ul className="jp-DebuggerVariables-branch">
|
|
329
|
+
{variables
|
|
330
|
+
.filter(
|
|
331
|
+
variable => !(filter || new Set()).has(variable.evaluateName || '')
|
|
332
|
+
)
|
|
333
|
+
.map(variable => {
|
|
334
|
+
const key = `${variable.name}-${variable.evaluateName}-${variable.type}-${variable.value}-${variable.variablesReference}`;
|
|
335
|
+
return (
|
|
336
|
+
<VariableComponent
|
|
337
|
+
key={key}
|
|
338
|
+
commands={commands}
|
|
339
|
+
data={variable}
|
|
340
|
+
service={service}
|
|
341
|
+
filter={filter}
|
|
342
|
+
translator={translator}
|
|
343
|
+
onSelect={handleSelectVariable}
|
|
344
|
+
onHoverChanged={onHoverChanged}
|
|
345
|
+
collapserIcon={collapserIcon}
|
|
346
|
+
/>
|
|
347
|
+
);
|
|
348
|
+
})}
|
|
349
|
+
</ul>
|
|
350
|
+
);
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* VariableComponent properties
|
|
355
|
+
*/
|
|
356
|
+
interface IVariableComponentProps {
|
|
357
|
+
/**
|
|
358
|
+
* The commands registry.
|
|
359
|
+
*/
|
|
360
|
+
commands: CommandRegistry;
|
|
361
|
+
/**
|
|
362
|
+
* Variable description
|
|
363
|
+
*/
|
|
364
|
+
data: IDebugger.IVariable;
|
|
365
|
+
/**
|
|
366
|
+
* Filter applied on the variable list
|
|
367
|
+
*/
|
|
368
|
+
filter?: Set<string>;
|
|
369
|
+
/**
|
|
370
|
+
* The Debugger service
|
|
371
|
+
*/
|
|
372
|
+
service: IDebugger;
|
|
373
|
+
/**
|
|
374
|
+
* The application language translator
|
|
375
|
+
*/
|
|
376
|
+
translator?: ITranslator;
|
|
377
|
+
/**
|
|
378
|
+
* Callback on selection
|
|
379
|
+
*/
|
|
380
|
+
onSelect?: (variable: IDebugger.IVariable) => void;
|
|
381
|
+
/**
|
|
382
|
+
* Callback on mouseOver/mouseLeave event.
|
|
383
|
+
*/
|
|
384
|
+
onHoverChanged?: (data: IHoverData) => void;
|
|
385
|
+
/**
|
|
386
|
+
* Collapser icon component
|
|
387
|
+
*/
|
|
388
|
+
collapserIcon: JSX.Element;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function _prepareDetail(variable: IDebugger.IVariable) {
|
|
392
|
+
const detail = convertType(variable);
|
|
393
|
+
if (variable.type === 'float' && isNaN(detail as number)) {
|
|
394
|
+
// silence React warning:
|
|
395
|
+
// `Received NaN for the `children` attribute. If this is expected, cast the value to a string`
|
|
396
|
+
return 'NaN';
|
|
397
|
+
}
|
|
398
|
+
return detail;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* A React component to display one node variable in tree.
|
|
403
|
+
*
|
|
404
|
+
* @param {object} props The component props.
|
|
405
|
+
* @param props.data An array of variables.
|
|
406
|
+
* @param props.service The debugger service.
|
|
407
|
+
* @param props.filter Optional variable filter list.
|
|
408
|
+
*/
|
|
409
|
+
const VariableComponent = (props: IVariableComponentProps): JSX.Element => {
|
|
410
|
+
const {
|
|
411
|
+
commands,
|
|
412
|
+
data,
|
|
413
|
+
service,
|
|
414
|
+
filter,
|
|
415
|
+
translator,
|
|
416
|
+
onSelect,
|
|
417
|
+
onHoverChanged,
|
|
418
|
+
collapserIcon
|
|
419
|
+
} = props;
|
|
420
|
+
const [variable] = useState(data);
|
|
421
|
+
const [expanded, setExpanded] = useState<boolean>();
|
|
422
|
+
const [variables, setVariables] = useState<DebugProtocol.Variable[]>();
|
|
423
|
+
|
|
424
|
+
const onSelection = onSelect ?? (() => void 0);
|
|
425
|
+
|
|
426
|
+
const expandable =
|
|
427
|
+
variable.variablesReference !== 0 || variable.type === 'function';
|
|
428
|
+
|
|
429
|
+
const onVariableClicked = async (e: React.MouseEvent): Promise<void> => {
|
|
430
|
+
if (!expandable) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
e.stopPropagation();
|
|
434
|
+
const variables = await service.inspectVariable(
|
|
435
|
+
variable.variablesReference
|
|
436
|
+
);
|
|
437
|
+
setExpanded(!expanded);
|
|
438
|
+
setVariables(variables);
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
<li
|
|
443
|
+
onClick={(e): Promise<void> => onVariableClicked(e)}
|
|
444
|
+
onMouseDown={e => {
|
|
445
|
+
e.stopPropagation();
|
|
446
|
+
onSelection(variable);
|
|
447
|
+
}}
|
|
448
|
+
onMouseOver={(event: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
|
|
449
|
+
if (onHoverChanged) {
|
|
450
|
+
onHoverChanged({ target: event.currentTarget, variable });
|
|
451
|
+
event.stopPropagation();
|
|
452
|
+
}
|
|
453
|
+
}}
|
|
454
|
+
onMouseLeave={(event: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
|
|
455
|
+
if (onHoverChanged) {
|
|
456
|
+
onHoverChanged({
|
|
457
|
+
target: event.relatedTarget as EventTarget & HTMLElement,
|
|
458
|
+
variable: null
|
|
459
|
+
});
|
|
460
|
+
event.stopPropagation();
|
|
461
|
+
}
|
|
462
|
+
}}
|
|
463
|
+
>
|
|
464
|
+
<span
|
|
465
|
+
className={
|
|
466
|
+
'jp-DebuggerVariables-collapser' +
|
|
467
|
+
(expanded ? ' jp-mod-expanded' : '')
|
|
468
|
+
}
|
|
469
|
+
>
|
|
470
|
+
{
|
|
471
|
+
// note: using React.cloneElement due to high typestyle cost
|
|
472
|
+
expandable ? React.cloneElement(collapserIcon) : null
|
|
473
|
+
}
|
|
474
|
+
</span>
|
|
475
|
+
<span className="jp-DebuggerVariables-name">{variable.name}</span>
|
|
476
|
+
<span className="jp-DebuggerVariables-detail">
|
|
477
|
+
{_prepareDetail(variable)}
|
|
478
|
+
</span>
|
|
479
|
+
{expanded && variables && (
|
|
480
|
+
<VariablesBranch
|
|
481
|
+
key={variable.name}
|
|
482
|
+
commands={commands}
|
|
483
|
+
data={variables}
|
|
484
|
+
service={service}
|
|
485
|
+
filter={filter}
|
|
486
|
+
translator={translator}
|
|
487
|
+
handleSelectVariable={onSelect}
|
|
488
|
+
onHoverChanged={onHoverChanged}
|
|
489
|
+
collapserIcon={collapserIcon}
|
|
490
|
+
/>
|
|
491
|
+
)}
|
|
492
|
+
</li>
|
|
493
|
+
);
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* A namespace for VariablesBodyTree `statics`.
|
|
498
|
+
*/
|
|
499
|
+
namespace VariablesBodyTree {
|
|
500
|
+
/**
|
|
501
|
+
* Instantiation options for `VariablesBodyTree`.
|
|
502
|
+
*/
|
|
503
|
+
export interface IOptions {
|
|
504
|
+
/**
|
|
505
|
+
* The variables model.
|
|
506
|
+
*/
|
|
507
|
+
model: IDebugger.Model.IVariables;
|
|
508
|
+
/**
|
|
509
|
+
* The debugger service.
|
|
510
|
+
*/
|
|
511
|
+
service: IDebugger;
|
|
512
|
+
/**
|
|
513
|
+
* The commands registry.
|
|
514
|
+
*/
|
|
515
|
+
commands: CommandRegistry;
|
|
516
|
+
/**
|
|
517
|
+
* The application language translator
|
|
518
|
+
*/
|
|
519
|
+
translator?: ITranslator;
|
|
520
|
+
}
|
|
521
|
+
}
|