@theia/debug 1.67.0-next.59 → 1.67.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/browser/breakpoint/breakpoint-manager.js +1 -1
- package/lib/browser/breakpoint/breakpoint-manager.js.map +1 -1
- package/lib/browser/console/debug-console-items.d.ts +13 -3
- package/lib/browser/console/debug-console-items.d.ts.map +1 -1
- package/lib/browser/console/debug-console-items.js +81 -20
- package/lib/browser/console/debug-console-items.js.map +1 -1
- package/lib/browser/console/debug-console-session.d.ts.map +1 -1
- package/lib/browser/console/debug-console-session.js +1 -0
- package/lib/browser/console/debug-console-session.js.map +1 -1
- package/lib/browser/debug-commands.d.ts +153 -0
- package/lib/browser/debug-commands.d.ts.map +1 -0
- package/lib/browser/debug-commands.js +399 -0
- package/lib/browser/debug-commands.js.map +1 -0
- package/lib/browser/debug-frontend-application-contribution.d.ts +1 -150
- package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.js +155 -532
- package/lib/browser/debug-frontend-application-contribution.js.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-contribution.d.ts +2 -1
- package/lib/browser/debug-session-contribution.d.ts.map +1 -1
- package/lib/browser/debug-session-contribution.js +5 -1
- package/lib/browser/debug-session-contribution.js.map +1 -1
- package/lib/browser/debug-session-manager.d.ts +11 -3
- package/lib/browser/debug-session-manager.d.ts.map +1 -1
- package/lib/browser/debug-session-manager.js +49 -8
- package/lib/browser/debug-session-manager.js.map +1 -1
- package/lib/browser/debug-session.d.ts +9 -3
- package/lib/browser/debug-session.d.ts.map +1 -1
- package/lib/browser/debug-session.js +13 -3
- package/lib/browser/debug-session.js.map +1 -1
- package/lib/browser/editor/debug-hover-source.d.ts +1 -0
- package/lib/browser/editor/debug-hover-source.d.ts.map +1 -1
- package/lib/browser/editor/debug-hover-source.js +9 -0
- package/lib/browser/editor/debug-hover-source.js.map +1 -1
- package/lib/browser/editor/debug-inline-value-decorator.js +1 -1
- package/lib/browser/editor/debug-inline-value-decorator.js.map +1 -1
- package/lib/browser/model/debug-breakpoint.d.ts +4 -2
- package/lib/browser/model/debug-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-breakpoint.js +10 -2
- package/lib/browser/model/debug-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-data-breakpoint.d.ts +2 -0
- package/lib/browser/model/debug-data-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-data-breakpoint.js +16 -5
- package/lib/browser/model/debug-data-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.d.ts +3 -0
- package/lib/browser/model/debug-function-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.js +17 -1
- package/lib/browser/model/debug-function-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-instruction-breakpoint.d.ts +2 -0
- package/lib/browser/model/debug-instruction-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-instruction-breakpoint.js +13 -1
- package/lib/browser/model/debug-instruction-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-source-breakpoint.d.ts +6 -1
- package/lib/browser/model/debug-source-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-source-breakpoint.js +17 -1
- package/lib/browser/model/debug-source-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-stack-frame.d.ts +2 -2
- package/lib/browser/model/debug-stack-frame.d.ts.map +1 -1
- package/lib/browser/model/debug-stack-frame.js +13 -5
- package/lib/browser/model/debug-stack-frame.js.map +1 -1
- package/lib/browser/model/debug-thread.d.ts +2 -2
- package/lib/browser/model/debug-thread.d.ts.map +1 -1
- package/lib/browser/model/debug-thread.js +13 -9
- package/lib/browser/model/debug-thread.js.map +1 -1
- package/lib/browser/view/debug-action.d.ts +1 -0
- package/lib/browser/view/debug-action.d.ts.map +1 -1
- package/lib/browser/view/debug-action.js +2 -2
- package/lib/browser/view/debug-action.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.d.ts +2 -0
- package/lib/browser/view/debug-breakpoints-source.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.js +6 -1
- package/lib/browser/view/debug-breakpoints-source.js.map +1 -1
- package/lib/browser/view/debug-configuration-widget.js +2 -2
- package/lib/browser/view/debug-configuration-widget.js.map +1 -1
- package/lib/browser/view/debug-exception-breakpoint.d.ts +9 -2
- package/lib/browser/view/debug-exception-breakpoint.d.ts.map +1 -1
- package/lib/browser/view/debug-exception-breakpoint.js +26 -5
- package/lib/browser/view/debug-exception-breakpoint.js.map +1 -1
- package/lib/browser/view/debug-session-widget.d.ts +0 -1
- package/lib/browser/view/debug-session-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-session-widget.js +0 -4
- package/lib/browser/view/debug-session-widget.js.map +1 -1
- package/lib/browser/view/debug-threads-widget.d.ts +6 -1
- package/lib/browser/view/debug-threads-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-threads-widget.js +69 -5
- package/lib/browser/view/debug-threads-widget.js.map +1 -1
- package/lib/browser/view/debug-toolbar-widget.d.ts +5 -18
- package/lib/browser/view/debug-toolbar-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-toolbar-widget.js +14 -58
- package/lib/browser/view/debug-toolbar-widget.js.map +1 -1
- package/lib/browser/view/debug-variables-source.d.ts.map +1 -1
- package/lib/browser/view/debug-variables-source.js +1 -0
- package/lib/browser/view/debug-variables-source.js.map +1 -1
- package/lib/browser/view/debug-variables-widget.d.ts +15 -0
- package/lib/browser/view/debug-variables-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-variables-widget.js +56 -1
- package/lib/browser/view/debug-variables-widget.js.map +1 -1
- package/lib/browser/view/debug-view-model.d.ts +4 -0
- package/lib/browser/view/debug-view-model.d.ts.map +1 -1
- package/lib/browser/view/debug-view-model.js +18 -9
- package/lib/browser/view/debug-view-model.js.map +1 -1
- package/lib/browser/view/debug-watch-expression.d.ts.map +1 -1
- package/lib/browser/view/debug-watch-expression.js +4 -5
- package/lib/browser/view/debug-watch-expression.js.map +1 -1
- package/lib/browser/view/debug-watch-source.d.ts.map +1 -1
- package/lib/browser/view/debug-watch-source.js +1 -0
- package/lib/browser/view/debug-watch-source.js.map +1 -1
- package/lib/common/debug-preferences.d.ts +1 -0
- package/lib/common/debug-preferences.d.ts.map +1 -1
- package/lib/common/debug-preferences.js +11 -1
- package/lib/common/debug-preferences.js.map +1 -1
- package/package.json +16 -16
- package/src/browser/breakpoint/breakpoint-manager.ts +1 -1
- package/src/browser/console/debug-console-items.tsx +90 -21
- package/src/browser/console/debug-console-session.ts +1 -0
- package/src/browser/debug-commands.ts +402 -0
- package/src/browser/debug-frontend-application-contribution.ts +35 -410
- package/src/browser/debug-prefix-configuration.ts +1 -1
- package/src/browser/debug-session-contribution.ts +7 -2
- package/src/browser/debug-session-manager.ts +62 -9
- package/src/browser/debug-session.tsx +17 -4
- package/src/browser/editor/debug-hover-source.tsx +6 -2
- package/src/browser/editor/debug-inline-value-decorator.ts +1 -1
- package/src/browser/model/debug-breakpoint.tsx +12 -3
- package/src/browser/model/debug-data-breakpoint.tsx +21 -6
- package/src/browser/model/debug-function-breakpoint.tsx +22 -1
- package/src/browser/model/debug-instruction-breakpoint.tsx +16 -1
- package/src/browser/model/debug-source-breakpoint.tsx +24 -3
- package/src/browser/model/debug-stack-frame.tsx +13 -6
- package/src/browser/model/debug-thread.tsx +14 -10
- package/src/browser/style/index.css +30 -5
- package/src/browser/view/debug-action.tsx +3 -2
- package/src/browser/view/debug-breakpoints-source.tsx +5 -1
- package/src/browser/view/debug-configuration-widget.tsx +1 -1
- package/src/browser/view/debug-exception-breakpoint.tsx +30 -5
- package/src/browser/view/debug-session-widget.ts +0 -5
- package/src/browser/view/debug-threads-widget.ts +84 -6
- package/src/browser/view/debug-toolbar-widget.tsx +13 -60
- package/src/browser/view/debug-variables-source.ts +1 -0
- package/src/browser/view/debug-variables-widget.ts +59 -0
- package/src/browser/view/debug-view-model.ts +20 -8
- package/src/browser/view/debug-watch-expression.tsx +5 -6
- package/src/browser/view/debug-watch-source.ts +1 -0
- package/src/common/debug-preferences.ts +12 -1
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { DisposableCollection, Emitter, Event, MessageService, nls, ProgressService, WaitUntilEvent } from '@theia/core';
|
|
17
|
+
import { CommandService, DisposableCollection, Emitter, Event, MessageService, nls, ProgressService, WaitUntilEvent } from '@theia/core';
|
|
18
18
|
import { LabelProvider, ApplicationShell, ConfirmDialog } from '@theia/core/lib/browser';
|
|
19
19
|
import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
20
20
|
import URI from '@theia/core/lib/common/uri';
|
|
@@ -39,6 +39,7 @@ import * as monaco from '@theia/monaco-editor-core';
|
|
|
39
39
|
import { DebugInstructionBreakpoint } from './model/debug-instruction-breakpoint';
|
|
40
40
|
import { DebugSessionConfigurationLabelProvider } from './debug-session-configuration-label-provider';
|
|
41
41
|
import { DebugDataBreakpoint } from './model/debug-data-breakpoint';
|
|
42
|
+
import { DebugVariable } from './console/debug-console-items';
|
|
42
43
|
|
|
43
44
|
export interface WillStartDebugSession extends WaitUntilEvent {
|
|
44
45
|
}
|
|
@@ -57,6 +58,11 @@ export interface DidChangeBreakpointsEvent {
|
|
|
57
58
|
uri: URI
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
export interface DidResolveLazyVariableEvent {
|
|
62
|
+
readonly session: DebugSession
|
|
63
|
+
readonly variable: DebugVariable
|
|
64
|
+
}
|
|
65
|
+
|
|
60
66
|
export interface DebugSessionCustomEvent {
|
|
61
67
|
readonly body?: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
62
68
|
readonly event: string
|
|
@@ -112,6 +118,9 @@ export class DebugSessionManager {
|
|
|
112
118
|
this.onDidChangeEmitter.fire(current);
|
|
113
119
|
}
|
|
114
120
|
|
|
121
|
+
protected readonly onDidResolveLazyVariableEmitter = new Emitter<DidResolveLazyVariableEvent>();
|
|
122
|
+
readonly onDidResolveLazyVariable: Event<DidResolveLazyVariableEvent> = this.onDidResolveLazyVariableEmitter.event;
|
|
123
|
+
|
|
115
124
|
@inject(DebugSessionFactory)
|
|
116
125
|
protected readonly debugSessionFactory: DebugSessionFactory;
|
|
117
126
|
|
|
@@ -124,6 +133,9 @@ export class DebugSessionManager {
|
|
|
124
133
|
@inject(EditorManager)
|
|
125
134
|
protected readonly editorManager: EditorManager;
|
|
126
135
|
|
|
136
|
+
@inject(CommandService)
|
|
137
|
+
protected commandService: CommandService;
|
|
138
|
+
|
|
127
139
|
@inject(BreakpointManager)
|
|
128
140
|
protected readonly breakpoints: BreakpointManager;
|
|
129
141
|
|
|
@@ -417,9 +429,15 @@ export class DebugSessionManager {
|
|
|
417
429
|
state = session.state;
|
|
418
430
|
if (state === DebugState.Stopped) {
|
|
419
431
|
this.onDidStopDebugSessionEmitter.fire(session);
|
|
432
|
+
// Only switch to this session if a thread actually stopped (not just state change)
|
|
433
|
+
if (session.currentThread && session.currentThread.stopped) {
|
|
434
|
+
this.updateCurrentSession(session);
|
|
435
|
+
}
|
|
420
436
|
}
|
|
421
437
|
}
|
|
422
|
-
|
|
438
|
+
// Always fire change event to update views (threads, variables, etc.)
|
|
439
|
+
// The selection logic in widgets will handle not jumping to non-stopped threads
|
|
440
|
+
this.fireDidChange(session);
|
|
423
441
|
});
|
|
424
442
|
session.onDidChangeBreakpoints(uri => this.fireDidChangeBreakpoints({ session, uri }));
|
|
425
443
|
session.on('terminated', async event => {
|
|
@@ -438,7 +456,14 @@ export class DebugSessionManager {
|
|
|
438
456
|
});
|
|
439
457
|
|
|
440
458
|
session.onDispose(() => this.cleanup(session));
|
|
441
|
-
session.start().then(() =>
|
|
459
|
+
session.start().then(() => {
|
|
460
|
+
this.onDidStartDebugSessionEmitter.fire(session);
|
|
461
|
+
// Set as current session if no current session exists
|
|
462
|
+
// This ensures the UI shows the running session and buttons are enabled
|
|
463
|
+
if (!this.currentSession) {
|
|
464
|
+
this.updateCurrentSession(session);
|
|
465
|
+
}
|
|
466
|
+
}).catch(e => {
|
|
442
467
|
session.stop(false, () => {
|
|
443
468
|
this.debug.terminateDebugSession(session.id);
|
|
444
469
|
});
|
|
@@ -544,6 +569,7 @@ export class DebugSessionManager {
|
|
|
544
569
|
}
|
|
545
570
|
this.fireDidChange(current);
|
|
546
571
|
}));
|
|
572
|
+
this.disposeOnCurrentSessionChanged.push(current.onDidResolveLazyVariable(variable => this.onDidResolveLazyVariableEmitter.fire({ session: current, variable })));
|
|
547
573
|
this.disposeOnCurrentSessionChanged.push(current.onDidFocusStackFrame(frame => this.onDidFocusStackFrameEmitter.fire(frame)));
|
|
548
574
|
this.disposeOnCurrentSessionChanged.push(current.onDidFocusThread(thread => this.onDidFocusThreadEmitter.fire(thread)));
|
|
549
575
|
const { currentThread } = current;
|
|
@@ -598,7 +624,7 @@ export class DebugSessionManager {
|
|
|
598
624
|
return currentThread && currentThread.topFrame;
|
|
599
625
|
}
|
|
600
626
|
|
|
601
|
-
getFunctionBreakpoints(session
|
|
627
|
+
getFunctionBreakpoints(session?: DebugSession): DebugFunctionBreakpoint[] {
|
|
602
628
|
if (session && session.state > DebugState.Initializing) {
|
|
603
629
|
return session.getFunctionBreakpoints();
|
|
604
630
|
}
|
|
@@ -606,7 +632,7 @@ export class DebugSessionManager {
|
|
|
606
632
|
return this.breakpoints.getFunctionBreakpoints().map(origin => new DebugFunctionBreakpoint(origin, { labelProvider, breakpoints, editorManager }));
|
|
607
633
|
}
|
|
608
634
|
|
|
609
|
-
getInstructionBreakpoints(session
|
|
635
|
+
getInstructionBreakpoints(session?: DebugSession): DebugInstructionBreakpoint[] {
|
|
610
636
|
if (session && session.state > DebugState.Initializing) {
|
|
611
637
|
return session.getInstructionBreakpoints();
|
|
612
638
|
}
|
|
@@ -626,12 +652,39 @@ export class DebugSessionManager {
|
|
|
626
652
|
getBreakpoints(uri: URI, session?: DebugSession): DebugSourceBreakpoint[];
|
|
627
653
|
getBreakpoints(arg?: URI | DebugSession, arg2?: DebugSession): DebugSourceBreakpoint[] {
|
|
628
654
|
const uri = arg instanceof URI ? arg : undefined;
|
|
629
|
-
const session = arg instanceof DebugSession ? arg : arg2 instanceof DebugSession ? arg2 :
|
|
655
|
+
const session = arg instanceof DebugSession ? arg : arg2 instanceof DebugSession ? arg2 : undefined;
|
|
630
656
|
if (session && session.state > DebugState.Initializing) {
|
|
631
657
|
return session.getSourceBreakpoints(uri);
|
|
632
658
|
}
|
|
659
|
+
|
|
660
|
+
const activeSessions = this.sessions.filter(s => s.state > DebugState.Initializing);
|
|
661
|
+
|
|
662
|
+
// Start with all breakpoints from markers (not installed = shows as filled circle)
|
|
633
663
|
const { labelProvider, breakpoints, editorManager } = this;
|
|
634
|
-
|
|
664
|
+
const breakpointMap = new Map<string, DebugSourceBreakpoint>();
|
|
665
|
+
const markers = this.breakpoints.findMarkers({ uri });
|
|
666
|
+
|
|
667
|
+
for (const { data } of markers) {
|
|
668
|
+
const bp = new DebugSourceBreakpoint(data, { labelProvider, breakpoints, editorManager }, this.commandService);
|
|
669
|
+
breakpointMap.set(bp.id, bp);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Overlay with VERIFIED breakpoints from active sessions only
|
|
673
|
+
// We only replace a marker-based breakpoint if the session has VERIFIED it
|
|
674
|
+
// This ensures breakpoints show as filled (not installed) rather than hollow (installed but unverified)
|
|
675
|
+
for (const activeSession of activeSessions) {
|
|
676
|
+
const sessionBps = activeSession.getSourceBreakpoints(uri);
|
|
677
|
+
|
|
678
|
+
for (const bp of sessionBps) {
|
|
679
|
+
if (bp.verified) {
|
|
680
|
+
// Session has verified this breakpoint - use the session's version
|
|
681
|
+
breakpointMap.set(bp.id, bp);
|
|
682
|
+
}
|
|
683
|
+
// If not verified, keep the marker-based one (shows as not installed = filled circle)
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return Array.from(breakpointMap.values());
|
|
635
688
|
}
|
|
636
689
|
|
|
637
690
|
getLineBreakpoints(uri: URI, line: number): DebugSourceBreakpoint[] {
|
|
@@ -641,7 +694,7 @@ export class DebugSessionManager {
|
|
|
641
694
|
}
|
|
642
695
|
const { labelProvider, breakpoints, editorManager } = this;
|
|
643
696
|
return this.breakpoints.getLineBreakpoints(uri, line).map(origin =>
|
|
644
|
-
new DebugSourceBreakpoint(origin, { labelProvider, breakpoints, editorManager })
|
|
697
|
+
new DebugSourceBreakpoint(origin, { labelProvider, breakpoints, editorManager }, this.commandService)
|
|
645
698
|
);
|
|
646
699
|
}
|
|
647
700
|
|
|
@@ -652,7 +705,7 @@ export class DebugSessionManager {
|
|
|
652
705
|
}
|
|
653
706
|
const origin = this.breakpoints.getInlineBreakpoint(uri, line, column);
|
|
654
707
|
const { labelProvider, breakpoints, editorManager } = this;
|
|
655
|
-
return origin && new DebugSourceBreakpoint(origin, { labelProvider, breakpoints, editorManager });
|
|
708
|
+
return origin && new DebugSourceBreakpoint(origin, { labelProvider, breakpoints, editorManager }, this.commandService);
|
|
656
709
|
}
|
|
657
710
|
|
|
658
711
|
/**
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
import * as React from '@theia/core/shared/react';
|
|
20
20
|
import { LabelProvider } from '@theia/core/lib/browser';
|
|
21
21
|
import { DebugProtocol } from '@vscode/debugprotocol';
|
|
22
|
-
import { Emitter, Event, DisposableCollection, Disposable, MessageClient, MessageType, Mutable, ContributionProvider } from '@theia/core/lib/common';
|
|
22
|
+
import { Emitter, Event, DisposableCollection, Disposable, MessageClient, MessageType, Mutable, ContributionProvider, CommandService } from '@theia/core/lib/common';
|
|
23
23
|
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
|
|
24
24
|
import { EditorManager } from '@theia/editor/lib/browser';
|
|
25
25
|
import { CompositeTreeElement } from '@theia/core/lib/browser/source-tree';
|
|
26
26
|
import { DebugSessionConnection, DebugRequestTypes, DebugEventTypes } from './debug-session-connection';
|
|
27
27
|
import { DebugThread, StoppedDetails, DebugThreadData } from './model/debug-thread';
|
|
28
|
-
import { DebugScope } from './console/debug-console-items';
|
|
28
|
+
import { DebugScope, DebugVariable } from './console/debug-console-items';
|
|
29
29
|
import { DebugStackFrame } from './model/debug-stack-frame';
|
|
30
30
|
import { DebugSource } from './model/debug-source';
|
|
31
31
|
import { DebugBreakpoint, DebugBreakpointOptions } from './model/debug-breakpoint';
|
|
@@ -47,6 +47,7 @@ import { nls } from '@theia/core';
|
|
|
47
47
|
import { TestService, TestServices } from '@theia/test/lib/browser/test-service';
|
|
48
48
|
import { DebugSessionManager } from './debug-session-manager';
|
|
49
49
|
import { DebugDataBreakpoint } from './model/debug-data-breakpoint';
|
|
50
|
+
import { DebugPreferences } from '../common/debug-preferences';
|
|
50
51
|
|
|
51
52
|
export enum DebugState {
|
|
52
53
|
Inactive,
|
|
@@ -103,6 +104,9 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
103
104
|
this.onDidChangeBreakpointsEmitter.fire(uri);
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
protected readonly onDidResolveLazyVariableEmitter = new Emitter<DebugVariable>();
|
|
108
|
+
readonly onDidResolveLazyVariable: Event<DebugVariable> = this.onDidResolveLazyVariableEmitter.event;
|
|
109
|
+
|
|
106
110
|
protected readonly childSessions = new Map<string, DebugSession>();
|
|
107
111
|
protected readonly toDispose = new DisposableCollection();
|
|
108
112
|
|
|
@@ -124,6 +128,8 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
124
128
|
protected readonly fileService: FileService,
|
|
125
129
|
protected readonly debugContributionProvider: ContributionProvider<DebugContribution>,
|
|
126
130
|
protected readonly workspaceService: WorkspaceService,
|
|
131
|
+
protected readonly debugPreferences: DebugPreferences,
|
|
132
|
+
protected readonly commandService: CommandService,
|
|
127
133
|
/**
|
|
128
134
|
* Number of millis after a `stop` request times out. It's 5 seconds by default.
|
|
129
135
|
*/
|
|
@@ -157,7 +163,10 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
157
163
|
this.connection.onDidClose(() => this.toDispose.dispose());
|
|
158
164
|
this.toDispose.pushAll([
|
|
159
165
|
this.onDidChangeEmitter,
|
|
166
|
+
this.onDidFocusStackFrameEmitter,
|
|
167
|
+
this.onDidFocusThreadEmitter,
|
|
160
168
|
this.onDidChangeBreakpointsEmitter,
|
|
169
|
+
this.onDidResolveLazyVariableEmitter,
|
|
161
170
|
Disposable.create(() => {
|
|
162
171
|
this.clearBreakpoints();
|
|
163
172
|
this.doUpdateThreads([]);
|
|
@@ -186,6 +195,10 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
186
195
|
return this._capabilities;
|
|
187
196
|
}
|
|
188
197
|
|
|
198
|
+
get autoExpandLazyVariables(): boolean {
|
|
199
|
+
return this.debugPreferences['debug.autoExpandLazyVariables'] === 'on';
|
|
200
|
+
}
|
|
201
|
+
|
|
189
202
|
protected readonly sources = new Map<string, DebugSource>();
|
|
190
203
|
getSource(raw: DebugProtocol.Source): DebugSource {
|
|
191
204
|
const uri = DebugSource.toUri(raw).toString();
|
|
@@ -675,7 +688,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
675
688
|
const origin = SourceBreakpoint.create(uri, { line: raw.line, column: raw.column });
|
|
676
689
|
if (this.breakpoints.addBreakpoint(origin)) {
|
|
677
690
|
const breakpoints = this.getSourceBreakpoints(uri);
|
|
678
|
-
const breakpoint = new DebugSourceBreakpoint(origin, this.asDebugBreakpointOptions());
|
|
691
|
+
const breakpoint = new DebugSourceBreakpoint(origin, this.asDebugBreakpointOptions(), this.commandService);
|
|
679
692
|
breakpoint.update({ raw });
|
|
680
693
|
breakpoints.push(breakpoint);
|
|
681
694
|
this.setSourceBreakpoints(uri, breakpoints);
|
|
@@ -812,7 +825,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
812
825
|
const known = this._breakpoints.get(affectedUri.toString());
|
|
813
826
|
const all = this.breakpoints.findMarkers({ uri: affectedUri }).map(({ data }) =>
|
|
814
827
|
known?.find((candidate): candidate is DebugSourceBreakpoint => candidate instanceof DebugSourceBreakpoint && candidate.origin.id === data.id) ??
|
|
815
|
-
new DebugSourceBreakpoint(data, this.asDebugBreakpointOptions())
|
|
828
|
+
new DebugSourceBreakpoint(data, this.asDebugBreakpointOptions(), this.commandService)
|
|
816
829
|
);
|
|
817
830
|
const enabled = all.filter(b => b.enabled);
|
|
818
831
|
try {
|
|
@@ -18,7 +18,7 @@ import * as React from '@theia/core/shared/react';
|
|
|
18
18
|
import { TreeSource, TreeElement } from '@theia/core/lib/browser/source-tree';
|
|
19
19
|
import { ExpressionContainer, ExpressionItem, DebugVariable } from '../console/debug-console-items';
|
|
20
20
|
import { DebugSessionManager } from '../debug-session-manager';
|
|
21
|
-
import { injectable, inject } from '@theia/core/shared/inversify';
|
|
21
|
+
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
|
|
22
22
|
|
|
23
23
|
@injectable()
|
|
24
24
|
export class DebugHoverSource extends TreeSource {
|
|
@@ -36,6 +36,11 @@ export class DebugHoverSource extends TreeSource {
|
|
|
36
36
|
return this.elements[Symbol.iterator]();
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
@postConstruct()
|
|
40
|
+
init(): void {
|
|
41
|
+
this.toDispose.push(this.sessions.onDidResolveLazyVariable(() => this.fireDidChange()));
|
|
42
|
+
}
|
|
43
|
+
|
|
39
44
|
protected renderTitle(element: ExpressionItem | DebugVariable): React.ReactNode {
|
|
40
45
|
return <div className='theia-debug-hover-title' title={element.value}>{element.value}</div>;
|
|
41
46
|
}
|
|
@@ -101,5 +106,4 @@ export class DebugHoverSource extends TreeSource {
|
|
|
101
106
|
return this.doFindVariable(variables[0], namesToFind.slice(1));
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
|
-
|
|
105
109
|
}
|
|
@@ -194,7 +194,7 @@ export class DebugInlineValueDecorator implements FrontendApplicationContributio
|
|
|
194
194
|
}
|
|
195
195
|
if (expr) {
|
|
196
196
|
const expression = new ExpressionItem(expr, () => stackFrame.thread.session);
|
|
197
|
-
await expression.evaluate('watch');
|
|
197
|
+
await expression.evaluate('watch', false);
|
|
198
198
|
if (expression.available) {
|
|
199
199
|
text = this.formatInlineValue(expr, expression.value);
|
|
200
200
|
}
|
|
@@ -18,8 +18,9 @@ import * as React from '@theia/core/shared/react';
|
|
|
18
18
|
import { DebugProtocol } from '@vscode/debugprotocol/lib/debugProtocol';
|
|
19
19
|
import URI from '@theia/core/lib/common/uri';
|
|
20
20
|
import { EditorManager } from '@theia/editor/lib/browser';
|
|
21
|
-
import { LabelProvider, DISABLED_CLASS } from '@theia/core/lib/browser';
|
|
21
|
+
import { LabelProvider, DISABLED_CLASS, TreeWidget } from '@theia/core/lib/browser';
|
|
22
22
|
import { TreeElement } from '@theia/core/lib/browser/source-tree';
|
|
23
|
+
import { SelectableTreeNode } from '@theia/core/lib/browser/tree/tree-selection';
|
|
23
24
|
import { DebugSession } from '../debug-session';
|
|
24
25
|
import { BaseBreakpoint } from '../breakpoint/breakpoint-marker';
|
|
25
26
|
import { BreakpointManager } from '../breakpoint/breakpoint-manager';
|
|
@@ -44,6 +45,7 @@ export class DebugBreakpointDecoration {
|
|
|
44
45
|
export abstract class DebugBreakpoint<T extends BaseBreakpoint = BaseBreakpoint> extends DebugBreakpointOptions implements TreeElement {
|
|
45
46
|
|
|
46
47
|
readonly raw?: DebugProtocol.Breakpoint;
|
|
48
|
+
protected treeWidget?: TreeWidget;
|
|
47
49
|
|
|
48
50
|
constructor(
|
|
49
51
|
readonly uri: URI,
|
|
@@ -76,7 +78,7 @@ export abstract class DebugBreakpoint<T extends BaseBreakpoint = BaseBreakpoint>
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
get verified(): boolean {
|
|
79
|
-
return !!this.raw ? this.raw.verified :
|
|
81
|
+
return !!this.raw ? this.raw.verified : false;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
get message(): string {
|
|
@@ -91,7 +93,8 @@ export abstract class DebugBreakpoint<T extends BaseBreakpoint = BaseBreakpoint>
|
|
|
91
93
|
this.setEnabled(event.target.checked);
|
|
92
94
|
};
|
|
93
95
|
|
|
94
|
-
render(): React.ReactNode {
|
|
96
|
+
render(host: TreeWidget): React.ReactNode {
|
|
97
|
+
this.treeWidget = host;
|
|
95
98
|
const classNames = ['theia-source-breakpoint'];
|
|
96
99
|
if (!this.isEnabled()) {
|
|
97
100
|
classNames.push(DISABLED_CLASS);
|
|
@@ -149,4 +152,10 @@ export abstract class DebugBreakpoint<T extends BaseBreakpoint = BaseBreakpoint>
|
|
|
149
152
|
|
|
150
153
|
protected abstract getBreakpointDecoration(message?: string[]): DebugBreakpointDecoration;
|
|
151
154
|
|
|
155
|
+
protected async selectInTree(): Promise<void> {
|
|
156
|
+
if (this.treeWidget?.model && SelectableTreeNode.is(this)) {
|
|
157
|
+
this.treeWidget.model.selectNode(this);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
152
161
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { nls } from '@theia/core';
|
|
18
18
|
import * as React from '@theia/core/shared/react';
|
|
19
|
+
import { codicon } from '@theia/core/lib/browser';
|
|
19
20
|
import { BreakpointManager } from '../breakpoint/breakpoint-manager';
|
|
20
21
|
import { DataBreakpoint } from '../breakpoint/breakpoint-marker';
|
|
21
22
|
import { DebugBreakpoint, DebugBreakpointDecoration, DebugBreakpointOptions } from './debug-breakpoint';
|
|
@@ -44,12 +45,26 @@ export class DebugDataBreakpoint extends DebugBreakpoint<DataBreakpoint> {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
protected doRender(): React.ReactNode {
|
|
47
|
-
return
|
|
48
|
-
<span className="
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
return <>
|
|
49
|
+
<span className="line-info theia-data-breakpoint" title={this.origin.info.description}>
|
|
50
|
+
<span className="name">{this.origin.info.description}</span>
|
|
51
|
+
<span className="theia-TreeNodeInfo theia-access-type" >{this.getAccessType()}</span>
|
|
52
|
+
</span>
|
|
53
|
+
{this.renderActions()}
|
|
54
|
+
</>;
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
protected renderActions(): React.ReactNode {
|
|
58
|
+
return <div className='theia-debug-breakpoint-actions'>
|
|
59
|
+
<div className={codicon('close', true)} title={nls.localizeByDefault('Remove Breakpoint')} onClick={this.onRemove} />
|
|
60
|
+
</div>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected onRemove = async () => {
|
|
64
|
+
await this.selectInTree();
|
|
65
|
+
this.remove();
|
|
66
|
+
};
|
|
67
|
+
|
|
53
68
|
protected getAccessType(): string {
|
|
54
69
|
switch (this.origin.raw.accessType) {
|
|
55
70
|
case 'read': return 'Read';
|
|
@@ -62,7 +77,7 @@ export class DebugDataBreakpoint extends DebugBreakpoint<DataBreakpoint> {
|
|
|
62
77
|
if (!this.isSupported()) {
|
|
63
78
|
return {
|
|
64
79
|
className: 'codicon-debug-breakpoint-unsupported',
|
|
65
|
-
message: message ?? [nls.
|
|
80
|
+
message: message ?? [nls.localizeByDefault('Data Breakpoint')],
|
|
66
81
|
};
|
|
67
82
|
}
|
|
68
83
|
if (this.origin.raw.condition || this.origin.raw.hitCondition) {
|
|
@@ -73,7 +88,7 @@ export class DebugDataBreakpoint extends DebugBreakpoint<DataBreakpoint> {
|
|
|
73
88
|
}
|
|
74
89
|
return {
|
|
75
90
|
className: 'codicon-debug-breakpoint-data',
|
|
76
|
-
message: message || [nls.
|
|
91
|
+
message: message || [nls.localizeByDefault('Data Breakpoint')]
|
|
77
92
|
};
|
|
78
93
|
}
|
|
79
94
|
}
|
|
@@ -21,6 +21,7 @@ import { BreakpointManager } from '../breakpoint/breakpoint-manager';
|
|
|
21
21
|
import { DebugBreakpoint, DebugBreakpointOptions, DebugBreakpointDecoration } from './debug-breakpoint';
|
|
22
22
|
import { SingleTextInputDialog } from '@theia/core/lib/browser/dialogs';
|
|
23
23
|
import { nls } from '@theia/core';
|
|
24
|
+
import { codicon } from '@theia/core/lib/browser';
|
|
24
25
|
|
|
25
26
|
export class DebugFunctionBreakpoint extends DebugBreakpoint<FunctionBreakpoint> implements TreeElement {
|
|
26
27
|
|
|
@@ -59,9 +60,29 @@ export class DebugFunctionBreakpoint extends DebugBreakpoint<FunctionBreakpoint>
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
protected doRender(): React.ReactNode {
|
|
62
|
-
return <
|
|
63
|
+
return <React.Fragment>
|
|
64
|
+
<span className='line-info'>{this.name}</span>
|
|
65
|
+
{this.renderActions()}
|
|
66
|
+
</React.Fragment>;
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
protected renderActions(): React.ReactNode {
|
|
70
|
+
return <div className='theia-debug-breakpoint-actions'>
|
|
71
|
+
<div className={codicon('edit', true)} title={nls.localizeByDefault('Edit Condition...')} onClick={this.onEdit} />
|
|
72
|
+
<div className={codicon('close', true)} title={nls.localizeByDefault('Remove Breakpoint')} onClick={this.onRemove} />
|
|
73
|
+
</div>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected onEdit = async () => {
|
|
77
|
+
await this.selectInTree();
|
|
78
|
+
this.open();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
protected onRemove = async () => {
|
|
82
|
+
await this.selectInTree();
|
|
83
|
+
this.remove();
|
|
84
|
+
};
|
|
85
|
+
|
|
65
86
|
protected override doGetDecoration(): DebugBreakpointDecoration {
|
|
66
87
|
if (!this.isSupported()) {
|
|
67
88
|
return this.getDisabledBreakpointDecoration(nls.localizeByDefault('Function breakpoints are not supported by this debug type'));
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { nls } from '@theia/core';
|
|
18
18
|
import * as React from '@theia/core/shared/react';
|
|
19
|
+
import { codicon } from '@theia/core/lib/browser';
|
|
19
20
|
import { BreakpointManager } from '../breakpoint/breakpoint-manager';
|
|
20
21
|
import { InstructionBreakpoint } from '../breakpoint/breakpoint-marker';
|
|
21
22
|
import { DebugBreakpoint, DebugBreakpointDecoration, DebugBreakpointOptions } from './debug-breakpoint';
|
|
@@ -44,9 +45,23 @@ export class DebugInstructionBreakpoint extends DebugBreakpoint<InstructionBreak
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
protected doRender(): React.ReactNode {
|
|
47
|
-
return <
|
|
48
|
+
return <React.Fragment>
|
|
49
|
+
<span className="line-info">{this.origin.instructionReference}</span>;
|
|
50
|
+
{this.renderActions()}
|
|
51
|
+
</React.Fragment>;
|
|
48
52
|
}
|
|
49
53
|
|
|
54
|
+
protected renderActions(): React.ReactNode {
|
|
55
|
+
return <div className='theia-debug-breakpoint-actions'>
|
|
56
|
+
<div className={codicon('close', true)} title={nls.localizeByDefault('Remove Breakpoint')} onClick={this.onRemove} />
|
|
57
|
+
</div>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected onRemove = async () => {
|
|
61
|
+
await this.selectInTree();
|
|
62
|
+
this.remove();
|
|
63
|
+
};
|
|
64
|
+
|
|
50
65
|
protected getBreakpointDecoration(message?: string[]): DebugBreakpointDecoration {
|
|
51
66
|
if (!this.isSupported()) {
|
|
52
67
|
return {
|
|
@@ -16,14 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
import * as React from '@theia/core/shared/react';
|
|
18
18
|
import { DebugProtocol } from '@vscode/debugprotocol/lib/debugProtocol';
|
|
19
|
-
import { nls, RecursivePartial } from '@theia/core';
|
|
19
|
+
import { CommandService, nls, RecursivePartial } from '@theia/core';
|
|
20
20
|
import URI from '@theia/core/lib/common/uri';
|
|
21
21
|
import { EditorWidget, Range } from '@theia/editor/lib/browser';
|
|
22
|
-
import { TREE_NODE_INFO_CLASS, WidgetOpenerOptions } from '@theia/core/lib/browser';
|
|
22
|
+
import { TREE_NODE_INFO_CLASS, WidgetOpenerOptions, codicon } from '@theia/core/lib/browser';
|
|
23
23
|
import { TreeElement } from '@theia/core/lib/browser/source-tree';
|
|
24
24
|
import { SourceBreakpoint } from '../breakpoint/breakpoint-marker';
|
|
25
25
|
import { DebugSource } from './debug-source';
|
|
26
26
|
import { DebugBreakpoint, DebugBreakpointOptions, DebugBreakpointData, DebugBreakpointDecoration } from './debug-breakpoint';
|
|
27
|
+
import { DebugCommands } from '../debug-commands';
|
|
27
28
|
|
|
28
29
|
export class DebugSourceBreakpointData extends DebugBreakpointData {
|
|
29
30
|
readonly origins: SourceBreakpoint[];
|
|
@@ -31,11 +32,13 @@ export class DebugSourceBreakpointData extends DebugBreakpointData {
|
|
|
31
32
|
|
|
32
33
|
export class DebugSourceBreakpoint extends DebugBreakpoint<SourceBreakpoint> implements TreeElement {
|
|
33
34
|
|
|
35
|
+
protected readonly commandService: CommandService;
|
|
34
36
|
readonly origins: SourceBreakpoint[];
|
|
35
37
|
|
|
36
|
-
constructor(origin: SourceBreakpoint, options: DebugBreakpointOptions) {
|
|
38
|
+
constructor(origin: SourceBreakpoint, options: DebugBreakpointOptions, commandService: CommandService) {
|
|
37
39
|
super(new URI(origin.uri), options);
|
|
38
40
|
this.origins = [origin];
|
|
41
|
+
this.commandService = commandService;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
override update(data: Partial<DebugSourceBreakpointData>): void {
|
|
@@ -150,10 +153,28 @@ export class DebugSourceBreakpoint extends DebugBreakpoint<SourceBreakpoint> imp
|
|
|
150
153
|
<span className='name'>{this.labelProvider.getName(this.uri)} </span>
|
|
151
154
|
<span className={'path ' + TREE_NODE_INFO_CLASS}>{this.labelProvider.getLongName(this.uri.parent)} </span>
|
|
152
155
|
</span>
|
|
156
|
+
{this.renderActions()}
|
|
153
157
|
<span className='line'>{this.renderPosition()}</span>
|
|
154
158
|
</React.Fragment>;
|
|
155
159
|
}
|
|
156
160
|
|
|
161
|
+
protected renderActions(): React.ReactNode {
|
|
162
|
+
return <div className='theia-debug-breakpoint-actions'>
|
|
163
|
+
<div className={codicon('edit', true)} title={nls.localizeByDefault('Edit Breakpoint')} onClick={this.onEdit} />
|
|
164
|
+
<div className={codicon('close', true)} title={nls.localizeByDefault('Remove Breakpoint')} onClick={this.onRemove} />
|
|
165
|
+
</div>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
protected onEdit = async () => {
|
|
169
|
+
await this.selectInTree();
|
|
170
|
+
this.commandService.executeCommand(DebugCommands.EDIT_BREAKPOINT.id, this);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
protected onRemove = async () => {
|
|
174
|
+
await this.selectInTree();
|
|
175
|
+
this.remove();
|
|
176
|
+
};
|
|
177
|
+
|
|
157
178
|
renderPosition(): string {
|
|
158
179
|
return this.line + (typeof this.column === 'number' ? ':' + this.column : '');
|
|
159
180
|
}
|
|
@@ -31,6 +31,7 @@ import { RecursivePartial } from '@theia/core';
|
|
|
31
31
|
import { DebugSession } from '../debug-session';
|
|
32
32
|
import { DebugThread } from './debug-thread';
|
|
33
33
|
import * as monaco from '@theia/monaco-editor-core';
|
|
34
|
+
import { stringHash } from '@theia/core/lib/common/hash';
|
|
34
35
|
|
|
35
36
|
export class DebugStackFrameData {
|
|
36
37
|
readonly raw: DebugProtocol.StackFrame;
|
|
@@ -40,15 +41,12 @@ export class DebugStackFrame extends DebugStackFrameData implements TreeElement
|
|
|
40
41
|
|
|
41
42
|
constructor(
|
|
42
43
|
readonly thread: DebugThread,
|
|
43
|
-
readonly session: DebugSession
|
|
44
|
+
readonly session: DebugSession,
|
|
45
|
+
readonly id: string
|
|
44
46
|
) {
|
|
45
47
|
super();
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
get id(): string {
|
|
49
|
-
return this.session.id + ':' + this.thread.id + ':' + this.raw.id;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
50
|
/**
|
|
53
51
|
* Returns the frame identifier from the debug protocol.
|
|
54
52
|
*/
|
|
@@ -115,7 +113,16 @@ export class DebugStackFrame extends DebugStackFrameData implements TreeElement
|
|
|
115
113
|
if (!response) {
|
|
116
114
|
return [];
|
|
117
115
|
}
|
|
118
|
-
|
|
116
|
+
const scopeIds = new Set<number>();
|
|
117
|
+
return response.body.scopes.map(raw => {
|
|
118
|
+
// just as in VS Code, the id is based on the name and location to retain expansion state across multiple pauses
|
|
119
|
+
let id = 0;
|
|
120
|
+
do {
|
|
121
|
+
id = stringHash(`${raw.name}:${raw.line}:${raw.column}`, id);
|
|
122
|
+
} while (scopeIds.has(id));
|
|
123
|
+
scopeIds.add(id);
|
|
124
|
+
return new DebugScope(raw, () => this.session, id);
|
|
125
|
+
});
|
|
119
126
|
}
|
|
120
127
|
|
|
121
128
|
// https://github.com/theia-ide/vscode/blob/standalone/0.19.x/src/vs/workbench/contrib/debug/common/debugModel.ts#L324-L335
|
|
@@ -164,7 +164,7 @@ export class DebugThread extends DebugThreadData implements TreeElement {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
protected readonly _frames = new Map<
|
|
167
|
+
protected readonly _frames = new Map<string, DebugStackFrame>();
|
|
168
168
|
get frames(): IterableIterator<DebugStackFrame> {
|
|
169
169
|
return this._frames.values();
|
|
170
170
|
}
|
|
@@ -189,7 +189,7 @@ export class DebugThread extends DebugThreadData implements TreeElement {
|
|
|
189
189
|
if (cancel.isCancellationRequested) {
|
|
190
190
|
return [];
|
|
191
191
|
}
|
|
192
|
-
return this.doUpdateFrames(frames);
|
|
192
|
+
return this.doUpdateFrames(start, frames);
|
|
193
193
|
} catch (e) {
|
|
194
194
|
console.error('fetchFrames failed:', e);
|
|
195
195
|
return [];
|
|
@@ -219,15 +219,19 @@ export class DebugThread extends DebugThreadData implements TreeElement {
|
|
|
219
219
|
return [];
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
|
-
protected doUpdateFrames(frames: DebugProtocol.StackFrame[]): DebugStackFrame[] {
|
|
222
|
+
protected doUpdateFrames(startFrame: number, frames: DebugProtocol.StackFrame[]): DebugStackFrame[] {
|
|
223
223
|
const result = new Set<DebugStackFrame>();
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
224
|
+
frames.forEach((raw, index) => {
|
|
225
|
+
// Similarly to VS Code, we no longer use `raw.frameId` in computation of the DebugStackFrame id.
|
|
226
|
+
// The `raw.frameId` was changing in every step and was not allowing us to correlate stack frames between step events.
|
|
227
|
+
// Refs: https://github.com/microsoft/vscode/commit/18fc2bcf718e22265b5e09bb7fd0e9c090264cd2, https://github.com/microsoft/vscode/issues/93230#issuecomment-642558395
|
|
228
|
+
const source = raw.source && this.session.getSource(raw.source);
|
|
229
|
+
const id = `${this.id}:${startFrame + index}:${source?.name}`;
|
|
230
|
+
const frame = this._frames.get(id) || new DebugStackFrame(this, this.session, id);
|
|
227
231
|
this._frames.set(id, frame);
|
|
228
232
|
frame.update({ raw });
|
|
229
233
|
result.add(frame);
|
|
230
|
-
}
|
|
234
|
+
});
|
|
231
235
|
this.updateCurrentFrame();
|
|
232
236
|
return [...result.values()];
|
|
233
237
|
}
|
|
@@ -247,9 +251,9 @@ export class DebugThread extends DebugThreadData implements TreeElement {
|
|
|
247
251
|
}
|
|
248
252
|
protected updateCurrentFrame(): void {
|
|
249
253
|
const { currentFrame } = this;
|
|
250
|
-
const
|
|
251
|
-
this.currentFrame = typeof
|
|
252
|
-
this._frames.get(
|
|
254
|
+
const id = currentFrame && currentFrame.id;
|
|
255
|
+
this.currentFrame = typeof id === 'string' &&
|
|
256
|
+
this._frames.get(id) ||
|
|
253
257
|
this._frames.values().next().value;
|
|
254
258
|
}
|
|
255
259
|
|