@theia/debug 1.53.0-next.5 → 1.53.0-next.55
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/README.md +62 -62
- package/lib/browser/debug-configuration-manager.js +6 -6
- package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
- package/lib/common/inline-debug-adapter.d.ts +1 -0
- package/lib/common/inline-debug-adapter.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/browser/breakpoint/breakpoint-manager.ts +369 -369
- package/src/browser/breakpoint/breakpoint-marker.ts +104 -104
- package/src/browser/console/debug-console-contribution.tsx +240 -240
- package/src/browser/console/debug-console-items.tsx +384 -384
- package/src/browser/console/debug-console-session.ts +205 -205
- package/src/browser/debug-call-stack-item-type-key.ts +20 -20
- package/src/browser/debug-configuration-manager.ts +591 -591
- package/src/browser/debug-configuration-model.ts +100 -100
- package/src/browser/debug-contribution.ts +43 -43
- package/src/browser/debug-frontend-application-contribution.ts +1551 -1551
- package/src/browser/debug-frontend-module.ts +133 -133
- package/src/browser/debug-package.spec.ts +20 -20
- package/src/browser/debug-preferences.ts +98 -98
- package/src/browser/debug-prefix-configuration.ts +195 -195
- package/src/browser/debug-resource.ts +59 -59
- package/src/browser/debug-schema-updater.ts +149 -149
- package/src/browser/debug-session-connection.ts +357 -357
- package/src/browser/debug-session-contribution.ts +157 -157
- package/src/browser/debug-session-manager.ts +683 -683
- package/src/browser/debug-session-options.ts +120 -120
- package/src/browser/debug-session.tsx +974 -974
- package/src/browser/debug-tab-bar-decorator.ts +57 -57
- package/src/browser/debug-watch-manager.ts +93 -93
- package/src/browser/disassembly-view/disassembly-view-accessibility-provider.ts +43 -43
- package/src/browser/disassembly-view/disassembly-view-breakpoint-renderer.ts +119 -119
- package/src/browser/disassembly-view/disassembly-view-contribution.ts +109 -109
- package/src/browser/disassembly-view/disassembly-view-instruction-renderer.ts +245 -245
- package/src/browser/disassembly-view/disassembly-view-table-delegate.ts +39 -39
- package/src/browser/disassembly-view/disassembly-view-utilities.ts +55 -55
- package/src/browser/disassembly-view/disassembly-view-widget.ts +463 -463
- package/src/browser/editor/debug-breakpoint-widget.tsx +293 -293
- package/src/browser/editor/debug-editor-model.ts +529 -529
- package/src/browser/editor/debug-editor-service.ts +192 -192
- package/src/browser/editor/debug-editor.ts +20 -20
- package/src/browser/editor/debug-exception-widget.tsx +122 -122
- package/src/browser/editor/debug-expression-provider.ts +78 -78
- package/src/browser/editor/debug-hover-source.tsx +105 -105
- package/src/browser/editor/debug-hover-widget.ts +298 -298
- package/src/browser/editor/debug-inline-value-decorator.ts +373 -373
- package/src/browser/model/debug-breakpoint.tsx +151 -151
- package/src/browser/model/debug-function-breakpoint.tsx +101 -101
- package/src/browser/model/debug-instruction-breakpoint.tsx +68 -68
- package/src/browser/model/debug-source-breakpoint.tsx +237 -237
- package/src/browser/model/debug-source.ts +93 -93
- package/src/browser/model/debug-stack-frame.tsx +177 -177
- package/src/browser/model/debug-thread.tsx +292 -292
- package/src/browser/preferences/launch-preferences.ts +38 -38
- package/src/browser/style/index.css +453 -453
- package/src/browser/view/debug-action.tsx +57 -57
- package/src/browser/view/debug-breakpoints-source.tsx +53 -53
- package/src/browser/view/debug-breakpoints-widget.ts +71 -71
- package/src/browser/view/debug-configuration-select.tsx +269 -269
- package/src/browser/view/debug-configuration-widget.tsx +121 -121
- package/src/browser/view/debug-exception-breakpoint.tsx +68 -68
- package/src/browser/view/debug-session-widget.ts +124 -124
- package/src/browser/view/debug-stack-frames-source.tsx +75 -75
- package/src/browser/view/debug-stack-frames-widget.ts +135 -135
- package/src/browser/view/debug-threads-source.tsx +48 -48
- package/src/browser/view/debug-threads-widget.ts +126 -126
- package/src/browser/view/debug-toolbar-widget.tsx +145 -145
- package/src/browser/view/debug-variables-source.ts +43 -43
- package/src/browser/view/debug-variables-widget.ts +61 -61
- package/src/browser/view/debug-view-model.ts +230 -230
- package/src/browser/view/debug-watch-expression.tsx +88 -88
- package/src/browser/view/debug-watch-source.ts +41 -41
- package/src/browser/view/debug-watch-widget.ts +61 -61
- package/src/browser/view/debug-widget.ts +97 -97
- package/src/common/debug-adapter-contribution-registry.ts +206 -206
- package/src/common/debug-adapter-session.ts +102 -102
- package/src/common/debug-common.ts +19 -19
- package/src/common/debug-compound.ts +33 -33
- package/src/common/debug-configuration.ts +112 -112
- package/src/common/debug-model.ts +200 -200
- package/src/common/debug-service.ts +184 -184
- package/src/common/debug-uri-utils.ts +24 -24
- package/src/common/inline-debug-adapter.ts +47 -47
- package/src/node/debug-adapter-factory.ts +107 -107
- package/src/node/debug-adapter-session-manager.ts +106 -106
- package/src/node/debug-backend-module.ts +57 -57
- package/src/node/debug-service-impl.ts +119 -119
- package/src/node/stream-debug-adapter.ts +126 -126
|
@@ -1,369 +1,369 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
|
|
17
|
-
import * as deepEqual from 'fast-deep-equal';
|
|
18
|
-
import { injectable, inject } from '@theia/core/shared/inversify';
|
|
19
|
-
import { Emitter } from '@theia/core/lib/common';
|
|
20
|
-
import { StorageService } from '@theia/core/lib/browser';
|
|
21
|
-
import { Marker } from '@theia/markers/lib/common/marker';
|
|
22
|
-
import { MarkerManager } from '@theia/markers/lib/browser/marker-manager';
|
|
23
|
-
import URI from '@theia/core/lib/common/uri';
|
|
24
|
-
import { SourceBreakpoint, BREAKPOINT_KIND, ExceptionBreakpoint, FunctionBreakpoint, BaseBreakpoint, InstructionBreakpoint } from './breakpoint-marker';
|
|
25
|
-
|
|
26
|
-
export interface BreakpointsChangeEvent<T extends BaseBreakpoint> {
|
|
27
|
-
uri: URI
|
|
28
|
-
added: T[]
|
|
29
|
-
removed: T[]
|
|
30
|
-
changed: T[]
|
|
31
|
-
}
|
|
32
|
-
export type SourceBreakpointsChangeEvent = BreakpointsChangeEvent<SourceBreakpoint>;
|
|
33
|
-
export type FunctionBreakpointsChangeEvent = BreakpointsChangeEvent<FunctionBreakpoint>;
|
|
34
|
-
export type InstructionBreakpointsChangeEvent = BreakpointsChangeEvent<InstructionBreakpoint>;
|
|
35
|
-
|
|
36
|
-
@injectable()
|
|
37
|
-
export class BreakpointManager extends MarkerManager<SourceBreakpoint> {
|
|
38
|
-
|
|
39
|
-
static EXCEPTION_URI = new URI('debug:exception://');
|
|
40
|
-
|
|
41
|
-
static FUNCTION_URI = new URI('debug:function://');
|
|
42
|
-
|
|
43
|
-
static INSTRUCTION_URI = new URI('debug:instruction://');
|
|
44
|
-
|
|
45
|
-
protected readonly owner = 'breakpoint';
|
|
46
|
-
|
|
47
|
-
@inject(StorageService)
|
|
48
|
-
protected readonly storage: StorageService;
|
|
49
|
-
|
|
50
|
-
getKind(): string {
|
|
51
|
-
return BREAKPOINT_KIND;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
protected readonly onDidChangeBreakpointsEmitter = new Emitter<SourceBreakpointsChangeEvent>();
|
|
55
|
-
readonly onDidChangeBreakpoints = this.onDidChangeBreakpointsEmitter.event;
|
|
56
|
-
|
|
57
|
-
protected readonly onDidChangeFunctionBreakpointsEmitter = new Emitter<FunctionBreakpointsChangeEvent>();
|
|
58
|
-
readonly onDidChangeFunctionBreakpoints = this.onDidChangeFunctionBreakpointsEmitter.event;
|
|
59
|
-
|
|
60
|
-
protected readonly onDidChangeInstructionBreakpointsEmitter = new Emitter<InstructionBreakpointsChangeEvent>();
|
|
61
|
-
readonly onDidChangeInstructionBreakpoints = this.onDidChangeInstructionBreakpointsEmitter.event;
|
|
62
|
-
|
|
63
|
-
override setMarkers(uri: URI, owner: string, newMarkers: SourceBreakpoint[]): Marker<SourceBreakpoint>[] {
|
|
64
|
-
const result = this.findMarkers({ uri, owner });
|
|
65
|
-
const added: SourceBreakpoint[] = [];
|
|
66
|
-
const removed: SourceBreakpoint[] = [];
|
|
67
|
-
const changed: SourceBreakpoint[] = [];
|
|
68
|
-
const oldMarkers = new Map(result.map(({ data }) => [data.id, data]));
|
|
69
|
-
const ids = new Set<string>();
|
|
70
|
-
let didChangeMarkers = false;
|
|
71
|
-
for (const newMarker of newMarkers) {
|
|
72
|
-
ids.add(newMarker.id);
|
|
73
|
-
const oldMarker = oldMarkers.get(newMarker.id);
|
|
74
|
-
if (!oldMarker) {
|
|
75
|
-
added.push(newMarker);
|
|
76
|
-
} else {
|
|
77
|
-
// We emit all existing markers as 'changed', but we only fire an event if something really did change.
|
|
78
|
-
// We also fire an event if oldMarker === newMarker, as we cannot actually detect a change in this case
|
|
79
|
-
// (https://github.com/eclipse-theia/theia/issues/12546).
|
|
80
|
-
didChangeMarkers ||= !!added.length || oldMarker === newMarker || !deepEqual(oldMarker, newMarker);
|
|
81
|
-
changed.push(newMarker);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
for (const [id, data] of oldMarkers.entries()) {
|
|
85
|
-
if (!ids.has(id)) {
|
|
86
|
-
removed.push(data);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (added.length || removed.length || didChangeMarkers) {
|
|
90
|
-
super.setMarkers(uri, owner, newMarkers);
|
|
91
|
-
this.onDidChangeBreakpointsEmitter.fire({ uri, added, removed, changed });
|
|
92
|
-
}
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
getLineBreakpoints(uri: URI, line: number): SourceBreakpoint[] {
|
|
97
|
-
return this.findMarkers({
|
|
98
|
-
uri,
|
|
99
|
-
dataFilter: breakpoint => breakpoint.raw.line === line
|
|
100
|
-
}).map(({ data }) => data);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
getInlineBreakpoint(uri: URI, line: number, column: number): SourceBreakpoint | undefined {
|
|
104
|
-
const marker = this.findMarkers({
|
|
105
|
-
uri,
|
|
106
|
-
dataFilter: breakpoint => breakpoint.raw.line === line && breakpoint.raw.column === column
|
|
107
|
-
})[0];
|
|
108
|
-
return marker && marker.data;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
getBreakpoints(uri?: URI): SourceBreakpoint[] {
|
|
112
|
-
return this.findMarkers({ uri }).map(marker => marker.data);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
setBreakpoints(uri: URI, breakpoints: SourceBreakpoint[]): void {
|
|
116
|
-
this.setMarkers(uri, this.owner, breakpoints.sort((a, b) => (a.raw.line - b.raw.line) || ((a.raw.column || 0) - (b.raw.column || 0))));
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
addBreakpoint(breakpoint: SourceBreakpoint): boolean {
|
|
120
|
-
const uri = new URI(breakpoint.uri);
|
|
121
|
-
const breakpoints = this.getBreakpoints(uri);
|
|
122
|
-
const newBreakpoints = breakpoints.filter(({ raw }) => !(raw.line === breakpoint.raw.line && raw.column === breakpoint.raw.column));
|
|
123
|
-
if (breakpoints.length === newBreakpoints.length) {
|
|
124
|
-
newBreakpoints.push(breakpoint);
|
|
125
|
-
this.setBreakpoints(uri, newBreakpoints);
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
enableAllBreakpoints(enabled: boolean): void {
|
|
132
|
-
for (const uriString of this.getUris()) {
|
|
133
|
-
let didChange = false;
|
|
134
|
-
const uri = new URI(uriString);
|
|
135
|
-
const markers = this.findMarkers({ uri });
|
|
136
|
-
for (const marker of markers) {
|
|
137
|
-
if (marker.data.enabled !== enabled) {
|
|
138
|
-
marker.data.enabled = enabled;
|
|
139
|
-
didChange = true;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (didChange) {
|
|
143
|
-
this.fireOnDidChangeMarkers(uri);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
let didChangeFunction = false;
|
|
147
|
-
for (const breakpoint of (this.getFunctionBreakpoints() as BaseBreakpoint[]).concat(this.getInstructionBreakpoints())) {
|
|
148
|
-
if (breakpoint.enabled !== enabled) {
|
|
149
|
-
breakpoint.enabled = enabled;
|
|
150
|
-
didChangeFunction = true;
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (didChangeFunction) {
|
|
155
|
-
this.fireOnDidChangeMarkers(BreakpointManager.FUNCTION_URI);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
protected _breakpointsEnabled = true;
|
|
160
|
-
get breakpointsEnabled(): boolean {
|
|
161
|
-
return this._breakpointsEnabled;
|
|
162
|
-
}
|
|
163
|
-
set breakpointsEnabled(breakpointsEnabled: boolean) {
|
|
164
|
-
if (this._breakpointsEnabled !== breakpointsEnabled) {
|
|
165
|
-
this._breakpointsEnabled = breakpointsEnabled;
|
|
166
|
-
for (const uri of this.getUris()) {
|
|
167
|
-
this.fireOnDidChangeMarkers(new URI(uri));
|
|
168
|
-
}
|
|
169
|
-
this.fireOnDidChangeMarkers(BreakpointManager.FUNCTION_URI);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
protected readonly exceptionBreakpoints = new Map<string, ExceptionBreakpoint>();
|
|
174
|
-
|
|
175
|
-
getExceptionBreakpoint(filter: string): ExceptionBreakpoint | undefined {
|
|
176
|
-
return this.exceptionBreakpoints.get(filter);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
getExceptionBreakpoints(): IterableIterator<ExceptionBreakpoint> {
|
|
180
|
-
return this.exceptionBreakpoints.values();
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
setExceptionBreakpoints(exceptionBreakpoints: ExceptionBreakpoint[]): void {
|
|
184
|
-
const toRemove = new Set(this.exceptionBreakpoints.keys());
|
|
185
|
-
for (const exceptionBreakpoint of exceptionBreakpoints) {
|
|
186
|
-
const filter = exceptionBreakpoint.raw.filter;
|
|
187
|
-
toRemove.delete(filter);
|
|
188
|
-
this.exceptionBreakpoints.set(filter, exceptionBreakpoint);
|
|
189
|
-
}
|
|
190
|
-
for (const filter of toRemove) {
|
|
191
|
-
this.exceptionBreakpoints.delete(filter);
|
|
192
|
-
}
|
|
193
|
-
if (toRemove.size || exceptionBreakpoints.length) {
|
|
194
|
-
this.fireOnDidChangeMarkers(BreakpointManager.EXCEPTION_URI);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
toggleExceptionBreakpoint(filter: string): void {
|
|
199
|
-
const breakpoint = this.getExceptionBreakpoint(filter);
|
|
200
|
-
if (breakpoint) {
|
|
201
|
-
breakpoint.enabled = !breakpoint.enabled;
|
|
202
|
-
this.fireOnDidChangeMarkers(BreakpointManager.EXCEPTION_URI);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
updateExceptionBreakpoint(filter: string, options: Partial<Pick<ExceptionBreakpoint, 'condition' | 'enabled'>>): void {
|
|
207
|
-
const breakpoint = this.getExceptionBreakpoint(filter);
|
|
208
|
-
if (breakpoint) {
|
|
209
|
-
Object.assign(breakpoint, options);
|
|
210
|
-
this.fireOnDidChangeMarkers(BreakpointManager.EXCEPTION_URI);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
protected functionBreakpoints: FunctionBreakpoint[] = [];
|
|
215
|
-
|
|
216
|
-
getFunctionBreakpoints(): FunctionBreakpoint[] {
|
|
217
|
-
return this.functionBreakpoints;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
setFunctionBreakpoints(functionBreakpoints: FunctionBreakpoint[]): void {
|
|
221
|
-
const oldBreakpoints = new Map(this.functionBreakpoints.map(b => [b.id, b] as [string, FunctionBreakpoint]));
|
|
222
|
-
|
|
223
|
-
this.functionBreakpoints = functionBreakpoints;
|
|
224
|
-
this.fireOnDidChangeMarkers(BreakpointManager.FUNCTION_URI);
|
|
225
|
-
|
|
226
|
-
const added: FunctionBreakpoint[] = [];
|
|
227
|
-
const removed: FunctionBreakpoint[] = [];
|
|
228
|
-
const changed: FunctionBreakpoint[] = [];
|
|
229
|
-
const ids = new Set<string>();
|
|
230
|
-
for (const newBreakpoint of functionBreakpoints) {
|
|
231
|
-
ids.add(newBreakpoint.id);
|
|
232
|
-
if (oldBreakpoints.has(newBreakpoint.id)) {
|
|
233
|
-
changed.push(newBreakpoint);
|
|
234
|
-
} else {
|
|
235
|
-
added.push(newBreakpoint);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
for (const [id, breakpoint] of oldBreakpoints.entries()) {
|
|
239
|
-
if (!ids.has(id)) {
|
|
240
|
-
removed.push(breakpoint);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
this.onDidChangeFunctionBreakpointsEmitter.fire({ uri: BreakpointManager.FUNCTION_URI, added, removed, changed });
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
protected instructionBreakpoints: InstructionBreakpoint[] = [];
|
|
247
|
-
|
|
248
|
-
getInstructionBreakpoints(): ReadonlyArray<InstructionBreakpoint> {
|
|
249
|
-
return Object.freeze(this.instructionBreakpoints.slice());
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
hasBreakpoints(): boolean {
|
|
253
|
-
return Boolean(this.getUris().next().value || this.functionBreakpoints.length || this.instructionBreakpoints.length);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
protected setInstructionBreakpoints(newBreakpoints: InstructionBreakpoint[]): void {
|
|
257
|
-
const oldBreakpoints = new Map(this.instructionBreakpoints.map(breakpoint => [breakpoint.id, breakpoint]));
|
|
258
|
-
const currentBreakpoints = new Map(newBreakpoints.map(breakpoint => [breakpoint.id, breakpoint]));
|
|
259
|
-
const added = [];
|
|
260
|
-
const changed = [];
|
|
261
|
-
for (const [id, breakpoint] of currentBreakpoints.entries()) {
|
|
262
|
-
const old = oldBreakpoints.get(id);
|
|
263
|
-
if (old) {
|
|
264
|
-
changed.push(old);
|
|
265
|
-
} else {
|
|
266
|
-
added.push(breakpoint);
|
|
267
|
-
}
|
|
268
|
-
oldBreakpoints.delete(id);
|
|
269
|
-
}
|
|
270
|
-
const removed = Array.from(oldBreakpoints.values());
|
|
271
|
-
this.instructionBreakpoints = Array.from(currentBreakpoints.values());
|
|
272
|
-
this.fireOnDidChangeMarkers(BreakpointManager.INSTRUCTION_URI);
|
|
273
|
-
this.onDidChangeInstructionBreakpointsEmitter.fire({ uri: BreakpointManager.INSTRUCTION_URI, added, removed, changed });
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
addInstructionBreakpoint(address: string, offset: number, condition?: string, hitCondition?: string): void {
|
|
277
|
-
this.setInstructionBreakpoints(this.instructionBreakpoints.concat(InstructionBreakpoint.create({
|
|
278
|
-
instructionReference: address,
|
|
279
|
-
offset,
|
|
280
|
-
condition,
|
|
281
|
-
hitCondition,
|
|
282
|
-
})));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
updateInstructionBreakpoint(id: string, options: Partial<Pick<InstructionBreakpoint, 'condition' | 'hitCondition' | 'enabled'>>): void {
|
|
286
|
-
const breakpoint = this.instructionBreakpoints.find(candidate => id === candidate.id);
|
|
287
|
-
if (breakpoint) {
|
|
288
|
-
Object.assign(breakpoint, options);
|
|
289
|
-
this.fireOnDidChangeMarkers(BreakpointManager.INSTRUCTION_URI);
|
|
290
|
-
this.onDidChangeInstructionBreakpointsEmitter.fire({ uri: BreakpointManager.INSTRUCTION_URI, changed: [breakpoint], added: [], removed: [] });
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
removeInstructionBreakpoint(address?: string): void {
|
|
295
|
-
if (!address) {
|
|
296
|
-
this.clearInstructionBreakpoints();
|
|
297
|
-
}
|
|
298
|
-
const breakpointIndex = this.instructionBreakpoints.findIndex(breakpoint => breakpoint.instructionReference === address);
|
|
299
|
-
if (breakpointIndex !== -1) {
|
|
300
|
-
const removed = this.instructionBreakpoints.splice(breakpointIndex, 1);
|
|
301
|
-
this.fireOnDidChangeMarkers(BreakpointManager.INSTRUCTION_URI);
|
|
302
|
-
this.onDidChangeInstructionBreakpointsEmitter.fire({ uri: BreakpointManager.INSTRUCTION_URI, added: [], changed: [], removed });
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
clearInstructionBreakpoints(): void {
|
|
307
|
-
this.setInstructionBreakpoints([]);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
removeBreakpoints(): void {
|
|
311
|
-
this.cleanAllMarkers();
|
|
312
|
-
this.setFunctionBreakpoints([]);
|
|
313
|
-
this.setInstructionBreakpoints([]);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
async load(): Promise<void> {
|
|
317
|
-
const data = await this.storage.getData<BreakpointManager.Data>('breakpoints', {
|
|
318
|
-
breakpointsEnabled: true,
|
|
319
|
-
breakpoints: {}
|
|
320
|
-
});
|
|
321
|
-
this._breakpointsEnabled = data.breakpointsEnabled;
|
|
322
|
-
// eslint-disable-next-line guard-for-in
|
|
323
|
-
for (const uri in data.breakpoints) {
|
|
324
|
-
this.setBreakpoints(new URI(uri), data.breakpoints[uri]);
|
|
325
|
-
}
|
|
326
|
-
if (data.functionBreakpoints) {
|
|
327
|
-
this.setFunctionBreakpoints(data.functionBreakpoints);
|
|
328
|
-
}
|
|
329
|
-
if (data.exceptionBreakpoints) {
|
|
330
|
-
this.setExceptionBreakpoints(data.exceptionBreakpoints);
|
|
331
|
-
}
|
|
332
|
-
if (data.instructionBreakpoints) {
|
|
333
|
-
this.setInstructionBreakpoints(data.instructionBreakpoints);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
save(): void {
|
|
338
|
-
const data: BreakpointManager.Data = {
|
|
339
|
-
breakpointsEnabled: this._breakpointsEnabled,
|
|
340
|
-
breakpoints: {}
|
|
341
|
-
};
|
|
342
|
-
const uris = this.getUris();
|
|
343
|
-
for (const uri of uris) {
|
|
344
|
-
data.breakpoints[uri] = this.findMarkers({ uri: new URI(uri) }).map(marker => marker.data);
|
|
345
|
-
}
|
|
346
|
-
if (this.functionBreakpoints.length) {
|
|
347
|
-
data.functionBreakpoints = this.functionBreakpoints;
|
|
348
|
-
}
|
|
349
|
-
if (this.exceptionBreakpoints.size) {
|
|
350
|
-
data.exceptionBreakpoints = [...this.exceptionBreakpoints.values()];
|
|
351
|
-
}
|
|
352
|
-
if (this.instructionBreakpoints.length) {
|
|
353
|
-
data.instructionBreakpoints = this.instructionBreakpoints;
|
|
354
|
-
}
|
|
355
|
-
this.storage.setData('breakpoints', data);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
export namespace BreakpointManager {
|
|
360
|
-
export interface Data {
|
|
361
|
-
breakpointsEnabled: boolean;
|
|
362
|
-
breakpoints: {
|
|
363
|
-
[uri: string]: SourceBreakpoint[];
|
|
364
|
-
}
|
|
365
|
-
exceptionBreakpoints?: ExceptionBreakpoint[];
|
|
366
|
-
functionBreakpoints?: FunctionBreakpoint[];
|
|
367
|
-
instructionBreakpoints?: InstructionBreakpoint[];
|
|
368
|
-
}
|
|
369
|
-
}
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import * as deepEqual from 'fast-deep-equal';
|
|
18
|
+
import { injectable, inject } from '@theia/core/shared/inversify';
|
|
19
|
+
import { Emitter } from '@theia/core/lib/common';
|
|
20
|
+
import { StorageService } from '@theia/core/lib/browser';
|
|
21
|
+
import { Marker } from '@theia/markers/lib/common/marker';
|
|
22
|
+
import { MarkerManager } from '@theia/markers/lib/browser/marker-manager';
|
|
23
|
+
import URI from '@theia/core/lib/common/uri';
|
|
24
|
+
import { SourceBreakpoint, BREAKPOINT_KIND, ExceptionBreakpoint, FunctionBreakpoint, BaseBreakpoint, InstructionBreakpoint } from './breakpoint-marker';
|
|
25
|
+
|
|
26
|
+
export interface BreakpointsChangeEvent<T extends BaseBreakpoint> {
|
|
27
|
+
uri: URI
|
|
28
|
+
added: T[]
|
|
29
|
+
removed: T[]
|
|
30
|
+
changed: T[]
|
|
31
|
+
}
|
|
32
|
+
export type SourceBreakpointsChangeEvent = BreakpointsChangeEvent<SourceBreakpoint>;
|
|
33
|
+
export type FunctionBreakpointsChangeEvent = BreakpointsChangeEvent<FunctionBreakpoint>;
|
|
34
|
+
export type InstructionBreakpointsChangeEvent = BreakpointsChangeEvent<InstructionBreakpoint>;
|
|
35
|
+
|
|
36
|
+
@injectable()
|
|
37
|
+
export class BreakpointManager extends MarkerManager<SourceBreakpoint> {
|
|
38
|
+
|
|
39
|
+
static EXCEPTION_URI = new URI('debug:exception://');
|
|
40
|
+
|
|
41
|
+
static FUNCTION_URI = new URI('debug:function://');
|
|
42
|
+
|
|
43
|
+
static INSTRUCTION_URI = new URI('debug:instruction://');
|
|
44
|
+
|
|
45
|
+
protected readonly owner = 'breakpoint';
|
|
46
|
+
|
|
47
|
+
@inject(StorageService)
|
|
48
|
+
protected readonly storage: StorageService;
|
|
49
|
+
|
|
50
|
+
getKind(): string {
|
|
51
|
+
return BREAKPOINT_KIND;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected readonly onDidChangeBreakpointsEmitter = new Emitter<SourceBreakpointsChangeEvent>();
|
|
55
|
+
readonly onDidChangeBreakpoints = this.onDidChangeBreakpointsEmitter.event;
|
|
56
|
+
|
|
57
|
+
protected readonly onDidChangeFunctionBreakpointsEmitter = new Emitter<FunctionBreakpointsChangeEvent>();
|
|
58
|
+
readonly onDidChangeFunctionBreakpoints = this.onDidChangeFunctionBreakpointsEmitter.event;
|
|
59
|
+
|
|
60
|
+
protected readonly onDidChangeInstructionBreakpointsEmitter = new Emitter<InstructionBreakpointsChangeEvent>();
|
|
61
|
+
readonly onDidChangeInstructionBreakpoints = this.onDidChangeInstructionBreakpointsEmitter.event;
|
|
62
|
+
|
|
63
|
+
override setMarkers(uri: URI, owner: string, newMarkers: SourceBreakpoint[]): Marker<SourceBreakpoint>[] {
|
|
64
|
+
const result = this.findMarkers({ uri, owner });
|
|
65
|
+
const added: SourceBreakpoint[] = [];
|
|
66
|
+
const removed: SourceBreakpoint[] = [];
|
|
67
|
+
const changed: SourceBreakpoint[] = [];
|
|
68
|
+
const oldMarkers = new Map(result.map(({ data }) => [data.id, data]));
|
|
69
|
+
const ids = new Set<string>();
|
|
70
|
+
let didChangeMarkers = false;
|
|
71
|
+
for (const newMarker of newMarkers) {
|
|
72
|
+
ids.add(newMarker.id);
|
|
73
|
+
const oldMarker = oldMarkers.get(newMarker.id);
|
|
74
|
+
if (!oldMarker) {
|
|
75
|
+
added.push(newMarker);
|
|
76
|
+
} else {
|
|
77
|
+
// We emit all existing markers as 'changed', but we only fire an event if something really did change.
|
|
78
|
+
// We also fire an event if oldMarker === newMarker, as we cannot actually detect a change in this case
|
|
79
|
+
// (https://github.com/eclipse-theia/theia/issues/12546).
|
|
80
|
+
didChangeMarkers ||= !!added.length || oldMarker === newMarker || !deepEqual(oldMarker, newMarker);
|
|
81
|
+
changed.push(newMarker);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
for (const [id, data] of oldMarkers.entries()) {
|
|
85
|
+
if (!ids.has(id)) {
|
|
86
|
+
removed.push(data);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (added.length || removed.length || didChangeMarkers) {
|
|
90
|
+
super.setMarkers(uri, owner, newMarkers);
|
|
91
|
+
this.onDidChangeBreakpointsEmitter.fire({ uri, added, removed, changed });
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getLineBreakpoints(uri: URI, line: number): SourceBreakpoint[] {
|
|
97
|
+
return this.findMarkers({
|
|
98
|
+
uri,
|
|
99
|
+
dataFilter: breakpoint => breakpoint.raw.line === line
|
|
100
|
+
}).map(({ data }) => data);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getInlineBreakpoint(uri: URI, line: number, column: number): SourceBreakpoint | undefined {
|
|
104
|
+
const marker = this.findMarkers({
|
|
105
|
+
uri,
|
|
106
|
+
dataFilter: breakpoint => breakpoint.raw.line === line && breakpoint.raw.column === column
|
|
107
|
+
})[0];
|
|
108
|
+
return marker && marker.data;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getBreakpoints(uri?: URI): SourceBreakpoint[] {
|
|
112
|
+
return this.findMarkers({ uri }).map(marker => marker.data);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
setBreakpoints(uri: URI, breakpoints: SourceBreakpoint[]): void {
|
|
116
|
+
this.setMarkers(uri, this.owner, breakpoints.sort((a, b) => (a.raw.line - b.raw.line) || ((a.raw.column || 0) - (b.raw.column || 0))));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
addBreakpoint(breakpoint: SourceBreakpoint): boolean {
|
|
120
|
+
const uri = new URI(breakpoint.uri);
|
|
121
|
+
const breakpoints = this.getBreakpoints(uri);
|
|
122
|
+
const newBreakpoints = breakpoints.filter(({ raw }) => !(raw.line === breakpoint.raw.line && raw.column === breakpoint.raw.column));
|
|
123
|
+
if (breakpoints.length === newBreakpoints.length) {
|
|
124
|
+
newBreakpoints.push(breakpoint);
|
|
125
|
+
this.setBreakpoints(uri, newBreakpoints);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
enableAllBreakpoints(enabled: boolean): void {
|
|
132
|
+
for (const uriString of this.getUris()) {
|
|
133
|
+
let didChange = false;
|
|
134
|
+
const uri = new URI(uriString);
|
|
135
|
+
const markers = this.findMarkers({ uri });
|
|
136
|
+
for (const marker of markers) {
|
|
137
|
+
if (marker.data.enabled !== enabled) {
|
|
138
|
+
marker.data.enabled = enabled;
|
|
139
|
+
didChange = true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (didChange) {
|
|
143
|
+
this.fireOnDidChangeMarkers(uri);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
let didChangeFunction = false;
|
|
147
|
+
for (const breakpoint of (this.getFunctionBreakpoints() as BaseBreakpoint[]).concat(this.getInstructionBreakpoints())) {
|
|
148
|
+
if (breakpoint.enabled !== enabled) {
|
|
149
|
+
breakpoint.enabled = enabled;
|
|
150
|
+
didChangeFunction = true;
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (didChangeFunction) {
|
|
155
|
+
this.fireOnDidChangeMarkers(BreakpointManager.FUNCTION_URI);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
protected _breakpointsEnabled = true;
|
|
160
|
+
get breakpointsEnabled(): boolean {
|
|
161
|
+
return this._breakpointsEnabled;
|
|
162
|
+
}
|
|
163
|
+
set breakpointsEnabled(breakpointsEnabled: boolean) {
|
|
164
|
+
if (this._breakpointsEnabled !== breakpointsEnabled) {
|
|
165
|
+
this._breakpointsEnabled = breakpointsEnabled;
|
|
166
|
+
for (const uri of this.getUris()) {
|
|
167
|
+
this.fireOnDidChangeMarkers(new URI(uri));
|
|
168
|
+
}
|
|
169
|
+
this.fireOnDidChangeMarkers(BreakpointManager.FUNCTION_URI);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
protected readonly exceptionBreakpoints = new Map<string, ExceptionBreakpoint>();
|
|
174
|
+
|
|
175
|
+
getExceptionBreakpoint(filter: string): ExceptionBreakpoint | undefined {
|
|
176
|
+
return this.exceptionBreakpoints.get(filter);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getExceptionBreakpoints(): IterableIterator<ExceptionBreakpoint> {
|
|
180
|
+
return this.exceptionBreakpoints.values();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
setExceptionBreakpoints(exceptionBreakpoints: ExceptionBreakpoint[]): void {
|
|
184
|
+
const toRemove = new Set(this.exceptionBreakpoints.keys());
|
|
185
|
+
for (const exceptionBreakpoint of exceptionBreakpoints) {
|
|
186
|
+
const filter = exceptionBreakpoint.raw.filter;
|
|
187
|
+
toRemove.delete(filter);
|
|
188
|
+
this.exceptionBreakpoints.set(filter, exceptionBreakpoint);
|
|
189
|
+
}
|
|
190
|
+
for (const filter of toRemove) {
|
|
191
|
+
this.exceptionBreakpoints.delete(filter);
|
|
192
|
+
}
|
|
193
|
+
if (toRemove.size || exceptionBreakpoints.length) {
|
|
194
|
+
this.fireOnDidChangeMarkers(BreakpointManager.EXCEPTION_URI);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
toggleExceptionBreakpoint(filter: string): void {
|
|
199
|
+
const breakpoint = this.getExceptionBreakpoint(filter);
|
|
200
|
+
if (breakpoint) {
|
|
201
|
+
breakpoint.enabled = !breakpoint.enabled;
|
|
202
|
+
this.fireOnDidChangeMarkers(BreakpointManager.EXCEPTION_URI);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
updateExceptionBreakpoint(filter: string, options: Partial<Pick<ExceptionBreakpoint, 'condition' | 'enabled'>>): void {
|
|
207
|
+
const breakpoint = this.getExceptionBreakpoint(filter);
|
|
208
|
+
if (breakpoint) {
|
|
209
|
+
Object.assign(breakpoint, options);
|
|
210
|
+
this.fireOnDidChangeMarkers(BreakpointManager.EXCEPTION_URI);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
protected functionBreakpoints: FunctionBreakpoint[] = [];
|
|
215
|
+
|
|
216
|
+
getFunctionBreakpoints(): FunctionBreakpoint[] {
|
|
217
|
+
return this.functionBreakpoints;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
setFunctionBreakpoints(functionBreakpoints: FunctionBreakpoint[]): void {
|
|
221
|
+
const oldBreakpoints = new Map(this.functionBreakpoints.map(b => [b.id, b] as [string, FunctionBreakpoint]));
|
|
222
|
+
|
|
223
|
+
this.functionBreakpoints = functionBreakpoints;
|
|
224
|
+
this.fireOnDidChangeMarkers(BreakpointManager.FUNCTION_URI);
|
|
225
|
+
|
|
226
|
+
const added: FunctionBreakpoint[] = [];
|
|
227
|
+
const removed: FunctionBreakpoint[] = [];
|
|
228
|
+
const changed: FunctionBreakpoint[] = [];
|
|
229
|
+
const ids = new Set<string>();
|
|
230
|
+
for (const newBreakpoint of functionBreakpoints) {
|
|
231
|
+
ids.add(newBreakpoint.id);
|
|
232
|
+
if (oldBreakpoints.has(newBreakpoint.id)) {
|
|
233
|
+
changed.push(newBreakpoint);
|
|
234
|
+
} else {
|
|
235
|
+
added.push(newBreakpoint);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const [id, breakpoint] of oldBreakpoints.entries()) {
|
|
239
|
+
if (!ids.has(id)) {
|
|
240
|
+
removed.push(breakpoint);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
this.onDidChangeFunctionBreakpointsEmitter.fire({ uri: BreakpointManager.FUNCTION_URI, added, removed, changed });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
protected instructionBreakpoints: InstructionBreakpoint[] = [];
|
|
247
|
+
|
|
248
|
+
getInstructionBreakpoints(): ReadonlyArray<InstructionBreakpoint> {
|
|
249
|
+
return Object.freeze(this.instructionBreakpoints.slice());
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
hasBreakpoints(): boolean {
|
|
253
|
+
return Boolean(this.getUris().next().value || this.functionBreakpoints.length || this.instructionBreakpoints.length);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
protected setInstructionBreakpoints(newBreakpoints: InstructionBreakpoint[]): void {
|
|
257
|
+
const oldBreakpoints = new Map(this.instructionBreakpoints.map(breakpoint => [breakpoint.id, breakpoint]));
|
|
258
|
+
const currentBreakpoints = new Map(newBreakpoints.map(breakpoint => [breakpoint.id, breakpoint]));
|
|
259
|
+
const added = [];
|
|
260
|
+
const changed = [];
|
|
261
|
+
for (const [id, breakpoint] of currentBreakpoints.entries()) {
|
|
262
|
+
const old = oldBreakpoints.get(id);
|
|
263
|
+
if (old) {
|
|
264
|
+
changed.push(old);
|
|
265
|
+
} else {
|
|
266
|
+
added.push(breakpoint);
|
|
267
|
+
}
|
|
268
|
+
oldBreakpoints.delete(id);
|
|
269
|
+
}
|
|
270
|
+
const removed = Array.from(oldBreakpoints.values());
|
|
271
|
+
this.instructionBreakpoints = Array.from(currentBreakpoints.values());
|
|
272
|
+
this.fireOnDidChangeMarkers(BreakpointManager.INSTRUCTION_URI);
|
|
273
|
+
this.onDidChangeInstructionBreakpointsEmitter.fire({ uri: BreakpointManager.INSTRUCTION_URI, added, removed, changed });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
addInstructionBreakpoint(address: string, offset: number, condition?: string, hitCondition?: string): void {
|
|
277
|
+
this.setInstructionBreakpoints(this.instructionBreakpoints.concat(InstructionBreakpoint.create({
|
|
278
|
+
instructionReference: address,
|
|
279
|
+
offset,
|
|
280
|
+
condition,
|
|
281
|
+
hitCondition,
|
|
282
|
+
})));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
updateInstructionBreakpoint(id: string, options: Partial<Pick<InstructionBreakpoint, 'condition' | 'hitCondition' | 'enabled'>>): void {
|
|
286
|
+
const breakpoint = this.instructionBreakpoints.find(candidate => id === candidate.id);
|
|
287
|
+
if (breakpoint) {
|
|
288
|
+
Object.assign(breakpoint, options);
|
|
289
|
+
this.fireOnDidChangeMarkers(BreakpointManager.INSTRUCTION_URI);
|
|
290
|
+
this.onDidChangeInstructionBreakpointsEmitter.fire({ uri: BreakpointManager.INSTRUCTION_URI, changed: [breakpoint], added: [], removed: [] });
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
removeInstructionBreakpoint(address?: string): void {
|
|
295
|
+
if (!address) {
|
|
296
|
+
this.clearInstructionBreakpoints();
|
|
297
|
+
}
|
|
298
|
+
const breakpointIndex = this.instructionBreakpoints.findIndex(breakpoint => breakpoint.instructionReference === address);
|
|
299
|
+
if (breakpointIndex !== -1) {
|
|
300
|
+
const removed = this.instructionBreakpoints.splice(breakpointIndex, 1);
|
|
301
|
+
this.fireOnDidChangeMarkers(BreakpointManager.INSTRUCTION_URI);
|
|
302
|
+
this.onDidChangeInstructionBreakpointsEmitter.fire({ uri: BreakpointManager.INSTRUCTION_URI, added: [], changed: [], removed });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
clearInstructionBreakpoints(): void {
|
|
307
|
+
this.setInstructionBreakpoints([]);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
removeBreakpoints(): void {
|
|
311
|
+
this.cleanAllMarkers();
|
|
312
|
+
this.setFunctionBreakpoints([]);
|
|
313
|
+
this.setInstructionBreakpoints([]);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async load(): Promise<void> {
|
|
317
|
+
const data = await this.storage.getData<BreakpointManager.Data>('breakpoints', {
|
|
318
|
+
breakpointsEnabled: true,
|
|
319
|
+
breakpoints: {}
|
|
320
|
+
});
|
|
321
|
+
this._breakpointsEnabled = data.breakpointsEnabled;
|
|
322
|
+
// eslint-disable-next-line guard-for-in
|
|
323
|
+
for (const uri in data.breakpoints) {
|
|
324
|
+
this.setBreakpoints(new URI(uri), data.breakpoints[uri]);
|
|
325
|
+
}
|
|
326
|
+
if (data.functionBreakpoints) {
|
|
327
|
+
this.setFunctionBreakpoints(data.functionBreakpoints);
|
|
328
|
+
}
|
|
329
|
+
if (data.exceptionBreakpoints) {
|
|
330
|
+
this.setExceptionBreakpoints(data.exceptionBreakpoints);
|
|
331
|
+
}
|
|
332
|
+
if (data.instructionBreakpoints) {
|
|
333
|
+
this.setInstructionBreakpoints(data.instructionBreakpoints);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
save(): void {
|
|
338
|
+
const data: BreakpointManager.Data = {
|
|
339
|
+
breakpointsEnabled: this._breakpointsEnabled,
|
|
340
|
+
breakpoints: {}
|
|
341
|
+
};
|
|
342
|
+
const uris = this.getUris();
|
|
343
|
+
for (const uri of uris) {
|
|
344
|
+
data.breakpoints[uri] = this.findMarkers({ uri: new URI(uri) }).map(marker => marker.data);
|
|
345
|
+
}
|
|
346
|
+
if (this.functionBreakpoints.length) {
|
|
347
|
+
data.functionBreakpoints = this.functionBreakpoints;
|
|
348
|
+
}
|
|
349
|
+
if (this.exceptionBreakpoints.size) {
|
|
350
|
+
data.exceptionBreakpoints = [...this.exceptionBreakpoints.values()];
|
|
351
|
+
}
|
|
352
|
+
if (this.instructionBreakpoints.length) {
|
|
353
|
+
data.instructionBreakpoints = this.instructionBreakpoints;
|
|
354
|
+
}
|
|
355
|
+
this.storage.setData('breakpoints', data);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
}
|
|
359
|
+
export namespace BreakpointManager {
|
|
360
|
+
export interface Data {
|
|
361
|
+
breakpointsEnabled: boolean;
|
|
362
|
+
breakpoints: {
|
|
363
|
+
[uri: string]: SourceBreakpoint[];
|
|
364
|
+
}
|
|
365
|
+
exceptionBreakpoints?: ExceptionBreakpoint[];
|
|
366
|
+
functionBreakpoints?: FunctionBreakpoint[];
|
|
367
|
+
instructionBreakpoints?: InstructionBreakpoint[];
|
|
368
|
+
}
|
|
369
|
+
}
|