From 31a99fb6b738007ad514ed247732eac34d58794c Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Tue, 25 Apr 2023 15:59:45 -0400 Subject: [PATCH] Associate root folder to dynamic debug configurations The methods is the `vscode` interface `DebugConfigurationProvider` specify the parameter `folder: WorksapceFolder | undefined'. The parameter can be `undefined` in the context of a folderless setup however some plugins expect it to be present always (e.g. ms-python.python). The original implementation of dynamic debug configurations did not provide this parameter. This change associates the root folder to the contributed configurations directly after the response for the call to 'provideDebugConfigurations' and it makes sure to preserve this parameter within the pick items presented to the user. Signed-off-by: Alvaro Sanchez-Leon --- CHANGELOG.md | 4 +- .../browser/debug-configuration-manager.ts | 43 +++++++++++++++---- .../src/browser/debug-prefix-configuration.ts | 21 +++++---- .../view/debug-configuration-select.tsx | 28 +++++++----- packages/debug/src/common/debug-service.ts | 4 +- packages/debug/src/node/debug-service-impl.ts | 2 +- .../browser/debug/plugin-debug-service.ts | 8 ++-- 7 files changed, 75 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37689bb96ee67..72388e58278da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,13 @@ - [Previous Changelogs](https://github.com/eclipse-theia/theia/tree/master/doc/changelogs/) -## v1.38.0 - 04/27/2023 +## v1.38.0 - [Breaking Changes:](#breaking_changes_1.38.0) - [core] moved `ToolbarAwareTabBar.Styles` to `ScrollableTabBar.Styles` [12411](https://github.com/eclipse-theia/theia/pull/12411/) +- [debug] Change the return type of (method) `DebugConfigurationManager.provideDynamicDebugConfigurations()` to
+`Promise>` [#12482](https://github.com/eclipse-theia/theia/pull/12482) ## v1.37.0 - 04/27/2023 diff --git a/packages/debug/src/browser/debug-configuration-manager.ts b/packages/debug/src/browser/debug-configuration-manager.ts index c4996ba79318e..d9ee87e0756ff 100644 --- a/packages/debug/src/browser/debug-configuration-manager.ts +++ b/packages/debug/src/browser/debug-configuration-manager.ts @@ -178,8 +178,8 @@ export class DebugConfigurationManager { // Refresh a dynamic configuration from the provider. // This allow providers to update properties before the execution e.g. program - const { providerType, configuration: { name } } = this._currentOptions; - const configuration = await this.fetchDynamicDebugConfiguration(name, providerType); + const { providerType, workspaceFolderUri, configuration: { name } } = this._currentOptions; + const configuration = await this.fetchDynamicDebugConfiguration(name, providerType, workspaceFolderUri); if (!configuration) { const message = nls.localize( @@ -188,7 +188,7 @@ export class DebugConfigurationManager { throw new Error(message); } - return { name, configuration, providerType }; + return { name, configuration, providerType, workspaceFolderUri }; } set current(option: DebugSessionOptions | undefined) { @@ -215,7 +215,8 @@ export class DebugConfigurationManager { protected dynamicOptionsMatch(one: DynamicDebugConfigurationSessionOptions, other: DynamicDebugConfigurationSessionOptions): boolean { return one.providerType !== undefined && one.configuration.name === other.configuration.name - && one.providerType === other.providerType; + && one.providerType === other.providerType + && one.workspaceFolderUri === other.workspaceFolderUri; } get recentDynamicOptions(): readonly DynamicDebugConfigurationSessionOptions[] { @@ -462,14 +463,40 @@ export class DebugConfigurationManager { await WaitUntilEvent.fire(this.onWillProvideDebugConfigurationEmitter, {}); } - async provideDynamicDebugConfigurations(): Promise> { + async provideDynamicDebugConfigurations(): Promise> { await this.fireWillProvideDynamicDebugConfiguration(); - return this.debug.provideDynamicDebugConfigurations!(); + const roots = this.workspaceService.tryGetRoots(); + const promises = roots.map(async root => { + const configsMap = await this.debug.provideDynamicDebugConfigurations!(root.resource.toString()); + const optionsMap = Object.fromEntries(Object.entries(configsMap).map(([type, configs]) => { + const options = configs.map(config => ({ + name: config.name, + providerType: type, + configuration: config, + workspaceFolderUri: root.resource.toString() + })); + return [type, options]; + })); + return optionsMap; + }); + + const typesToOptionsRecords = await Promise.all(promises); + const consolidatedTypesToOptions: Record = {}; + + for (const typesToOptionsInstance of typesToOptionsRecords) { + for (const [providerType, configurationsOptions] of Object.entries(typesToOptionsInstance)) { + if (!consolidatedTypesToOptions[providerType]) { + consolidatedTypesToOptions[providerType] = []; + } + consolidatedTypesToOptions[providerType].push(...configurationsOptions); + } + } + return consolidatedTypesToOptions; } - async fetchDynamicDebugConfiguration(name: string, type: string): Promise { + async fetchDynamicDebugConfiguration(name: string, type: string, folder?: string): Promise { await this.fireWillProvideDynamicDebugConfiguration(); - return this.debug.fetchDynamicDebugConfiguration(name, type); + return this.debug.fetchDynamicDebugConfiguration(name, type, folder); } protected async fireWillProvideDynamicDebugConfiguration(): Promise { diff --git a/packages/debug/src/browser/debug-prefix-configuration.ts b/packages/debug/src/browser/debug-prefix-configuration.ts index 70bbcc6330f2e..613b5c4d71c47 100644 --- a/packages/debug/src/browser/debug-prefix-configuration.ts +++ b/packages/debug/src/browser/debug-prefix-configuration.ts @@ -107,6 +107,12 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan }); } + protected resolveRootFolderName(uri: string | undefined): string | undefined { + return uri && this.workspaceService.isMultiRootWorkspaceOpened + ? this.labelProvider.getName(new URI(uri)) + : ''; + } + async getPicks(filter: string, token: CancellationToken): Promise { const items: QuickPickItemOrSeparator[] = []; const configurations = this.debugConfigurationManager.all; @@ -114,27 +120,26 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan for (const config of configurations) { items.push({ label: config.name, - description: this.workspaceService.isMultiRootWorkspaceOpened - ? this.labelProvider.getName(new URI(config.workspaceFolderUri)) - : '', + description: this.resolveRootFolderName(config.workspaceFolderUri), execute: () => this.runConfiguration(config) }); } // Resolve dynamic configurations from providers const record = await this.debugConfigurationManager.provideDynamicDebugConfigurations(); - for (const [providerType, dynamicConfigurations] of Object.entries(record)) { - if (dynamicConfigurations.length > 0) { + for (const [providerType, configurationOptions] of Object.entries(record)) { + if (configurationOptions.length > 0) { items.push({ label: providerType, type: 'separator' }); } - for (const configuration of dynamicConfigurations) { + for (const options of configurationOptions) { items.push({ - label: configuration.name, - execute: () => this.runConfiguration({ name: configuration.name, configuration, providerType }) + label: options.name, + description: this.resolveRootFolderName(options.workspaceFolderUri), + execute: () => this.runConfiguration({ name: options.name, configuration: options.configuration, providerType, workspaceFolderUri: options.workspaceFolderUri }) }); } } diff --git a/packages/debug/src/browser/view/debug-configuration-select.tsx b/packages/debug/src/browser/view/debug-configuration-select.tsx index 091ef1b3b31e4..7e3f1537128ec 100644 --- a/packages/debug/src/browser/view/debug-configuration-select.tsx +++ b/packages/debug/src/browser/view/debug-configuration-select.tsx @@ -22,7 +22,7 @@ import { SelectComponent, SelectOption } from '@theia/core/lib/browser/widgets/s import { QuickInputService } from '@theia/core/lib/browser'; import { nls } from '@theia/core/lib/common/nls'; -interface DynamicPickItem { label: string, configurationType: string, request: string, providerType: string } +interface DynamicPickItem { label: string, configurationType: string, request: string, providerType: string, workspaceFolderUri?: string } export interface DebugConfigurationSelectProps { manager: DebugConfigurationManager, @@ -130,11 +130,13 @@ export class DebugConfigurationSelect extends React.Component ({ - label: configuration.name, - configurationType: configuration.type, - request: configuration.request, - providerType + return configurationsOfProviderType.map(options => ({ + label: options.configuration.name, + configurationType: options.configuration.type, + request: options.configuration.request, + providerType: options.providerType, + description: this.toBaseName(options.workspaceFolderUri), + workspaceFolderUri: options.workspaceFolderUri })); } @@ -161,15 +163,15 @@ export class DebugConfigurationSelect extends React.Component { - const configsPerType = await this.manager.provideDynamicDebugConfigurations(); + const configsOptionsPerType = await this.manager.provideDynamicDebugConfigurations(); const providerTypes = []; - for (const [type, configurations] of Object.entries(configsPerType)) { - if (configurations.length > 0) { + for (const [type, configurationsOptions] of Object.entries(configsOptionsPerType)) { + if (configurationsOptions.length > 0) { providerTypes.push(type); } } @@ -251,6 +253,10 @@ export class DebugConfigurationSelect extends React.Component>; + provideDynamicDebugConfigurations?(folder: string | undefined): Promise>; /** * Provides a dynamic debug configuration matching the name and the provider debug type */ - fetchDynamicDebugConfiguration(name: string, type: string): Promise; + fetchDynamicDebugConfiguration(name: string, type: string, folder: string | undefined): Promise; /** * Resolves a [debug configuration](#DebugConfiguration) by filling in missing values diff --git a/packages/debug/src/node/debug-service-impl.ts b/packages/debug/src/node/debug-service-impl.ts index c4304390b1947..159b504506716 100644 --- a/packages/debug/src/node/debug-service-impl.ts +++ b/packages/debug/src/node/debug-service-impl.ts @@ -71,7 +71,7 @@ export class DebugServiceImpl implements DebugService { // TODO: Support dynamic debug configurations through Theia extensions? return {}; } - fetchDynamicDebugConfiguration(name: string, type: string): Promise { + fetchDynamicDebugConfiguration(name: string, type: string, folder: string | undefined): Promise { // TODO: Support dynamic debug configurations through Theia extensions? return Promise.resolve(undefined); } diff --git a/packages/plugin-ext/src/main/browser/debug/plugin-debug-service.ts b/packages/plugin-ext/src/main/browser/debug/plugin-debug-service.ts index 1e7576edeab2a..ab981e41b7425 100644 --- a/packages/plugin-ext/src/main/browser/debug/plugin-debug-service.ts +++ b/packages/plugin-ext/src/main/browser/debug/plugin-debug-service.ts @@ -142,7 +142,7 @@ export class PluginDebugService implements DebugService { return results; } - async fetchDynamicDebugConfiguration(name: string, providerType: string): Promise { + async fetchDynamicDebugConfiguration(name: string, providerType: string, folder: string | undefined): Promise { const pluginProviders = Array.from(this.configurationProviders.values()).filter(p => ( p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic && @@ -151,7 +151,7 @@ export class PluginDebugService implements DebugService { )); for (const provider of pluginProviders) { - const configurations = await provider.provideDebugConfigurations(undefined); + const configurations = await provider.provideDebugConfigurations(folder); for (const configuration of configurations) { if (configuration.name === name) { return configuration; @@ -160,7 +160,7 @@ export class PluginDebugService implements DebugService { } } - async provideDynamicDebugConfigurations(): Promise> { + async provideDynamicDebugConfigurations(folder: string | undefined): Promise> { const pluginProviders = Array.from(this.configurationProviders.values()).filter(p => ( p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic && @@ -170,7 +170,7 @@ export class PluginDebugService implements DebugService { const configurationsRecord: Record = {}; await Promise.all(pluginProviders.map(async provider => { - const configurations = await provider.provideDebugConfigurations(undefined); + const configurations = await provider.provideDebugConfigurations(folder); let configurationsPerType = configurationsRecord[provider.type]; configurationsPerType = configurationsPerType ? configurationsPerType.concat(configurations) : configurations;