提交 644d57dd 编写于 作者: A Andre Weinand

pass config to adapterExecutableCommand; fixes #45220

上级 82a2a476
......@@ -437,6 +437,9 @@ declare module 'vscode' {
* Represents a debug adapter executable and optional arguments passed to it.
*/
export class DebugAdapterExecutable {
readonly type: 'executable';
/**
* The command path of the debug adapter executable.
* A command must be either an absolute path or the name of an executable looked up via the PATH environment variable.
......@@ -455,6 +458,23 @@ declare module 'vscode' {
constructor(command: string, args?: string[]);
}
export class DebugAdapterServer {
readonly type: 'server';
/**
* The port.
*/
readonly port: number;
/**
* Create a new debug adapter specification.
*/
constructor(port: number);
}
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer;
export interface DebugConfigurationProvider {
/**
* This optional method is called just before a debug adapter is started to determine its executable path and arguments.
......@@ -462,8 +482,18 @@ declare module 'vscode' {
* @param folder The workspace folder from which the configuration originates from or undefined for a folderless setup.
* @param token A cancellation token.
* @return a [debug adapter's executable and optional arguments](#DebugAdapterExecutable) or undefined.
* @deprecated Use DebugConfigurationProvider.provideDebugAdapter instead
*/
debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>;
/**
* This optional method is called just before a debug adapter is started to determine its executable path and arguments.
* Registering more than one provideDebugAdapter for a type results in an error.
* @param folder The workspace folder from which the configuration originates from or undefined for a folderless setup.
* @param token A cancellation token.
* @return a [debug adapter's descriptor](#DebugAdapterDescriptor) or undefined.
*/
provideDebugAdapter?(session: DebugSession, folder: WorkspaceFolder | undefined, executable: DebugAdapterExecutable, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugAdapterDescriptor>;
}
//#endregion
......
......@@ -6,11 +6,11 @@
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { URI as uri } from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IAdapterExecutable, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider, IDebugSession } from 'vs/workbench/parts/debug/common/debug';
import { TPromise } from 'vs/base/common/winjs.base';
import {
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
} from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import severity from 'vs/base/common/severity';
......@@ -36,33 +36,31 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDebugService);
this._toDispose = [];
this._toDispose.push(debugService.onDidNewSession(session => {
this._proxy.$acceptDebugSessionStarted(<DebugSessionUUID>session.getId(), session.configuration.type, session.getName(false));
this._proxy.$acceptDebugSessionStarted(this.getSessionDto(session));
}));
// Need to start listening early to new session events because a custom event can come while a session is initialising
this._toDispose.push(debugService.onWillNewSession(session => {
this._toDispose.push(session.onDidCustomEvent(event => this._proxy.$acceptDebugSessionCustomEvent(session.getId(), session.configuration.type, session.configuration.name, event)));
this._toDispose.push(session.onDidCustomEvent(event => this._proxy.$acceptDebugSessionCustomEvent(this.getSessionDto(session), event)));
}));
this._toDispose.push(debugService.onDidEndSession(session => {
this._proxy.$acceptDebugSessionTerminated(<DebugSessionUUID>session.getId(), session.configuration.type, session.getName(false));
this._proxy.$acceptDebugSessionTerminated(this.getSessionDto(session));
}));
this._toDispose.push(debugService.getViewModel().onDidFocusSession(proc => {
if (proc) {
this._proxy.$acceptDebugSessionActiveChanged(<DebugSessionUUID>proc.getId(), proc.configuration.type, proc.getName(false));
} else {
this._proxy.$acceptDebugSessionActiveChanged(undefined);
}
this._toDispose.push(debugService.getViewModel().onDidFocusSession(session => {
this._proxy.$acceptDebugSessionActiveChanged(this.getSessionDto(session));
}));
this._debugAdapters = new Map<number, ExtensionHostDebugAdapter>();
}
public $registerDebugTypes(debugTypes: string[]) {
this._toDispose.push(this.debugService.getConfigurationManager().registerDebugAdapterProvider(debugTypes, this));
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
createDebugAdapter(debugType: string, adapterInfo, debugPort: number): IDebugAdapter {
// interface IDebugAdapterProvider
createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter {
const handle = this._debugAdaptersHandleCounter++;
const da = new ExtensionHostDebugAdapter(handle, this._proxy, debugType, adapterInfo, debugPort);
const da = new ExtensionHostDebugAdapter(handle, this._proxy, this.getSessionDto(session), folder, config);
this._debugAdapters.set(handle, da);
return da;
}
......@@ -75,8 +73,11 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return TPromise.wrap(this._proxy.$runInTerminal(args, config));
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
// RPC methods (MainThreadDebugServiceShape)
public $registerDebugTypes(debugTypes: string[]) {
this._toDispose.push(this.debugService.getConfigurationManager().registerDebugAdapterProvider(debugTypes, this));
}
public $startBreakpointEvents(): Thenable<void> {
......@@ -147,54 +148,25 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return void 0;
}
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint>)): (ISourceBreakpointDto | IFunctionBreakpointDto)[] {
return bps.map(bp => {
if ('name' in bp) {
const fbp = <IFunctionBreakpoint>bp;
return <IFunctionBreakpointDto>{
type: 'function',
id: fbp.getId(),
enabled: fbp.enabled,
condition: fbp.condition,
hitCondition: fbp.hitCondition,
logMessage: fbp.logMessage,
functionName: fbp.name
};
} else {
const sbp = <IBreakpoint>bp;
return <ISourceBreakpointDto>{
type: 'source',
id: sbp.getId(),
enabled: sbp.enabled,
condition: sbp.condition,
hitCondition: sbp.hitCondition,
logMessage: sbp.logMessage,
uri: sbp.uri,
line: sbp.lineNumber > 0 ? sbp.lineNumber - 1 : 0,
character: (typeof sbp.column === 'number' && sbp.column > 0) ? sbp.column - 1 : 0,
};
}
});
}
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasDebugAdapterExecutable: boolean, handle: number): Thenable<void> {
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasProvideDebugAdapter: boolean, handle: number): Thenable<void> {
const provider = <IDebugConfigurationProvider>{
type: debugType
};
if (hasProvide) {
provider.provideDebugConfigurations = folder => {
provider.provideDebugConfigurations = (folder) => {
return TPromise.wrap(this._proxy.$provideDebugConfigurations(handle, folder));
};
}
if (hasResolve) {
provider.resolveDebugConfiguration = (folder, debugConfiguration) => {
return TPromise.wrap(this._proxy.$resolveDebugConfiguration(handle, folder, debugConfiguration));
provider.resolveDebugConfiguration = (folder, config) => {
return TPromise.wrap(this._proxy.$resolveDebugConfiguration(handle, folder, config));
};
}
if (hasDebugAdapterExecutable) {
provider.debugAdapterExecutable = (folder) => {
return TPromise.wrap(this._proxy.$debugAdapterExecutable(handle, folder));
if (hasProvideDebugAdapter) {
provider.provideDebugAdapter = (session, folder, config) => {
return TPromise.wrap(this._proxy.$provideDebugAdapter(handle, this.getSessionDto(session), folder, config));
};
}
this.debugService.getConfigurationManager().registerDebugConfigurationProvider(handle, provider);
......@@ -255,6 +227,49 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
public $acceptDAExit(handle: number, code: number, signal: string) {
this._debugAdapters.get(handle).fireExit(handle, code, signal);
}
// dto helpers
private getSessionDto(session: IDebugSession): IDebugSessionDto {
if (session) {
return {
id: <DebugSessionUUID>session.getId(),
type: session.configuration.type,
name: session.getName(false)
};
}
return undefined;
}
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint>)): (ISourceBreakpointDto | IFunctionBreakpointDto)[] {
return bps.map(bp => {
if ('name' in bp) {
const fbp = <IFunctionBreakpoint>bp;
return <IFunctionBreakpointDto>{
type: 'function',
id: fbp.getId(),
enabled: fbp.enabled,
condition: fbp.condition,
hitCondition: fbp.hitCondition,
logMessage: fbp.logMessage,
functionName: fbp.name
};
} else {
const sbp = <IBreakpoint>bp;
return <ISourceBreakpointDto>{
type: 'source',
id: sbp.getId(),
enabled: sbp.enabled,
condition: sbp.condition,
hitCondition: sbp.hitCondition,
logMessage: sbp.logMessage,
uri: sbp.uri,
line: sbp.lineNumber > 0 ? sbp.lineNumber - 1 : 0,
character: (typeof sbp.column === 'number' && sbp.column > 0) ? sbp.column - 1 : 0,
};
}
});
}
}
/**
......@@ -262,7 +277,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
*/
class ExtensionHostDebugAdapter extends AbstractDebugAdapter {
constructor(private _handle: number, private _proxy: ExtHostDebugServiceShape, private _debugType: string, private _adapterExecutable: IAdapterExecutable | null, private _debugPort: number) {
constructor(private _handle: number, private _proxy: ExtHostDebugServiceShape, private _sessionDto: IDebugSessionDto, private folder: IWorkspaceFolder, private config: IConfig) {
super();
}
......@@ -275,7 +290,7 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter {
}
public startSession(): TPromise<void> {
return TPromise.wrap(this._proxy.$startDASession(this._handle, this._debugType, this._adapterExecutable, this._debugPort));
return TPromise.wrap(this._proxy.$startDASession(this._handle, this._sessionDto, this.folder ? this.folder.uri : undefined, this.config));
}
public sendMessage(message: DebugProtocol.ProtocolMessage): void {
......
......@@ -725,6 +725,7 @@ export function createApiFactory(
CompletionTriggerKind: extHostTypes.CompletionTriggerKind,
ConfigurationTarget: extHostTypes.ConfigurationTarget,
DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable,
DebugAdapterServer: extHostTypes.DebugAdapterServer,
DecorationRangeBehavior: extHostTypes.DecorationRangeBehavior,
Diagnostic: extHostTypes.Diagnostic,
DiagnosticRelatedInformation: extHostTypes.DiagnosticRelatedInformation,
......
......@@ -33,7 +33,7 @@ import { EndOfLine, IFileOperationOptions, TextEditorLineNumbersStyle } from 'vs
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { TaskDTO, TaskExecutionDTO, TaskFilterDTO, TaskHandleDTO, TaskProcessEndedDTO, TaskProcessStartedDTO, TaskSystemInfoDTO } from 'vs/workbench/api/shared/tasks';
import { ITreeItem } from 'vs/workbench/common/views';
import { IAdapterExecutable, IConfig, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug';
import { IConfig, ITerminalSettings, IAdapterDescriptor } from 'vs/workbench/parts/debug/common/debug';
import { TaskSet } from 'vs/workbench/parts/tasks/common/tasks';
import { ITerminalDimensions } from 'vs/workbench/parts/terminal/common/terminal';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
......@@ -943,20 +943,26 @@ export interface ISourceMultiBreakpointDto {
}[];
}
export interface IDebugSessionDto {
id: DebugSessionUUID;
type: string;
name: string;
}
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): Thenable<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Thenable<void>;
$startDASession(handle: number, debugType: string, adapterExecutableInfo: IAdapterExecutable | null, debugPort: number): Thenable<void>;
$startDASession(handle: number, session: IDebugSessionDto, folder: UriComponents | undefined, debugConfiguration: IConfig): Thenable<void>;
$stopDASession(handle: number): Thenable<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): Thenable<IConfig>;
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined): Thenable<IConfig[]>;
$debugAdapterExecutable(handle: number, folder: UriComponents | undefined): Thenable<IAdapterExecutable>;
$acceptDebugSessionStarted(id: DebugSessionUUID, type: string, name: string): void;
$acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void;
$acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void;
$acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void;
$acceptBreakpointsDelta(delat: IBreakpointsDeltaDto): void;
$provideDebugAdapter(handle: number, session: IDebugSessionDto, folderUri: UriComponents | undefined, debugConfiguration: IConfig): Thenable<IAdapterDescriptor>;
$acceptDebugSessionStarted(session: IDebugSessionDto): void;
$acceptDebugSessionTerminated(session: IDebugSessionDto): void;
$acceptDebugSessionActiveChanged(session: IDebugSessionDto): void;
$acceptDebugSessionCustomEvent(session: IDebugSessionDto, event: any): void;
$acceptBreakpointsDelta(delta: IBreakpointsDeltaDto): void;
}
......
......@@ -1889,6 +1889,7 @@ export class FunctionBreakpoint extends Breakpoint {
}
export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
readonly type = 'executable';
readonly command: string;
readonly args: string[];
......@@ -1898,6 +1899,15 @@ export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
}
}
export class DebugAdapterServer implements vscode.DebugAdapterServer {
readonly type = 'server';
readonly port: number;
constructor(port: number) {
this.port = port;
}
}
export enum LogLevel {
Trace = 1,
Debug = 2,
......
......@@ -111,7 +111,7 @@ export interface IExpression extends IReplElement, IExpressionContainer {
}
export interface IDebugger {
createDebugAdapter(root: IWorkspaceFolder, outputService: IOutputService, debugPort?: number): TPromise<IDebugAdapter>;
createDebugAdapter(session: IDebugSession, root: IWorkspaceFolder, config: IConfig, outputService: IOutputService): TPromise<IDebugAdapter>;
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): TPromise<void>;
getCustomTelemetryService(): TPromise<TelemetryService>;
}
......@@ -452,15 +452,23 @@ export interface IDebugAdapter extends IDisposable {
}
export interface IDebugAdapterProvider extends ITerminalLauncher {
createDebugAdapter(debugType: string, adapterInfo: IAdapterExecutable | null, debugPort: number): IDebugAdapter;
createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter;
substituteVariables(folder: IWorkspaceFolder, config: IConfig): TPromise<IConfig>;
}
export interface IAdapterExecutable {
readonly command?: string;
readonly args?: string[];
readonly type: 'executable';
readonly command: string;
readonly args: string[];
}
export interface IAdapterServer {
readonly type: 'server';
readonly port: number;
}
export type IAdapterDescriptor = IAdapterExecutable | IAdapterServer;
export interface IPlatformSpecificAdapterContribution {
program?: string;
args?: string[];
......@@ -498,7 +506,7 @@ export interface IDebugConfigurationProvider {
handle: number;
resolveDebugConfiguration?(folderUri: uri | undefined, debugConfiguration: IConfig): TPromise<IConfig>;
provideDebugConfigurations?(folderUri: uri | undefined): TPromise<IConfig[]>;
debugAdapterExecutable(folderUri: uri | undefined): TPromise<IAdapterExecutable>;
provideDebugAdapter?(session: IDebugSession, folderUri: uri | undefined, config: IConfig): TPromise<IAdapterDescriptor>;
}
export interface ITerminalLauncher {
......@@ -549,10 +557,11 @@ export interface IConfigurationManager {
unregisterDebugConfigurationProvider(handle: number): void;
resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: any): TPromise<any>;
debugAdapterExecutable(folderUri: uri | undefined, type: string): TPromise<IAdapterExecutable | undefined>;
provideDebugAdapter(session: IDebugSession, folderUri: uri | undefined, config: IConfig): TPromise<IAdapterDescriptor | undefined>;
registerDebugAdapterProvider(debugTypes: string[], debugAdapterLauncher: IDebugAdapterProvider): IDisposable;
createDebugAdapter(debugType: string, adapterExecutable: IAdapterExecutable | null, debugPort?: number): IDebugAdapter | undefined;
createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter;
substituteVariables(debugType: string, folder: IWorkspaceFolder, config: IConfig): TPromise<IConfig>;
runInTerminal(debugType: string, args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void>;
}
......
......@@ -22,7 +22,7 @@ import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IAdapterExecutable, IDebugAdapterProvider, IDebugAdapter, ITerminalSettings, ITerminalLauncher } from 'vs/workbench/parts/debug/common/debug';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterProvider, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor } from 'vs/workbench/parts/debug/common/debug';
import { Debugger } from 'vs/workbench/parts/debug/node/debugger';
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
......@@ -119,10 +119,12 @@ export class ConfigurationManager implements IConfigurationManager {
.then(results => results.reduce((first, second) => first.concat(second), []));
}
public debugAdapterExecutable(folderUri: uri | undefined, type: string): TPromise<IAdapterExecutable | undefined> {
const providers = this.providers.filter(p => p.type === type && p.debugAdapterExecutable);
public provideDebugAdapter(session: IDebugSession, folderUri: uri | undefined, config: IConfig): TPromise<IAdapterDescriptor | undefined> {
const providers = this.providers.filter(p => p.type === config.type && p.provideDebugAdapter);
if (providers.length === 1) {
return providers[0].debugAdapterExecutable(folderUri);
return providers[0].provideDebugAdapter(session, folderUri, config);
} else {
// TODO@AW handle n > 1 case
}
return TPromise.as(undefined);
}
......@@ -140,10 +142,10 @@ export class ConfigurationManager implements IConfigurationManager {
return this.debugAdapterProviders.get(type);
}
public createDebugAdapter(debugType: string, adapterExecutable: IAdapterExecutable, debugPort: number): IDebugAdapter | undefined {
let dap = this.getDebugAdapterProvider(debugType);
public createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter {
let dap = this.getDebugAdapterProvider(config.type);
if (dap) {
return dap.createDebugAdapter(debugType, adapterExecutable, debugPort);
return dap.createDebugAdapter(session, folder, config);
}
return undefined;
}
......
......@@ -127,7 +127,7 @@ export class DebugSession implements IDebugSession {
return dbgr.getCustomTelemetryService().then(customTelemetryService => {
return dbgr.createDebugAdapter(this.root, this.outputService, this._configuration.resolved.debugServer).then(debugAdapter => {
return dbgr.createDebugAdapter(this, this.root, this._configuration.resolved, this.outputService).then(debugAdapter => {
this._raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService);
......
......@@ -294,12 +294,8 @@ export class DebugAdapter extends StreamDebugAdapter {
private serverProcess: cp.ChildProcess;
constructor(private debugType: string, private adapterExecutable: IAdapterExecutable | null, extensionDescriptions: IExtensionDescription[], private outputService?: IOutputService) {
constructor(private debugType: string, private adapterExecutable: IAdapterExecutable, private outputService?: IOutputService) {
super();
if (!this.adapterExecutable) {
this.adapterExecutable = DebugAdapter.platformAdapterExecutable(extensionDescriptions, this.debugType);
}
}
startSession(): TPromise<void> {
......@@ -492,11 +488,13 @@ export class DebugAdapter extends StreamDebugAdapter {
if (runtime) {
return {
type: 'executable',
command: runtime,
args: (runtimeArgs || []).concat([program]).concat(args || [])
};
} else {
return {
type: 'executable',
command: program,
args: args || []
};
......
......@@ -11,7 +11,7 @@ import * as objects from 'vs/base/common/objects';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IConfig, IDebuggerContribution, IAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, IDebugConfiguration, ITerminalSettings, IDebugger } from 'vs/workbench/parts/debug/common/debug';
import { IConfig, IDebuggerContribution, IAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, IDebugConfiguration, ITerminalSettings, IDebugger, IDebugSession, IAdapterDescriptor, IAdapterServer } from 'vs/workbench/parts/debug/common/debug';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
......@@ -39,36 +39,43 @@ export class Debugger implements IDebugger {
public hasConfigurationProvider = false;
public createDebugAdapter(root: IWorkspaceFolder, outputService: IOutputService, debugPort?: number): TPromise<IDebugAdapter> {
return this.getAdapterExecutable(root).then(adapterExecutable => {
if (this.inEH()) {
return this.configurationManager.createDebugAdapter(this.type, adapterExecutable, debugPort);
} else {
if (debugPort) {
return new SocketDebugAdapter(debugPort);
} else {
return new DebugAdapter(this.type, adapterExecutable, this.mergedExtensionDescriptions, outputService);
public createDebugAdapter(session: IDebugSession, root: IWorkspaceFolder, config: IConfig, outputService: IOutputService): TPromise<IDebugAdapter> {
if (this.inEH()) {
return TPromise.as(this.configurationManager.createDebugAdapter(session, root, config));
} else {
return this.getAdapterDescriptor(session, root, config).then(adapterDescriptor => {
switch (adapterDescriptor.type) {
case 'server':
return new SocketDebugAdapter(adapterDescriptor.port);
case 'executable':
return new DebugAdapter(this.type, adapterDescriptor, outputService);
default:
return undefined;
}
}
});
});
}
}
public getAdapterExecutable(root: IWorkspaceFolder): TPromise<IAdapterExecutable | null> {
private getAdapterDescriptor(session: IDebugSession, root: IWorkspaceFolder, config: IConfig): TPromise<IAdapterDescriptor> {
// first try to get an executable from DebugConfigurationProvider
return this.configurationManager.debugAdapterExecutable(root ? root.uri : undefined, this.type).then(adapterExecutable => {
// try deprecated command based extension API to receive an executable
if (this.debuggerContribution.adapterExecutableCommand) {
const adapterExecutable = this.commandService.executeCommand<IAdapterExecutable>(this.debuggerContribution.adapterExecutableCommand, root ? root.uri.toString() : undefined);
return TPromise.wrap(adapterExecutable);
}
if (adapterExecutable) {
return adapterExecutable;
return this.configurationManager.provideDebugAdapter(session, root ? root.uri : undefined, config).then(adapter => {
if (adapter) {
return adapter;
}
// try deprecated command based extension API to receive an executable
if (this.debuggerContribution.adapterExecutableCommand) {
return this.commandService.executeCommand<IAdapterExecutable>(this.debuggerContribution.adapterExecutableCommand, root ? root.uri.toString() : undefined);
if (typeof config.debugServer === 'number') {
return <IAdapterServer>{
type: 'server',
port: config.debugServer
};
}
// give up and let DebugAdapter determine executable based on package.json contribution
return TPromise.as(null);
// fallback: use information from package.json
return DebugAdapter.platformAdapterExecutable(this.mergedExtensionDescriptions, this.type);
});
}
......
......@@ -6,7 +6,7 @@
import * as assert from 'assert';
import * as paths from 'vs/base/common/paths';
import * as platform from 'vs/base/common/platform';
import { IAdapterExecutable, IConfigurationManager } from 'vs/workbench/parts/debug/common/debug';
import { IAdapterExecutable, IConfigurationManager, IConfig, IDebugSession } from 'vs/workbench/parts/debug/common/debug';
import { Debugger } from 'vs/workbench/parts/debug/node/debugger';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { URI } from 'vs/base/common/uri';
......@@ -117,7 +117,7 @@ suite('Debug - Debugger', () => {
const configurationManager = <IConfigurationManager>{
debugAdapterExecutable(folderUri: URI | undefined, type: string): TPromise<IAdapterExecutable | undefined> {
provideDebugAdapter(session: IDebugSession, folderUri: URI | undefined, config: IConfig): TPromise<IAdapterExecutable | undefined> {
return TPromise.as(undefined);
}
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册