src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts/ConfigurationManager/getDynamicProviders
class ConfigurationManager:	async getDynamicProviders(): Promise<{ label: string, type: string, getProvider: () => Promise<IDebugConfigurationProvider | undefined>, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[]> {
		const extensions = await this.extensionService.getExtensions();
		const onDebugDynamicConfigurationsName = 'onDebugDynamicConfigurations';
		const debugDynamicExtensionsTypes = extensions.reduce((acc, e) => {
			if (!e.activationEvents) {
				return acc;
			}

			const explicitTypes: string[] = [];
			let hasGenericEvent = false;
			for (const event of e.activationEvents) {
				if (event === onDebugDynamicConfigurationsName) {
					hasGenericEvent = true;
				} else if (event.startsWith(`${onDebugDynamicConfigurationsName}:`)) {
					explicitTypes.push(event.slice(onDebugDynamicConfigurationsName.length + 1));
				}
			}

			if (explicitTypes.length) {
				return acc.concat(explicitTypes);
			}

			if (hasGenericEvent) {
				const debuggerType = e.contributes?.debuggers?.[0].type;
				return debuggerType ? acc.concat(debuggerType) : acc;
			}

			return acc;
		}, [] as string[]);

		return debugDynamicExtensionsTypes.map(type => {
			return {
				label: this.adapterManager.getDebuggerLabel(type)!,
				getProvider: async () => {
					await this.activateDebuggers(onDebugDynamicConfigurationsName, type);
					return this.configProviders.find(p => p.type === type && p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic && p.provideDebugConfigurations);
				},
				type,
				pick: async () => {
					// Do a late 'onDebugDynamicConfigurationsName' activation so extensions are not activated too early #108578
					await this.activateDebuggers(onDebugDynamicConfigurationsName, type);
					const disposables = new DisposableStore();
					const input = disposables.add(this.quickInputService.createQuickPick<IDynamicPickItem>());
					input.busy = true;
					input.placeholder = nls.localize('selectConfiguration', "Select Launch Configuration");
					input.show();

					const chosenPromise = new Promise<IDynamicPickItem | undefined>(resolve => {
						disposables.add(input.onDidAccept(() => resolve(input.activeItems[0])));
						disposables.add(input.onDidTriggerItemButton(async (context) => {
							resolve(undefined);
							const { launch, config } = context.item;
							await launch.openConfigFile(false, config.type);
							// Only Launch have a pin trigger button
							await (launch as Launch).writeConfiguration(config);
							await this.selectConfiguration(launch, config.name);
						}));
					});

					const token = new CancellationTokenSource();
					const picks: Promise<IDynamicPickItem[]>[] = [];
					const provider = this.configProviders.find(p => p.type === type && p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic && p.provideDebugConfigurations);
					this.getLaunches().forEach(launch => {
						if (launch.workspace && provider) {
							picks.push(provider.provideDebugConfigurations!(launch.workspace.uri, token.token).then(configurations => configurations.map(config => ({
								label: config.name,
								description: launch.name,
								config,
								buttons: [{
									iconClass: ThemeIcon.asClassName(debugConfigure),
									tooltip: nls.localize('editLaunchConfig', "Edit Debug Configuration in launch.json")
								}],
								launch
							}))));
						}
					});

					const nestedPicks = await Promise.all(picks);
					const items = flatten(nestedPicks);

					input.items = items;
					input.busy = false;
					const chosen = await chosenPromise;

					disposables.dispose();

					if (!chosen) {
						// User canceled quick input we should notify the provider to cancel computing configurations
						token.cancel();
						return;
					}

					return chosen;
				}
			};
		});
	}