mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
debug: compounds in launch.json
This commit is contained in:
parent
86ba67bc93
commit
4ef68195da
|
@ -53,7 +53,7 @@ function updateLaunchJsonDecorations(editor: vscode.TextEditor) {
|
|||
let addPropertyAndValue = false;
|
||||
visit(editor.document.getText(), {
|
||||
onObjectProperty: (property, offset, length) => {
|
||||
addPropertyAndValue = property === 'version' || property === 'type' || property === 'request' || property === 'configurations';
|
||||
addPropertyAndValue = property === 'version' || property === 'type' || property === 'request' || property === 'configurations' || property === 'compounds';
|
||||
if (addPropertyAndValue) {
|
||||
ranges.push(new vscode.Range(editor.document.positionAt(offset), editor.document.positionAt(offset + length)));
|
||||
}
|
||||
|
|
|
@ -37,9 +37,13 @@ export class SelectConfigurationActionItem extends SelectActionItem {
|
|||
if (!config || !config.configurations || config.configurations.length === 0) {
|
||||
this.setOptions([nls.localize('noConfigurations', "No Configurations")], 0);
|
||||
} else {
|
||||
const configurationNames = config.configurations.filter(cfg => !!cfg.name).map(cfg => cfg.name);
|
||||
const selected = configurationNames.indexOf(this.debugService.getViewModel().selectedConfigurationName);
|
||||
this.setOptions(configurationNames, selected);
|
||||
const options = config.configurations.filter(cfg => !!cfg.name).map(cfg => cfg.name);
|
||||
if (config.compounds) {
|
||||
options.push(...config.compounds.filter(compound => !!compound.name).map(compound => compound.name));
|
||||
}
|
||||
|
||||
const selected = options.indexOf(this.debugService.getViewModel().selectedConfigurationName);
|
||||
this.setOptions(options, selected);
|
||||
}
|
||||
|
||||
if (changeDebugConfiguration) {
|
||||
|
|
|
@ -285,6 +285,7 @@ export interface IDebugConfiguration {
|
|||
export interface IGlobalConfig {
|
||||
version: string;
|
||||
debugServer?: number;
|
||||
compounds: ICompound[];
|
||||
configurations: IConfig[];
|
||||
}
|
||||
|
||||
|
@ -296,8 +297,6 @@ export interface IEnvConfig {
|
|||
preLaunchTask?: string;
|
||||
debugServer?: number;
|
||||
noDebug?: boolean;
|
||||
silentlyAbort?: boolean;
|
||||
configurationNames?: string[];
|
||||
}
|
||||
|
||||
export interface IConfig extends IEnvConfig {
|
||||
|
@ -306,6 +305,11 @@ export interface IConfig extends IEnvConfig {
|
|||
linux?: IEnvConfig;
|
||||
}
|
||||
|
||||
export interface ICompound {
|
||||
name: string;
|
||||
launches: string[];
|
||||
}
|
||||
|
||||
export interface IRawEnvAdapter {
|
||||
type?: string;
|
||||
label?: string;
|
||||
|
@ -340,6 +344,12 @@ export interface IConfigurationManager {
|
|||
*/
|
||||
getConfiguration(nameOrConfig: string | IConfig): TPromise<IConfig>;
|
||||
|
||||
/**
|
||||
* Returns a compound with the specified name.
|
||||
* Returns null if there is no compound with the specified name.
|
||||
*/
|
||||
getCompound(name: string): ICompound;
|
||||
|
||||
/**
|
||||
* Opens the launch.json file
|
||||
*/
|
||||
|
|
|
@ -8,7 +8,6 @@ import * as lifecycle from 'vs/base/common/lifecycle';
|
|||
import { guessMimeTypes } from 'vs/base/common/mime';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import uri from 'vs/base/common/uri';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
|
@ -548,59 +547,61 @@ export class DebugService implements debug.IDebugService {
|
|||
const sessionId = generateUuid();
|
||||
this.setStateAndEmit(sessionId, debug.State.Initializing);
|
||||
|
||||
return this.textFileService.saveAll() // make sure all dirty files are saved
|
||||
.then(() => this.configurationService.reloadConfiguration() // make sure configuration is up to date
|
||||
.then(() => this.extensionService.onReady()
|
||||
.then(() => this.configurationManager.getConfiguration(configurationOrName)
|
||||
.then(configuration => {
|
||||
if (!configuration) {
|
||||
return this.configurationManager.openConfigFile(false).then(openend => {
|
||||
if (openend) {
|
||||
this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file for your application."));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (configuration.silentlyAbort) {
|
||||
return;
|
||||
}
|
||||
if (strings.equalsIgnoreCase(configuration.type, 'composite') && configuration.configurationNames) {
|
||||
return TPromise.join(configuration.configurationNames.map(name => this.createProcess(name)));
|
||||
}
|
||||
// make sure all dirty files are saved and make sure configuration is up to date
|
||||
return this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration().then(() => this.extensionService.onReady().then(() => {
|
||||
const compound = typeof configurationOrName === 'string' ? this.configurationManager.getCompound(configurationOrName) : null;
|
||||
if (compound) {
|
||||
if (!compound.launches) {
|
||||
return TPromise.wrapError(new Error(nls.localize('compoundMustHaveConfigurationNames', "Compound must have \"configurationNames\" attribute set in order to start multiple configurations.")));
|
||||
}
|
||||
|
||||
if (!this.configurationManager.getAdapter(configuration.type)) {
|
||||
return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type)))
|
||||
: TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the chosen launch configuration."),
|
||||
{ actions: [this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL), CloseAction] }));
|
||||
}
|
||||
return TPromise.join(compound.launches.map(name => this.createProcess(name)));
|
||||
}
|
||||
|
||||
return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => {
|
||||
const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0;
|
||||
const successExitCode = taskSummary && taskSummary.exitCode === 0;
|
||||
const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0;
|
||||
if (successExitCode || (errorCount === 0 && !failureExitCode)) {
|
||||
return this.doCreateProcess(sessionId, configuration);
|
||||
}
|
||||
return this.configurationManager.getConfiguration(configurationOrName).then(configuration => {
|
||||
if (!configuration) {
|
||||
return this.configurationManager.openConfigFile(false).then(openend => {
|
||||
if (openend) {
|
||||
this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file for your application."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.messageService.show(severity.Error, {
|
||||
message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) :
|
||||
errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) :
|
||||
nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode),
|
||||
actions: [new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => {
|
||||
this.messageService.hideAll();
|
||||
return this.doCreateProcess(sessionId, configuration);
|
||||
}), CloseAction]
|
||||
});
|
||||
}, (err: TaskError) => {
|
||||
if (err.code !== TaskErrors.NotConfigured) {
|
||||
throw err;
|
||||
}
|
||||
if (!this.configurationManager.getAdapter(configuration.type)) {
|
||||
return configuration.type ? TPromise.wrapError(new Error(nls.localize('debugTypeNotSupported', "Configured debug type '{0}' is not supported.", configuration.type)))
|
||||
: TPromise.wrapError(errors.create(nls.localize('debugTypeMissing', "Missing property 'type' for the chosen launch configuration."),
|
||||
{ actions: [this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL), CloseAction] }));
|
||||
}
|
||||
|
||||
this.messageService.show(err.severity, {
|
||||
message: err.message,
|
||||
actions: [this.taskService.configureAction(), CloseAction]
|
||||
});
|
||||
});
|
||||
}))));
|
||||
return this.runPreLaunchTask(configuration.preLaunchTask).then((taskSummary: ITaskSummary) => {
|
||||
const errorCount = configuration.preLaunchTask ? this.markerService.getStatistics().errors : 0;
|
||||
const successExitCode = taskSummary && taskSummary.exitCode === 0;
|
||||
const failureExitCode = taskSummary && taskSummary.exitCode !== undefined && taskSummary.exitCode !== 0;
|
||||
if (successExitCode || (errorCount === 0 && !failureExitCode)) {
|
||||
return this.doCreateProcess(sessionId, configuration);
|
||||
}
|
||||
|
||||
this.messageService.show(severity.Error, {
|
||||
message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) :
|
||||
errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", configuration.preLaunchTask) :
|
||||
nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", configuration.preLaunchTask, taskSummary.exitCode),
|
||||
actions: [new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => {
|
||||
this.messageService.hideAll();
|
||||
return this.doCreateProcess(sessionId, configuration);
|
||||
}), CloseAction]
|
||||
});
|
||||
}, (err: TaskError) => {
|
||||
if (err.code !== TaskErrors.NotConfigured) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
this.messageService.show(err.severity, {
|
||||
message: err.message,
|
||||
actions: [this.taskService.configureAction(), CloseAction]
|
||||
});
|
||||
});
|
||||
});
|
||||
})));
|
||||
}
|
||||
|
||||
private doCreateProcess(sessionId: string, configuration: debug.IConfig): TPromise<any> {
|
||||
|
|
|
@ -130,12 +130,12 @@ export class Adapter {
|
|||
}
|
||||
const properties = attributes.properties;
|
||||
properties.type = {
|
||||
enum: [this.type, 'composite'],
|
||||
enum: [this.type],
|
||||
description: nls.localize('debugType', "Type of configuration.")
|
||||
};
|
||||
properties.name = {
|
||||
type: 'string',
|
||||
description: nls.localize('debugName', "Name of configuration; appears in the launch configuration drop down menu."),
|
||||
description: nls.localize('debugName', "Name of configuration. Appears in the launch configuration drop down menu."),
|
||||
default: 'Launch'
|
||||
};
|
||||
properties.request = {
|
||||
|
@ -146,11 +146,6 @@ export class Adapter {
|
|||
type: 'number',
|
||||
description: nls.localize('debugServer', "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode")
|
||||
};
|
||||
properties.configurationNames = {
|
||||
type: 'array',
|
||||
default: [],
|
||||
description: nls.localize({ key: 'debugConfigurationNames', comment: ['"composite" is not localizable'] }, "Configurations that will be launched as part of this \"composite\" configuration. Only respected if type of this configuration is \"composite\".")
|
||||
};
|
||||
properties.preLaunchTask = {
|
||||
type: ['string', 'null'],
|
||||
default: null,
|
||||
|
|
|
@ -140,6 +140,7 @@ export const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registe
|
|||
// debug general schema
|
||||
|
||||
export const schemaId = 'vscode://schemas/launch';
|
||||
const defaultCompound: debug.ICompound = { name: 'Compound', launches: [] };
|
||||
const schema: IJSONSchema = {
|
||||
id: schemaId,
|
||||
type: 'object',
|
||||
|
@ -164,6 +165,32 @@ const schema: IJSONSchema = {
|
|||
type: 'number',
|
||||
description: nls.localize('app.launch.json.debugServer', "DEPRECATED: please move debugServer inside a configuration.")
|
||||
},
|
||||
compounds: {
|
||||
type: 'array',
|
||||
description: nls.localize('app.launch.json.compounds', "List of compounds. Each compound references multiple configurations which will get launched together."),
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['name', 'launches'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: nls.localize('app.launch.json.compound.name', "Name of compound. Appears in the launch configuration drop down menu.")
|
||||
},
|
||||
launches: {
|
||||
type: 'array',
|
||||
default: [],
|
||||
items: {
|
||||
type: 'string'
|
||||
},
|
||||
description: nls.localize('app.launch.json.compounds.launches', "Names of configurations that will be launched as part of this compound.")
|
||||
}
|
||||
},
|
||||
default: defaultCompound
|
||||
},
|
||||
default: [
|
||||
defaultCompound
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -227,7 +254,6 @@ export class ConfigurationManager implements debug.IConfigurationManager {
|
|||
});
|
||||
|
||||
// update the schema to include all attributes and types from extensions.
|
||||
// debug.schema.properties['configurations'].items.properties.type.enum = this.adapters.map(adapter => adapter.type);
|
||||
this.adapters.forEach(adapter => {
|
||||
const schemaAttributes = adapter.getSchemaAttributes();
|
||||
if (schemaAttributes) {
|
||||
|
@ -249,6 +275,15 @@ export class ConfigurationManager implements debug.IConfigurationManager {
|
|||
return this.adapters.filter(adapter => strings.equalsIgnoreCase(adapter.type, type)).pop();
|
||||
}
|
||||
|
||||
public getCompound(name: string): debug.ICompound {
|
||||
const config = this.configurationService.getConfiguration<debug.IGlobalConfig>('launch');
|
||||
if (!config || !config.compounds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return config.compounds.filter(compound => compound.name === name).pop();
|
||||
}
|
||||
|
||||
public getConfiguration(nameOrConfig: string | debug.IConfig): TPromise<debug.IConfig> {
|
||||
const config = this.configurationService.getConfiguration<debug.IGlobalConfig>('launch');
|
||||
|
||||
|
|
Loading…
Reference in a new issue