Skip to content

Commit e2f7445

Browse files
Show problem lines when notebook cell execution stops
1 parent 210abca commit e2f7445

7 files changed

Lines changed: 151 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Added the ability to convert a notebook to a PDF! This requires an additional ex
3232

3333
For notebook cells, syntax errors are now highlighted and problems are reported on the lines that have errors. This behaves the same as PRO files when using the debug console as well.
3434

35+
When you run a notebook cell, and IDL stops running, we now show the line in the cell that was stopped on to help track down problems.
36+
3537
Improved the user experience for breakpoints when working with IDL. Some of the new behaviors include:
3638

3739
- Properly setting breakpoints when you add them to a file before IDL starts

compliance/IMAGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ Updated as we go, but here is the source for the images that we use in the exten
1414
https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Abug_report%3AFILL%401%3Bwght%40400%3BGRAD%400%3Bopsz%4048
1515
- code.svg
1616
https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Acode%3AFILL%400%3Bwght%40400%3BGRAD%400%3Bopsz%4048
17+
- debug-stackframe.svg
18+
From the VSCode icons repository on GitHub.
19+
Repo: https://github.com/microsoft/vscode-icons
20+
License: Creative Commons Attribution 4.0 International
21+
License URL: https://github.com/microsoft/vscode-icons/blob/main/LICENSE
1722
- file-batch.svg
1823
https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Adescription%3AFILL%400%3Bwght%40400%3BGRAD%400%3Bopsz%4048
1924
- file-play.svg
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

libs/vscode/decorations/src/lib/idl-decorations-manager.class.ts

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {
1717
ICodeCoverageLookup,
1818
IDecorationLookup,
1919
IDLDecorationsResetFlag,
20+
IStackTraceLookup,
21+
STACK_TRACE_DECORATION,
2022
SYNTAX_ERROR_DECORATION,
2123
} from './idl-decorations-manager.interface';
2224

@@ -35,9 +37,12 @@ export class IDLDecorationsManager {
3537
syntaxErrors: IDecorationLookup;
3638
/** Information about code coverage */
3739
coverage: ICodeCoverageLookup;
40+
/** Information about the current stack */
41+
stack: IStackTraceLookup;
3842
} = {
3943
syntaxErrors: {},
4044
coverage: {},
45+
stack: {},
4146
};
4247

4348
/**
@@ -112,6 +117,11 @@ export class IDLDecorationsManager {
112117
if (asString in this.decorations.coverage) {
113118
this.addCodeCoverageDecorations(uri, this.decorations.coverage[asString]);
114119
}
120+
121+
// apply stack trace decorations
122+
if (asString in this.decorations.stack) {
123+
this.addStackTraceDecorations(uri, this.decorations.stack[asString]);
124+
}
115125
}
116126

117127
/**
@@ -217,6 +227,8 @@ export class IDLDecorationsManager {
217227
// apply again
218228
if (reApply) {
219229
this.addSyntaxErrorDecorations(uri, errors);
230+
} else {
231+
delete this.decorations.syntaxErrors[uriStrings[i]];
220232
}
221233
}
222234
}
@@ -309,6 +321,68 @@ export class IDLDecorationsManager {
309321
// apply again
310322
if (reApply) {
311323
this.addCodeCoverageDecorations(uri, coverage);
324+
} else {
325+
delete this.decorations.coverage[uriStrings[i]];
326+
}
327+
}
328+
}
329+
330+
/**
331+
* Add decorations for stack track
332+
*/
333+
addStackTraceDecorations(uri: vscode.Uri, lines: number[]) {
334+
/** Get string URI */
335+
const asString = uri.toString();
336+
337+
// save decorations
338+
this.decorations.stack[asString] = lines;
339+
340+
/**
341+
* Decorations for lines we are on
342+
*/
343+
const show: vscode.DecorationOptions[] = [];
344+
345+
// process each line
346+
for (let i = 0; i < lines.length; i++) {
347+
show.push({ range: this._rangeFromLine(lines[i]) });
348+
}
349+
350+
// apply decorations
351+
this._applyDecorations(asString, STACK_TRACE_DECORATION, show);
352+
}
353+
354+
/**
355+
* Resets stack trace decorations
356+
*
357+
* Not private so it can be toggled on and off on demand
358+
*/
359+
resetStackTraceDecorations(flag: IDLDecorationsResetFlag, reApply = false) {
360+
/**
361+
* Get all files we track
362+
*/
363+
const uriStrings = Object.keys(this.decorations.stack);
364+
365+
// process each file
366+
for (let i = 0; i < uriStrings.length; i++) {
367+
// skip if we cant reset
368+
if (!this._canResetEntry(uriStrings[i], flag)) {
369+
continue;
370+
}
371+
372+
/** Get stack trace */
373+
const stack = this.decorations.stack[uriStrings[i]];
374+
375+
/** Parse as URI */
376+
const uri = vscode.Uri.parse(uriStrings[i]);
377+
378+
// reset
379+
this.addStackTraceDecorations(uri, []);
380+
381+
// apply again
382+
if (reApply) {
383+
this.addStackTraceDecorations(uri, stack);
384+
} else {
385+
delete this.decorations.stack[uriStrings[i]];
312386
}
313387
}
314388
}
@@ -342,15 +416,28 @@ export class IDLDecorationsManager {
342416
* Removes decorations for a given URI
343417
*/
344418
remove(uri: vscode.Uri) {
419+
/** Convert to string */
420+
const asString = uri.toString();
421+
422+
// remove code coverage
345423
this.addCodeCoverageDecorations(uri, []);
424+
delete this.decorations.coverage[asString];
425+
426+
// remove stack trace
427+
this.addStackTraceDecorations(uri, []);
428+
delete this.decorations.stack[asString];
429+
430+
// remove syntax errors
346431
this.addSyntaxErrorDecorations(uri, []);
432+
delete this.decorations.syntaxErrors[asString];
347433
}
348434

349435
/**
350436
* Resets or re-applies decorations
351437
*/
352438
reset(flag: IDLDecorationsResetFlag, reApply = false) {
353-
this._resetSyntaxErrorDecorations(flag, reApply);
354439
this.resetCodeCoverageDecorations(flag, reApply);
440+
this.resetStackTraceDecorations(flag, reApply);
441+
this._resetSyntaxErrorDecorations(flag, reApply);
355442
}
356443
}

