mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 21:55:38 +00:00
Debug API: add DebugAdapterExecutableOptions; for #62977
This commit is contained in:
parent
66b963d0cd
commit
61b9a88e52
114
src/vs/vscode.proposed.d.ts
vendored
114
src/vs/vscode.proposed.d.ts
vendored
|
@ -505,38 +505,54 @@ declare module 'vscode' {
|
||||||
//#region André: debug
|
//#region André: debug
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a debug adapter executable and optional arguments passed to it.
|
* Represents a debug adapter executable and optional arguments and runtime options passed to it.
|
||||||
*/
|
*/
|
||||||
export class DebugAdapterExecutable {
|
export class DebugAdapterExecutable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command path of the debug adapter executable.
|
* Creates a description for a debug adapter based on an executable program.
|
||||||
* A command must be either an absolute path or the name of an executable looked up via the PATH environment variable.
|
*
|
||||||
* The special value 'node' will be mapped to VS Code's built-in node runtime.
|
* @param command The command or executable path that implements the debug adapter.
|
||||||
|
* @param args Optional arguments to be passed to the command or executable.
|
||||||
|
* @param options Optional options to be used when starting the command or executable.
|
||||||
|
*/
|
||||||
|
constructor(command: string, args?: string[], options?: DebugAdapterExecutableOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command or path of the debug adapter executable.
|
||||||
|
* A command must be either an absolute path of an executable or the name of an command to be looked up via the PATH environment variable.
|
||||||
|
* The special value 'node' will be mapped to VS Code's built-in Node.js runtime.
|
||||||
*/
|
*/
|
||||||
readonly command: string;
|
readonly command: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional arguments passed to the debug adapter executable.
|
* The arguments passed to the debug adapter executable. Defaults to an empty array.
|
||||||
*/
|
*/
|
||||||
readonly args: string[];
|
readonly args: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional options to be used when the debug adapter is started.
|
||||||
|
* Defaults to undefined.
|
||||||
|
*/
|
||||||
|
readonly options?: DebugAdapterExecutableOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for a debug adapter executable.
|
||||||
|
*/
|
||||||
|
export interface DebugAdapterExecutableOptions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The additional environment of the executed program or shell. If omitted
|
* The additional environment of the executed program or shell. If omitted
|
||||||
* the parent process' environment is used. If provided it is merged with
|
* the parent process' environment is used. If provided it is merged with
|
||||||
* the parent process' environment.
|
* the parent process' environment.
|
||||||
*/
|
*/
|
||||||
readonly env?: { [key: string]: string };
|
env?: { [key: string]: string };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The working directory for the debug adapter.
|
* The current working directory for the executed debug adapter.
|
||||||
*/
|
*/
|
||||||
readonly cwd?: string;
|
cwd?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a description for a debug adapter based on an executable program.
|
|
||||||
*/
|
|
||||||
constructor(command: string, args?: string[], env?: { [key: string]: string }, cwd?: string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -576,41 +592,38 @@ declare module 'vscode' {
|
||||||
|
|
||||||
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer | DebugAdapterImplementation;
|
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer | DebugAdapterImplementation;
|
||||||
|
|
||||||
export interface DebugConfigurationProvider {
|
|
||||||
/**
|
|
||||||
* Deprecated, use DebugAdapterProvider.provideDebugAdapter instead.
|
|
||||||
* @deprecated Use DebugAdapterProvider.provideDebugAdapter instead
|
|
||||||
*/
|
|
||||||
debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The optional method 'provideDebugAdapterTracker' is called at the start of a debug session to provide a tracker that gives access to the communication between VS Code and a Debug Adapter.
|
|
||||||
* @param session The [debug session](#DebugSession) for which the tracker will be used.
|
|
||||||
* @param token A cancellation token.
|
|
||||||
*/
|
|
||||||
provideDebugAdapterTracker?(session: DebugSession, token?: CancellationToken): ProviderResult<DebugAdapterTracker>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DebugAdapterProvider {
|
export interface DebugAdapterProvider {
|
||||||
/**
|
/**
|
||||||
* Method 'provideDebugAdapter' is called at the start of a debug session to provide details about the debug adapter to use.
|
* 'provideDebugAdapter' is called at the start of a debug session to provide details about the debug adapter to use.
|
||||||
* These details must be returned as objects of type DebugAdapterDescriptor.
|
* These details must be returned as objects of type [DebugAdapterDescriptor](#DebugAdapterDescriptor).
|
||||||
* Currently two types of debug adapters are supported:
|
* Currently two types of debug adapters are supported:
|
||||||
* - a debug adapter executable specified as a command path and arguments (see DebugAdapterExecutable),
|
* - a debug adapter executable is specified as a command path and arguments (see [DebugAdapterExecutable](#DebugAdapterExecutable)),
|
||||||
* - a debug adapter server reachable via a communication port (see DebugAdapterServer).
|
* - a debug adapter server reachable via a communication port (see [DebugAdapterServer](#DebugAdapterServer)).
|
||||||
* If the method is not implemented the default behavior is this:
|
* If the method is not implemented the default behavior is this:
|
||||||
* provideDebugAdapter(session: DebugSession, folder: WorkspaceFolder | undefined, executable: DebugAdapterExecutable, config: DebugConfiguration, token?: CancellationToken) {
|
* provideDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable) {
|
||||||
* if (typeof config.debugServer === 'number') {
|
* if (typeof session.configuration.debugServer === 'number') {
|
||||||
* return new DebugAdapterServer(config.debugServer);
|
* return new DebugAdapterServer(session.configuration.debugServer);
|
||||||
* }
|
* }
|
||||||
* return executable;
|
* return executable;
|
||||||
* }
|
* }
|
||||||
* @param session The [debug session](#DebugSession) for which the debug adapter will be used.
|
* @param session The [debug session](#DebugSession) for which the debug adapter will be used.
|
||||||
* @param executable The debug adapter's executable information as specified in the package.json (or undefined if no such information exists).
|
* @param executable The debug adapter's executable information as specified in the package.json (or undefined if no such information exists).
|
||||||
* @param token A cancellation token.
|
* @return a [debug adapter descriptor](#DebugAdapterDescriptor) or undefined.
|
||||||
* @return a [debug adapter's descriptor](#DebugAdapterDescriptor) or undefined.
|
|
||||||
*/
|
*/
|
||||||
provideDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable | undefined, token?: CancellationToken): ProviderResult<DebugAdapterDescriptor>;
|
provideDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace debug {
|
||||||
|
/**
|
||||||
|
* Register a [debug adapter provider](#DebugAdapterProvider) for a specific debug type.
|
||||||
|
* An extension is only allowed to register a DebugAdapterProvider for the debug type(s) defined by the extension. Otherwise an error is thrown.
|
||||||
|
* Registering more than one DebugAdapterProvider for a debug type results in an error.
|
||||||
|
*
|
||||||
|
* @param type The debug type for which the provider is registered.
|
||||||
|
* @param provider The [debug adapter provider](#DebugAdapterProvider) to register.
|
||||||
|
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||||
|
*/
|
||||||
|
export function registerDebugAdapterProvider(debugType: string, provider: DebugAdapterProvider): Disposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -628,18 +641,21 @@ declare module 'vscode' {
|
||||||
debugAdapterExit?(code?: number, signal?: string): void;
|
debugAdapterExit?(code?: number, signal?: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace debug {
|
export interface DebugConfigurationProvider {
|
||||||
/**
|
/**
|
||||||
* Register a [debug adapter provider](#DebugAdapterProvider) for a specific debug type.
|
* Deprecated, use DebugAdapterProvider.provideDebugAdapter instead.
|
||||||
* Only one provider can be registered for the same type.
|
* @deprecated Use DebugAdapterProvider.provideDebugAdapter instead
|
||||||
* An extension is only allowed to register a DebugAdapterProvider for the debug type defined by the extension. Otherwise an error is thrown.
|
|
||||||
* Registering more than one DebugAdapterProvider for a debug type results in an error.
|
|
||||||
*
|
|
||||||
* @param type The debug type for which the provider is registered.
|
|
||||||
* @param provider The [debug adapter provider](#DebugAdapterProvider) to register.
|
|
||||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
|
||||||
*/
|
*/
|
||||||
export function registerDebugAdapterProvider(debugType: string, provider: DebugAdapterProvider): Disposable;
|
debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preliminary API, do not use in production.
|
||||||
|
*
|
||||||
|
* The optional method 'provideDebugAdapterTracker' is called at the start of a debug session to provide a tracker that gives access to the communication between VS Code and a Debug Adapter.
|
||||||
|
* @param session The [debug session](#DebugSession) for which the tracker will be used.
|
||||||
|
* @param token A cancellation token.
|
||||||
|
*/
|
||||||
|
provideDebugAdapterTracker?(session: DebugSession, workspaceFolder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugAdapterTracker>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -596,8 +596,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||||
type: 'executable',
|
type: 'executable',
|
||||||
command: x.command,
|
command: x.command,
|
||||||
args: x.args,
|
args: x.args,
|
||||||
cwd: x.cwd,
|
options: x.options
|
||||||
env: x.env
|
|
||||||
};
|
};
|
||||||
} else if (x instanceof DebugAdapterServer) {
|
} else if (x instanceof DebugAdapterServer) {
|
||||||
return <IDebugAdapterServer>{
|
return <IDebugAdapterServer>{
|
||||||
|
@ -662,7 +661,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||||
const type = config.type;
|
const type = config.type;
|
||||||
const promises = this._configProviders
|
const promises = this._configProviders
|
||||||
.filter(pair => pair.provider.provideDebugAdapterTracker && (pair.type === type || pair.type === '*'))
|
.filter(pair => pair.provider.provideDebugAdapterTracker && (pair.type === type || pair.type === '*'))
|
||||||
.map(pair => asThenable(() => (pair.provider as any).provideDebugAdapterTracker(session, session.workspaceFolder, session.configuration, CancellationToken.None)).then(p => p).catch(err => null));
|
.map(pair => asThenable(() => pair.provider.provideDebugAdapterTracker(session, session.workspaceFolder, session.configuration, CancellationToken.None)).then(p => p).catch(err => null));
|
||||||
|
|
||||||
return Promise.race([
|
return Promise.race([
|
||||||
Promise.all(promises).then(trackers => {
|
Promise.all(promises).then(trackers => {
|
||||||
|
@ -701,7 +700,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapterProvider) {
|
if (adapterProvider) {
|
||||||
return asThenable(() => adapterProvider.provideDebugAdapter(session, this.daExecutableFromPackage(session), CancellationToken.None));
|
return asThenable(() => adapterProvider.provideDebugAdapter(session, this.daExecutableFromPackage(session)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// try deprecated command based extension API "adapterExecutableCommand" to determine the executable
|
// try deprecated command based extension API "adapterExecutableCommand" to determine the executable
|
||||||
|
@ -719,9 +718,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||||
return Promise.resolve(this.daExecutableFromPackage(session));
|
return Promise.resolve(this.daExecutableFromPackage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
private daExecutableFromPackage(session: ExtHostDebugSession): DebugAdapterExecutable {
|
private daExecutableFromPackage(session: ExtHostDebugSession): DebugAdapterExecutable | undefined {
|
||||||
const dae = ExecutableDebugAdapter.platformAdapterExecutable(this._extensionService.getAllExtensionDescriptions(), session.type);
|
const dae = ExecutableDebugAdapter.platformAdapterExecutable(this._extensionService.getAllExtensionDescriptions(), session.type);
|
||||||
return new DebugAdapterExecutable(dae.command, dae.args, dae.env, dae.cwd);
|
if (dae) {
|
||||||
|
return new DebugAdapterExecutable(dae.command, dae.args, dae.options);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private startBreakpoints() {
|
private startBreakpoints() {
|
||||||
|
|
|
@ -1934,14 +1934,12 @@ export class FunctionBreakpoint extends Breakpoint {
|
||||||
export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
|
export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
|
||||||
readonly command: string;
|
readonly command: string;
|
||||||
readonly args: string[];
|
readonly args: string[];
|
||||||
readonly env?: { [key: string]: string };
|
readonly options?: vscode.DebugAdapterExecutableOptions;
|
||||||
readonly cwd?: string;
|
|
||||||
|
|
||||||
constructor(command: string, args?: string[], env?: { [key: string]: string }, cwd?: string) {
|
constructor(command: string, args: string[], options?: vscode.DebugAdapterExecutableOptions) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
this.args = args;
|
this.args = args || [];
|
||||||
this.env = env;
|
this.options = options;
|
||||||
this.cwd = cwd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -472,12 +472,16 @@ export interface IDebugAdapterFactory extends ITerminalLauncher {
|
||||||
substituteVariables(folder: IWorkspaceFolder, config: IConfig): Promise<IConfig>;
|
substituteVariables(folder: IWorkspaceFolder, config: IConfig): Promise<IConfig>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IDebugAdapterExecutableOptions {
|
||||||
|
cwd?: string;
|
||||||
|
env?: { [key: string]: string };
|
||||||
|
}
|
||||||
|
|
||||||
export interface IDebugAdapterExecutable {
|
export interface IDebugAdapterExecutable {
|
||||||
readonly type: 'executable';
|
readonly type: 'executable';
|
||||||
readonly command: string;
|
readonly command: string;
|
||||||
readonly args: string[];
|
readonly args: string[];
|
||||||
readonly cwd?: string;
|
readonly options?: IDebugAdapterExecutableOptions;
|
||||||
readonly env?: { [key: string]: string };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDebugAdapterServer {
|
export interface IDebugAdapterServer {
|
||||||
|
|
|
@ -336,14 +336,14 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter {
|
||||||
if (Array.isArray(this.adapterExecutable.args) && this.adapterExecutable.args.length > 0) {
|
if (Array.isArray(this.adapterExecutable.args) && this.adapterExecutable.args.length > 0) {
|
||||||
const isElectron = !!process.env['ELECTRON_RUN_AS_NODE'] || !!process.versions['electron'];
|
const isElectron = !!process.env['ELECTRON_RUN_AS_NODE'] || !!process.versions['electron'];
|
||||||
const options: cp.ForkOptions = {
|
const options: cp.ForkOptions = {
|
||||||
env: this.adapterExecutable.env
|
env: this.adapterExecutable.options && this.adapterExecutable.options.env
|
||||||
? objects.mixin(objects.mixin({}, process.env), this.adapterExecutable.env)
|
? objects.mixin(objects.mixin({}, process.env), this.adapterExecutable.options.env)
|
||||||
: process.env,
|
: process.env,
|
||||||
execArgv: isElectron ? ['-e', 'delete process.env.ELECTRON_RUN_AS_NODE;require(process.argv[1])'] : [],
|
execArgv: isElectron ? ['-e', 'delete process.env.ELECTRON_RUN_AS_NODE;require(process.argv[1])'] : [],
|
||||||
silent: true
|
silent: true
|
||||||
};
|
};
|
||||||
if (this.adapterExecutable.cwd) {
|
if (this.adapterExecutable.options && this.adapterExecutable.options.cwd) {
|
||||||
options.cwd = this.adapterExecutable.cwd;
|
options.cwd = this.adapterExecutable.options.cwd;
|
||||||
}
|
}
|
||||||
const child = cp.fork(this.adapterExecutable.args[0], this.adapterExecutable.args.slice(1), options);
|
const child = cp.fork(this.adapterExecutable.args[0], this.adapterExecutable.args.slice(1), options);
|
||||||
if (!child.pid) {
|
if (!child.pid) {
|
||||||
|
@ -356,12 +356,12 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const options: cp.SpawnOptions = {
|
const options: cp.SpawnOptions = {
|
||||||
env: this.adapterExecutable.env
|
env: this.adapterExecutable.options && this.adapterExecutable.options.env
|
||||||
? objects.mixin(objects.mixin({}, process.env), this.adapterExecutable.env)
|
? objects.mixin(objects.mixin({}, process.env), this.adapterExecutable.options.env)
|
||||||
: process.env
|
: process.env
|
||||||
};
|
};
|
||||||
if (this.adapterExecutable.cwd) {
|
if (this.adapterExecutable.options && this.adapterExecutable.options.cwd) {
|
||||||
options.cwd = this.adapterExecutable.cwd;
|
options.cwd = this.adapterExecutable.options.cwd;
|
||||||
}
|
}
|
||||||
this.serverProcess = cp.spawn(this.adapterExecutable.command, this.adapterExecutable.args, options);
|
this.serverProcess = cp.spawn(this.adapterExecutable.command, this.adapterExecutable.args, options);
|
||||||
resolve(null);
|
resolve(null);
|
||||||
|
@ -474,8 +474,8 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static platformAdapterExecutable(extensionDescriptions: IExtensionDescription[], debugType: string): IDebugAdapterExecutable {
|
static platformAdapterExecutable(extensionDescriptions: IExtensionDescription[], debugType: string): IDebugAdapterExecutable | undefined {
|
||||||
const result: IDebuggerContribution = Object.create(null);
|
let result: IDebuggerContribution = Object.create(null);
|
||||||
debugType = debugType.toLowerCase();
|
debugType = debugType.toLowerCase();
|
||||||
|
|
||||||
// merge all contributions into one
|
// merge all contributions into one
|
||||||
|
@ -488,7 +488,7 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter {
|
||||||
const extractedDbg = ExecutableDebugAdapter.extract(dbg, ed.extensionLocation.fsPath);
|
const extractedDbg = ExecutableDebugAdapter.extract(dbg, ed.extensionLocation.fsPath);
|
||||||
|
|
||||||
// merge
|
// merge
|
||||||
objects.mixin(result, extractedDbg, ed.isBuiltin);
|
result = objects.mixin(result, extractedDbg, ed.isBuiltin);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,12 +519,15 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter {
|
||||||
command: runtime,
|
command: runtime,
|
||||||
args: (runtimeArgs || []).concat([program]).concat(args || [])
|
args: (runtimeArgs || []).concat([program]).concat(args || [])
|
||||||
};
|
};
|
||||||
} else {
|
} else if (program) {
|
||||||
return {
|
return {
|
||||||
type: 'executable',
|
type: 'executable',
|
||||||
command: program,
|
command: program,
|
||||||
args: args || []
|
args: args || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nothing found
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,13 @@ export class Debugger implements IDebugger {
|
||||||
// TODO@AW: this.inExtHost() should now return true
|
// TODO@AW: this.inExtHost() should now return true
|
||||||
return Promise.resolve(this.configurationManager.createDebugAdapter(session));
|
return Promise.resolve(this.configurationManager.createDebugAdapter(session));
|
||||||
default:
|
default:
|
||||||
throw new Error('Cannot create debug adapter.');
|
throw new Error('unknown type');
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
if (err && err.message) {
|
||||||
|
throw new Error(nls.localize('cannot.create.da.with.err', "Cannot create debug adapter ({0}).", err.message));
|
||||||
|
} else {
|
||||||
|
throw new Error(nls.localize('cannot.create.da', "Cannot create debug adapter."));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -92,7 +98,11 @@ export class Debugger implements IDebugger {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback: use executable information from package.json
|
// fallback: use executable information from package.json
|
||||||
return ExecutableDebugAdapter.platformAdapterExecutable(this.mergedExtensionDescriptions, this.type);
|
const ae = ExecutableDebugAdapter.platformAdapterExecutable(this.mergedExtensionDescriptions, this.type);
|
||||||
|
if (ae === undefined) {
|
||||||
|
throw new Error('no executable specified in package.json');
|
||||||
|
}
|
||||||
|
return ae;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue