@theia/debug 1.70.0-next.71 → 1.70.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.d.ts +80 -45
- package/lib/browser/breakpoint/breakpoint-manager.d.ts.map +1 -1
- package/lib/browser/breakpoint/breakpoint-manager.js +553 -170
- package/lib/browser/breakpoint/breakpoint-manager.js.map +1 -1
- package/lib/browser/breakpoint/breakpoint-manager.spec.d.ts +2 -0
- package/lib/browser/breakpoint/breakpoint-manager.spec.d.ts.map +1 -0
- package/lib/browser/breakpoint/breakpoint-manager.spec.js +861 -0
- package/lib/browser/breakpoint/breakpoint-manager.spec.js.map +1 -0
- package/lib/browser/breakpoint/breakpoint-marker.d.ts +7 -10
- package/lib/browser/breakpoint/breakpoint-marker.d.ts.map +1 -1
- package/lib/browser/breakpoint/breakpoint-marker.js +14 -11
- package/lib/browser/breakpoint/breakpoint-marker.js.map +1 -1
- package/lib/browser/breakpoint/debug-data-breakpoint-actions.js +1 -1
- package/lib/browser/breakpoint/debug-data-breakpoint-actions.js.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.d.ts +1 -2
- package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.js +13 -21
- package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
- package/lib/browser/debug-frontend-module.d.ts.map +1 -1
- package/lib/browser/debug-frontend-module.js +3 -0
- package/lib/browser/debug-frontend-module.js.map +1 -1
- package/lib/browser/debug-session-manager.d.ts +8 -27
- package/lib/browser/debug-session-manager.d.ts.map +1 -1
- package/lib/browser/debug-session-manager.js +14 -132
- package/lib/browser/debug-session-manager.js.map +1 -1
- package/lib/browser/debug-session.d.ts +3 -21
- package/lib/browser/debug-session.d.ts.map +1 -1
- package/lib/browser/debug-session.js +89 -203
- package/lib/browser/debug-session.js.map +1 -1
- package/lib/browser/disassembly-view/disassembly-view-breakpoint-renderer.js +1 -1
- package/lib/browser/disassembly-view/disassembly-view-breakpoint-renderer.js.map +1 -1
- package/lib/browser/disassembly-view/disassembly-view-widget.d.ts.map +1 -1
- package/lib/browser/disassembly-view/disassembly-view-widget.js +17 -24
- package/lib/browser/disassembly-view/disassembly-view-widget.js.map +1 -1
- package/lib/browser/editor/debug-editor-model.d.ts +15 -5
- package/lib/browser/editor/debug-editor-model.d.ts.map +1 -1
- package/lib/browser/editor/debug-editor-model.js +56 -32
- package/lib/browser/editor/debug-editor-model.js.map +1 -1
- package/lib/browser/model/debug-breakpoint-opener.d.ts +14 -0
- package/lib/browser/model/debug-breakpoint-opener.d.ts.map +1 -0
- package/lib/browser/model/debug-breakpoint-opener.js +67 -0
- package/lib/browser/model/debug-breakpoint-opener.js.map +1 -0
- package/lib/browser/model/debug-breakpoint.d.ts +32 -13
- package/lib/browser/model/debug-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-breakpoint.js +76 -16
- package/lib/browser/model/debug-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-data-breakpoint.d.ts +1 -0
- package/lib/browser/model/debug-data-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-data-breakpoint.js +6 -5
- package/lib/browser/model/debug-data-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.d.ts +4 -1
- package/lib/browser/model/debug-function-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.js +20 -29
- package/lib/browser/model/debug-function-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-instruction-breakpoint.d.ts +2 -1
- package/lib/browser/model/debug-instruction-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-instruction-breakpoint.js +8 -8
- package/lib/browser/model/debug-instruction-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-source-breakpoint.d.ts +6 -15
- package/lib/browser/model/debug-source-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-source-breakpoint.js +16 -90
- package/lib/browser/model/debug-source-breakpoint.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.d.ts +0 -2
- package/lib/browser/view/debug-breakpoints-source.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.js +2 -10
- package/lib/browser/view/debug-breakpoints-source.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-widget.d.ts +2 -0
- package/lib/browser/view/debug-breakpoints-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-widget.js +3 -0
- package/lib/browser/view/debug-breakpoints-widget.js.map +1 -1
- package/lib/browser/view/debug-exception-breakpoint.d.ts +18 -11
- package/lib/browser/view/debug-exception-breakpoint.d.ts.map +1 -1
- package/lib/browser/view/debug-exception-breakpoint.js +58 -24
- package/lib/browser/view/debug-exception-breakpoint.js.map +1 -1
- package/lib/browser/view/debug-view-model.d.ts +8 -4
- package/lib/browser/view/debug-view-model.d.ts.map +1 -1
- package/lib/browser/view/debug-view-model.js +16 -9
- package/lib/browser/view/debug-view-model.js.map +1 -1
- package/package.json +16 -16
- package/src/browser/breakpoint/breakpoint-manager.spec.ts +1106 -0
- package/src/browser/breakpoint/breakpoint-manager.ts +583 -194
- package/src/browser/breakpoint/breakpoint-marker.ts +21 -15
- package/src/browser/breakpoint/debug-data-breakpoint-actions.ts +1 -1
- package/src/browser/debug-frontend-application-contribution.ts +18 -23
- package/src/browser/debug-frontend-module.ts +5 -1
- package/src/browser/debug-session-manager.ts +15 -147
- package/src/browser/debug-session.tsx +99 -222
- package/src/browser/disassembly-view/disassembly-view-breakpoint-renderer.ts +1 -1
- package/src/browser/disassembly-view/disassembly-view-widget.ts +17 -23
- package/src/browser/editor/debug-editor-model.ts +58 -35
- package/src/browser/model/debug-breakpoint-opener.ts +51 -0
- package/src/browser/model/debug-breakpoint.tsx +101 -20
- package/src/browser/model/debug-data-breakpoint.tsx +8 -5
- package/src/browser/model/debug-function-breakpoint.tsx +18 -29
- package/src/browser/model/debug-instruction-breakpoint.tsx +10 -8
- package/src/browser/model/debug-source-breakpoint.tsx +23 -101
- package/src/browser/view/debug-breakpoints-source.tsx +2 -9
- package/src/browser/view/debug-breakpoints-widget.ts +6 -0
- package/src/browser/view/debug-exception-breakpoint.tsx +66 -27
- package/src/browser/view/debug-view-model.ts +21 -13
|
@@ -19,7 +19,18 @@
|
|
|
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 {
|
|
22
|
+
import {
|
|
23
|
+
Emitter,
|
|
24
|
+
Event,
|
|
25
|
+
DisposableCollection,
|
|
26
|
+
Disposable,
|
|
27
|
+
MessageClient,
|
|
28
|
+
MessageType,
|
|
29
|
+
Mutable,
|
|
30
|
+
ContributionProvider,
|
|
31
|
+
CommandService,
|
|
32
|
+
CancellationError
|
|
33
|
+
} from '@theia/core/lib/common';
|
|
23
34
|
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
|
|
24
35
|
import { EditorManager } from '@theia/editor/lib/browser';
|
|
25
36
|
import { CompositeTreeElement } from '@theia/core/lib/browser/source-tree';
|
|
@@ -28,25 +39,22 @@ import { DebugThread, StoppedDetails, DebugThreadData } from './model/debug-thre
|
|
|
28
39
|
import { DebugScope, DebugVariable } from './console/debug-console-items';
|
|
29
40
|
import { DebugStackFrame } from './model/debug-stack-frame';
|
|
30
41
|
import { DebugSource } from './model/debug-source';
|
|
31
|
-
import { DebugBreakpoint
|
|
32
|
-
import { DebugSourceBreakpoint } from './model/debug-source-breakpoint';
|
|
42
|
+
import { DebugBreakpoint } from './model/debug-breakpoint';
|
|
33
43
|
import debounce = require('p-debounce');
|
|
34
44
|
import URI from '@theia/core/lib/common/uri';
|
|
35
45
|
import { BreakpointManager } from './breakpoint/breakpoint-manager';
|
|
36
46
|
import { DebugConfigurationSessionOptions, InternalDebugSessionOptions, TestRunReference } from './debug-session-options';
|
|
37
47
|
import { DebugConfiguration, DebugConsoleMode } from '../common/debug-common';
|
|
38
|
-
import { SourceBreakpoint
|
|
48
|
+
import { SourceBreakpoint } from './breakpoint/breakpoint-marker';
|
|
39
49
|
import { TerminalWidgetOptions, TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
|
|
40
|
-
import { DebugFunctionBreakpoint } from './model/debug-function-breakpoint';
|
|
41
50
|
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
42
51
|
import { DebugContribution } from './debug-contribution';
|
|
43
52
|
import { Deferred, waitForEvent } from '@theia/core/lib/common/promise-util';
|
|
44
53
|
import { WorkspaceService } from '@theia/workspace/lib/browser';
|
|
45
|
-
import { DebugInstructionBreakpoint } from './model/debug-instruction-breakpoint';
|
|
46
54
|
import { nls } from '@theia/core';
|
|
47
55
|
import { TestService, TestServices } from '@theia/test/lib/browser/test-service';
|
|
48
56
|
import { DebugSessionManager } from './debug-session-manager';
|
|
49
|
-
|
|
57
|
+
|
|
50
58
|
import { DebugPreferences } from '../common/debug-preferences';
|
|
51
59
|
|
|
52
60
|
export enum DebugState {
|
|
@@ -98,12 +106,6 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
98
106
|
return this.onDidFocusThreadEmitter.event;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
protected readonly onDidChangeBreakpointsEmitter = new Emitter<URI>();
|
|
102
|
-
readonly onDidChangeBreakpoints: Event<URI> = this.onDidChangeBreakpointsEmitter.event;
|
|
103
|
-
protected fireDidChangeBreakpoints(uri: URI): void {
|
|
104
|
-
this.onDidChangeBreakpointsEmitter.fire(uri);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
109
|
protected readonly onDidResolveLazyVariableEmitter = new Emitter<DebugVariable>();
|
|
108
110
|
readonly onDidResolveLazyVariable: Event<DebugVariable> = this.onDidResolveLazyVariableEmitter.event;
|
|
109
111
|
|
|
@@ -112,6 +114,9 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
112
114
|
|
|
113
115
|
protected isStopping: boolean = false;
|
|
114
116
|
|
|
117
|
+
/** Maximum time to wait for the shell integration prompt before proceeding. */
|
|
118
|
+
protected readonly PROMPT_READY_TIMEOUT_MS = 3000;
|
|
119
|
+
|
|
115
120
|
constructor(
|
|
116
121
|
readonly id: string,
|
|
117
122
|
readonly options: DebugConfigurationSessionOptions,
|
|
@@ -165,10 +170,8 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
165
170
|
this.onDidChangeEmitter,
|
|
166
171
|
this.onDidFocusStackFrameEmitter,
|
|
167
172
|
this.onDidFocusThreadEmitter,
|
|
168
|
-
this.onDidChangeBreakpointsEmitter,
|
|
169
173
|
this.onDidResolveLazyVariableEmitter,
|
|
170
174
|
Disposable.create(() => {
|
|
171
|
-
this.clearBreakpoints();
|
|
172
175
|
this.doUpdateThreads([]);
|
|
173
176
|
}),
|
|
174
177
|
this.connection,
|
|
@@ -228,7 +231,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
228
231
|
sourceReference: Number(uri.query)
|
|
229
232
|
};
|
|
230
233
|
}
|
|
231
|
-
const name = uri
|
|
234
|
+
const name = this.labelProvider.getName(uri);
|
|
232
235
|
let path;
|
|
233
236
|
const underlying = await this.fileService.toUnderlyingResource(uri);
|
|
234
237
|
if (underlying.scheme === 'file') {
|
|
@@ -396,12 +399,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
396
399
|
protected async configure(): Promise<void> {
|
|
397
400
|
await this.didReceiveCapabilities.promise;
|
|
398
401
|
if (this.capabilities.exceptionBreakpointFilters) {
|
|
399
|
-
|
|
400
|
-
for (const filter of this.capabilities.exceptionBreakpointFilters) {
|
|
401
|
-
const origin = this.breakpoints.getExceptionBreakpoint(filter.filter);
|
|
402
|
-
exceptionBreakpoints.push(ExceptionBreakpoint.create(filter, origin));
|
|
403
|
-
}
|
|
404
|
-
this.breakpoints.setExceptionBreakpoints(exceptionBreakpoints);
|
|
402
|
+
this.breakpoints.addExceptionBreakpoints(this.capabilities.exceptionBreakpointFilters, this.id);
|
|
405
403
|
}
|
|
406
404
|
// mark as initialized, so updated breakpoints are shown in editor
|
|
407
405
|
this.initialized = true;
|
|
@@ -520,8 +518,21 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
520
518
|
}
|
|
521
519
|
|
|
522
520
|
if (!terminal) {
|
|
523
|
-
terminal = await this.terminalServer.newTerminal(options);
|
|
521
|
+
terminal = await this.terminalServer.newTerminal({ ...options, kind: 'debug' });
|
|
524
522
|
await terminal.start();
|
|
523
|
+
try {
|
|
524
|
+
if (terminal.commandHistoryState) {
|
|
525
|
+
// delay opening of the terminal until the terminal prompt appears to prevent duplicate commands in the terminal buffer
|
|
526
|
+
await waitForEvent(terminal.commandHistoryState.onTerminalPromptShown, this.PROMPT_READY_TIMEOUT_MS);
|
|
527
|
+
}
|
|
528
|
+
} catch (error) {
|
|
529
|
+
if (error instanceof CancellationError) {
|
|
530
|
+
console.warn('Shell integration did not emit a prompt within the timeout; proceeding anyway.');
|
|
531
|
+
} else {
|
|
532
|
+
console.error('Unexpected error while waiting for terminal prompt:', error);
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
525
536
|
}
|
|
526
537
|
this.terminalServer.open(terminal);
|
|
527
538
|
return terminal;
|
|
@@ -611,71 +622,6 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
611
622
|
this.deferredOnDidConfigureCapabilities.resolve();
|
|
612
623
|
}
|
|
613
624
|
|
|
614
|
-
protected readonly _breakpoints = new Map<string, DebugBreakpoint[]>();
|
|
615
|
-
get breakpointUris(): IterableIterator<string> {
|
|
616
|
-
return this._breakpoints.keys();
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
getSourceBreakpoints(uri?: URI): DebugSourceBreakpoint[] {
|
|
620
|
-
const breakpoints = [];
|
|
621
|
-
for (const breakpoint of this.getBreakpoints(uri)) {
|
|
622
|
-
if (breakpoint instanceof DebugSourceBreakpoint) {
|
|
623
|
-
breakpoints.push(breakpoint);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
return breakpoints;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
getFunctionBreakpoints(): DebugFunctionBreakpoint[] {
|
|
630
|
-
return this.getBreakpoints(BreakpointManager.FUNCTION_URI).filter((breakpoint): breakpoint is DebugFunctionBreakpoint => breakpoint instanceof DebugFunctionBreakpoint);
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
getInstructionBreakpoints(): DebugInstructionBreakpoint[] {
|
|
634
|
-
if (this.capabilities.supportsInstructionBreakpoints) {
|
|
635
|
-
return this.getBreakpoints(BreakpointManager.INSTRUCTION_URI)
|
|
636
|
-
.filter((breakpoint): breakpoint is DebugInstructionBreakpoint => breakpoint instanceof DebugInstructionBreakpoint);
|
|
637
|
-
}
|
|
638
|
-
return this.breakpoints.getInstructionBreakpoints().map(origin => new DebugInstructionBreakpoint(origin, this.asDebugBreakpointOptions()));
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
getDataBreakpoints(): DebugDataBreakpoint[] {
|
|
642
|
-
if (this.capabilities.supportsDataBreakpoints) {
|
|
643
|
-
return this.getBreakpoints(BreakpointManager.DATA_URI)
|
|
644
|
-
.filter((breakpoint): breakpoint is DebugDataBreakpoint => breakpoint instanceof DebugDataBreakpoint);
|
|
645
|
-
}
|
|
646
|
-
return this.breakpoints.getDataBreakpoints().map(origin => new DebugDataBreakpoint(origin, this.asDebugBreakpointOptions()));
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
getBreakpoints(uri?: URI): DebugBreakpoint[] {
|
|
650
|
-
if (uri) {
|
|
651
|
-
return this._breakpoints.get(uri.toString()) || [];
|
|
652
|
-
}
|
|
653
|
-
const result = [];
|
|
654
|
-
for (const breakpoints of this._breakpoints.values()) {
|
|
655
|
-
result.push(...breakpoints);
|
|
656
|
-
}
|
|
657
|
-
return result;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
getBreakpoint(id: string): DebugBreakpoint | undefined {
|
|
661
|
-
for (const breakpoints of this._breakpoints.values()) {
|
|
662
|
-
const breakpoint = breakpoints.find(b => b.id === id);
|
|
663
|
-
if (breakpoint) {
|
|
664
|
-
return breakpoint;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
}
|
|
668
|
-
return undefined;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
protected clearBreakpoints(): void {
|
|
672
|
-
const uris = [...this._breakpoints.keys()];
|
|
673
|
-
this._breakpoints.clear();
|
|
674
|
-
for (const uri of uris) {
|
|
675
|
-
this.fireDidChangeBreakpoints(new URI(uri));
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
625
|
protected updatingBreakpoints = false;
|
|
680
626
|
|
|
681
627
|
protected updateBreakpoint(body: DebugProtocol.BreakpointEvent['body']): void {
|
|
@@ -686,54 +632,33 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
686
632
|
if (raw.source && typeof raw.line === 'number') {
|
|
687
633
|
const uri = DebugSource.toUri(raw.source);
|
|
688
634
|
const origin = SourceBreakpoint.create(uri, { line: raw.line, column: raw.column });
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
const breakpoint = new DebugSourceBreakpoint(origin, this.asDebugBreakpointOptions(), this.commandService);
|
|
692
|
-
breakpoint.update({ raw });
|
|
693
|
-
breakpoints.push(breakpoint);
|
|
694
|
-
this.setSourceBreakpoints(uri, breakpoints);
|
|
695
|
-
}
|
|
635
|
+
const breakpoint = this.breakpoints.addBreakpoint(origin);
|
|
636
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, new Map<string, DebugProtocol.Breakpoint>([[breakpoint.id, raw]]));
|
|
696
637
|
}
|
|
697
638
|
}
|
|
698
639
|
if (body.reason === 'removed' && typeof raw.id === 'number') {
|
|
699
|
-
const toRemove = this.findBreakpoint(b => b.
|
|
640
|
+
const toRemove = this.findBreakpoint(b => b.getIdForSession(this.id) === raw.id);
|
|
700
641
|
if (toRemove) {
|
|
701
642
|
toRemove.remove();
|
|
702
|
-
const breakpoints = this.getBreakpoints(toRemove.uri);
|
|
703
|
-
const index = breakpoints.indexOf(toRemove);
|
|
704
|
-
if (index !== -1) {
|
|
705
|
-
breakpoints.splice(index, 1);
|
|
706
|
-
this.setBreakpoints(toRemove.uri, breakpoints);
|
|
707
|
-
}
|
|
708
643
|
}
|
|
709
644
|
}
|
|
710
645
|
if (body.reason === 'changed' && typeof raw.id === 'number') {
|
|
711
|
-
const toUpdate = this.findBreakpoint(b => b.
|
|
646
|
+
const toUpdate = this.findBreakpoint(b => b.getIdForSession(this.id) === raw.id);
|
|
712
647
|
if (toUpdate) {
|
|
713
|
-
|
|
714
|
-
if (toUpdate instanceof DebugSourceBreakpoint) {
|
|
715
|
-
const sourceBreakpoints = this.getSourceBreakpoints(toUpdate.uri);
|
|
716
|
-
// in order to dedup again if a debugger converted line breakpoint to inline breakpoint
|
|
717
|
-
// i.e. assigned a column to a line breakpoint
|
|
718
|
-
this.setSourceBreakpoints(toUpdate.uri, sourceBreakpoints);
|
|
719
|
-
} else {
|
|
720
|
-
this.fireDidChangeBreakpoints(toUpdate.uri);
|
|
721
|
-
}
|
|
648
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, new Map([[toUpdate.id, raw]]));
|
|
722
649
|
}
|
|
723
650
|
}
|
|
724
651
|
} finally {
|
|
725
652
|
this.updatingBreakpoints = false;
|
|
726
653
|
}
|
|
727
654
|
}
|
|
655
|
+
|
|
728
656
|
protected findBreakpoint(match: (breakpoint: DebugBreakpoint) => boolean): DebugBreakpoint | undefined {
|
|
729
|
-
for (const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
return breakpoint;
|
|
733
|
-
}
|
|
657
|
+
for (const bp of this.breakpoints.allBreakpoints()) {
|
|
658
|
+
if (match(bp)) {
|
|
659
|
+
return bp;
|
|
734
660
|
}
|
|
735
661
|
}
|
|
736
|
-
return undefined;
|
|
737
662
|
}
|
|
738
663
|
|
|
739
664
|
protected async updateBreakpoints(options: {
|
|
@@ -763,71 +688,61 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
763
688
|
protected async sendExceptionBreakpoints(): Promise<void> {
|
|
764
689
|
const filters: string[] = [];
|
|
765
690
|
const filterOptions: DebugProtocol.ExceptionFilterOptions[] | undefined = this.capabilities.supportsExceptionFilterOptions ? [] : undefined;
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
691
|
+
const toSend = this.breakpoints.getExceptionBreakpoints().filter(candidate => candidate.origin.enabled);
|
|
692
|
+
const updates = new Map<string, DebugProtocol.Breakpoint>();
|
|
693
|
+
for (const breakpoint of toSend) {
|
|
694
|
+
if (filterOptions) {
|
|
695
|
+
filterOptions.push({
|
|
696
|
+
filterId: breakpoint.origin.raw.filter,
|
|
697
|
+
condition: breakpoint.origin.condition
|
|
698
|
+
});
|
|
699
|
+
} else {
|
|
700
|
+
filters.push(breakpoint.origin.raw.filter);
|
|
776
701
|
}
|
|
777
702
|
}
|
|
778
|
-
|
|
703
|
+
try {
|
|
704
|
+
const res = await this.sendRequest('setExceptionBreakpoints', { filters, filterOptions });
|
|
705
|
+
res.body?.breakpoints?.forEach((bp, index) => toSend[index] && updates.set(toSend[index].id, bp));
|
|
706
|
+
} catch (err) {
|
|
707
|
+
console.error('Failed to set exception breakpoints:', err);
|
|
708
|
+
const message = (err as Error)?.message ? `${err.message}` : 'Failed to set exception breakpoints.';
|
|
709
|
+
toSend.forEach(bp => updates.set(bp.id, { verified: false, message }));
|
|
710
|
+
}
|
|
711
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, updates);
|
|
779
712
|
}
|
|
780
713
|
|
|
781
714
|
protected async sendFunctionBreakpoints(affectedUri: URI): Promise<void> {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
);
|
|
715
|
+
if (!this.capabilities.supportsFunctionBreakpoints) { return; }
|
|
716
|
+
const all = this.breakpoints.getFunctionBreakpoints();
|
|
785
717
|
const enabled = all.filter(b => b.enabled);
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
enabled[index].update({ raw });
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
} catch (error) {
|
|
803
|
-
// could be error or promise rejection of DebugProtocol.SetFunctionBreakpoints
|
|
804
|
-
if (error instanceof Error) {
|
|
805
|
-
console.error(`Error setting breakpoints: ${error.message}`);
|
|
806
|
-
} else {
|
|
807
|
-
// handle adapters that send failed DebugProtocol.SetFunctionBreakpoints for invalid breakpoints
|
|
808
|
-
const genericMessage: string = 'Function breakpoint not valid for current debug session';
|
|
809
|
-
const message: string = error.message ? `${error.message}` : genericMessage;
|
|
810
|
-
console.warn(`Could not handle function breakpoints: ${message}, disabling...`);
|
|
811
|
-
enabled.forEach(b => b.update({
|
|
812
|
-
raw: {
|
|
813
|
-
verified: false,
|
|
814
|
-
message
|
|
815
|
-
}
|
|
816
|
-
}));
|
|
718
|
+
const updates = new Map<string, DebugProtocol.Breakpoint>();
|
|
719
|
+
try {
|
|
720
|
+
const response = await this.sendRequest('setFunctionBreakpoints', {
|
|
721
|
+
breakpoints: enabled.map(b => b.origin.raw)
|
|
722
|
+
});
|
|
723
|
+
// Apparently, `body` and `breakpoints` can be missing.
|
|
724
|
+
// https://github.com/eclipse-theia/theia/issues/11885
|
|
725
|
+
// https://github.com/microsoft/vscode/blob/80004351ccf0884b58359f7c8c801c91bb827d83/src/vs/workbench/contrib/debug/browser/debugSession.ts#L448-L449
|
|
726
|
+
response?.body?.breakpoints.forEach((raw, index) => {
|
|
727
|
+
// node debug adapter returns more breakpoints sometimes
|
|
728
|
+
if (enabled[index]) {
|
|
729
|
+
updates.set(enabled[index].id, raw);
|
|
817
730
|
}
|
|
818
|
-
}
|
|
731
|
+
});
|
|
732
|
+
} catch (error) {
|
|
733
|
+
const genericMessage: string = 'Function breakpoint not valid for current debug session';
|
|
734
|
+
const message: string = error.message ? `${error.message}` : genericMessage;
|
|
735
|
+
console.warn(`Could not handle function breakpoints: ${message}, disabling...`);
|
|
736
|
+
enabled.forEach(b => updates.set(b.id, { verified: false, message }));
|
|
819
737
|
}
|
|
820
|
-
this.
|
|
738
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, updates);
|
|
821
739
|
}
|
|
822
740
|
|
|
823
741
|
protected async sendSourceBreakpoints(affectedUri: URI, sourceModified?: boolean): Promise<void> {
|
|
824
742
|
const source = await this.toSource(affectedUri);
|
|
825
|
-
const
|
|
826
|
-
const all = this.breakpoints.findMarkers({ uri: affectedUri }).map(({ data }) =>
|
|
827
|
-
known?.find((candidate): candidate is DebugSourceBreakpoint => candidate instanceof DebugSourceBreakpoint && candidate.origin.id === data.id) ??
|
|
828
|
-
new DebugSourceBreakpoint(data, this.asDebugBreakpointOptions(), this.commandService)
|
|
829
|
-
);
|
|
743
|
+
const all = this.breakpoints.getBreakpoints(affectedUri);
|
|
830
744
|
const enabled = all.filter(b => b.enabled);
|
|
745
|
+
const updates = new Map<string, DebugProtocol.Breakpoint>();
|
|
831
746
|
try {
|
|
832
747
|
const breakpoints = enabled.map(({ origin }) => origin.raw);
|
|
833
748
|
const response = await this.sendRequest('setBreakpoints', {
|
|
@@ -839,7 +754,7 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
839
754
|
response.body.breakpoints.forEach((raw, index) => {
|
|
840
755
|
// node debug adapter returns more breakpoints sometimes
|
|
841
756
|
if (enabled[index]) {
|
|
842
|
-
enabled[index].
|
|
757
|
+
updates.set(enabled[index].id, raw);
|
|
843
758
|
}
|
|
844
759
|
});
|
|
845
760
|
} catch (error) {
|
|
@@ -851,77 +766,44 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
851
766
|
const genericMessage: string = 'Breakpoint not valid for current debug session';
|
|
852
767
|
const message: string = error.message ? `${error.message}` : genericMessage;
|
|
853
768
|
console.warn(`Could not handle breakpoints for ${affectedUri}: ${message}, disabling...`);
|
|
854
|
-
enabled.forEach(b => b.
|
|
855
|
-
raw: {
|
|
856
|
-
verified: false,
|
|
857
|
-
message
|
|
858
|
-
}
|
|
859
|
-
}));
|
|
769
|
+
enabled.forEach(b => updates.set(b.id, { verified: false, message }));
|
|
860
770
|
}
|
|
861
771
|
}
|
|
862
|
-
this.
|
|
772
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, updates);
|
|
863
773
|
}
|
|
864
774
|
|
|
865
775
|
protected async sendInstructionBreakpoints(): Promise<void> {
|
|
866
776
|
if (!this.capabilities.supportsInstructionBreakpoints) {
|
|
867
777
|
return;
|
|
868
778
|
}
|
|
869
|
-
const all = this.breakpoints.getInstructionBreakpoints()
|
|
779
|
+
const all = this.breakpoints.getInstructionBreakpoints();
|
|
870
780
|
const enabled = all.filter(breakpoint => breakpoint.enabled);
|
|
781
|
+
const updates = new Map<string, DebugProtocol.Breakpoint>();
|
|
871
782
|
try {
|
|
872
783
|
const response = await this.sendRequest('setInstructionBreakpoints', {
|
|
873
|
-
breakpoints: enabled.map(renderable => renderable.origin),
|
|
784
|
+
breakpoints: enabled.map(renderable => renderable.origin.raw),
|
|
874
785
|
});
|
|
875
|
-
response.body.breakpoints.forEach((raw, index) => enabled[index]
|
|
786
|
+
response.body.breakpoints.forEach((raw, index) => enabled[index] && updates.set(enabled[index].id, raw));
|
|
876
787
|
} catch {
|
|
877
|
-
enabled.forEach(breakpoint => breakpoint.
|
|
788
|
+
enabled.forEach(breakpoint => updates.set(breakpoint.id, { verified: false }));
|
|
878
789
|
}
|
|
879
|
-
this.
|
|
790
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, updates);
|
|
880
791
|
}
|
|
881
792
|
|
|
882
793
|
protected async sendDataBreakpoints(): Promise<void> {
|
|
883
794
|
if (!this.capabilities.supportsDataBreakpoints) { return; }
|
|
884
|
-
const
|
|
885
|
-
const all = this.breakpoints.getDataBreakpoints().map<DebugDataBreakpoint>(bp =>
|
|
886
|
-
known?.find((candidate): candidate is DebugDataBreakpoint => candidate instanceof DebugDataBreakpoint && candidate.id === bp.id)
|
|
887
|
-
?? new DebugDataBreakpoint(bp, this.asDebugBreakpointOptions())
|
|
888
|
-
);
|
|
795
|
+
const all = this.breakpoints.getDataBreakpoints();
|
|
889
796
|
const enabled = all.filter(bp => bp.enabled);
|
|
797
|
+
const updates = new Map<string, DebugProtocol.Breakpoint>();
|
|
890
798
|
try {
|
|
891
799
|
const response = await this.sendRequest('setDataBreakpoints', {
|
|
892
800
|
breakpoints: enabled.map(({ origin }) => origin.raw)
|
|
893
801
|
});
|
|
894
|
-
response.body.breakpoints.forEach((raw, index) => enabled[index].
|
|
802
|
+
response.body.breakpoints.forEach((raw, index) => enabled[index] && updates.set(enabled[index].id, raw));
|
|
895
803
|
} catch {
|
|
896
|
-
enabled.forEach(breakpoint => breakpoint.
|
|
804
|
+
enabled.forEach(breakpoint => updates.set(breakpoint.id, { verified: false }));
|
|
897
805
|
}
|
|
898
|
-
this.
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
protected setBreakpoints(uri: URI, breakpoints: DebugBreakpoint[]): void {
|
|
902
|
-
this._breakpoints.set(uri.toString(), breakpoints);
|
|
903
|
-
this.fireDidChangeBreakpoints(uri);
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
protected setSourceBreakpoints(uri: URI, breakpoints: DebugSourceBreakpoint[]): void {
|
|
907
|
-
const distinct = this.dedupSourceBreakpoints(breakpoints);
|
|
908
|
-
this.setBreakpoints(uri, distinct);
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
protected dedupSourceBreakpoints(all: DebugSourceBreakpoint[]): DebugSourceBreakpoint[] {
|
|
912
|
-
const positions = new Map<string, DebugSourceBreakpoint>();
|
|
913
|
-
for (const breakpoint of all) {
|
|
914
|
-
let primary = positions.get(breakpoint.renderPosition()) || breakpoint;
|
|
915
|
-
if (primary !== breakpoint) {
|
|
916
|
-
let secondary = breakpoint;
|
|
917
|
-
if (secondary.raw && secondary.raw.line === secondary.origin.raw.line && secondary.raw.column === secondary.origin.raw.column) {
|
|
918
|
-
[primary, secondary] = [breakpoint, primary];
|
|
919
|
-
}
|
|
920
|
-
primary.origins.push(...secondary.origins);
|
|
921
|
-
}
|
|
922
|
-
positions.set(primary.renderPosition(), primary);
|
|
923
|
-
}
|
|
924
|
-
return [...positions.values()];
|
|
806
|
+
this.breakpoints.updateSessionData(this.id, this.capabilities, updates);
|
|
925
807
|
}
|
|
926
808
|
|
|
927
809
|
protected *getAffectedUris(uri?: URI): IterableIterator<URI> {
|
|
@@ -937,11 +819,6 @@ export class DebugSession implements CompositeTreeElement {
|
|
|
937
819
|
}
|
|
938
820
|
}
|
|
939
821
|
|
|
940
|
-
protected asDebugBreakpointOptions(): DebugBreakpointOptions {
|
|
941
|
-
const { labelProvider, breakpoints, editorManager } = this;
|
|
942
|
-
return { labelProvider, breakpoints, editorManager, session: this };
|
|
943
|
-
}
|
|
944
|
-
|
|
945
822
|
get label(): string {
|
|
946
823
|
const suffixes = [];
|
|
947
824
|
if (InternalDebugSessionOptions.is(this.options) && this.options.id) {
|
|
@@ -69,7 +69,7 @@ export class BreakpointRenderer implements ITableRenderer<DisassembledInstructio
|
|
|
69
69
|
// click show hint while waiting for BP to resolve.
|
|
70
70
|
icon.classList.add(this._breakpointHintIcon);
|
|
71
71
|
if (currentElement.element.isBreakpointSet) {
|
|
72
|
-
this._debugService.
|
|
72
|
+
this._debugService.removeInstructionBreakpointAt(currentElement.element.instruction.address);
|
|
73
73
|
|
|
74
74
|
} else if (currentElement.element.allowBreakpoint && !currentElement.element.isBreakpointSet) {
|
|
75
75
|
this._debugService.addInstructionBreakpoint(currentElement.element.instruction.address, 0);
|
|
@@ -168,40 +168,34 @@ export class DisassemblyViewWidget extends BaseWidget {
|
|
|
168
168
|
// draw viewable BP
|
|
169
169
|
let changed = false;
|
|
170
170
|
bpEvent.added?.forEach(bp => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
changed = true;
|
|
177
|
-
}
|
|
171
|
+
const index = this.getIndexFromAddress(bp.origin.raw.instructionReference);
|
|
172
|
+
if (index >= 0) {
|
|
173
|
+
this._disassembledInstructions!.row(index).isBreakpointSet = true;
|
|
174
|
+
this._disassembledInstructions!.row(index).isBreakpointEnabled = bp.enabled;
|
|
175
|
+
changed = true;
|
|
178
176
|
}
|
|
179
177
|
});
|
|
180
178
|
|
|
181
179
|
bpEvent.removed?.forEach(bp => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
changed = true;
|
|
187
|
-
}
|
|
180
|
+
const index = this.getIndexFromAddress(bp.origin.raw.instructionReference);
|
|
181
|
+
if (index >= 0) {
|
|
182
|
+
this._disassembledInstructions!.row(index).isBreakpointSet = false;
|
|
183
|
+
changed = true;
|
|
188
184
|
}
|
|
189
185
|
});
|
|
190
186
|
|
|
191
187
|
bpEvent.changed?.forEach(bp => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (index
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
changed = true;
|
|
198
|
-
}
|
|
188
|
+
const index = this.getIndexFromAddress(bp.origin.raw.instructionReference);
|
|
189
|
+
if (index >= 0) {
|
|
190
|
+
if (this._disassembledInstructions!.row(index).isBreakpointEnabled !== bp.enabled) {
|
|
191
|
+
this._disassembledInstructions!.row(index).isBreakpointEnabled = bp.enabled;
|
|
192
|
+
changed = true;
|
|
199
193
|
}
|
|
200
194
|
}
|
|
201
195
|
});
|
|
202
196
|
|
|
203
197
|
// get an updated list so that items beyond the current range would render when reached.
|
|
204
|
-
this._instructionBpList = this.breakpointManager.getInstructionBreakpoints();
|
|
198
|
+
this._instructionBpList = this.breakpointManager.getInstructionBreakpoints().map(({ origin }) => origin);
|
|
205
199
|
|
|
206
200
|
if (changed) {
|
|
207
201
|
this._onDidChangeStackFrame.fire();
|
|
@@ -344,7 +338,7 @@ export class DisassemblyViewWidget extends BaseWidget {
|
|
|
344
338
|
let lastLocation: DebugProtocol.Source | undefined;
|
|
345
339
|
let lastLine: IRange | undefined;
|
|
346
340
|
for (let i = 0; i < resultEntries.length; i++) {
|
|
347
|
-
const found = this._instructionBpList.find(p => p.instructionReference === resultEntries[i].address);
|
|
341
|
+
const found = this._instructionBpList.find(p => p.raw.instructionReference === resultEntries[i].address);
|
|
348
342
|
const instruction = resultEntries[i];
|
|
349
343
|
|
|
350
344
|
// Forward fill the missing location as detailed in the DAP spec.
|
|
@@ -424,7 +418,7 @@ export class DisassemblyViewWidget extends BaseWidget {
|
|
|
424
418
|
if (this._disassembledInstructions) {
|
|
425
419
|
this._loadingLock = true; // stop scrolling during the load.
|
|
426
420
|
this._disassembledInstructions.splice(0, this._disassembledInstructions.length, [disassemblyNotAvailable]);
|
|
427
|
-
this._instructionBpList = this.breakpointManager.getInstructionBreakpoints();
|
|
421
|
+
this._instructionBpList = this.breakpointManager.getInstructionBreakpoints().map(({ origin }) => origin);
|
|
428
422
|
this.loadDisassembledInstructions(targetAddress, -DisassemblyViewWidget.NUM_INSTRUCTIONS_TO_LOAD * 4, DisassemblyViewWidget.NUM_INSTRUCTIONS_TO_LOAD * 8).then(() => {
|
|
429
423
|
// on load, set the target instruction in the middle of the page.
|
|
430
424
|
if (this._disassembledInstructions!.length > 0) {
|