libs/vscode/decorations/src/lib/idl-decorations-manager.interface.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { IDLCodeCoverage } from '@idl/idl';
2+
import { GetExtensionPath } from '@idl/shared';
23
import * as vscode from 'vscode';
34

45
/** When resetting decorations, what do we reset for? */
@@ -24,6 +25,32 @@ export interface ICodeCoverageLookup {
2425
[key: string]: IDLCodeCoverage;
2526
}
2627

28+
/**
29+
* Data structure for stack trace
30+
*/
31+
export interface IStackTraceLookup {
32+
[key: string]: number[];
33+
}
34+
35+
/**
36+
* Decorate stack trace lines
37+
*
38+
* From: https://github.com/ryanluker/vscode-coverage-gutters/blob/master/package.json#L47-L76
39+
*/
40+
export const STACK_TRACE_DECORATION =
41+
vscode.window.createTextEditorDecorationType({
42+
backgroundColor: 'rgba(163, 149, 0, 0.4)',
43+
gutterIconPath: GetExtensionPath(
44+
'extension/images/dark/debug-stackframe.svg'
45+
),
46+
light: {
47+
backgroundColor: 'rgba(255, 235, 0, 0.2)',
48+
gutterIconPath: GetExtensionPath(
49+
'extension/images/light/debug-stackframe.svg'
50+
),
51+
},
52+
});
53+
2754
/**
2855
* Decorate problem lines
2956
*

libs/vscode/notebooks/src/lib/controller/idl-notebook-controller.class.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,8 @@ export class IDLNotebookController {
156156
log: IDL_NOTEBOOK_LOG,
157157
content: [`Stopped because: "${reason}"`, stack],
158158
});
159+
159160
await this._endCellExecution(false);
160-
// this.stopped = {
161-
// reason,
162-
// stack,
163-
// };
164-
// this.sendEvent(
165-
// new StoppedEvent(this.stopped.reason, IDLDebugAdapter.THREAD_ID)
166-
// );
167161
});
168162

169163
// listen for debug output
@@ -386,6 +380,25 @@ export class IDLNotebookController {
386380

387381
// always return from current scope
388382
if (this.isStarted()) {
383+
// get the current scope
384+
const stack = (await this._runtime.getCurrentStack()).reverse();
385+
386+
// get the fsPath for the current cell
387+
const fsPath = IDLFileHelper.notebookCellUriToFSPath(
388+
cell.cell.document.uri
389+
);
390+
391+
/** Check if any of our scope items are in this notebook cell */
392+
const ourFile = stack.filter((item) => item.file === fsPath);
393+
394+
// see if we have a location we stopped on
395+
if (ourFile.length > 0) {
396+
IDL_DECORATIONS_MANAGER.addStackTraceDecorations(
397+
cell.cell.document.uri,
398+
ourFile.map((item) => item.line - 1) // in notebooks, we need zero-based instead of one
399+
);
400+
}
401+
389402
/**
390403
* Commands to run after executing a cell
391404
*
@@ -731,6 +744,9 @@ export class IDLNotebookController {
731744
// reset cell output
732745
execution.clearOutput();
733746

747+
// reset stack trace
748+
IDL_DECORATIONS_MANAGER.resetStackTraceDecorations('notebook');
749+
734750
/** Folder where we write notebook cell, check if NB is saved to disk */
735751
const nbDir =
736752
cell.notebook.uri.scheme === 'file'

0 commit comments

Comments
 (0)