提交 be713f75 编写于 作者: A Andre Weinand

support env vars when creating a DA; fixes #56646

上级 3193667f
......@@ -452,10 +452,22 @@ declare module 'vscode' {
*/
readonly args: string[];
/**
* 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.
*/
readonly env?: { [key: string]: string };
/**
* The working directory for the debug adapter.
*/
readonly cwd?: string;
/**
* Create a new debug adapter specification.
*/
constructor(command: string, args?: string[]);
constructor(command: string, args?: string[], env?: { [key: string]: string }, cwd?: string);
}
export class DebugAdapterServer {
......@@ -467,10 +479,15 @@ declare module 'vscode' {
*/
readonly port: number;
/**
* The host.
*/
readonly host?: string;
/**
* Create a new debug adapter specification.
*/
constructor(port: number);
constructor(port: number, host?: string);
}
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer;
......
......@@ -347,7 +347,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
mythis._debugServiceProxy.$acceptDAMessage(handle, message);
}
}(adapter.port);
}(adapter);
break;
case 'executable':
......@@ -363,7 +363,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
mythis._debugServiceProxy.$acceptDAMessage(handle, message);
}
}(config.type, adapter);
}(adapter, config.type);
break;
default:
......
......@@ -1892,19 +1892,25 @@ export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
readonly type = 'executable';
readonly command: string;
readonly args: string[];
readonly env?: { [key: string]: string };
readonly cwd?: string;
constructor(command: string, args?: string[]) {
constructor(command: string, args?: string[], env?: { [key: string]: string }, cwd?: string) {
this.command = command;
this.args = args;
this.env = env;
this.cwd = cwd;
}
}
export class DebugAdapterServer implements vscode.DebugAdapterServer {
readonly type = 'server';
readonly port: number;
readonly host: string;
constructor(port: number) {
constructor(port: number, host?: string) {
this.port = port;
this.host = host;
}
}
......
......@@ -460,11 +460,14 @@ export interface IAdapterExecutable {
readonly type: 'executable';
readonly command: string;
readonly args: string[];
readonly cwd?: string;
readonly env?: { [key: string]: string };
}
export interface IAdapterServer {
readonly type: 'server';
readonly port: number;
readonly host?: string;
}
export type IAdapterDescriptor = IAdapterExecutable | IAdapterServer;
......
......@@ -17,7 +17,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IOutputService } from 'vs/workbench/parts/output/common/output';
import { IDebugAdapter, IAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution } from 'vs/workbench/parts/debug/common/debug';
import { IDebugAdapter, IAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IAdapterServer } from 'vs/workbench/parts/debug/common/debug';
/**
* Abstract implementation of the low level API for a debug adapter.
......@@ -245,14 +245,14 @@ export class SocketDebugAdapter extends StreamDebugAdapter {
private socket: net.Socket;
constructor(private port: number, private host = '127.0.0.1') {
constructor(private adapterServer: IAdapterServer) {
super();
}
startSession(): TPromise<void> {
return new TPromise<void>((resolve, reject) => {
let connected = false;
this.socket = net.createConnection(this.port, this.host, () => {
this.socket = net.createConnection(this.adapterServer.port, this.adapterServer.host || '127.0.0.1', () => {
this.connect(this.socket, this.socket);
resolve(null);
connected = true;
......@@ -294,19 +294,19 @@ export class DebugAdapter extends StreamDebugAdapter {
private serverProcess: cp.ChildProcess;
constructor(private debugType: string, private adapterExecutable: IAdapterExecutable, private outputService?: IOutputService) {
constructor(private adapterExecutable: IAdapterExecutable, private debugType: string, private outputService?: IOutputService) {
super();
}
startSession(): TPromise<void> {
return new TPromise<void>((c, e) => {
return new TPromise<void>((resolve, reject) => {
// verify executables
if (this.adapterExecutable.command) {
if (paths.isAbsolute(this.adapterExecutable.command)) {
if (!fs.existsSync(this.adapterExecutable.command)) {
e(new Error(nls.localize('debugAdapterBinNotFound', "Debug adapter executable '{0}' does not exist.", this.adapterExecutable.command)));
reject(new Error(nls.localize('debugAdapterBinNotFound', "Debug adapter executable '{0}' does not exist.", this.adapterExecutable.command)));
}
} else {
// relative path
......@@ -316,28 +316,43 @@ export class DebugAdapter extends StreamDebugAdapter {
}
}
} else {
e(new Error(nls.localize({ key: 'debugAdapterCannotDetermineExecutable', comment: ['Adapter executable file not found'] },
reject(new Error(nls.localize({ key: 'debugAdapterCannotDetermineExecutable', comment: ['Adapter executable file not found'] },
"Cannot determine executable for debug adapter '{0}'.", this.debugType)));
}
if (this.adapterExecutable.command === 'node') {
if (Array.isArray(this.adapterExecutable.args) && this.adapterExecutable.args.length > 0) {
const isElectron = process.env['ELECTRON_RUN_AS_NODE'] || process.versions['electron'];
const child = cp.fork(this.adapterExecutable.args[0], this.adapterExecutable.args.slice(1), {
const isElectron = !!process.env['ELECTRON_RUN_AS_NODE'] || !!process.versions['electron'];
const options: cp.ForkOptions = {
env: this.adapterExecutable.env
? objects.mixin(objects.mixin({}, process.env), this.adapterExecutable.env)
: process.env,
execArgv: isElectron ? ['-e', 'delete process.env.ELECTRON_RUN_AS_NODE;require(process.argv[1])'] : [],
silent: true
});
};
if (this.adapterExecutable.cwd) {
options.cwd = this.adapterExecutable.cwd;
}
const child = cp.fork(this.adapterExecutable.args[0], this.adapterExecutable.args.slice(1), options);
if (!child.pid) {
e(new Error(nls.localize('unableToLaunchDebugAdapter', "Unable to launch debug adapter from '{0}'.", this.adapterExecutable.args[0])));
reject(new Error(nls.localize('unableToLaunchDebugAdapter', "Unable to launch debug adapter from '{0}'.", this.adapterExecutable.args[0])));
}
this.serverProcess = child;
c(null);
resolve(null);
} else {
e(new Error(nls.localize('unableToLaunchDebugAdapterNoArgs', "Unable to launch debug adapter.")));
reject(new Error(nls.localize('unableToLaunchDebugAdapterNoArgs', "Unable to launch debug adapter.")));
}
} else {
this.serverProcess = cp.spawn(this.adapterExecutable.command, this.adapterExecutable.args);
c(null);
const options: cp.SpawnOptions = {
env: this.adapterExecutable.env
? objects.mixin(objects.mixin({}, process.env), this.adapterExecutable.env)
: process.env
};
if (this.adapterExecutable.cwd) {
options.cwd = this.adapterExecutable.cwd;
}
this.serverProcess = cp.spawn(this.adapterExecutable.command, this.adapterExecutable.args, options);
resolve(null);
}
}).then(_ => {
this.serverProcess.on('error', err => {
......
......@@ -46,9 +46,9 @@ export class Debugger implements IDebugger {
return this.getAdapterDescriptor(session, root, config).then(adapterDescriptor => {
switch (adapterDescriptor.type) {
case 'server':
return new SocketDebugAdapter(adapterDescriptor.port);
return new SocketDebugAdapter(adapterDescriptor);
case 'executable':
return new DebugAdapter(this.type, adapterDescriptor, outputService);
return new DebugAdapter(adapterDescriptor, this.type, outputService);
default:
return undefined;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册