@theia/debug 1.27.0-next.7 → 1.27.0-next.8
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/console/debug-console-contribution.js +2 -2
- package/lib/browser/console/debug-console-contribution.js.map +1 -1
- package/lib/browser/debug-configuration-manager.d.ts +21 -5
- package/lib/browser/debug-configuration-manager.d.ts.map +1 -1
- package/lib/browser/debug-configuration-manager.js +81 -11
- package/lib/browser/debug-configuration-manager.js.map +1 -1
- package/lib/browser/debug-prefix-configuration.d.ts +2 -7
- package/lib/browser/debug-prefix-configuration.d.ts.map +1 -1
- package/lib/browser/debug-prefix-configuration.js +6 -13
- package/lib/browser/debug-prefix-configuration.js.map +1 -1
- package/lib/browser/debug-session-options.d.ts +9 -2
- package/lib/browser/debug-session-options.d.ts.map +1 -1
- package/lib/browser/debug-session-options.js +18 -1
- package/lib/browser/debug-session-options.js.map +1 -1
- package/lib/browser/editor/debug-breakpoint-widget.js +1 -1
- package/lib/browser/editor/debug-breakpoint-widget.js.map +1 -1
- package/lib/browser/view/debug-configuration-select.d.ts +59 -0
- package/lib/browser/view/debug-configuration-select.d.ts.map +1 -0
- package/lib/browser/view/debug-configuration-select.js +183 -0
- package/lib/browser/view/debug-configuration-select.js.map +1 -0
- package/lib/browser/view/debug-configuration-widget.d.ts +5 -10
- package/lib/browser/view/debug-configuration-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-configuration-widget.js +21 -54
- package/lib/browser/view/debug-configuration-widget.js.map +1 -1
- package/lib/common/debug-configuration.d.ts +0 -2
- package/lib/common/debug-configuration.d.ts.map +1 -1
- package/lib/common/debug-configuration.js.map +1 -1
- package/lib/common/debug-service.d.ts +10 -1
- package/lib/common/debug-service.d.ts.map +1 -1
- package/lib/common/debug-service.js.map +1 -1
- package/lib/node/debug-service-impl.d.ts +4 -0
- package/lib/node/debug-service-impl.d.ts.map +1 -1
- package/lib/node/debug-service-impl.js +12 -0
- package/lib/node/debug-service-impl.js.map +1 -1
- package/package.json +14 -14
- package/src/browser/console/debug-console-contribution.tsx +2 -2
- package/src/browser/debug-configuration-manager.ts +111 -16
- package/src/browser/debug-prefix-configuration.ts +6 -14
- package/src/browser/debug-session-options.ts +30 -3
- package/src/browser/editor/debug-breakpoint-widget.tsx +1 -1
- package/src/browser/view/debug-configuration-select.tsx +234 -0
- package/src/browser/view/debug-configuration-widget.tsx +24 -55
- package/src/common/debug-configuration.ts +0 -3
- package/src/common/debug-service.ts +12 -1
- package/src/node/debug-service-impl.ts +13 -1
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/debug",
|
|
3
|
-
"version": "1.27.0-next.
|
|
3
|
+
"version": "1.27.0-next.8+e1e200a7bfb",
|
|
4
4
|
"description": "Theia - Debug Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/console": "1.27.0-next.
|
|
7
|
-
"@theia/core": "1.27.0-next.
|
|
8
|
-
"@theia/editor": "1.27.0-next.
|
|
9
|
-
"@theia/filesystem": "1.27.0-next.
|
|
10
|
-
"@theia/markers": "1.27.0-next.
|
|
11
|
-
"@theia/monaco": "1.27.0-next.
|
|
6
|
+
"@theia/console": "1.27.0-next.8+e1e200a7bfb",
|
|
7
|
+
"@theia/core": "1.27.0-next.8+e1e200a7bfb",
|
|
8
|
+
"@theia/editor": "1.27.0-next.8+e1e200a7bfb",
|
|
9
|
+
"@theia/filesystem": "1.27.0-next.8+e1e200a7bfb",
|
|
10
|
+
"@theia/markers": "1.27.0-next.8+e1e200a7bfb",
|
|
11
|
+
"@theia/monaco": "1.27.0-next.8+e1e200a7bfb",
|
|
12
12
|
"@theia/monaco-editor-core": "1.65.2",
|
|
13
|
-
"@theia/output": "1.27.0-next.
|
|
14
|
-
"@theia/process": "1.27.0-next.
|
|
15
|
-
"@theia/task": "1.27.0-next.
|
|
16
|
-
"@theia/terminal": "1.27.0-next.
|
|
17
|
-
"@theia/variable-resolver": "1.27.0-next.
|
|
18
|
-
"@theia/workspace": "1.27.0-next.
|
|
13
|
+
"@theia/output": "1.27.0-next.8+e1e200a7bfb",
|
|
14
|
+
"@theia/process": "1.27.0-next.8+e1e200a7bfb",
|
|
15
|
+
"@theia/task": "1.27.0-next.8+e1e200a7bfb",
|
|
16
|
+
"@theia/terminal": "1.27.0-next.8+e1e200a7bfb",
|
|
17
|
+
"@theia/variable-resolver": "1.27.0-next.8+e1e200a7bfb",
|
|
18
|
+
"@theia/workspace": "1.27.0-next.8+e1e200a7bfb",
|
|
19
19
|
"jsonc-parser": "^2.2.0",
|
|
20
20
|
"mkdirp": "^0.5.0",
|
|
21
21
|
"p-debounce": "^2.1.0",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"nyc": {
|
|
69
69
|
"extends": "../../configs/nyc.json"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "e1e200a7bfb9c7b9b87bf63dd8e101e734281222"
|
|
72
72
|
}
|
|
@@ -189,7 +189,7 @@ export class DebugConsoleContribution extends AbstractViewContribution<ConsoleWi
|
|
|
189
189
|
return <SelectComponent
|
|
190
190
|
key="debugConsoleSeverity"
|
|
191
191
|
options={severityElements}
|
|
192
|
-
|
|
192
|
+
defaultValue={this.consoleSessionManager.severity || Severity.Ignore}
|
|
193
193
|
onChange={this.changeSeverity} />;
|
|
194
194
|
}
|
|
195
195
|
|
|
@@ -207,7 +207,7 @@ export class DebugConsoleContribution extends AbstractViewContribution<ConsoleWi
|
|
|
207
207
|
return <SelectComponent
|
|
208
208
|
key="debugConsoleSelector"
|
|
209
209
|
options={availableConsoles}
|
|
210
|
-
|
|
210
|
+
defaultValue={0}
|
|
211
211
|
onChange={this.changeDebugConsole} />;
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -86,10 +86,16 @@ export class DebugConfigurationManager {
|
|
|
86
86
|
return this.onWillProvideDynamicDebugConfigurationEmitter.event;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
get onDidChangeConfigurationProviders(): Event<void> {
|
|
90
|
+
return this.debug.onDidChangeDebugConfigurationProviders;
|
|
91
|
+
}
|
|
92
|
+
|
|
89
93
|
protected debugConfigurationTypeKey: ContextKey<string>;
|
|
90
94
|
|
|
91
95
|
protected initialized: Promise<void>;
|
|
92
96
|
|
|
97
|
+
protected recentDynamicOptionsTracker: DebugSessionOptions[] = [];
|
|
98
|
+
|
|
93
99
|
@postConstruct()
|
|
94
100
|
protected async init(): Promise<void> {
|
|
95
101
|
this.debugConfigurationTypeKey = this.contextKeyService.createKey<string>('debugConfigurationType', undefined);
|
|
@@ -126,6 +132,9 @@ export class DebugConfigurationManager {
|
|
|
126
132
|
this.updateCurrent();
|
|
127
133
|
}, 500);
|
|
128
134
|
|
|
135
|
+
/**
|
|
136
|
+
* All _non-dynamic_ debug configurations.
|
|
137
|
+
*/
|
|
129
138
|
get all(): IterableIterator<DebugSessionOptions> {
|
|
130
139
|
return this.getAll();
|
|
131
140
|
}
|
|
@@ -160,11 +169,61 @@ export class DebugConfigurationManager {
|
|
|
160
169
|
get current(): DebugSessionOptions | undefined {
|
|
161
170
|
return this._currentOptions;
|
|
162
171
|
}
|
|
172
|
+
|
|
173
|
+
async getSelectedConfiguration(): Promise<DebugSessionOptions | undefined> {
|
|
174
|
+
// providerType applies to dynamic configurations only
|
|
175
|
+
if (!this._currentOptions?.providerType) {
|
|
176
|
+
return this._currentOptions;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Refresh a dynamic configuration from the provider.
|
|
180
|
+
// This allow providers to update properties before the execution e.g. program
|
|
181
|
+
const { providerType, configuration: { name } } = this._currentOptions;
|
|
182
|
+
const configuration = await this.fetchDynamicDebugConfiguration(name, providerType);
|
|
183
|
+
|
|
184
|
+
if (!configuration) {
|
|
185
|
+
const message = nls.localize(
|
|
186
|
+
'theia/debug/missingConfiguration',
|
|
187
|
+
"Dynamic configuration '{0}:{1}' is missing or not applicable", providerType, name);
|
|
188
|
+
throw new Error(message);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return { configuration, providerType };
|
|
192
|
+
}
|
|
193
|
+
|
|
163
194
|
set current(option: DebugSessionOptions | undefined) {
|
|
164
195
|
this.updateCurrent(option);
|
|
196
|
+
this.updateRecentlyUsedDynamicConfigurationOptions(option);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
protected updateRecentlyUsedDynamicConfigurationOptions(option: DebugSessionOptions | undefined): void {
|
|
200
|
+
if (option?.providerType) { // if it's a dynamic configuration option
|
|
201
|
+
// Removing an item already present in the list
|
|
202
|
+
const index = this.recentDynamicOptionsTracker.findIndex(item => this.dynamicOptionsMatch(item, option));
|
|
203
|
+
if (index > -1) {
|
|
204
|
+
this.recentDynamicOptionsTracker.splice(index, 1);
|
|
205
|
+
}
|
|
206
|
+
// Adding new item, most recent at the top of the list
|
|
207
|
+
const recentMax = 3;
|
|
208
|
+
if (this.recentDynamicOptionsTracker.unshift(option) > recentMax) {
|
|
209
|
+
// Keep the latest 3 dynamic configuration options to not clutter the dropdown.
|
|
210
|
+
this.recentDynamicOptionsTracker.splice(recentMax);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
165
213
|
}
|
|
214
|
+
|
|
215
|
+
protected dynamicOptionsMatch(one: DebugSessionOptions, other: DebugSessionOptions): boolean {
|
|
216
|
+
return one.providerType !== undefined
|
|
217
|
+
&& one.configuration.name === other.configuration.name
|
|
218
|
+
&& one.providerType === other.providerType;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
get recentDynamicOptions(): readonly DebugSessionOptions[] {
|
|
222
|
+
return this.recentDynamicOptionsTracker;
|
|
223
|
+
}
|
|
224
|
+
|
|
166
225
|
protected updateCurrent(options: DebugSessionOptions | undefined = this._currentOptions): void {
|
|
167
|
-
this._currentOptions = options &&
|
|
226
|
+
this._currentOptions = options && this.find(options.configuration, options.workspaceFolderUri, options.providerType);
|
|
168
227
|
|
|
169
228
|
if (!this._currentOptions) {
|
|
170
229
|
const model = this.getModel();
|
|
@@ -181,7 +240,24 @@ export class DebugConfigurationManager {
|
|
|
181
240
|
this.debugConfigurationTypeKey.set(this.current && this.current.configuration.type);
|
|
182
241
|
this.onDidChangeEmitter.fire(undefined);
|
|
183
242
|
}
|
|
184
|
-
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @deprecated since v1.27.0
|
|
246
|
+
*/
|
|
247
|
+
find(name: string, workspaceFolderUri: string): DebugSessionOptions | undefined;
|
|
248
|
+
/**
|
|
249
|
+
* Find / Resolve DebugSessionOptions from a given target debug configuration
|
|
250
|
+
*/
|
|
251
|
+
find(targetConfiguration: DebugConfiguration, workspaceFolderUri?: string, providerType?: string): DebugSessionOptions | undefined;
|
|
252
|
+
find(nameOrTargetConfiguration: string | DebugConfiguration, workspaceFolderUri?: string, providerType?: string): DebugSessionOptions | undefined {
|
|
253
|
+
// providerType is only applicable to dynamic debug configurations
|
|
254
|
+
if (typeof nameOrTargetConfiguration === 'object' && providerType) {
|
|
255
|
+
return {
|
|
256
|
+
configuration: nameOrTargetConfiguration,
|
|
257
|
+
providerType
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const name = typeof nameOrTargetConfiguration === 'string' ? nameOrTargetConfiguration : nameOrTargetConfiguration.name;
|
|
185
261
|
for (const model of this.models.values()) {
|
|
186
262
|
if (model.workspaceFolderUri === workspaceFolderUri) {
|
|
187
263
|
for (const configuration of model.configurations) {
|
|
@@ -194,7 +270,6 @@ export class DebugConfigurationManager {
|
|
|
194
270
|
}
|
|
195
271
|
}
|
|
196
272
|
}
|
|
197
|
-
return undefined;
|
|
198
273
|
}
|
|
199
274
|
|
|
200
275
|
async openConfiguration(): Promise<void> {
|
|
@@ -349,7 +424,13 @@ export class DebugConfigurationManager {
|
|
|
349
424
|
return this.debug.provideDynamicDebugConfigurations!();
|
|
350
425
|
}
|
|
351
426
|
|
|
427
|
+
async fetchDynamicDebugConfiguration(name: string, type: string): Promise<DebugConfiguration | undefined> {
|
|
428
|
+
await this.fireWillProvideDynamicDebugConfiguration();
|
|
429
|
+
return this.debug.fetchDynamicDebugConfiguration(name, type);
|
|
430
|
+
}
|
|
431
|
+
|
|
352
432
|
protected async fireWillProvideDynamicDebugConfiguration(): Promise<void> {
|
|
433
|
+
await this.initialized;
|
|
353
434
|
await WaitUntilEvent.fire(this.onWillProvideDynamicDebugConfigurationEmitter, {});
|
|
354
435
|
}
|
|
355
436
|
|
|
@@ -384,29 +465,43 @@ export class DebugConfigurationManager {
|
|
|
384
465
|
async load(): Promise<void> {
|
|
385
466
|
await this.initialized;
|
|
386
467
|
const data = await this.storage.getData<DebugConfigurationManager.Data>('debug.configurations', {});
|
|
387
|
-
|
|
388
|
-
|
|
468
|
+
this.resolveRecentDynamicOptionsFromData(data.recentDynamicOptions);
|
|
469
|
+
|
|
470
|
+
// Between versions v1.26 and v1.27, the expected format of the data changed so that old stored data
|
|
471
|
+
// may not contain the configuration key.
|
|
472
|
+
if (data.current && 'configuration' in data.current) {
|
|
473
|
+
this.current = this.find(data.current.configuration, data.current.workspaceFolderUri, data.current.providerType);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
protected resolveRecentDynamicOptionsFromData(options?: DebugSessionOptions[]): void {
|
|
478
|
+
if (!options || this.recentDynamicOptionsTracker.length !== 0) {
|
|
479
|
+
return;
|
|
389
480
|
}
|
|
481
|
+
|
|
482
|
+
this.recentDynamicOptionsTracker = options;
|
|
390
483
|
}
|
|
391
484
|
|
|
392
485
|
save(): void {
|
|
393
486
|
const data: DebugConfigurationManager.Data = {};
|
|
394
|
-
const { current } = this;
|
|
487
|
+
const { current, recentDynamicOptionsTracker } = this;
|
|
395
488
|
if (current) {
|
|
396
|
-
data.current =
|
|
397
|
-
name: current.configuration.name,
|
|
398
|
-
workspaceFolderUri: current.workspaceFolderUri
|
|
399
|
-
};
|
|
489
|
+
data.current = current;
|
|
400
490
|
}
|
|
401
|
-
this.storage.setData('debug.configurations', data);
|
|
402
|
-
}
|
|
403
491
|
|
|
492
|
+
if (this.recentDynamicOptionsTracker.length > 0) {
|
|
493
|
+
data.recentDynamicOptions = recentDynamicOptionsTracker;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (Object.keys(data).length > 0) {
|
|
497
|
+
this.storage.setData('debug.configurations', data);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
404
500
|
}
|
|
501
|
+
|
|
405
502
|
export namespace DebugConfigurationManager {
|
|
406
503
|
export interface Data {
|
|
407
|
-
current?:
|
|
408
|
-
|
|
409
|
-
workspaceFolderUri?: string
|
|
410
|
-
}
|
|
504
|
+
current?: DebugSessionOptions,
|
|
505
|
+
recentDynamicOptions?: DebugSessionOptions[]
|
|
411
506
|
}
|
|
412
507
|
}
|
|
@@ -123,10 +123,10 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan
|
|
|
123
123
|
|
|
124
124
|
// Resolve dynamic configurations from providers
|
|
125
125
|
const record = await this.debugConfigurationManager.provideDynamicDebugConfigurations();
|
|
126
|
-
for (const [
|
|
126
|
+
for (const [providerType, dynamicConfigurations] of Object.entries(record)) {
|
|
127
127
|
if (dynamicConfigurations.length > 0) {
|
|
128
128
|
items.push({
|
|
129
|
-
label:
|
|
129
|
+
label: providerType,
|
|
130
130
|
type: 'separator'
|
|
131
131
|
});
|
|
132
132
|
}
|
|
@@ -134,7 +134,7 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan
|
|
|
134
134
|
for (const configuration of dynamicConfigurations) {
|
|
135
135
|
items.push({
|
|
136
136
|
label: configuration.name,
|
|
137
|
-
execute: () => this.
|
|
137
|
+
execute: () => this.runConfiguration({ configuration, providerType })
|
|
138
138
|
});
|
|
139
139
|
}
|
|
140
140
|
}
|
|
@@ -145,21 +145,13 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan
|
|
|
145
145
|
/**
|
|
146
146
|
* Set the current debug configuration, and execute debug start command.
|
|
147
147
|
*
|
|
148
|
-
* @param
|
|
148
|
+
* @param configurationOptions the `DebugSessionOptions`.
|
|
149
149
|
*/
|
|
150
|
-
protected runConfiguration(
|
|
151
|
-
this.debugConfigurationManager.current =
|
|
150
|
+
protected runConfiguration(configurationOptions: DebugSessionOptions): void {
|
|
151
|
+
this.debugConfigurationManager.current = configurationOptions;
|
|
152
152
|
this.commandRegistry.executeCommand(DebugCommands.START.id);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
/**
|
|
156
|
-
* Execute the debug start command without affecting the current debug configuration
|
|
157
|
-
* @param configuration the `DebugSessionOptions`.
|
|
158
|
-
*/
|
|
159
|
-
protected runDynamicConfiguration(configuration: DebugSessionOptions): void {
|
|
160
|
-
this.commandRegistry.executeCommand(DebugCommands.START.id, configuration);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
155
|
/**
|
|
164
156
|
* Handle the visibility of the debug status bar.
|
|
165
157
|
* @param event the preference change event.
|
|
@@ -16,15 +16,42 @@
|
|
|
16
16
|
|
|
17
17
|
import { DebugConfiguration } from '../common/debug-common';
|
|
18
18
|
|
|
19
|
-
export interface
|
|
19
|
+
export interface DebugSessionOptionsBase {
|
|
20
|
+
workspaceFolderUri?: string,
|
|
21
|
+
providerType?: string // Applicable to dynamic configurations
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DebugSessionOptions extends DebugSessionOptionsBase {
|
|
20
25
|
configuration: DebugConfiguration
|
|
21
|
-
workspaceFolderUri?: string
|
|
22
26
|
}
|
|
27
|
+
|
|
28
|
+
export interface DebugSessionOptionsData extends DebugSessionOptionsBase, DebugConfiguration {
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
export interface InternalDebugSessionOptions extends DebugSessionOptions {
|
|
24
32
|
id: number
|
|
25
33
|
}
|
|
26
34
|
export namespace InternalDebugSessionOptions {
|
|
35
|
+
|
|
36
|
+
const SEPARATOR = '__CONF__';
|
|
37
|
+
|
|
27
38
|
export function is(options: DebugSessionOptions): options is InternalDebugSessionOptions {
|
|
28
|
-
return
|
|
39
|
+
return 'id' in options;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function toValue(debugSessionOptions: DebugSessionOptions): string {
|
|
43
|
+
return debugSessionOptions.configuration.name + SEPARATOR +
|
|
44
|
+
debugSessionOptions.configuration.type + SEPARATOR +
|
|
45
|
+
debugSessionOptions.configuration.request + SEPARATOR +
|
|
46
|
+
debugSessionOptions.workspaceFolderUri + SEPARATOR +
|
|
47
|
+
debugSessionOptions.providerType;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function parseValue(value: string): DebugSessionOptionsData {
|
|
51
|
+
const split = value.split(SEPARATOR);
|
|
52
|
+
if (split.length !== 5) {
|
|
53
|
+
throw new Error('Unexpected argument, the argument is expected to have been generated by the \'toValue\' function');
|
|
54
|
+
}
|
|
55
|
+
return {name: split[0], type: split[1], request: split[2], workspaceFolderUri: split[3], providerType: split[4]};
|
|
29
56
|
}
|
|
30
57
|
}
|
|
@@ -214,7 +214,7 @@ export class DebugBreakpointWidget implements Disposable {
|
|
|
214
214
|
this._input.getControl().setValue(this._values[this.context] || '');
|
|
215
215
|
}
|
|
216
216
|
ReactDOM.render(<SelectComponent
|
|
217
|
-
|
|
217
|
+
defaultValue={this.context} onChange={this.updateInput}
|
|
218
218
|
options={[
|
|
219
219
|
{ value: 'condition', label: nls.localizeByDefault('Expression') },
|
|
220
220
|
{ value: 'hitCondition', label: nls.localizeByDefault('Hit Count') },
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2021 Ericsson 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 WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
import URI from '@theia/core/lib/common/uri';
|
|
18
|
+
import * as React from '@theia/core/shared/react';
|
|
19
|
+
import { DebugConfigurationManager } from '../debug-configuration-manager';
|
|
20
|
+
import { DebugSessionOptions, InternalDebugSessionOptions } from '../debug-session-options';
|
|
21
|
+
import { SelectComponent, SelectOption } from '@theia/core/lib/browser/widgets/select-component';
|
|
22
|
+
import { QuickInputService } from '@theia/core/lib/browser';
|
|
23
|
+
import { nls } from '@theia/core/lib/common/nls';
|
|
24
|
+
|
|
25
|
+
interface DynamicPickItem { label: string, configurationType: string, request: string, providerType: string }
|
|
26
|
+
|
|
27
|
+
export interface DebugConfigurationSelectProps {
|
|
28
|
+
manager: DebugConfigurationManager,
|
|
29
|
+
quickInputService: QuickInputService,
|
|
30
|
+
isMultiRoot: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface DebugProviderSelectState {
|
|
34
|
+
providerTypes: string[],
|
|
35
|
+
currentValue: string | undefined
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class DebugConfigurationSelect extends React.Component<DebugConfigurationSelectProps, DebugProviderSelectState> {
|
|
39
|
+
protected static readonly SEPARATOR = '──────────';
|
|
40
|
+
protected static readonly PICK = '__PICK__';
|
|
41
|
+
protected static readonly NO_CONFIGURATION = '__NO_CONF__';
|
|
42
|
+
protected static readonly ADD_CONFIGURATION = '__ADD_CONF__';
|
|
43
|
+
|
|
44
|
+
private readonly selectRef = React.createRef<SelectComponent>();
|
|
45
|
+
private manager: DebugConfigurationManager;
|
|
46
|
+
private quickInputService: QuickInputService;
|
|
47
|
+
|
|
48
|
+
constructor(props: DebugConfigurationSelectProps) {
|
|
49
|
+
super(props);
|
|
50
|
+
this.manager = props.manager;
|
|
51
|
+
this.quickInputService = props.quickInputService;
|
|
52
|
+
this.state = {
|
|
53
|
+
providerTypes: [],
|
|
54
|
+
currentValue: undefined
|
|
55
|
+
};
|
|
56
|
+
this.manager.onDidChangeConfigurationProviders(() => {
|
|
57
|
+
this.refreshDebugConfigurations();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
override componentDidMount(): void {
|
|
62
|
+
this.refreshDebugConfigurations();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override render(): React.ReactNode {
|
|
66
|
+
return <SelectComponent
|
|
67
|
+
options={this.renderOptions()}
|
|
68
|
+
defaultValue={this.currentValue}
|
|
69
|
+
onChange={option => this.setCurrentConfiguration(option)}
|
|
70
|
+
onFocus={() => this.refreshDebugConfigurations()}
|
|
71
|
+
onBlur={() => this.refreshDebugConfigurations()}
|
|
72
|
+
ref={this.selectRef}
|
|
73
|
+
/>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected get currentValue(): string {
|
|
77
|
+
const { current } = this.manager;
|
|
78
|
+
return current ? InternalDebugSessionOptions.toValue(current) : DebugConfigurationSelect.NO_CONFIGURATION;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected readonly setCurrentConfiguration = (option: SelectOption) => {
|
|
82
|
+
const value = option.value;
|
|
83
|
+
if (!value) {
|
|
84
|
+
return false;
|
|
85
|
+
} else if (value === DebugConfigurationSelect.ADD_CONFIGURATION) {
|
|
86
|
+
this.manager.addConfiguration();
|
|
87
|
+
} else if (value.startsWith(DebugConfigurationSelect.PICK)) {
|
|
88
|
+
const providerType = this.parsePickValue(value);
|
|
89
|
+
this.selectDynamicConfigFromQuickPick(providerType);
|
|
90
|
+
} else {
|
|
91
|
+
const { name, type, request, workspaceFolderUri, providerType } = InternalDebugSessionOptions.parseValue(value);
|
|
92
|
+
this.manager.current = this.manager.find(
|
|
93
|
+
{ name, type, request },
|
|
94
|
+
workspaceFolderUri,
|
|
95
|
+
providerType === 'undefined' ? undefined : providerType
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
protected toPickValue(providerType: string): string {
|
|
101
|
+
return DebugConfigurationSelect.PICK + providerType;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
protected parsePickValue(value: string): string {
|
|
105
|
+
return value.slice(DebugConfigurationSelect.PICK.length);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
protected async resolveDynamicConfigurationPicks(providerType: string): Promise<DynamicPickItem[]> {
|
|
109
|
+
const configurationsOfProviderType =
|
|
110
|
+
(await this.manager.provideDynamicDebugConfigurations())[providerType];
|
|
111
|
+
|
|
112
|
+
if (!configurationsOfProviderType) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return configurationsOfProviderType.map(configuration => ({
|
|
117
|
+
label: configuration.name,
|
|
118
|
+
configurationType: configuration.type,
|
|
119
|
+
request: configuration.request,
|
|
120
|
+
providerType
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
protected async selectDynamicConfigFromQuickPick(providerType: string): Promise<void> {
|
|
125
|
+
const picks: DynamicPickItem[] = await this.resolveDynamicConfigurationPicks(providerType);
|
|
126
|
+
|
|
127
|
+
if (picks.length === 0) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const selected: DynamicPickItem | undefined = await this.quickInputService.showQuickPick(
|
|
132
|
+
picks,
|
|
133
|
+
{
|
|
134
|
+
placeholder: nls.localizeByDefault('Select Launch Configuration')
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
if (!selected) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const selectedConfiguration = {
|
|
143
|
+
name: selected.label,
|
|
144
|
+
type: selected.configurationType,
|
|
145
|
+
request: selected.request
|
|
146
|
+
};
|
|
147
|
+
this.manager.current = this.manager.find(selectedConfiguration, undefined, selected.providerType);
|
|
148
|
+
this.refreshDebugConfigurations();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
protected refreshDebugConfigurations = async () => {
|
|
152
|
+
const configsPerType = await this.manager.provideDynamicDebugConfigurations();
|
|
153
|
+
const providerTypes = [];
|
|
154
|
+
for (const [ type, configurations ] of Object.entries(configsPerType)) {
|
|
155
|
+
if (configurations.length > 0) {
|
|
156
|
+
providerTypes.push(type);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.selectRef.current!.value = this.currentValue;
|
|
160
|
+
this.setState({ providerTypes, currentValue: this.currentValue });
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
protected renderOptions(): SelectOption[] {
|
|
164
|
+
const options: SelectOption[] = [];
|
|
165
|
+
|
|
166
|
+
// Add non dynamic debug configurations
|
|
167
|
+
for (const config of this.manager.all) {
|
|
168
|
+
const value = InternalDebugSessionOptions.toValue(config);
|
|
169
|
+
options.push({
|
|
170
|
+
value,
|
|
171
|
+
label: this.toName(config, this.props.isMultiRoot)
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Add recently used dynamic debug configurations
|
|
176
|
+
const { recentDynamicOptions } = this.manager;
|
|
177
|
+
if (recentDynamicOptions.length > 0) {
|
|
178
|
+
if (options.length > 0) {
|
|
179
|
+
options.push({
|
|
180
|
+
separator: true
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
for (const dynamicOption of recentDynamicOptions) {
|
|
184
|
+
const value = InternalDebugSessionOptions.toValue(dynamicOption);
|
|
185
|
+
options.push({
|
|
186
|
+
value,
|
|
187
|
+
label: this.toName(dynamicOption, this.props.isMultiRoot) + ' (' + dynamicOption.providerType + ')'
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Placing a 'No Configuration' entry enables proper functioning of the 'onChange' event, by
|
|
193
|
+
// having an entry to switch from (E.g. a case where only one dynamic configuration type is available)
|
|
194
|
+
if (options.length === 0) {
|
|
195
|
+
const value = DebugConfigurationSelect.NO_CONFIGURATION;
|
|
196
|
+
options.push({
|
|
197
|
+
value,
|
|
198
|
+
label: nls.localizeByDefault('No Configurations')
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Add dynamic configuration types for quick pick selection
|
|
203
|
+
const types = this.state.providerTypes;
|
|
204
|
+
if (types.length > 0) {
|
|
205
|
+
options.push({
|
|
206
|
+
separator: true
|
|
207
|
+
});
|
|
208
|
+
for (const type of types) {
|
|
209
|
+
const value = this.toPickValue(type);
|
|
210
|
+
options.push({
|
|
211
|
+
value,
|
|
212
|
+
label: type + '...'
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
options.push({
|
|
218
|
+
separator: true
|
|
219
|
+
});
|
|
220
|
+
options.push({
|
|
221
|
+
value: DebugConfigurationSelect.ADD_CONFIGURATION,
|
|
222
|
+
label: nls.localizeByDefault('Add Configuration...')
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
return options;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
protected toName({ configuration, workspaceFolderUri }: DebugSessionOptions, multiRoot: boolean): string {
|
|
229
|
+
if (!workspaceFolderUri || !multiRoot) {
|
|
230
|
+
return configuration.name;
|
|
231
|
+
}
|
|
232
|
+
return `${configuration.name} (${new URI(workspaceFolderUri).path.base})`;
|
|
233
|
+
}
|
|
234
|
+
}
|