Path: blob/main/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { IQuickPickSeparator } from '../../../../platform/quickinput/common/quickInput.js';6import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from '../../../../platform/quickinput/browser/pickerQuickAccess.js';7import { localize } from '../../../../nls.js';8import { INotificationService } from '../../../../platform/notification/common/notification.js';9import { IDebugService } from '../common/debug.js';10import { IWorkspaceContextService, WorkbenchState } from '../../../../platform/workspace/common/workspace.js';11import { ICommandService } from '../../../../platform/commands/common/commands.js';12import { matchesFuzzy } from '../../../../base/common/filters.js';13import { ADD_CONFIGURATION_ID, DEBUG_QUICK_ACCESS_PREFIX } from './debugCommands.js';14import { debugConfigure, debugRemoveConfig } from './debugIcons.js';15import { ThemeIcon } from '../../../../base/common/themables.js';1617export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {1819constructor(20@IDebugService private readonly debugService: IDebugService,21@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,22@ICommandService private readonly commandService: ICommandService,23@INotificationService private readonly notificationService: INotificationService,24) {25super(DEBUG_QUICK_ACCESS_PREFIX, {26noResultsPick: {27label: localize('noDebugResults', "No matching launch configurations")28}29});30}3132protected async _getPicks(filter: string): Promise<(IQuickPickSeparator | IPickerQuickAccessItem)[]> {33const picks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];34if (!this.debugService.getAdapterManager().hasEnabledDebuggers()) {35return [];36}3738picks.push({ type: 'separator', label: 'launch.json' });3940const configManager = this.debugService.getConfigurationManager();41const selectedConfiguration = configManager.selectedConfiguration;4243// Entries: configs44let lastGroup: string | undefined;45for (const config of configManager.getAllConfigurations()) {46const highlights = matchesFuzzy(filter, config.name, true);47if (highlights) {4849const pick = {50label: config.name,51description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? config.launch.name : '',52highlights: { label: highlights },53buttons: [{54iconClass: ThemeIcon.asClassName(debugConfigure),55tooltip: localize('customizeLaunchConfig', "Configure Launch Configuration")56}],57trigger: () => {58config.launch.openConfigFile({ preserveFocus: false });5960return TriggerAction.CLOSE_PICKER;61},62accept: async () => {63await configManager.selectConfiguration(config.launch, config.name);64try {65await this.debugService.startDebugging(config.launch, undefined, { startedByUser: true });66} catch (error) {67this.notificationService.error(error);68}69}70};7172// Most recently used configuration73if (selectedConfiguration.name === config.name && selectedConfiguration.launch === config.launch) {74const separator: IQuickPickSeparator = { type: 'separator', label: localize('mostRecent', 'Most Recent') };75picks.unshift(separator, pick);76continue;77}7879// Separator80if (lastGroup !== config.presentation?.group) {81picks.push({ type: 'separator' });82lastGroup = config.presentation?.group;83}8485// Launch entry8687picks.push(pick);88}89}9091// Entries detected configurations92const dynamicProviders = await configManager.getDynamicProviders();93if (dynamicProviders.length > 0) {94picks.push({95type: 'separator', label: localize({96key: 'contributed',97comment: ['contributed is lower case because it looks better like that in UI. Nothing preceeds it. It is a name of the grouping of debug configurations.']98}, "contributed")99});100}101102configManager.getRecentDynamicConfigurations().forEach(({ name, type }) => {103const highlights = matchesFuzzy(filter, name, true);104if (highlights) {105picks.push({106label: name,107highlights: { label: highlights },108buttons: [{109iconClass: ThemeIcon.asClassName(debugRemoveConfig),110tooltip: localize('removeLaunchConfig', "Remove Launch Configuration")111}],112trigger: () => {113configManager.removeRecentDynamicConfigurations(name, type);114return TriggerAction.CLOSE_PICKER;115},116accept: async () => {117await configManager.selectConfiguration(undefined, name, undefined, { type });118try {119const { launch, getConfig } = configManager.selectedConfiguration;120const config = await getConfig();121await this.debugService.startDebugging(launch, config, { startedByUser: true });122} catch (error) {123this.notificationService.error(error);124}125}126});127}128});129130dynamicProviders.forEach(provider => {131picks.push({132label: `$(folder) ${provider.label}...`,133ariaLabel: localize({ key: 'providerAriaLabel', comment: ['Placeholder stands for the provider label. For example "NodeJS".'] }, "{0} contributed configurations", provider.label),134accept: async () => {135const pick = await provider.pick();136if (pick) {137// Use the type of the provider, not of the config since config sometimes have subtypes (for example "node-terminal")138await configManager.selectConfiguration(pick.launch, pick.config.name, pick.config, { type: provider.type });139this.debugService.startDebugging(pick.launch, pick.config, { startedByUser: true });140}141}142});143});144145146// Entries: launches147const visibleLaunches = configManager.getLaunches().filter(launch => !launch.hidden);148149// Separator150if (visibleLaunches.length > 0) {151picks.push({ type: 'separator', label: localize('configure', "configure") });152}153154for (const launch of visibleLaunches) {155const label = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ?156localize("addConfigTo", "Add Config ({0})...", launch.name) :157localize('addConfiguration', "Add Configuration...");158159// Add Config entry160picks.push({161label,162description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? launch.name : '',163highlights: { label: matchesFuzzy(filter, label, true) ?? undefined },164accept: () => this.commandService.executeCommand(ADD_CONFIGURATION_ID, launch.uri.toString())165});166}167168return picks;169}170}171172173