Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 14 additions & 35 deletions src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { flatten } from 'vs/base/common/arrays';
import { getVisibleAndSorted } from 'vs/workbench/contrib/debug/common/debugUtils';
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes';
import * as path from 'vs/base/common/path';

const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
jsonRegistry.registerSchema(launchSchemaId, launchSchema);

const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname';
const DEBUG_SELECTED_ROOT = 'debug.selectedroot';
// Debug type is only stored if a dynamic configuration is used for better restore
const DEBUG_SELECTED_TYPE = 'debug.selectedtype';

interface IDynamicPickItem { label: string, launch: ILaunch, config: IConfig }
Expand Down Expand Up @@ -99,8 +99,6 @@ export class ConfigurationManager implements IConfigurationManager {
}
}

// debuggers

registerDebugAdapterFactory(debugTypes: string[], debugAdapterLauncher: IDebugAdapterFactory): IDisposable {
debugTypes.forEach(debugType => this.debugAdapterFactories.set(debugType, debugAdapterLauncher));
this.debuggersAvailable.set(this.debugAdapterFactories.size > 0);
Expand Down Expand Up @@ -141,8 +139,6 @@ export class ConfigurationManager implements IConfigurationManager {
return Promise.resolve(void 0);
}

// debug adapter

registerDebugAdapterDescriptorFactory(debugAdapterProvider: IDebugAdapterDescriptorFactory): IDisposable {
this.adapterDescriptorFactories.push(debugAdapterProvider);
return {
Expand All @@ -163,20 +159,16 @@ export class ConfigurationManager implements IConfigurationManager {

const config = session.configuration;

// first try legacy proposed API: DebugConfigurationProvider.debugAdapterExecutable
const providers0 = this.configProviders.filter(p => p.type === config.type && p.debugAdapterExecutable);
if (providers0.length === 1 && providers0[0].debugAdapterExecutable) {
return providers0[0].debugAdapterExecutable(session.root ? session.root.uri : undefined);
} else {
// TODO@AW handle n > 1 case
}

// new API
const providers = this.adapterDescriptorFactories.filter(p => p.type === config.type && p.createDebugAdapterDescriptor);
if (providers.length === 1) {
return providers[0].createDebugAdapterDescriptor(session);
} else {
// TODO@AW handle n > 1 case
}
return Promise.resolve(undefined);
}
Expand All @@ -194,8 +186,6 @@ export class ConfigurationManager implements IConfigurationManager {
return this._onDidRegisterDebugger.event;
}

// debug configurations

registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable {
this.configProviders.push(debugConfigurationProvider);
return {
Expand All @@ -212,27 +202,21 @@ export class ConfigurationManager implements IConfigurationManager {
}
}

/**
* if scope is not specified,a value of DebugConfigurationProvideTrigger.Initial is assumed.
*/
hasDebugConfigurationProvider(debugType: string, triggerKind?: DebugConfigurationProviderTriggerKind): boolean {
if (triggerKind === undefined) {
triggerKind = DebugConfigurationProviderTriggerKind.Initial;
}
// check if there are providers for the given type that contribute a provideDebugConfigurations method
const provider = this.configProviders.find(p => p.provideDebugConfigurations && (p.type === debugType) && (p.triggerKind === triggerKind));
return !!provider;
}

async resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, config: IConfig, token: CancellationToken): Promise<IConfig | null | undefined> {
await this.activateDebuggers('onDebugResolve', type);
// pipe the config through the promises sequentially. Append at the end the '*' types
const providers = this.configProviders.filter(p => p.type === type && p.resolveDebugConfiguration)
.concat(this.configProviders.filter(p => p.type === '*' && p.resolveDebugConfiguration));

let result: IConfig | null | undefined = config;
await sequence(providers.map(provider => async () => {
// If any provider returned undefined or null make sure to respect that and do not pass the result to more resolver
if (result) {
result = await provider.resolveDebugConfiguration!(folderUri, result, token);
}
Expand All @@ -242,13 +226,11 @@ export class ConfigurationManager implements IConfigurationManager {
}

async resolveDebugConfigurationWithSubstitutedVariables(folderUri: uri | undefined, type: string | undefined, config: IConfig, token: CancellationToken): Promise<IConfig | null | undefined> {
// pipe the config through the promises sequentially. Append at the end the '*' types
const providers = this.configProviders.filter(p => p.type === type && p.resolveDebugConfigurationWithSubstitutedVariables)
.concat(this.configProviders.filter(p => p.type === '*' && p.resolveDebugConfigurationWithSubstitutedVariables));

let result: IConfig | null | undefined = config;
await sequence(providers.map(provider => async () => {
// If any provider returned undefined or null make sure to respect that and do not pass the result to more resolver
if (result) {
result = await provider.resolveDebugConfigurationWithSubstitutedVariables!(folderUri, result, token);
}
Expand Down Expand Up @@ -314,7 +296,6 @@ export class ConfigurationManager implements IConfigurationManager {
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);
}));
Expand Down Expand Up @@ -343,7 +324,6 @@ export class ConfigurationManager implements IConfigurationManager {

let chosen: IDynamicPickItem | undefined;

// If there's exactly one item to choose from, pick it automatically
if (items.length === 1 && !chosenDidCancel) {
chosen = items[0];
} else {
Expand All @@ -355,7 +335,6 @@ export class ConfigurationManager implements IConfigurationManager {
disposables.dispose();

if (!chosen) {
// User canceled quick input we should notify the provider to cancel computing configurations
token.cancel();
return;
}
Expand Down Expand Up @@ -404,7 +383,6 @@ export class ConfigurationManager implements IConfigurationManager {
});
});

// take care of all wildcard contributions
extensions.forEach(extension => {
extension.value.forEach(rawAdapter => {
if (rawAdapter.type === '*') {
Expand All @@ -418,7 +396,6 @@ export class ConfigurationManager implements IConfigurationManager {
this.debuggers = this.debuggers.filter(d => removedTypes.indexOf(d.type) === -1);
});

// update the schema to include all attributes, snippets and types from extensions.
this.debuggers.forEach(adapter => {
const items = (<IJSONSchema>launchSchema.properties!['configurations'].items);
const schemaAttributes = adapter.getSchemaAttributes();
Expand Down Expand Up @@ -450,7 +427,6 @@ export class ConfigurationManager implements IConfigurationManager {
}));
this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('launch')) {
// A change happen in the launch.json. If there is already a launch configuration selected, do not change the selection.
this.selectConfiguration(undefined);
this.setCompoundSchemaValues();
}
Expand Down Expand Up @@ -538,8 +514,6 @@ export class ConfigurationManager implements IConfigurationManager {
if ((name && names.indexOf(name) >= 0) || config) {
this.setSelectedLaunchName(name);
} else if (!this.selectedName || names.indexOf(this.selectedName) === -1) {
// We could not find the previously used name. We should get all dynamic configurations from providers
// And potentially auto select the previously used dynamic configuration #96293
const providers = await this.getDynamicProviders();
const provider = providers.find(p => p.provider && p.provider.type === type);
let nameToSet = names.length ? names[0] : undefined;
Expand Down Expand Up @@ -574,7 +548,6 @@ export class ConfigurationManager implements IConfigurationManager {
canSetBreakpointsIn(model: ITextModel): boolean {
const modeId = model.getLanguageIdentifier().language;
if (!modeId || modeId === 'jsonc' || modeId === 'log') {
// do not allow breakpoints in our settings files and output
return false;
}
if (this.configurationService.getValue<IDebugConfiguration>('debug').allowBreakpointsEverywhere) {
Expand Down Expand Up @@ -694,13 +667,21 @@ abstract class AbstractLaunch {
}

getConfiguration(name: string): IConfig | undefined {
// We need to clone the configuration in order to be able to make changes to it #42198
const config = objects.deepClone(this.getConfig());
if (!config || !config.configurations) {
return undefined;
}

return config.configurations.find(config => config && config.name === name);
const configuration = config.configurations.find(config => config && config.name === name);
if (configuration) {
if (this instanceof UserLaunch) {
configuration.__configurationTarget = ConfigurationTarget.USER;
} else if (this instanceof WorkspaceLaunch) {
configuration.__configurationTarget = ConfigurationTarget.WORKSPACE;
} else {
configuration.__configurationTarget = ConfigurationTarget.WORKSPACE_FOLDER;
}
}
return configuration;
}

async getInitialConfigurationContent(folderUri?: uri, type?: string, token?: CancellationToken): Promise<string> {
Expand Down Expand Up @@ -751,10 +732,9 @@ class Launch extends AbstractLaunch implements ILaunch {
const fileContent = await this.fileService.readFile(resource);
content = fileContent.value.toString();
} catch {
// launch.json not found: create one by collecting launch configs from debugConfigProviders
content = await this.getInitialConfigurationContent(this.workspace.uri, type, token);
if (content) {
created = true; // pin only if config file is created #8727
created = true;
try {
await this.textFileService.write(resource, content);
} catch (error) {
Expand Down Expand Up @@ -831,7 +811,6 @@ class WorkspaceLaunch extends AbstractLaunch implements ILaunch {
async openConfigFile(preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }> {
let launchExistInFile = !!this.getConfig();
if (!launchExistInFile) {
// Launch property in workspace config not found: create one by collecting launch configs from debugConfigProviders
let content = await this.getInitialConfigurationContent(undefined, type, token);
if (content) {
await this.configurationService.updateValue('launch', json.parse(content), ConfigurationTarget.WORKSPACE);
Expand Down Expand Up @@ -889,4 +868,4 @@ class UserLaunch extends AbstractLaunch implements ILaunch {
created: false
});
}
}
}
Loading